pull/2/head
gorhill 10 years ago
parent e3dcf085a8
commit 186d10bf48

@ -396,63 +396,59 @@ body.powerOff .matrix .g3Meta.g3Collapsed ~ .matRow.ro {
} }
/* Cell coloring */ /* Cell coloring */
.rd { .t81 {
color: white; color: white;
background-color: #c00; background-color: #c00;
} }
.gd { .t82 {
color: white; color: white;
background-color: #080; background-color: #080;
} }
.ri, .t1 {
.rg {
border-color: #debaba; border-color: #debaba;
color: black; color: black;
background-color: #f8d0d0; background-color: #f8d0d0;
} }
.gi, .t2 {
.gg {
border-color: #bad6ba; border-color: #bad6ba;
color: black; color: black;
background-color: #d0f0d0; background-color: #d0f0d0;
} }
.matCell.rdp { .matCell.p81 {
background-image: url('/img/permanent-black-small.png'); background-image: url('/img/permanent-black-small.png');
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: -1px -1px; background-position: -1px -1px;
} }
.matCell.gdp { .matCell.p82 {
background-image: url('/img/permanent-white-small.png'); background-image: url('/img/permanent-white-small.png');
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: -1px -1px; background-position: -1px -1px;
} }
/* Cell coloring for color blind-friendly (hopefully) */ /* Cell coloring for color blind-friendly (hopefully) */
body.colorblind .rd { body.colorblind .t81 {
color: white; color: white;
background-color: #000; background-color: #000;
} }
body.colorblind .gd { body.colorblind .t82 {
border-color: #aaa; border-color: #aaa;
color: black; color: black;
background-color: #fff; background-color: #fff;
} }
body.colorblind .ri, body.colorblind .t1 {
body.colorblind .rg {
border-color: #333; border-color: #333;
color: white; color: white;
background-color: #555; background-color: #555;
} }
body.colorblind .gi, body.colorblind .t2 {
body.colorblind .gg {
border-color: #aaa; border-color: #aaa;
color: black; color: black;
background-color: #ddd; background-color: #ddd;
} }
body.colorblind .matCell.rdp { body.colorblind .matCell.p81 {
background-image: url('/img/permanent-black-small-cb.png'); background-image: url('/img/permanent-black-small-cb.png');
} }
body.colorblind .matCell.gdp { body.colorblind .matCell.p82 {
background-image: url('/img/permanent-white-small-cb.png'); background-image: url('/img/permanent-white-small-cb.png');
} }
@ -499,56 +495,48 @@ body.powerOff .matRow.rw .matCell {
body.powerOff #whitelist, body.powerOff #blacklist { body.powerOff #whitelist, body.powerOff #blacklist {
display: none; display: none;
} }
.rw .matCell.ri #whitelist:hover, .rw .matCell.t1 #whitelist:hover {
.rw .matCell.rg #whitelist:hover {
background-color: #080; background-color: #080;
opacity: 0.25; opacity: 0.25;
} }
body.colorblind .rw .matCell.ri #whitelist:hover, body.colorblind .rw .matCell.t1 #whitelist:hover {
body.colorblind .rw .matCell.rg #whitelist:hover {
background-color: #fff; background-color: #fff;
opacity: 0.6; opacity: 0.6;
} }
.rw .matCell.gi #whitelist:hover, .rw .matCell.t2 #whitelist:hover {
.rw .matCell.gg #whitelist:hover {
background-color: #080; background-color: #080;
opacity: 0.25; opacity: 0.25;
} }
body.colorblind .rw .matCell.gi #whitelist:hover, body.colorblind .rw .matCell.t2 #whitelist:hover {
body.colorblind .rw .matCell.gg #whitelist:hover {
background-color: #fff; background-color: #fff;
opacity: 0.6; opacity: 0.6;
} }
.matCell.rdt #whitelist:hover { .matCell.t81 #whitelist:hover {
background-color: transparent; background-color: transparent;
} }
.matCell.gdt #whitelist:hover { .matCell.t82 #whitelist:hover {
background-color: transparent; background-color: transparent;
} }
.rw .matCell.ri #blacklist:hover, .rw .matCell.t1 #blacklist:hover {
.rw .matCell.rg #blacklist:hover {
background-color: #c00; background-color: #c00;
opacity: 0.25; opacity: 0.25;
} }
body.colorblind .rw .matCell.ri #blacklist:hover, body.colorblind .rw .matCell.t1 #blacklist:hover {
body.colorblind .rw .matCell.rg #blacklist:hover {
background-color: #000; background-color: #000;
opacity: 0.4; opacity: 0.4;
} }
.rw .matCell.gi #blacklist:hover, .rw .matCell.t2 #blacklist:hover {
.rw .matCell.gg #blacklist:hover {
background-color: #c00; background-color: #c00;
opacity: 0.25; opacity: 0.25;
} }
body.colorblind .rw .matCell.gi #blacklist:hover, body.colorblind .rw .matCell.t2 #blacklist:hover {
body.colorblind .rw .matCell.gg #blacklist:hover {
background-color: #000; background-color: #000;
opacity: 0.4; opacity: 0.4;
} }
.matCell.rd #blacklist:hover { .matCell.t81 #blacklist:hover {
background-color: transparent; background-color: transparent;
} }
.matCell.gd #blacklist:hover { .matCell.t82 #blacklist:hover {
background-color: transparent; background-color: transparent;
} }
#domainOnly { #domainOnly {

@ -39,13 +39,13 @@ var Matrix = function() {
/******************************************************************************/ /******************************************************************************/
Matrix.Transparent = 0; Matrix.Transparent = 0;
Matrix.Red = 1; Matrix.Red = 1;
Matrix.Green = 2; Matrix.Green = 2;
Matrix.Gray = 3; Matrix.Gray = 3;
Matrix.Direct = 0x00; Matrix.Indirect = 0x00;
Matrix.Indirect = 0x80; Matrix.Direct = 0x80;
Matrix.RedDirect = Matrix.Red | Matrix.Direct; Matrix.RedDirect = Matrix.Red | Matrix.Direct;
Matrix.RedIndirect = Matrix.Red | Matrix.Indirect; Matrix.RedIndirect = Matrix.Red | Matrix.Indirect;
@ -210,7 +210,7 @@ Matrix.prototype.evaluateCell = function(srcHostname, desHostname, type) {
var key = srcHostname + ' ' + desHostname; var key = srcHostname + ' ' + desHostname;
var bitmap = this.rules[key]; var bitmap = this.rules[key];
if ( bitmap === undefined ) { if ( bitmap === undefined ) {
return undefined; return 0;
} }
return bitmap >> typeBitOffsets[type] & 3; return bitmap >> typeBitOffsets[type] & 3;
}; };
@ -307,7 +307,21 @@ Matrix.prototype.evaluateRowZXY = function(srcHostname, desHostname) {
} }
out.push(this.evaluateCellZXY(srcHostname, desHostname, type)); out.push(this.evaluateCellZXY(srcHostname, desHostname, type));
} }
return out.join(''); return out;
};
/******************************************************************************/
Matrix.prototype.getColumnHeaders = function() {
var out = {};
var i = 0;
for ( var type in typeBitOffsets ) {
if ( typeBitOffsets.hasOwnProperty(type) === false ) {
continue;
}
out[type] = i++;
}
return out;
}; };
/******************************************************************************/ /******************************************************************************/

@ -21,16 +21,18 @@
/* global chrome, µMatrix */ /* global chrome, µMatrix */
/******************************************************************************/
/******************************************************************************/ /******************************************************************************/
(function() { (function() {
// popup.js // popup.js
var µm = µMatrix;
/******************************************************************************/ /******************************************************************************/
var smartReload = function(tabs) { var smartReload = function(tabs) {
var µm = µMatrix;
var i = tabs.length; var i = tabs.length;
while ( i-- ) { while ( i-- ) {
µm.smartReloadTabs(µm.userSettings.smartAutoReload, tabs[i].id); µm.smartReloadTabs(µm.userSettings.smartAutoReload, tabs[i].id);
@ -39,6 +41,123 @@ var smartReload = function(tabs) {
/******************************************************************************/ /******************************************************************************/
// Constructor is faster than object literal
var HostnameSnapshot = function(srcHostname, desHostname, desDomain) {
this.domain = desDomain;
this.temporary = µm.tMatrix.evaluateRowZXY(srcHostname, desHostname);
this.permanent = µm.pMatrix.evaluateRowZXY(srcHostname, desHostname);
this.counts = HostnameSnapshot.counts.slice();
this.totals = HostnameSnapshot.counts.slice();
};
HostnameSnapshot.counts = (function() {
var i = Object.keys(µm.tMatrix.getColumnHeaders()).length;
var aa = new Array(i);
while ( i-- ) {
aa[i] = 0;
}
return aa;
})();
/******************************************************************************/
var matrixSnapshot = function (tabId) {
var r = {
tabId: tabId,
url: '',
hostname: '',
domain: '',
scope: '*',
headers: µm.tMatrix.getColumnHeaders(),
rows: {},
rowCount: 0
};
var pageStore = µm.pageStatsFromTabId(tabId);
if ( !pageStore ) {
return r;
}
var headers = r.headers;
r.url = pageStore.pageUrl;
r.hostname = pageStore.pageHostname;
r.domain = pageStore.pageDomain;
if ( µm.userSettings.scopeLevel === 'site' ) {
r.scope = r.hostname;
} else if ( µm.userSettings.scopeLevel === 'domain' ) {
r.scope = r.domain;
}
// This one always exist
r.rows['*'] = new HostnameSnapshot(r.hostname, '*', '*');
r.rowCount += 1;
var µmuri = µm.URI;
var reqKey, reqType, reqHostname, reqDomain;
var desHostname;
var row, typeIndex;
var anyIndex = headers['*'];
var pageRequests = pageStore.requests;
var reqKeys = pageRequests.getRequestKeys();
var iReqKey = reqKeys.length;
var pos;
while ( iReqKey-- ) {
reqKey = reqKeys[iReqKey];
reqType = pageRequests.typeFromRequestKey(reqKey);
reqHostname = pageRequests.hostnameFromRequestKey(reqKey);
// rhill 2013-10-23: hostname can be empty if the request is a data url
// https://github.com/gorhill/httpswitchboard/issues/26
if ( reqHostname === '' ) {
reqHostname = pageStore.pageHostname;
}
reqDomain = µmuri.domainFromHostname(reqHostname) || reqHostname;
// We want rows of self and ancestors
desHostname = reqHostname;
for ( ;; ) {
// If row exists, ancestors exist
if ( r.rows.hasOwnProperty(desHostname) !== false ) {
break;
}
r.rows[desHostname] = new HostnameSnapshot(r.hostname, desHostname, reqDomain);
r.rowCount += 1;
if ( desHostname === reqDomain ) {
break;
}
pos = desHostname.indexOf('.');
if ( pos === -1 ) {
break;
}
desHostname = desHostname.slice(pos + 1);
}
typeIndex = headers[reqType];
row = r.rows[reqHostname];
row.counts[typeIndex] += 1;
row.counts[anyIndex] += 1;
if ( reqDomain !== reqHostname ) {
row = r.rows[reqDomain];
row.totals[typeIndex] += 1;
row.totals[anyIndex] += 1;
}
row = r.rows['*'];
row.totals[typeIndex] += 1;
row.totals[anyIndex] += 1;
}
return r;
};
/******************************************************************************/
var onMessage = function(request, sender, callback) { var onMessage = function(request, sender, callback) {
// Async // Async
switch ( request.what ) { switch ( request.what ) {
@ -57,6 +176,10 @@ var onMessage = function(request, sender, callback) {
} }
break; break;
case 'matrixSnapshot':
response = matrixSnapshot(request.tabId);
break;
default: default:
return µMatrix.messaging.defaultHandler(request, sender, callback); return µMatrix.messaging.defaultHandler(request, sender, callback);
} }
@ -68,6 +191,7 @@ var onMessage = function(request, sender, callback) {
})(); })();
/******************************************************************************/
/******************************************************************************/ /******************************************************************************/
// content scripts // content scripts
@ -200,6 +324,7 @@ var onMessage = function(request, sender, callback) {
})(); })();
/******************************************************************************/
/******************************************************************************/ /******************************************************************************/
// settings.js // settings.js
@ -230,6 +355,7 @@ var onMessage = function(request, sender, callback) {
})(); })();
/******************************************************************************/
/******************************************************************************/ /******************************************************************************/
// info.js // info.js
@ -241,7 +367,7 @@ var getRequestLog = function(pageURL) {
var requestLogs = {}; var requestLogs = {};
var pageStores = µMatrix.pageStats; var pageStores = µMatrix.pageStats;
var pageURLs = pageURL ? [pageURL] : Object.keys(pageStores); var pageURLs = pageURL ? [pageURL] : Object.keys(pageStores);
var pageRequestLog, logEntries, i, j, logEntry; var pageStore, pageRequestLog, logEntries, j, logEntry;
for ( var i = 0; i < pageURLs.length; i++ ) { for ( var i = 0; i < pageURLs.length; i++ ) {
pageURL = pageURLs[i]; pageURL = pageURLs[i];
@ -315,6 +441,7 @@ var onMessage = function(request, sender, callback) {
})(); })();
/******************************************************************************/
/******************************************************************************/ /******************************************************************************/
// ubiquitous-rules.js // ubiquitous-rules.js
@ -345,6 +472,7 @@ var onMessage = function(request, sender, callback) {
})(); })();
/******************************************************************************/
/******************************************************************************/ /******************************************************************************/
// about.js // about.js

@ -459,7 +459,7 @@ function PageStore(pageUrl) {
PageStore.prototype.init = function(pageUrl) { PageStore.prototype.init = function(pageUrl) {
this.pageUrl = pageUrl; this.pageUrl = pageUrl;
this.pageHostname = µm.URI.hostnameFromURI(pageUrl); this.pageHostname = µm.URI.hostnameFromURI(pageUrl);
this.pageDomain = µm.URI.domainFromHostname(this.pageHostname); this.pageDomain = µm.URI.domainFromHostname(this.pageHostname) || this.pageHostname;
this.pageScriptBlocked = false; this.pageScriptBlocked = false;
this.thirdpartyScript = false; this.thirdpartyScript = false;
this.requests = µm.PageRequestStats.factory(); this.requests = µm.PageRequestStats.factory();

@ -19,7 +19,8 @@
Home: https://github.com/gorhill/uMatrix Home: https://github.com/gorhill/uMatrix
*/ */
// TODO: cleanup /* global punycode, uDom, messaging */
/* jshint esnext: true, bitwise: false */
/******************************************************************************/ /******************************************************************************/
/******************************************************************************/ /******************************************************************************/
@ -30,14 +31,28 @@
/******************************************************************************/ /******************************************************************************/
var µMatrix = chrome.extension.getBackgroundPage().µMatrix; var µMatrix = chrome.extension.getBackgroundPage().µMatrix;
var matrixSnapshot = {};
var matrixStats = {};
var targetTabId; var targetTabId;
var targetPageURL; var targetPageURL;
var targetPageHostname; var targetPageHostname;
var targetPageDomain; var targetPageDomain;
var targetScope = '*'; var targetScope = '*';
var matrixCellHotspots = null; var matrixCellHotspots = null;
var matrixHasRows = false;
// Must be consistent with definitions in matrix.js
const Pale = 0x00;
const Dark = 0x80;
const Transparent = 0;
const Red = 1;
const Green = 2;
const Gray = 3;
const DarkRed = Dark | Red;
const PaleRed = Pale | Red;
const DarkGreen = Dark | Green;
const PaleGreen = Pale | Green;
const DarkGray = Dark | Gray;
const PaleGray = Pale | Gray;
/******************************************************************************/ /******************************************************************************/
/******************************************************************************/ /******************************************************************************/
@ -79,148 +94,8 @@ function setUserSetting(setting, value) {
/******************************************************************************/ /******************************************************************************/
function EntryStats(hostname, type) {
this.hostname = hostname;
this.type = type;
this.count = 0;
this.temporaryColor = '';
this.permanentColor = '';
}
EntryStats.prototype.reset = function(hostname, type) {
if ( hostname ) {
this.hostname = hostname;
}
if ( type ) {
this.type = type;
}
this.count = 0;
};
EntryStats.prototype.colourize = function(µm, scopeKey) {
µm = µm || µMatrix;
if ( !this.hostname || !this.type ) {
return;
}
this.temporaryColor = µm.getTemporaryColor(scopeKey, this.type, this.hostname);
this.permanentColor = µm.getPermanentColor(scopeKey, this.type, this.hostname);
};
EntryStats.prototype.add = function(other) {
this.count += other.count;
};
/******************************************************************************/
function HostnameStats(hostname) {
this.hostname = hostname;
this.types = {
'*': new EntryStats(hostname, '*'),
cookie: new EntryStats(hostname, 'cookie'),
css: new EntryStats(hostname, 'css'),
image: new EntryStats(hostname, 'image'),
plugin: new EntryStats(hostname, 'plugin'),
script: new EntryStats(hostname, 'script'),
xhr: new EntryStats(hostname, 'xhr'),
frame: new EntryStats(hostname, 'frame'),
other: new EntryStats(hostname, 'other')
};
}
HostnameStats.prototype.junkyard = [];
HostnameStats.prototype.factory = function(hostname) {
var domainStats = HostnameStats.prototype.junkyard.pop();
if ( domainStats ) {
domainStats.reset(hostname);
} else {
domainStats = new HostnameStats(hostname);
}
return domainStats;
};
HostnameStats.prototype.reset = function(hostname) {
if ( hostname ) {
this.hostname = hostname;
} else {
hostname = this.hostname;
}
this.types['*'].reset(hostname);
this.types.cookie.reset(hostname);
this.types.css.reset(hostname);
this.types.image.reset(hostname);
this.types.plugin.reset(hostname);
this.types.script.reset(hostname);
this.types.xhr.reset(hostname);
this.types.frame.reset(hostname);
this.types.other.reset(hostname);
};
HostnameStats.prototype.dispose = function() {
HostnameStats.prototype.junkyard.push(this);
};
HostnameStats.prototype.colourize = function(µm, scopeKey) {
µm = µm || µMatrix;
this.types['*'].colourize(µm, scopeKey);
this.types.cookie.colourize(µm, scopeKey);
this.types.css.colourize(µm, scopeKey);
this.types.image.colourize(µm, scopeKey);
this.types.plugin.colourize(µm, scopeKey);
this.types.script.colourize(µm, scopeKey);
this.types.xhr.colourize(µm, scopeKey);
this.types.frame.colourize(µm, scopeKey);
this.types.other.colourize(µm, scopeKey);
};
HostnameStats.prototype.add = function(other) {
var thisTypes = this.types;
var otherTypes = other.types;
thisTypes['*'].add(otherTypes['*']);
thisTypes.cookie.add(otherTypes.cookie);
thisTypes.css.add(otherTypes.css);
thisTypes.image.add(otherTypes.image);
thisTypes.plugin.add(otherTypes.plugin);
thisTypes.script.add(otherTypes.script);
thisTypes.xhr.add(otherTypes.xhr);
thisTypes.frame.add(otherTypes.frame);
thisTypes.other.add(otherTypes.other);
};
/******************************************************************************/
function MatrixStats() {
// hostname '*' always present
this['*'] = HostnameStats.prototype.factory('*');
}
MatrixStats.prototype.createMatrixStats = function() {
return new MatrixStats();
};
MatrixStats.prototype.reset = function() {
var hostnames = Object.keys(this);
var i = hostnames.length;
var hostname, prop;
while ( i-- ) {
hostname = hostnames[i];
prop = this[hostname];
if ( hostname !== '*' && prop instanceof HostnameStats ) {
prop.dispose();
delete this[hostname];
}
}
this['*'].reset();
};
/******************************************************************************/
var HTTPSBPopup = { var HTTPSBPopup = {
scopeKey: '*',
matrixDomains: {}, matrixDomains: {},
matrixStats: MatrixStats.prototype.createMatrixStats(),
matrixHeaderTypes: ['*'], matrixHeaderTypes: ['*'],
matrixGroup3Collapsed: false, matrixGroup3Collapsed: false,
@ -244,76 +119,14 @@ var HTTPSBPopup = {
/******************************************************************************/ /******************************************************************************/
// This creates a stats entry for each possible rows in the matrix. function updateMatrixSnapshot() {
var snapshotReady = function(response) {
function initMatrixStats() { matrixSnapshot = response;
var pageStats = getPageStats(); updateMatrixColors();
if ( !pageStats ) { updateMatrixBehavior();
return; updateMatrixButtons();
} };
messaging.ask({ what: 'matrixSnapshot', tabId: matrixSnapshot.tabId }, snapshotReady);
var matrixStats = HTTPSBPopup.matrixStats;
matrixStats.reset();
// collect all hostnames and ancestors from net traffic
var µmuri = µMatrix.URI;
var hostname, reqType, nodes, iNode, node, reqKey, types;
var pageRequests = pageStats.requests;
var reqKeys = pageRequests.getRequestKeys();
var iReqKey = reqKeys.length;
matrixHasRows = iReqKey > 0;
while ( iReqKey-- ) {
reqKey = reqKeys[iReqKey];
hostname = pageRequests.hostnameFromRequestKey(reqKey);
// rhill 2013-10-23: hostname can be empty if the request is a data url
// https://github.com/gorhill/httpswitchboard/issues/26
if ( hostname === '' ) {
hostname = targetPageHostname;
}
reqType = pageRequests.typeFromRequestKey(reqKey);
// we want a row for self and ancestors
nodes = µmuri.allHostnamesFromHostname(hostname);
iNode = nodes.length;
while ( iNode-- ) {
node = nodes[iNode];
if ( !matrixStats[node] ) {
matrixStats[node] = HostnameStats.prototype.factory(node);
}
}
types = matrixStats[hostname].types;
// Count only types which make sense to count
if ( types.hasOwnProperty(reqType) ) {
types[reqType].count += 1;
}
// https://github.com/gorhill/httpswitchboard/issues/12
// Count requests for whole row.
types['*'].count += 1;
}
updateMatrixStats();
return matrixStats;
}
/******************************************************************************/
function updateMatrixStats() {
// For each hostname/type occurrence, evaluate colors
var µm = µMatrix;
var scopeKey = targetScope;
var matrixStats = HTTPSBPopup.matrixStats;
for ( var hostname in matrixStats ) {
if ( matrixStats.hasOwnProperty(hostname) ) {
matrixStats[hostname].colourize(µm, scopeKey);
}
}
} }
/******************************************************************************/ /******************************************************************************/
@ -328,98 +141,79 @@ function getGroupStats() {
// Try to not reshuffle groups around while popup is opened if // Try to not reshuffle groups around while popup is opened if
// no new hostname added. // no new hostname added.
var matrixStats = HTTPSBPopup.matrixStats; var latestDomainListSnapshot = Object.keys(matrixSnapshot.rows).sort().join();
var latestDomainListSnapshot = Object.keys(matrixStats).sort().join();
if ( latestDomainListSnapshot === HTTPSBPopup.domainListSnapshot ) { if ( latestDomainListSnapshot === HTTPSBPopup.domainListSnapshot ) {
return HTTPSBPopup.groupsSnapshot; return HTTPSBPopup.groupsSnapshot;
} }
HTTPSBPopup.domainListSnapshot = latestDomainListSnapshot; HTTPSBPopup.domainListSnapshot = latestDomainListSnapshot;
var groups = [
{},
{},
{},
{}
];
// First, group according to whether at least one node in the domain // First, group according to whether at least one node in the domain
// hierarchy is white or blacklisted // hierarchy is white or blacklisted
var µmuri = µMatrix.URI;
var pageDomain = targetPageDomain; var pageDomain = targetPageDomain;
var hostname, domain, nodes, node; var rows = matrixSnapshot.rows;
var temporaryColor; var columnOffsets = matrixSnapshot.headers;
var dark, group; var anyTypeOffset = columnOffsets['*'];
var hostnames = Object.keys(matrixStats); var hostname, domain;
var iHostname = hostnames.length; var row, color, groupIndex;
while ( iHostname-- ) { var domainToGroupMap = {};
hostname = hostnames[iHostname];
// '*' is for header, ignore, since header is always at the top // First pass: put each domain in a group
for ( hostname in rows ) {
if ( rows.hasOwnProperty(hostname) === false ) {
continue;
}
// '*' is for header, ignore since header is always at the top
if ( hostname === '*' ) { if ( hostname === '*' ) {
continue; continue;
} }
// https://github.com/gorhill/httpswitchboard/issues/12 row = rows[hostname];
// Ignore rows with no request for now. domain = row.domain;
if ( matrixStats[hostname].types['*'].count === 0 ) { // 1st-party always into group 0
if ( domain === pageDomain ) {
domainToGroupMap[domain] = 0;
continue; continue;
} }
// Walk upward the chain of hostname and find at least one which color = row.temporary[anyTypeOffset];
// is expressly whitelisted or blacklisted. groupIndex = domainToGroupMap[domain] || 2; // anything overrides 2
nodes = µmuri.allHostnamesFromHostname(hostname); // group 1: whitelisted (does not override 0)
domain = nodes[nodes.length-1]; if ( color === DarkGreen ) {
domainToGroupMap[domain] = 1;
while ( true ) { continue;
node = nodes.shift(); }
if ( !node ) { // group 3: blacklisted (does not override 0, 1)
break; if ( color === DarkRed ) {
} if ( groupIndex === 2 ) {
temporaryColor = matrixStats[node].types['*'].temporaryColor; domainToGroupMap[domain] = 3;
dark = temporaryColor.charAt(1) === 'd';
if ( dark ) {
break;
} }
continue;
} }
// Domain of the page comes first
if ( domain === pageDomain ) { // group 2: graylisted (does not override 0, 1, 3)
group = 0; if ( groupIndex !== 2 ) {
continue;
} }
// Whitelisted hostnames are second, blacklisted are fourth
else if ( dark ) { domainToGroupMap[domain] = 2;
group = temporaryColor.charAt(0) === 'g' ? 1 : 3; }
// Graylisted are third
} else { // Second pass: put each domain in a group
group = 2; var groups = [ {}, {}, {}, {} ];
var group;
for ( hostname in rows ) {
if ( rows.hasOwnProperty(hostname) === false ) {
continue;
} }
if ( !groups[group][domain] ) { if ( hostname === '*' ) {
groups[group][domain] = { all: {}, withRules: {} }; continue;
} }
groups[group][domain].withRules[hostname] = true; row = rows[hostname];
} domain = row.domain;
// At this point, one domain could end up in two different groups. groupIndex = domainToGroupMap[domain];
group = groups[groupIndex];
// Generate all nodes possible for each groups, this is useful if ( group.hasOwnProperty(domain) === false ) {
// to allow users to toggle permissions for higher-level hostnames group[domain] = {};
// which are not explicitly part of the web page.
var iGroup = groups.length;
var domains, iDomain;
while ( iGroup-- ) {
group = groups[iGroup];
domains = Object.keys(group);
iDomain = domains.length;
while ( iDomain-- ) {
domain = domains[iDomain];
hostnames = Object.keys(group[domain].withRules);
iHostname = hostnames.length;
while ( iHostname-- ) {
nodes = µmuri.allHostnamesFromHostname(hostnames[iHostname]);
while ( true ) {
node = nodes.shift();
if ( !node ) {
break;
}
group[domain].all[node] = group[domain].withRules[node];
}
}
} }
group[domain][hostname] = true;
} }
HTTPSBPopup.groupsSnapshot = groups; HTTPSBPopup.groupsSnapshot = groups;
@ -431,51 +225,36 @@ function getGroupStats() {
// helpers // helpers
function getCellStats(hostname, type) {
var matrixStats = HTTPSBPopup.matrixStats;
if ( matrixStats[hostname] ) {
return matrixStats[hostname].types[type];
}
return null;
}
function getTemporaryColor(hostname, type) { function getTemporaryColor(hostname, type) {
var entry = getCellStats(hostname, type); return matrixSnapshot.rows[hostname].temporary[matrixSnapshot.headers[type]];
if ( entry ) {
return entry.temporaryColor;
}
return '';
} }
function getPermanentColor(hostname, type) { function getPermanentColor(hostname, type) {
var entry = getCellStats(hostname, type); return matrixSnapshot.rows[hostname].permanent[matrixSnapshot.headers[type]];
if ( entry ) {
return entry.permanentColor;
}
return '';
} }
function getCellClass(hostname, type) { function getCellClass(hostname, type) {
return getTemporaryColor(hostname, type) + ' ' + getPermanentColor(hostname, type) + 'p'; return 't' + getTemporaryColor(hostname, type).toString(16) +
' p' + getPermanentColor(hostname, type).toString(16);
} }
// compute next state
function getNextAction(hostname, type, leaning) { function getNextAction(hostname, type, leaning) {
var entry = HTTPSBPopup.matrixStats[hostname].types[type]; var temporaryColor = getTemporaryColor(hostname, type);
var temporaryColor = entry.temporaryColor; var hue = temporaryColor & 0x03;
var saturation = temporaryColor & 0x80;
// special case: root toggle only between two states // special case: root toggle only between two states
if ( type === '*' && hostname === '*' ) { if ( type === '*' && hostname === '*' ) {
return temporaryColor.charAt(0) === 'g' ? 'blacklist' : 'whitelist'; return hue === Green ? 'blacklist' : 'whitelist';
} }
// Lean toward whitelisting? // Lean toward whitelisting?
if ( leaning === 'whitelisting' ) { if ( leaning === 'whitelisting' ) {
if ( temporaryColor.charAt(1) !== 'd' ) { if ( saturation !== Dark ) {
return 'whitelist'; return 'whitelist';
} }
return 'graylist'; return 'graylist';
} }
// Lean toward blacklisting // Lean toward blacklisting
if ( temporaryColor.charAt(1) !== 'd' ) { if ( saturation !== Dark ) {
return 'blacklist'; return 'blacklist';
} }
return 'graylist'; return 'graylist';
@ -556,14 +335,6 @@ function updateMatrixColors() {
/******************************************************************************/ /******************************************************************************/
// Update request count of matrix cells(s)
// Count changes when number of distinct requests changes
function updateMatrixCounts() {
}
/******************************************************************************/
// Update behavior of matrix: // Update behavior of matrix:
// - Whether a section is collapsible or not. It is collapsible if: // - Whether a section is collapsible or not. It is collapsible if:
// - It has at least one subdomain AND // - It has at least one subdomain AND
@ -605,10 +376,7 @@ function handleFilter(button, leaning) {
} else { } else {
µm.graylistTemporarily(targetScope, hostname, type); µm.graylistTemporarily(targetScope, hostname, type);
} }
updateMatrixStats(); updateMatrixSnapshot();
updateMatrixColors();
updateMatrixBehavior();
updateMatrixButtons();
} }
function handleWhitelistFilter(button) { function handleWhitelistFilter(button) {
@ -623,7 +391,6 @@ function handleBlacklistFilter(button) {
function getTemporaryRuleset() { function getTemporaryRuleset() {
var µm = µMatrix; var µm = µMatrix;
var matrixStats = HTTPSBPopup.matrixStats;
var temporaryRules = {}; var temporaryRules = {};
var permanentRules = {}; var permanentRules = {};
var temporarySwitches = {}; var temporarySwitches = {};
@ -713,7 +480,7 @@ var endMatrixUpdate = function() {
// to ensure the extension pop-up is properly sized. This is needed because // to ensure the extension pop-up is properly sized. This is needed because
// the header pane's `position` property is `fixed`, which means it doesn't // the header pane's `position` property is `fixed`, which means it doesn't
// affect layout size, hence the matrix header row will be truncated. // affect layout size, hence the matrix header row will be truncated.
if ( !matrixHasRows ) { if ( matrixSnapshot.rowCount <= 1 ) {
matrixList.append(createMatrixRow().css('visibility', 'hidden')); matrixList.append(createMatrixRow().css('visibility', 'hidden'));
} }
updateMatrixBehavior(); updateMatrixBehavior();
@ -826,27 +593,29 @@ function renderMatrixMetaCellDomain(cell, domain) {
contents.nodeAt(1).textContent = ' '; contents.nodeAt(1).textContent = ' ';
} }
function renderMatrixCellType(cell, hostname, type, stats) { function renderMatrixCellType(cell, hostname, type, count) {
cell.prop('reqType', type) cell.prop('reqType', type)
.prop('hostname', hostname) .prop('hostname', hostname)
.prop('count', stats.count) .prop('count', count)
.addClass(getCellClass(hostname, type)); .addClass(getCellClass(hostname, type));
if ( stats.count ) { if ( count ) {
cell.text(stats.count); cell.text(count);
} else { } else {
cell.text('\u00A0'); cell.text('\u00A0');
} }
} }
function renderMatrixCellTypes(cells, hostname, stats) { function renderMatrixCellTypes(cells, hostname, countName) {
renderMatrixCellType(cells.at(1), hostname, 'cookie', stats.cookie); var counts = matrixSnapshot.rows[hostname][countName];
renderMatrixCellType(cells.at(2), hostname, 'css', stats.css); var countIndices = matrixSnapshot.headers;
renderMatrixCellType(cells.at(3), hostname, 'image', stats.image); renderMatrixCellType(cells.at(1), hostname, 'cookie', counts[countIndices.cookie]);
renderMatrixCellType(cells.at(4), hostname, 'plugin', stats.plugin); renderMatrixCellType(cells.at(2), hostname, 'css', counts[countIndices.css]);
renderMatrixCellType(cells.at(5), hostname, 'script', stats.script); renderMatrixCellType(cells.at(3), hostname, 'image', counts[countIndices.image]);
renderMatrixCellType(cells.at(6), hostname, 'xhr', stats.xhr); renderMatrixCellType(cells.at(4), hostname, 'plugin', counts[countIndices.plugin]);
renderMatrixCellType(cells.at(7), hostname, 'frame', stats.frame); renderMatrixCellType(cells.at(5), hostname, 'script', counts[countIndices.script]);
renderMatrixCellType(cells.at(8), hostname, 'other', stats.other); renderMatrixCellType(cells.at(6), hostname, 'xhr', counts[countIndices.xhr]);
renderMatrixCellType(cells.at(7), hostname, 'frame', counts[countIndices.frame]);
renderMatrixCellType(cells.at(8), hostname, 'other', counts[countIndices.other]);
} }
/******************************************************************************/ /******************************************************************************/
@ -855,7 +624,7 @@ function makeMatrixRowDomain(domain) {
var matrixRow = createMatrixRow().addClass('rw'); var matrixRow = createMatrixRow().addClass('rw');
var cells = matrixRow.descendants('.matCell'); var cells = matrixRow.descendants('.matCell');
renderMatrixCellDomain(cells.at(0), domain); renderMatrixCellDomain(cells.at(0), domain);
renderMatrixCellTypes(cells, domain, HTTPSBPopup.matrixStats[domain].types); renderMatrixCellTypes(cells, domain, 'counts');
return matrixRow; return matrixRow;
} }
@ -863,66 +632,60 @@ function makeMatrixRowSubdomain(domain, subdomain) {
var matrixRow = createMatrixRow().addClass('rw'); var matrixRow = createMatrixRow().addClass('rw');
var cells = matrixRow.descendants('.matCell'); var cells = matrixRow.descendants('.matCell');
renderMatrixCellSubdomain(cells.at(0), domain, subdomain); renderMatrixCellSubdomain(cells.at(0), domain, subdomain);
renderMatrixCellTypes(cells, subdomain, HTTPSBPopup.matrixStats[subdomain].types); renderMatrixCellTypes(cells, subdomain, 'counts');
return matrixRow; return matrixRow;
} }
function makeMatrixMetaRowDomain(domain, stats) { function makeMatrixMetaRowDomain(domain) {
var matrixRow = createMatrixRow().addClass('rw'); var matrixRow = createMatrixRow().addClass('rw');
var cells = matrixRow.descendants('.matCell'); var cells = matrixRow.descendants('.matCell');
renderMatrixMetaCellDomain(cells.at(0), domain); renderMatrixMetaCellDomain(cells.at(0), domain);
renderMatrixCellTypes(cells, domain, stats); renderMatrixCellTypes(cells, domain, 'totals');
return matrixRow; return matrixRow;
} }
/******************************************************************************/ /******************************************************************************/
function renderMatrixMetaCellType(cell, count) { function renderMatrixMetaCellType(cell, count) {
cell.addClass('ri'); cell.addClass('t1');
if ( count ) { if ( count ) {
cell.text(count); cell.text(count);
} }
} }
function makeMatrixMetaRow(stats) { function makeMatrixMetaRow(totals) {
var typeStats = stats.types; var typeOffsets = matrixSnapshot.headers;
var matrixRow = createMatrixRow().at(0).addClass('ro'); var matrixRow = createMatrixRow().at(0).addClass('ro');
var cells = matrixRow.descendants('.matCell'); var cells = matrixRow.descendants('.matCell');
var contents = cells.at(0).addClass('rd').contents(); var contents = cells.at(0).addClass('t81').contents();
contents.nodeAt(0).textContent = ' '; contents.nodeAt(0).textContent = ' ';
contents.nodeAt(1).textContent = '\u202A' + typeStats['*'].count + ' blacklisted hostname(s)'; contents.nodeAt(1).textContent = '\u202A' + totals[typeOffsets['*']] + ' blacklisted hostname(s)';
renderMatrixMetaCellType(cells.at(1), typeStats.cookie.count); renderMatrixMetaCellType(cells.at(1), totals[typeOffsets.cookie]);
renderMatrixMetaCellType(cells.at(2), typeStats.css.count); renderMatrixMetaCellType(cells.at(2), totals[typeOffsets.css]);
renderMatrixMetaCellType(cells.at(3), typeStats.image.count); renderMatrixMetaCellType(cells.at(3), totals[typeOffsets.image]);
renderMatrixMetaCellType(cells.at(4), typeStats.plugin.count); renderMatrixMetaCellType(cells.at(4), totals[typeOffsets.plugin]);
renderMatrixMetaCellType(cells.at(5), typeStats.script.count); renderMatrixMetaCellType(cells.at(5), totals[typeOffsets.script]);
renderMatrixMetaCellType(cells.at(6), typeStats.xhr.count); renderMatrixMetaCellType(cells.at(6), totals[typeOffsets.xhr]);
renderMatrixMetaCellType(cells.at(7), typeStats.frame.count); renderMatrixMetaCellType(cells.at(7), totals[typeOffsets.frame]);
renderMatrixMetaCellType(cells.at(8), typeStats.other.count); renderMatrixMetaCellType(cells.at(8), totals[typeOffsets.other]);
return matrixRow; return matrixRow;
} }
/******************************************************************************/ /******************************************************************************/
function computeMatrixGroupMetaStats(group) { function computeMatrixGroupMetaStats(group) {
var metaStats = new HostnameStats(); var types = Object.keys(matrixSnapshot.headers);
var i = types.length, j;
var totals = new Array(i);
var domains = Object.keys(group); var domains = Object.keys(group);
var blacklistedCount = 0;
var i = domains.length;
var hostnames, hostname, j;
while ( i-- ) { while ( i-- ) {
hostnames = Object.keys(group[domains[i]].all); totals[i] = 0;
j = hostnames.length; j = domains.length;
while ( j-- ) { while ( j-- ) {
hostname = hostnames[j]; totals[i] += matrixSnapshot.rows[domains[j]].totals[i];
if ( getTemporaryColor(hostname, '*') === 'rd' ) {
blacklistedCount++;
}
metaStats.add(HTTPSBPopup.matrixStats[hostname]);
} }
} }
metaStats.types['*'].count = blacklistedCount; return totals;
return metaStats;
} }
/******************************************************************************/ /******************************************************************************/
@ -956,14 +719,8 @@ function makeMatrixGroup0SectionSubomain(domain, subdomain) {
.addClass('g0 l2'); .addClass('g0 l2');
} }
function makeMatrixGroup0SectionMetaDomain(hostnames) { function makeMatrixGroup0SectionMetaDomain(domain) {
var metaStats = new HostnameStats(); return makeMatrixMetaRowDomain(domain).addClass('g0 l1 meta');
var i = hostnames.length;
while ( i-- ) {
metaStats.add(HTTPSBPopup.matrixStats[hostnames[i]]);
}
return makeMatrixMetaRowDomain(hostnames[0], metaStats.types)
.addClass('g0 l1 meta');
} }
function makeMatrixGroup0Section(hostnames) { function makeMatrixGroup0Section(hostnames) {
@ -972,7 +729,7 @@ function makeMatrixGroup0Section(hostnames) {
.toggleClass('collapsed', getCollapseState(domain)) .toggleClass('collapsed', getCollapseState(domain))
.prop('domain', domain); .prop('domain', domain);
if ( hostnames.length > 1 ) { if ( hostnames.length > 1 ) {
makeMatrixGroup0SectionMetaDomain(hostnames) makeMatrixGroup0SectionMetaDomain(domain)
.appendTo(domainDiv); .appendTo(domainDiv);
} }
makeMatrixGroup0SectionDomain(domain) makeMatrixGroup0SectionDomain(domain)
@ -987,12 +744,11 @@ function makeMatrixGroup0Section(hostnames) {
function makeMatrixGroup0(group) { function makeMatrixGroup0(group) {
var domains = Object.keys(group).sort(hostnameCompare); var domains = Object.keys(group).sort(hostnameCompare);
if ( domains.length ) { if ( domains.length ) {
var groupDiv = createMatrixGroup() var groupDiv = createMatrixGroup().addClass('g0');
.addClass('g0'); makeMatrixGroup0Section(Object.keys(group[domains[0]]).sort(hostnameCompare))
makeMatrixGroup0Section(Object.keys(group[domains[0]].all).sort(hostnameCompare))
.appendTo(groupDiv); .appendTo(groupDiv);
for ( var i = 1; i < domains.length; i++ ) { for ( var i = 1; i < domains.length; i++ ) {
makeMatrixGroup0Section(Object.keys(group[domains[i]].all).sort(hostnameCompare)) makeMatrixGroup0Section(Object.keys(group[domains[i]]).sort(hostnameCompare))
.appendTo(groupDiv); .appendTo(groupDiv);
} }
groupDiv.appendTo(matrixList); groupDiv.appendTo(matrixList);
@ -1011,14 +767,8 @@ function makeMatrixGroup1SectionSubomain(domain, subdomain) {
.addClass('g1 l2'); .addClass('g1 l2');
} }
function makeMatrixGroup1SectionMetaDomain(hostnames) { function makeMatrixGroup1SectionMetaDomain(domain) {
var metaStats = new HostnameStats(); return makeMatrixMetaRowDomain(domain).addClass('g1 l1 meta');
var i = hostnames.length;
while ( i-- ) {
metaStats.add(HTTPSBPopup.matrixStats[hostnames[i]]);
}
return makeMatrixMetaRowDomain(hostnames[0], metaStats.types)
.addClass('g1 l1 meta');
} }
function makeMatrixGroup1Section(hostnames) { function makeMatrixGroup1Section(hostnames) {
@ -1027,8 +777,7 @@ function makeMatrixGroup1Section(hostnames) {
.toggleClass('collapsed', getCollapseState(domain)) .toggleClass('collapsed', getCollapseState(domain))
.prop('domain', domain); .prop('domain', domain);
if ( hostnames.length > 1 ) { if ( hostnames.length > 1 ) {
makeMatrixGroup1SectionMetaDomain(hostnames) makeMatrixGroup1SectionMetaDomain(domain).appendTo(domainDiv);
.appendTo(domainDiv);
} }
makeMatrixGroup1SectionDomain(domain) makeMatrixGroup1SectionDomain(domain)
.appendTo(domainDiv); .appendTo(domainDiv);
@ -1044,10 +793,10 @@ function makeMatrixGroup1(group) {
if ( domains.length) { if ( domains.length) {
var groupDiv = createMatrixGroup() var groupDiv = createMatrixGroup()
.addClass('g1'); .addClass('g1');
makeMatrixGroup1Section(Object.keys(group[domains[0]].all).sort(hostnameCompare)) makeMatrixGroup1Section(Object.keys(group[domains[0]]).sort(hostnameCompare))
.appendTo(groupDiv); .appendTo(groupDiv);
for ( var i = 1; i < domains.length; i++ ) { for ( var i = 1; i < domains.length; i++ ) {
makeMatrixGroup1Section(Object.keys(group[domains[i]].all).sort(hostnameCompare)) makeMatrixGroup1Section(Object.keys(group[domains[i]]).sort(hostnameCompare))
.appendTo(groupDiv); .appendTo(groupDiv);
} }
groupDiv.appendTo(matrixList); groupDiv.appendTo(matrixList);
@ -1066,14 +815,8 @@ function makeMatrixGroup2SectionSubomain(domain, subdomain) {
.addClass('g2 l2'); .addClass('g2 l2');
} }
function makeMatrixGroup2SectionMetaDomain(hostnames) { function makeMatrixGroup2SectionMetaDomain(domain) {
var metaStats = new HostnameStats(); return makeMatrixMetaRowDomain(domain).addClass('g2 l1 meta');
var i = hostnames.length;
while ( i-- ) {
metaStats.add(HTTPSBPopup.matrixStats[hostnames[i]]);
}
return makeMatrixMetaRowDomain(hostnames[0], metaStats.types)
.addClass('g2 l1 meta');
} }
function makeMatrixGroup2Section(hostnames) { function makeMatrixGroup2Section(hostnames) {
@ -1082,8 +825,7 @@ function makeMatrixGroup2Section(hostnames) {
.toggleClass('collapsed', getCollapseState(domain)) .toggleClass('collapsed', getCollapseState(domain))
.prop('domain', domain); .prop('domain', domain);
if ( hostnames.length > 1 ) { if ( hostnames.length > 1 ) {
makeMatrixGroup2SectionMetaDomain(hostnames) makeMatrixGroup2SectionMetaDomain(domain).appendTo(domainDiv);
.appendTo(domainDiv);
} }
makeMatrixGroup2SectionDomain(domain) makeMatrixGroup2SectionDomain(domain)
.appendTo(domainDiv); .appendTo(domainDiv);
@ -1099,10 +841,10 @@ function makeMatrixGroup2(group) {
if ( domains.length) { if ( domains.length) {
var groupDiv = createMatrixGroup() var groupDiv = createMatrixGroup()
.addClass('g2'); .addClass('g2');
makeMatrixGroup2Section(Object.keys(group[domains[0]].all).sort(hostnameCompare)) makeMatrixGroup2Section(Object.keys(group[domains[0]]).sort(hostnameCompare))
.appendTo(groupDiv); .appendTo(groupDiv);
for ( var i = 1; i < domains.length; i++ ) { for ( var i = 1; i < domains.length; i++ ) {
makeMatrixGroup2Section(Object.keys(group[domains[i]].all).sort(hostnameCompare)) makeMatrixGroup2Section(Object.keys(group[domains[i]]).sort(hostnameCompare))
.appendTo(groupDiv); .appendTo(groupDiv);
} }
groupDiv.appendTo(matrixList); groupDiv.appendTo(matrixList);
@ -1147,10 +889,10 @@ function makeMatrixGroup3(group) {
.appendTo(groupDiv); .appendTo(groupDiv);
makeMatrixMetaRow(computeMatrixGroupMetaStats(group), 'g3') makeMatrixMetaRow(computeMatrixGroupMetaStats(group), 'g3')
.appendTo(groupDiv); .appendTo(groupDiv);
makeMatrixGroup3Section(Object.keys(group[domains[0]].all).sort(hostnameCompare)) makeMatrixGroup3Section(Object.keys(group[domains[0]]).sort(hostnameCompare))
.appendTo(groupDiv); .appendTo(groupDiv);
for ( var i = 1; i < domains.length; i++ ) { for ( var i = 1; i < domains.length; i++ ) {
makeMatrixGroup3Section(Object.keys(group[domains[i]].all).sort(hostnameCompare)) makeMatrixGroup3Section(Object.keys(group[domains[i]]).sort(hostnameCompare))
.appendTo(groupDiv); .appendTo(groupDiv);
} }
groupDiv.appendTo(matrixList); groupDiv.appendTo(matrixList);
@ -1158,8 +900,7 @@ function makeMatrixGroup3(group) {
/******************************************************************************/ /******************************************************************************/
function makeMenu() { var makeMenu = function() {
initMatrixStats();
var groupStats = getGroupStats(); var groupStats = getGroupStats();
if ( Object.keys(groupStats).length === 0 ) { if ( Object.keys(groupStats).length === 0 ) {
@ -1182,7 +923,7 @@ function makeMenu() {
initScopeCell(); initScopeCell();
updateMatrixButtons(); updateMatrixButtons();
} };
/******************************************************************************/ /******************************************************************************/
@ -1209,30 +950,21 @@ function initMenuEnvironment() {
function createGlobalScope() { function createGlobalScope() {
targetScope = '*'; targetScope = '*';
setUserSetting('scopeLevel', '*'); setUserSetting('scopeLevel', '*');
updateMatrixStats(); updateMatrixSnapshot();
updateMatrixColors();
updateMatrixBehavior();
updateMatrixButtons();
dropDownMenuHide(); dropDownMenuHide();
} }
function createDomainScope() { function createDomainScope() {
targetScope = targetPageDomain; targetScope = targetPageDomain;
setUserSetting('scopeLevel', 'domain'); setUserSetting('scopeLevel', 'domain');
updateMatrixStats(); updateMatrixSnapshot();
updateMatrixColors();
updateMatrixBehavior();
updateMatrixButtons();
dropDownMenuHide(); dropDownMenuHide();
} }
function createSiteScope() { function createSiteScope() {
targetScope = targetPageHostname; targetScope = targetPageHostname;
setUserSetting('scopeLevel', 'site'); setUserSetting('scopeLevel', 'site');
updateMatrixStats(); updateMatrixSnapshot();
updateMatrixColors();
updateMatrixBehavior();
updateMatrixButtons();
dropDownMenuHide(); dropDownMenuHide();
} }
@ -1294,10 +1026,7 @@ function updateMtxbutton() {
function toggleMtxFiltering() { function toggleMtxFiltering() {
var µm = µMatrix; var µm = µMatrix;
µm.toggleTemporaryMtxFiltering(targetScope); µm.toggleTemporaryMtxFiltering(targetScope);
updateMatrixStats(); updateMatrixSnapshot();
updateMatrixColors();
updateMatrixBehavior();
updateMatrixButtons();
} }
/******************************************************************************/ /******************************************************************************/
@ -1319,10 +1048,7 @@ function persistScope() {
var µm = µMatrix; var µm = µMatrix;
var ruleset = getTemporaryRuleset(); var ruleset = getTemporaryRuleset();
µm.applyRulesetPermanently(ruleset); µm.applyRulesetPermanently(ruleset);
updateMatrixStats(); updateMatrixSnapshot();
updateMatrixColors();
updateMatrixBehavior();
updateMatrixButtons();
} }
/******************************************************************************/ /******************************************************************************/
@ -1334,10 +1060,7 @@ function revertScope() {
var µm = µMatrix; var µm = µMatrix;
var ruleset = getTemporaryRuleset(); var ruleset = getTemporaryRuleset();
µm.revertScopeRules(ruleset.tScopeKey); µm.revertScopeRules(ruleset.tScopeKey);
updateMatrixStats(); updateMatrixSnapshot();
updateMatrixColors();
updateMatrixBehavior();
updateMatrixButtons();
} }
/******************************************************************************/ /******************************************************************************/
@ -1354,10 +1077,7 @@ function updateMatrixButtons() {
function revertAll() { function revertAll() {
µMatrix.revertAllRules(); µMatrix.revertAllRules();
updateMatrixStats(); updateMatrixSnapshot();
updateMatrixColors();
updateMatrixBehavior();
updateMatrixButtons();
} }
/******************************************************************************/ /******************************************************************************/
@ -1411,14 +1131,14 @@ function dropDownMenuHide() {
// Because chrome.tabs.query() is async // Because chrome.tabs.query() is async
var bindToTab = function(tabs) { var onMatrixSnapshotReady = function(response) {
/*
// TODO: can tabs be empty? // TODO: can tabs be empty?
if ( !tabs.length ) { if ( !tabs.length ) {
return; return;
} }
var µm = µMatrix; var µm = µMatrix;
var tab = tabs[0];
// Important! Before calling makeMenu() // Important! Before calling makeMenu()
// Allow to scope on behind-the-scene virtual tab // Allow to scope on behind-the-scene virtual tab
@ -1429,8 +1149,13 @@ var bindToTab = function(tabs) {
targetTabId = tab.id; targetTabId = tab.id;
targetPageURL = µm.pageUrlFromTabId(targetTabId); targetPageURL = µm.pageUrlFromTabId(targetTabId);
} }
targetPageHostname = µm.URI.hostnameFromURI(targetPageURL); */
targetPageDomain = µm.URI.domainFromHostname(targetPageHostname) || targetPageHostname; matrixSnapshot = response;
targetTabId = response.tabId;
targetPageURL = response.url;
targetPageHostname = response.hostname;
targetPageDomain = response.domain;
// Now that tabId and pageURL are set, we can build our menu // Now that tabId and pageURL are set, we can build our menu
initMenuEnvironment(); initMenuEnvironment();
@ -1447,13 +1172,22 @@ var bindToTab = function(tabs) {
} }
}; };
/******************************************************************************/
var onTabsReceived = function(tabs) {
if ( tabs.length === 0 ) {
return;
}
messaging.ask({ what: 'matrixSnapshot', tabId: tabs[0].id }, onMatrixSnapshotReady);
};
/******************************************************************************/ /******************************************************************************/
// Make menu only when popup html is fully loaded // Make menu only when popup html is fully loaded
uDom.onLoad(function() { uDom.onLoad(function() {
chrome.tabs.query({ active: true, currentWindow: true }, onTabsReceived);
chrome.tabs.query({ currentWindow: true, active: true }, bindToTab);
// Below is UI stuff which is not key to make the menu, so this can // Below is UI stuff which is not key to make the menu, so this can
// be done without having to wait for a tab to be bound to the menu. // be done without having to wait for a tab to be bound to the menu.

Loading…
Cancel
Save