|
|
@ -44,16 +44,11 @@ const PaleGreen = Pale | Green;
|
|
|
|
const DarkGray = Dark | Gray;
|
|
|
|
const DarkGray = Dark | Gray;
|
|
|
|
const PaleGray = Pale | Gray;
|
|
|
|
const PaleGray = Pale | Gray;
|
|
|
|
|
|
|
|
|
|
|
|
var µMatrix = chrome.extension.getBackgroundPage().µMatrix;
|
|
|
|
|
|
|
|
var matrixSnapshot = {};
|
|
|
|
var matrixSnapshot = {};
|
|
|
|
var groupsSnapshot = [];
|
|
|
|
var groupsSnapshot = [];
|
|
|
|
var allHostnamesSnapshot = 'do not leave this initial string empty';
|
|
|
|
var allHostnamesSnapshot = 'do not leave this initial string empty';
|
|
|
|
|
|
|
|
|
|
|
|
var targetTabId;
|
|
|
|
var targetTabId;
|
|
|
|
var targetPageURL;
|
|
|
|
|
|
|
|
var targetPageHostname;
|
|
|
|
|
|
|
|
var targetPageDomain;
|
|
|
|
|
|
|
|
var targetScope = '*';
|
|
|
|
|
|
|
|
var matrixCellHotspots = null;
|
|
|
|
var matrixCellHotspots = null;
|
|
|
|
|
|
|
|
|
|
|
|
var matrixHeaderPrettyNames = {
|
|
|
|
var matrixHeaderPrettyNames = {
|
|
|
@ -77,7 +72,7 @@ messaging.start('popup.js');
|
|
|
|
|
|
|
|
|
|
|
|
var onMessage = function(msg) {
|
|
|
|
var onMessage = function(msg) {
|
|
|
|
if ( msg.what === 'urlStatsChanged' ) {
|
|
|
|
if ( msg.what === 'urlStatsChanged' ) {
|
|
|
|
if ( targetPageURL === msg.pageURL ) {
|
|
|
|
if ( matrixSnapshot.url === msg.pageURL ) {
|
|
|
|
makeMenu();
|
|
|
|
makeMenu();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -88,17 +83,12 @@ messaging.listen(onMessage);
|
|
|
|
/******************************************************************************/
|
|
|
|
/******************************************************************************/
|
|
|
|
/******************************************************************************/
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
function getPageStats() {
|
|
|
|
|
|
|
|
return µMatrix.pageStatsFromTabId(targetTabId);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function getUserSetting(setting) {
|
|
|
|
function getUserSetting(setting) {
|
|
|
|
return µMatrix.userSettings[setting];
|
|
|
|
return matrixSnapshot.userSettings[setting];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function setUserSetting(setting, value) {
|
|
|
|
function setUserSetting(setting, value) {
|
|
|
|
|
|
|
|
matrixSnapshot.userSettings[setting] = value;
|
|
|
|
messaging.tell({
|
|
|
|
messaging.tell({
|
|
|
|
what: 'userSettings',
|
|
|
|
what: 'userSettings',
|
|
|
|
name: setting,
|
|
|
|
name: setting,
|
|
|
@ -138,7 +128,7 @@ function getGroupStats() {
|
|
|
|
|
|
|
|
|
|
|
|
// 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 pageDomain = targetPageDomain;
|
|
|
|
var pageDomain = matrixSnapshot.domain;
|
|
|
|
var rows = matrixSnapshot.rows;
|
|
|
|
var rows = matrixSnapshot.rows;
|
|
|
|
var columnOffsets = matrixSnapshot.headers;
|
|
|
|
var columnOffsets = matrixSnapshot.headers;
|
|
|
|
var anyTypeOffset = columnOffsets['*'];
|
|
|
|
var anyTypeOffset = columnOffsets['*'];
|
|
|
@ -227,28 +217,6 @@ function getCellClass(hostname, type) {
|
|
|
|
' p' + getPermanentColor(hostname, type).toString(16);
|
|
|
|
' p' + getPermanentColor(hostname, type).toString(16);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function getNextAction(hostname, type, leaning) {
|
|
|
|
|
|
|
|
var temporaryColor = getTemporaryColor(hostname, type);
|
|
|
|
|
|
|
|
var hue = temporaryColor & 0x03;
|
|
|
|
|
|
|
|
var saturation = temporaryColor & 0x80;
|
|
|
|
|
|
|
|
// special case: root toggle only between two states
|
|
|
|
|
|
|
|
if ( type === '*' && hostname === '*' ) {
|
|
|
|
|
|
|
|
return hue === Green ? 'blacklist' : 'whitelist';
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Lean toward whitelisting?
|
|
|
|
|
|
|
|
if ( leaning === 'whitelisting' ) {
|
|
|
|
|
|
|
|
if ( saturation !== Dark ) {
|
|
|
|
|
|
|
|
return 'whitelist';
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return 'graylist';
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Lean toward blacklisting
|
|
|
|
|
|
|
|
if ( saturation !== Dark ) {
|
|
|
|
|
|
|
|
return 'blacklist';
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return 'graylist';
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
// This is required for when we update the matrix while it is open:
|
|
|
|
// This is required for when we update the matrix while it is open:
|
|
|
@ -351,21 +319,33 @@ function updateMatrixBehavior() {
|
|
|
|
|
|
|
|
|
|
|
|
// handle user interaction with filters
|
|
|
|
// handle user interaction with filters
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function getCellAction(hostname, type, leaning) {
|
|
|
|
|
|
|
|
var temporaryColor = getTemporaryColor(hostname, type);
|
|
|
|
|
|
|
|
var hue = temporaryColor & 0x03;
|
|
|
|
|
|
|
|
// Special case: root toggle only between two states
|
|
|
|
|
|
|
|
if ( type === '*' && hostname === '*' ) {
|
|
|
|
|
|
|
|
return hue === Green ? 'blacklistMatrixCell' : 'whitelistMatrixCell';
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// When explicitly blocked/allowed, can only graylist
|
|
|
|
|
|
|
|
var saturation = temporaryColor & 0x80;
|
|
|
|
|
|
|
|
if ( saturation === Dark ) {
|
|
|
|
|
|
|
|
return 'graylistMatrixCell';
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return leaning === 'whitelisting' ? 'whitelistMatrixCell' : 'blacklistMatrixCell';
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function handleFilter(button, leaning) {
|
|
|
|
function handleFilter(button, leaning) {
|
|
|
|
var µm = µMatrix;
|
|
|
|
|
|
|
|
// our parent cell knows who we are
|
|
|
|
// our parent cell knows who we are
|
|
|
|
var cell = button.ancestors('div.matCell');
|
|
|
|
var cell = button.ancestors('div.matCell');
|
|
|
|
var type = cell.prop('reqType');
|
|
|
|
var type = cell.prop('reqType');
|
|
|
|
var hostname = cell.prop('hostname');
|
|
|
|
var hostname = cell.prop('hostname');
|
|
|
|
var nextAction = getNextAction(hostname, type, leaning);
|
|
|
|
var request = {
|
|
|
|
if ( nextAction === 'blacklist' ) {
|
|
|
|
what: getCellAction(hostname, type, leaning),
|
|
|
|
µm.blacklistTemporarily(targetScope, hostname, type);
|
|
|
|
srcHostname: matrixSnapshot.scope,
|
|
|
|
} else if ( nextAction === 'whitelist' ) {
|
|
|
|
desHostname: hostname,
|
|
|
|
µm.whitelistTemporarily(targetScope, hostname, type);
|
|
|
|
type: type
|
|
|
|
} else {
|
|
|
|
};
|
|
|
|
µm.graylistTemporarily(targetScope, hostname, type);
|
|
|
|
messaging.ask(request, updateMatrixSnapshot);
|
|
|
|
}
|
|
|
|
|
|
|
|
updateMatrixSnapshot();
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function handleWhitelistFilter(button) {
|
|
|
|
function handleWhitelistFilter(button) {
|
|
|
@ -854,6 +834,9 @@ var makeMenu = function() {
|
|
|
|
// Do all the stuff that needs to be done before building menu et al.
|
|
|
|
// Do all the stuff that needs to be done before building menu et al.
|
|
|
|
|
|
|
|
|
|
|
|
function initMenuEnvironment() {
|
|
|
|
function initMenuEnvironment() {
|
|
|
|
|
|
|
|
uDom('body').css('font-size', getUserSetting('displayTextSize'));
|
|
|
|
|
|
|
|
uDom('body').toggleClass('colorblind', getUserSetting('colorBlindFriendly') === true);
|
|
|
|
|
|
|
|
|
|
|
|
var prettyNames = matrixHeaderPrettyNames;
|
|
|
|
var prettyNames = matrixHeaderPrettyNames;
|
|
|
|
var keys = Object.keys(prettyNames);
|
|
|
|
var keys = Object.keys(prettyNames);
|
|
|
|
var i = keys.length;
|
|
|
|
var i = keys.length;
|
|
|
@ -871,32 +854,29 @@ function initMenuEnvironment() {
|
|
|
|
|
|
|
|
|
|
|
|
// Create page scopes for the web page
|
|
|
|
// Create page scopes for the web page
|
|
|
|
|
|
|
|
|
|
|
|
function createGlobalScope() {
|
|
|
|
function selectGlobalScope() {
|
|
|
|
targetScope = '*';
|
|
|
|
setUserSetting('popupScopeLevel', '*');
|
|
|
|
setUserSetting('scopeLevel', '*');
|
|
|
|
|
|
|
|
updateMatrixSnapshot();
|
|
|
|
updateMatrixSnapshot();
|
|
|
|
dropDownMenuHide();
|
|
|
|
dropDownMenuHide();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function createDomainScope() {
|
|
|
|
function selectDomainScope() {
|
|
|
|
targetScope = targetPageDomain;
|
|
|
|
setUserSetting('popupScopeLevel', 'domain');
|
|
|
|
setUserSetting('scopeLevel', 'domain');
|
|
|
|
|
|
|
|
updateMatrixSnapshot();
|
|
|
|
updateMatrixSnapshot();
|
|
|
|
dropDownMenuHide();
|
|
|
|
dropDownMenuHide();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function createSiteScope() {
|
|
|
|
function selectSiteScope() {
|
|
|
|
targetScope = targetPageHostname;
|
|
|
|
setUserSetting('popupScopeLevel', 'site');
|
|
|
|
setUserSetting('scopeLevel', 'site');
|
|
|
|
|
|
|
|
updateMatrixSnapshot();
|
|
|
|
updateMatrixSnapshot();
|
|
|
|
dropDownMenuHide();
|
|
|
|
dropDownMenuHide();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function getClassFromTargetScope() {
|
|
|
|
function getClassFromScope() {
|
|
|
|
if ( targetScope === '*' ) {
|
|
|
|
if ( matrixSnapshot.scope === '*' ) {
|
|
|
|
return 'tScopeGlobal';
|
|
|
|
return 'tScopeGlobal';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( targetScope === targetPageDomain ) {
|
|
|
|
if ( matrixSnapshot.scope === matrixSnapshot.domain ) {
|
|
|
|
return 'tScopeNarrow';
|
|
|
|
return 'tScopeNarrow';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 'tScopeNarrow';
|
|
|
|
return 'tScopeNarrow';
|
|
|
@ -905,52 +885,44 @@ function getClassFromTargetScope() {
|
|
|
|
function initScopeCell() {
|
|
|
|
function initScopeCell() {
|
|
|
|
// It's possible there is no page URL at this point: some pages cannot
|
|
|
|
// It's possible there is no page URL at this point: some pages cannot
|
|
|
|
// be filtered by µMatrix.
|
|
|
|
// be filtered by µMatrix.
|
|
|
|
if ( !targetPageURL ) {
|
|
|
|
if ( matrixSnapshot.url === '' ) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Fill in the scope menu entries
|
|
|
|
// Fill in the scope menu entries
|
|
|
|
if ( targetPageDomain === '' || targetPageDomain === targetPageHostname ) {
|
|
|
|
if ( matrixSnapshot.hostname === matrixSnapshot.domain ) {
|
|
|
|
uDom('#scopeKeyDomain').css('display', 'none');
|
|
|
|
uDom('#scopeKeySite').css('display', 'none');
|
|
|
|
} else {
|
|
|
|
|
|
|
|
uDom('#scopeKeyDomain').text(targetPageDomain);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
uDom('#scopeKeySite').text(targetPageHostname);
|
|
|
|
|
|
|
|
var scopeLevel = getUserSetting('scopeLevel');
|
|
|
|
|
|
|
|
if ( scopeLevel === 'site' ) {
|
|
|
|
|
|
|
|
targetScope = targetPageHostname;
|
|
|
|
|
|
|
|
} else if ( scopeLevel === 'domain' ) {
|
|
|
|
|
|
|
|
targetScope = targetPageDomain;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
targetScope = '*';
|
|
|
|
uDom('#scopeKeySite').text(matrixSnapshot.hostname);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uDom('#scopeKeyDomain').text(matrixSnapshot.domain);
|
|
|
|
updateScopeCell();
|
|
|
|
updateScopeCell();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function updateScopeCell() {
|
|
|
|
function updateScopeCell() {
|
|
|
|
uDom('body')
|
|
|
|
uDom('body')
|
|
|
|
.removeClass('tScopeGlobal tScopeNarrow')
|
|
|
|
.removeClass('tScopeGlobal tScopeNarrow')
|
|
|
|
.addClass(getClassFromTargetScope());
|
|
|
|
.addClass(getClassFromScope());
|
|
|
|
uDom('#scopeCell').text(targetScope.replace('*', '\u2217'));
|
|
|
|
uDom('#scopeCell').text(matrixSnapshot.scope.replace('*', '\u2217'));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
function updateMtxbutton() {
|
|
|
|
function updateMtxbutton() {
|
|
|
|
var µm = µMatrix;
|
|
|
|
|
|
|
|
var masterSwitch = matrixSnapshot.tSwitch;
|
|
|
|
var masterSwitch = matrixSnapshot.tSwitch;
|
|
|
|
var pageStats = getPageStats();
|
|
|
|
var count = matrixSnapshot.blockedCount;
|
|
|
|
var count = pageStats ? pageStats.requestStats.blocked.all : '';
|
|
|
|
|
|
|
|
var button = uDom('#buttonMtxFiltering');
|
|
|
|
var button = uDom('#buttonMtxFiltering');
|
|
|
|
button.toggleClass('disabled', !masterSwitch);
|
|
|
|
button.toggleClass('disabled', !masterSwitch);
|
|
|
|
button.descendants('span.badge').text(µm.formatCount(count));
|
|
|
|
button.descendants('span.badge').text(count.toLocaleString());
|
|
|
|
button.attr('data-tip', button.attr('data-tip').replace('{{count}}', count));
|
|
|
|
button.attr('data-tip', button.attr('data-tip').replace('{{count}}', count));
|
|
|
|
uDom('body').toggleClass('powerOff', !masterSwitch);
|
|
|
|
uDom('body').toggleClass('powerOff', !masterSwitch);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function toggleMtxFiltering() {
|
|
|
|
function toggleMtxFiltering() {
|
|
|
|
var µm = µMatrix;
|
|
|
|
var request = {
|
|
|
|
µm.toggleTemporaryMtxFiltering(targetScope);
|
|
|
|
what: 'toggleMatrixSwitch',
|
|
|
|
updateMatrixSnapshot();
|
|
|
|
srcHostname: matrixSnapshot.scope
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
messaging.ask(request, updateMatrixSnapshot);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/******************************************************************************/
|
|
|
@ -1015,7 +987,7 @@ function revertAll() {
|
|
|
|
function buttonReloadHandler() {
|
|
|
|
function buttonReloadHandler() {
|
|
|
|
messaging.tell({
|
|
|
|
messaging.tell({
|
|
|
|
what: 'forceReloadTab',
|
|
|
|
what: 'forceReloadTab',
|
|
|
|
pageURL: targetPageURL
|
|
|
|
pageURL: matrixSnapshot.url
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -1065,16 +1037,13 @@ var onMatrixSnapshotReady = function(response) {
|
|
|
|
matrixSnapshot = response;
|
|
|
|
matrixSnapshot = response;
|
|
|
|
|
|
|
|
|
|
|
|
targetTabId = response.tabId;
|
|
|
|
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();
|
|
|
|
makeMenu();
|
|
|
|
makeMenu();
|
|
|
|
|
|
|
|
|
|
|
|
// After popup menu is built, check whether there is a non-empty matrix
|
|
|
|
// After popup menu is built, check whether there is a non-empty matrix
|
|
|
|
if ( !targetPageURL ) {
|
|
|
|
if ( matrixSnapshot.url === '' ) {
|
|
|
|
uDom('#matHead').remove();
|
|
|
|
uDom('#matHead').remove();
|
|
|
|
uDom('#toolbarLeft').remove();
|
|
|
|
uDom('#toolbarLeft').remove();
|
|
|
|
|
|
|
|
|
|
|
@ -1116,10 +1085,6 @@ uDom.onLoad(function() {
|
|
|
|
// 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.
|
|
|
|
|
|
|
|
|
|
|
|
// Matrix appearance
|
|
|
|
|
|
|
|
uDom('body').css('font-size', getUserSetting('displayTextSize'));
|
|
|
|
|
|
|
|
uDom('body').toggleClass('colorblind', getUserSetting('colorBlindFriendly') === true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// We reuse for all cells the one and only cell hotspots.
|
|
|
|
// We reuse for all cells the one and only cell hotspots.
|
|
|
|
uDom('#whitelist').on('click', function() {
|
|
|
|
uDom('#whitelist').on('click', function() {
|
|
|
|
handleWhitelistFilter(uDom(this));
|
|
|
|
handleWhitelistFilter(uDom(this));
|
|
|
@ -1137,9 +1102,9 @@ uDom.onLoad(function() {
|
|
|
|
uDom('body')
|
|
|
|
uDom('body')
|
|
|
|
.on('mouseenter', '.matCell', mouseenterMatrixCellHandler)
|
|
|
|
.on('mouseenter', '.matCell', mouseenterMatrixCellHandler)
|
|
|
|
.on('mouseleave', '.matCell', mouseleaveMatrixCellHandler);
|
|
|
|
.on('mouseleave', '.matCell', mouseleaveMatrixCellHandler);
|
|
|
|
uDom('#scopeKeyGlobal').on('click', createGlobalScope);
|
|
|
|
uDom('#scopeKeyGlobal').on('click', selectGlobalScope);
|
|
|
|
uDom('#scopeKeyDomain').on('click', createDomainScope);
|
|
|
|
uDom('#scopeKeyDomain').on('click', selectDomainScope);
|
|
|
|
uDom('#scopeKeySite').on('click', createSiteScope);
|
|
|
|
uDom('#scopeKeySite').on('click', selectSiteScope);
|
|
|
|
uDom('#buttonMtxFiltering').on('click', toggleMtxFiltering);
|
|
|
|
uDom('#buttonMtxFiltering').on('click', toggleMtxFiltering);
|
|
|
|
uDom('#buttonPersist').on('click', persistMatrix);
|
|
|
|
uDom('#buttonPersist').on('click', persistMatrix);
|
|
|
|
uDom('#buttonRevertScope').on('click', revertMatrix);
|
|
|
|
uDom('#buttonRevertScope').on('click', revertMatrix);
|
|
|
@ -1155,7 +1120,7 @@ uDom.onLoad(function() {
|
|
|
|
uDom('#matList').on('click', '.g3Meta', function() {
|
|
|
|
uDom('#matList').on('click', '.g3Meta', function() {
|
|
|
|
var collapsed = uDom(this)
|
|
|
|
var collapsed = uDom(this)
|
|
|
|
.toggleClass('g3Collapsed')
|
|
|
|
.toggleClass('g3Collapsed')
|
|
|
|
.hasClass('g3Collapsed');
|
|
|
|
.hasClassName('g3Collapsed');
|
|
|
|
setUserSetting('popupHideBlacklisted', collapsed);
|
|
|
|
setUserSetting('popupHideBlacklisted', collapsed);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|