aboutsummaryrefslogtreecommitdiffstats
path: root/js/messaging.js
diff options
context:
space:
mode:
authorAlessio Vanni <vannilla@firemail.cc>2019-02-19 21:06:09 +0100
committerAlessio Vanni <vannilla@firemail.cc>2019-02-19 21:06:09 +0100
commitfe2f8acc8210c2ddead4621797b47106a9b38f5b (patch)
tree5fb103d45d7e4345f56fc068ce8173b82fa7051f /js/messaging.js
downloadematrix-fe2f8acc8210c2ddead4621797b47106a9b38f5b.tar.lz
ematrix-fe2f8acc8210c2ddead4621797b47106a9b38f5b.tar.xz
ematrix-fe2f8acc8210c2ddead4621797b47106a9b38f5b.zip
Fork uMatrix
Pretty much just changing the name and the copyright.
Diffstat (limited to 'js/messaging.js')
-rw-r--r--js/messaging.js963
1 files changed, 963 insertions, 0 deletions
diff --git a/js/messaging.js b/js/messaging.js
new file mode 100644
index 0000000..d5c472f
--- /dev/null
+++ b/js/messaging.js
@@ -0,0 +1,963 @@
+/*******************************************************************************
+
+ ηMatrix - a browser extension to black/white list requests.
+ Copyright (C) 2014-2019 Raymond Hill
+ Copyright (C) 2019 Alessio Vanni
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see {http://www.gnu.org/licenses/}.
+
+ uMatrix Home: https://github.com/gorhill/uMatrix
+*/
+
+'use strict';
+
+/******************************************************************************/
+/******************************************************************************/
+
+// Default handler
+
+(function() {
+
+var µm = µMatrix;
+
+/******************************************************************************/
+
+// Default is for commonly used message.
+
+function onMessage(request, sender, callback) {
+ // Async
+ switch ( request.what ) {
+ case 'getAssetContent':
+ µm.assets.get(request.url, { dontCache: true }, callback);
+ return;
+
+ case 'selectHostsFiles':
+ µm.selectHostsFiles(request, callback);
+ return;
+
+ default:
+ break;
+ }
+
+ // Sync
+ var response;
+
+ switch ( request.what ) {
+ case 'forceReloadTab':
+ µm.forceReload(request.tabId, request.bypassCache);
+ break;
+
+ case 'forceUpdateAssets':
+ µm.scheduleAssetUpdater(0);
+ µm.assets.updateStart({ delay: 2000 });
+ break;
+
+ case 'getUserSettings':
+ response = {
+ userSettings: µm.userSettings,
+ matrixSwitches: {
+ 'https-strict': µm.pMatrix.evaluateSwitch('https-strict', '*') === 1,
+ 'referrer-spoof': µm.pMatrix.evaluateSwitch('referrer-spoof', '*') === 1,
+ 'noscript-spoof': µm.pMatrix.evaluateSwitch('noscript-spoof', '*') === 1
+ }
+ };
+ break;
+
+ case 'gotoExtensionURL':
+ µm.gotoExtensionURL(request);
+ break;
+
+ case 'gotoURL':
+ µm.gotoURL(request);
+ break;
+
+ case 'mustBlock':
+ response = µm.mustBlock(
+ request.scope,
+ request.hostname,
+ request.type
+ );
+ break;
+
+ case 'readRawSettings':
+ response = µm.stringFromRawSettings();
+ break;
+
+ case 'reloadHostsFiles':
+ µm.reloadHostsFiles();
+ break;
+
+ case 'setMatrixSwitch':
+ µm.tMatrix.setSwitch(request.switchName, '*', request.state);
+ if ( µm.pMatrix.setSwitch(request.switchName, '*', request.state) ) {
+ µm.saveMatrix();
+ }
+ break;
+
+ case 'userSettings':
+ if ( request.hasOwnProperty('value') === false ) {
+ request.value = undefined;
+ }
+ response = µm.changeUserSettings(request.name, request.value);
+ break;
+
+ case 'writeRawSettings':
+ µm.rawSettingsFromString(request.content);
+ break;
+
+ default:
+ return vAPI.messaging.UNHANDLED;
+ }
+
+ callback(response);
+}
+
+/******************************************************************************/
+
+vAPI.messaging.setup(onMessage);
+
+/******************************************************************************/
+
+})();
+
+/******************************************************************************/
+/******************************************************************************/
+
+(function() {
+
+// popup.js
+
+var µm = µMatrix;
+
+/******************************************************************************/
+
+// Constructor is faster than object literal
+
+var RowSnapshot = function(srcHostname, desHostname, desDomain) {
+ this.domain = desDomain;
+ this.temporary = µm.tMatrix.evaluateRowZXY(srcHostname, desHostname);
+ this.permanent = µm.pMatrix.evaluateRowZXY(srcHostname, desHostname);
+ this.counts = RowSnapshot.counts.slice();
+ this.totals = RowSnapshot.counts.slice();
+};
+
+RowSnapshot.counts = (function() {
+ var aa = [];
+ for ( var i = 0, n = µm.Matrix.columnHeaderIndices.size; i < n; i++ ) {
+ aa[i] = 0;
+ }
+ return aa;
+})();
+
+/******************************************************************************/
+
+var matrixSnapshot = function(pageStore, details) {
+ var µmuser = µm.userSettings;
+ var headerIndices = µm.Matrix.columnHeaderIndices;
+
+ var r = {
+ appVersion: vAPI.app.version,
+ blockedCount: pageStore.requestStats.blocked.all,
+ collapseAllDomains: µmuser.popupCollapseAllDomains,
+ collapseBlacklistedDomains: µmuser.popupCollapseBlacklistedDomains,
+ diff: [],
+ domain: pageStore.pageDomain,
+ has3pReferrer: pageStore.has3pReferrer,
+ hasMixedContent: pageStore.hasMixedContent,
+ hasNoscriptTags: pageStore.hasNoscriptTags,
+ hasWebWorkers: pageStore.hasWebWorkers,
+ headerIndices: Array.from(headerIndices),
+ hostname: pageStore.pageHostname,
+ mtxContentModified: pageStore.mtxContentModifiedTime !== details.mtxContentModifiedTime,
+ mtxCountModified: pageStore.mtxCountModifiedTime !== details.mtxCountModifiedTime,
+ mtxContentModifiedTime: pageStore.mtxContentModifiedTime,
+ mtxCountModifiedTime: pageStore.mtxCountModifiedTime,
+ pMatrixModified: µm.pMatrix.modifiedTime !== details.pMatrixModifiedTime,
+ pMatrixModifiedTime: µm.pMatrix.modifiedTime,
+ pSwitches: {},
+ rows: {},
+ rowCount: 0,
+ scope: '*',
+ tabId: pageStore.tabId,
+ tMatrixModified: µm.tMatrix.modifiedTime !== details.tMatrixModifiedTime,
+ tMatrixModifiedTime: µm.tMatrix.modifiedTime,
+ tSwitches: {},
+ url: pageStore.pageUrl,
+ userSettings: {
+ colorBlindFriendly: µmuser.colorBlindFriendly,
+ displayTextSize: µmuser.displayTextSize,
+ popupScopeLevel: µmuser.popupScopeLevel
+ }
+ };
+
+ if ( typeof details.scope === 'string' ) {
+ r.scope = details.scope;
+ } else if ( µmuser.popupScopeLevel === 'site' ) {
+ r.scope = r.hostname;
+ } else if ( µmuser.popupScopeLevel === 'domain' ) {
+ r.scope = r.domain;
+ }
+
+ for ( var switchName of µm.Matrix.switchNames ) {
+ r.tSwitches[switchName] = µm.tMatrix.evaluateSwitchZ(switchName, r.scope);
+ r.pSwitches[switchName] = µm.pMatrix.evaluateSwitchZ(switchName, r.scope);
+ }
+
+ // These rows always exist
+ r.rows['*'] = new RowSnapshot(r.scope, '*', '*');
+ r.rows['1st-party'] = new RowSnapshot(r.scope, '1st-party', '1st-party');
+ r.rowCount += 1;
+
+ var µmuri = µm.URI;
+ var reqType, reqHostname, reqDomain;
+ var desHostname;
+ var row, typeIndex;
+ var anyIndex = headerIndices.get('*');
+ var pos, count;
+
+ for ( var entry of pageStore.hostnameTypeCells ) {
+ pos = entry[0].indexOf(' ');
+ reqHostname = entry[0].slice(0, pos);
+ reqType = entry[0].slice(pos + 1);
+ // 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 RowSnapshot(r.scope, desHostname, reqDomain);
+ r.rowCount += 1;
+ if ( desHostname === reqDomain ) { break; }
+ pos = desHostname.indexOf('.');
+ if ( pos === -1 ) { break; }
+ desHostname = desHostname.slice(pos + 1);
+ }
+
+ count = entry[1].size;
+ typeIndex = headerIndices.get(reqType);
+ row = r.rows[reqHostname];
+ row.counts[typeIndex] += count;
+ row.counts[anyIndex] += count;
+ row = r.rows[reqDomain];
+ row.totals[typeIndex] += count;
+ row.totals[anyIndex] += count;
+ row = r.rows['*'];
+ row.totals[typeIndex] += count;
+ row.totals[anyIndex] += count;
+ }
+
+ r.diff = µm.tMatrix.diff(µm.pMatrix, r.hostname, Object.keys(r.rows));
+
+ return r;
+};
+
+/******************************************************************************/
+
+var matrixSnapshotFromTabId = function(details, callback) {
+ var matrixSnapshotIf = function(tabId, details) {
+ var pageStore = µm.pageStoreFromTabId(tabId);
+ if ( pageStore === null ) {
+ callback('ENOTFOUND');
+ return;
+ }
+
+ // First verify whether we must return data or not.
+ if (
+ µm.tMatrix.modifiedTime === details.tMatrixModifiedTime &&
+ µm.pMatrix.modifiedTime === details.pMatrixModifiedTime &&
+ pageStore.mtxContentModifiedTime === details.mtxContentModifiedTime &&
+ pageStore.mtxCountModifiedTime === details.mtxCountModifiedTime
+ ) {
+ callback('ENOCHANGE');
+ return ;
+ }
+
+ callback(matrixSnapshot(pageStore, details));
+ };
+
+ // Specific tab id requested?
+ if ( details.tabId ) {
+ matrixSnapshotIf(details.tabId, details);
+ return;
+ }
+
+ // Fall back to currently active tab
+ var onTabReady = function(tab) {
+ if ( tab instanceof Object === false ) {
+ callback('ENOTFOUND');
+ return;
+ }
+
+ // Allow examination of behind-the-scene requests
+ var tabId = tab.url.lastIndexOf(vAPI.getURL('dashboard.html'), 0) !== 0 ?
+ tab.id :
+ vAPI.noTabId;
+ matrixSnapshotIf(tabId, details);
+ };
+
+ vAPI.tabs.get(null, onTabReady);
+};
+
+/******************************************************************************/
+
+var onMessage = function(request, sender, callback) {
+ // Async
+ switch ( request.what ) {
+ case 'matrixSnapshot':
+ matrixSnapshotFromTabId(request, callback);
+ return;
+
+ default:
+ break;
+ }
+
+ // Sync
+ var response;
+
+ switch ( request.what ) {
+ case 'toggleMatrixSwitch':
+ µm.tMatrix.setSwitchZ(
+ request.switchName,
+ request.srcHostname,
+ µm.tMatrix.evaluateSwitchZ(request.switchName, request.srcHostname) === false
+ );
+ break;
+
+ case 'blacklistMatrixCell':
+ µm.tMatrix.blacklistCell(
+ request.srcHostname,
+ request.desHostname,
+ request.type
+ );
+ break;
+
+ case 'whitelistMatrixCell':
+ µm.tMatrix.whitelistCell(
+ request.srcHostname,
+ request.desHostname,
+ request.type
+ );
+ break;
+
+ case 'graylistMatrixCell':
+ µm.tMatrix.graylistCell(
+ request.srcHostname,
+ request.desHostname,
+ request.type
+ );
+ break;
+
+ case 'applyDiffToPermanentMatrix': // aka "persist"
+ if ( µm.pMatrix.applyDiff(request.diff, µm.tMatrix) ) {
+ µm.saveMatrix();
+ }
+ break;
+
+ case 'applyDiffToTemporaryMatrix': // aka "revert"
+ µm.tMatrix.applyDiff(request.diff, µm.pMatrix);
+ break;
+
+ case 'revertTemporaryMatrix':
+ µm.tMatrix.assign(µm.pMatrix);
+ break;
+
+ default:
+ return vAPI.messaging.UNHANDLED;
+ }
+
+ callback(response);
+};
+
+vAPI.messaging.listen('popup.js', onMessage);
+
+})();
+
+/******************************************************************************/
+/******************************************************************************/
+
+// content scripts
+
+(function() {
+
+var µm = µMatrix;
+
+/******************************************************************************/
+
+var foundInlineCode = function(tabId, pageStore, details, type) {
+ if ( pageStore === null ) { return; }
+
+ var pageHostname = pageStore.pageHostname,
+ µmuri = µm.URI.set(details.documentURI),
+ frameURL = µmuri.normalizedURI();
+
+ var blocked = details.blocked;
+ if ( blocked === undefined ) {
+ blocked = µm.mustBlock(pageHostname, µmuri.hostname, type);
+ }
+
+ var mapTo = {
+ css: 'style',
+ script: 'script'
+ };
+
+ // https://github.com/gorhill/httpswitchboard/issues/333
+ // Look-up here whether inline scripting is blocked for the frame.
+ var url = frameURL + '{inline_' + mapTo[type] + '}';
+ pageStore.recordRequest(type, url, blocked);
+ µm.logger.writeOne(tabId, 'net', pageHostname, url, type, blocked);
+};
+
+/******************************************************************************/
+
+var contentScriptLocalStorageHandler = function(tabId, originURL) {
+ var tabContext = µm.tabContextManager.lookup(tabId);
+ if ( tabContext === null ) { return; }
+
+ var blocked = µm.mustBlock(
+ tabContext.rootHostname,
+ µm.URI.hostnameFromURI(originURL),
+ 'cookie'
+ );
+
+ var pageStore = µm.pageStoreFromTabId(tabId);
+ if ( pageStore !== null ) {
+ var requestURL = originURL + '/{localStorage}';
+ pageStore.recordRequest('cookie', requestURL, blocked);
+ µm.logger.writeOne(tabId, 'net', tabContext.rootHostname, requestURL, 'cookie', blocked);
+ }
+
+ var removeStorage = blocked && µm.userSettings.deleteLocalStorage;
+ if ( removeStorage ) {
+ µm.localStorageRemovedCounter++;
+ }
+
+ return removeStorage;
+};
+
+/******************************************************************************/
+
+// Evaluate many URLs against the matrix.
+
+var lookupBlockedCollapsibles = function(tabId, requests) {
+ if ( placeholdersReadTime < µm.rawSettingsWriteTime ) {
+ placeholders = undefined;
+ }
+
+ if ( placeholders === undefined ) {
+ placeholders = {
+ frame: µm.rawSettings.framePlaceholder,
+ image: µm.rawSettings.imagePlaceholder
+ };
+ if ( placeholders.frame ) {
+ placeholders.frameDocument =
+ µm.rawSettings.framePlaceholderDocument.replace(
+ '{{bg}}',
+ µm.rawSettings.framePlaceholderBackground !== 'default' ?
+ µm.rawSettings.framePlaceholderBackground :
+ µm.rawSettings.placeholderBackground
+ );
+ }
+ if ( placeholders.image ) {
+ placeholders.imageBorder =
+ µm.rawSettings.imagePlaceholderBorder !== 'default' ?
+ µm.rawSettings.imagePlaceholderBorder :
+ µm.rawSettings.placeholderBorder;
+ placeholders.imageBackground =
+ µm.rawSettings.imagePlaceholderBackground !== 'default' ?
+ µm.rawSettings.imagePlaceholderBackground :
+ µm.rawSettings.placeholderBackground;
+ }
+ placeholdersReadTime = Date.now();
+ }
+
+ var response = {
+ blockedResources: [],
+ hash: requests.hash,
+ id: requests.id,
+ placeholders: placeholders
+ };
+
+ var tabContext = µm.tabContextManager.lookup(tabId);
+ if ( tabContext === null ) {
+ return response;
+ }
+
+ var pageStore = µm.pageStoreFromTabId(tabId);
+ if ( pageStore !== null ) {
+ pageStore.lookupBlockedCollapsibles(requests, response);
+ }
+
+ return response;
+};
+
+var placeholders,
+ placeholdersReadTime = 0;
+
+/******************************************************************************/
+
+var onMessage = function(request, sender, callback) {
+ // Async
+ switch ( request.what ) {
+ default:
+ break;
+ }
+
+ var tabId = sender && sender.tab ? sender.tab.id || 0 : 0,
+ tabContext = µm.tabContextManager.lookup(tabId),
+ rootHostname = tabContext && tabContext.rootHostname,
+ pageStore = µm.pageStoreFromTabId(tabId);
+
+ // Sync
+ var response;
+
+ switch ( request.what ) {
+ case 'contentScriptHasLocalStorage':
+ response = contentScriptLocalStorageHandler(tabId, request.originURL);
+ break;
+
+ case 'lookupBlockedCollapsibles':
+ response = lookupBlockedCollapsibles(tabId, request);
+ break;
+
+ case 'mustRenderNoscriptTags?':
+ if ( tabContext === null ) { break; }
+ response =
+ µm.tMatrix.mustBlock(rootHostname, rootHostname, 'script') &&
+ µm.tMatrix.evaluateSwitchZ('noscript-spoof', rootHostname);
+ if ( pageStore !== null ) {
+ pageStore.hasNoscriptTags = true;
+ }
+ // https://github.com/gorhill/uMatrix/issues/225
+ // A good place to force an update of the page title, as at
+ // this point the DOM has been loaded.
+ µm.updateTitle(tabId);
+ break;
+
+ case 'securityPolicyViolation':
+ if ( request.directive === 'worker-src' ) {
+ var url = µm.URI.hostnameFromURI(request.blockedURI) !== '' ?
+ request.blockedURI :
+ request.documentURI;
+ if ( pageStore !== null ) {
+ pageStore.hasWebWorkers = true;
+ pageStore.recordRequest('script', url, true);
+ }
+ if ( tabContext !== null ) {
+ µm.logger.writeOne(tabId, 'net', rootHostname, url, 'worker', request.blocked);
+ }
+ } else if ( request.directive === 'script-src' ) {
+ foundInlineCode(tabId, pageStore, request, 'script');
+ } else if ( request.directive === 'style-src' ) {
+ foundInlineCode(tabId, pageStore, request, 'css');
+ }
+ break;
+
+ case 'shutdown?':
+ if ( tabContext !== null ) {
+ response = µm.tMatrix.evaluateSwitchZ('matrix-off', rootHostname);
+ }
+ break;
+
+ default:
+ return vAPI.messaging.UNHANDLED;
+ }
+
+ callback(response);
+};
+
+vAPI.messaging.listen('contentscript.js', onMessage);
+
+/******************************************************************************/
+
+})();
+
+/******************************************************************************/
+/******************************************************************************/
+
+// cloud-ui.js
+
+(function() {
+
+/******************************************************************************/
+
+var µm = µMatrix;
+
+/******************************************************************************/
+
+var onMessage = function(request, sender, callback) {
+ // Async
+ switch ( request.what ) {
+ case 'cloudGetOptions':
+ vAPI.cloud.getOptions(function(options) {
+ options.enabled = µm.userSettings.cloudStorageEnabled === true;
+ callback(options);
+ });
+ return;
+
+ case 'cloudSetOptions':
+ vAPI.cloud.setOptions(request.options, callback);
+ return;
+
+ case 'cloudPull':
+ return vAPI.cloud.pull(request.datakey, callback);
+
+ case 'cloudPush':
+ return vAPI.cloud.push(request.datakey, request.data, callback);
+
+ default:
+ break;
+ }
+
+ // Sync
+ var response;
+
+ switch ( request.what ) {
+ // For when cloud storage is disabled.
+ case 'cloudPull':
+ // fallthrough
+ case 'cloudPush':
+ break;
+
+ default:
+ return vAPI.messaging.UNHANDLED;
+ }
+
+ callback(response);
+};
+
+/******************************************************************************/
+
+vAPI.messaging.listen('cloud-ui.js', onMessage);
+
+})();
+
+/******************************************************************************/
+/******************************************************************************/
+
+// user-rules.js
+
+(function() {
+
+var µm = µMatrix;
+
+/******************************************************************************/
+
+var onMessage = function(request, sender, callback) {
+
+ // Async
+ switch ( request.what ) {
+ default:
+ break;
+ }
+
+ // Sync
+ var response;
+
+ switch ( request.what ) {
+ case 'getUserRules':
+ response = {
+ temporaryRules: µm.tMatrix.toString(),
+ permanentRules: µm.pMatrix.toString()
+ };
+ break;
+
+ case 'setUserRules':
+ if ( typeof request.temporaryRules === 'string' ) {
+ µm.tMatrix.fromString(request.temporaryRules);
+ }
+ if ( typeof request.permanentRules === 'string' ) {
+ µm.pMatrix.fromString(request.permanentRules);
+ µm.saveMatrix();
+ }
+ response = {
+ temporaryRules: µm.tMatrix.toString(),
+ permanentRules: µm.pMatrix.toString()
+ };
+ break;
+
+ default:
+ return vAPI.messaging.UNHANDLED;
+ }
+
+ callback(response);
+};
+
+vAPI.messaging.listen('user-rules.js', onMessage);
+
+})();
+
+/******************************************************************************/
+/******************************************************************************/
+
+// hosts-files.js
+
+(function() {
+
+var µm = µMatrix;
+
+/******************************************************************************/
+
+var prepEntries = function(entries) {
+ var µmuri = µm.URI;
+ var entry;
+ for ( var k in entries ) {
+ if ( entries.hasOwnProperty(k) === false ) {
+ continue;
+ }
+ entry = entries[k];
+ if ( typeof entry.homeURL === 'string' ) {
+ entry.homeHostname = µmuri.hostnameFromURI(entry.homeURL);
+ entry.homeDomain = µmuri.domainFromHostname(entry.homeHostname);
+ }
+ }
+};
+
+/******************************************************************************/
+
+var getLists = function(callback) {
+ var r = {
+ autoUpdate: µm.userSettings.autoUpdate,
+ available: null,
+ cache: null,
+ current: µm.liveHostsFiles,
+ blockedHostnameCount: µm.ubiquitousBlacklist.count
+ };
+ var onMetadataReady = function(entries) {
+ r.cache = entries;
+ prepEntries(r.cache);
+ callback(r);
+ };
+ var onAvailableHostsFilesReady = function(lists) {
+ r.available = lists;
+ prepEntries(r.available);
+ µm.assets.metadata(onMetadataReady);
+ };
+ µm.getAvailableHostsFiles(onAvailableHostsFilesReady);
+};
+
+/******************************************************************************/
+
+var onMessage = function(request, sender, callback) {
+ var µm = µMatrix;
+
+ // Async
+ switch ( request.what ) {
+ case 'getLists':
+ return getLists(callback);
+
+ default:
+ break;
+ }
+
+ // Sync
+ var response;
+
+ switch ( request.what ) {
+ case 'purgeCache':
+ µm.assets.purge(request.assetKey);
+ µm.assets.remove('compiled/' + request.assetKey);
+ break;
+
+ case 'purgeAllCaches':
+ if ( request.hard ) {
+ µm.assets.remove(/./);
+ } else {
+ µm.assets.purge(/./, 'public_suffix_list.dat');
+ }
+ break;
+
+ default:
+ return vAPI.messaging.UNHANDLED;
+ }
+
+ callback(response);
+};
+
+vAPI.messaging.listen('hosts-files.js', onMessage);
+
+})();
+
+/******************************************************************************/
+/******************************************************************************/
+
+// about.js
+
+(function() {
+
+var µm = µMatrix;
+
+/******************************************************************************/
+
+var restoreUserData = function(userData) {
+ var countdown = 4;
+ var onCountdown = function() {
+ countdown -= 1;
+ if ( countdown === 0 ) {
+ vAPI.app.restart();
+ }
+ };
+
+ var onAllRemoved = function() {
+ vAPI.storage.set(userData.settings, onCountdown);
+ vAPI.storage.set({ userMatrix: userData.rules }, onCountdown);
+ vAPI.storage.set({ liveHostsFiles: userData.hostsFiles }, onCountdown);
+ if ( userData.rawSettings instanceof Object ) {
+ µMatrix.saveRawSettings(userData.rawSettings, onCountdown);
+ }
+ };
+
+ // If we are going to restore all, might as well wipe out clean local
+ // storage
+ µm.XAL.keyvalRemoveAll(onAllRemoved);
+};
+
+/******************************************************************************/
+
+var resetUserData = function() {
+ var onAllRemoved = function() {
+ vAPI.app.restart();
+ };
+ µm.XAL.keyvalRemoveAll(onAllRemoved);
+};
+
+/******************************************************************************/
+
+var onMessage = function(request, sender, callback) {
+ // Async
+ switch ( request.what ) {
+ default:
+ break;
+ }
+
+ // Sync
+ var response;
+
+ switch ( request.what ) {
+ case 'getAllUserData':
+ response = {
+ app: vAPI.app.name,
+ version: vAPI.app.version,
+ when: Date.now(),
+ settings: µm.userSettings,
+ rules: µm.pMatrix.toString(),
+ hostsFiles: µm.liveHostsFiles,
+ rawSettings: µm.rawSettings
+ };
+ break;
+
+ case 'getSomeStats':
+ response = {
+ version: vAPI.app.version,
+ storageUsed: µm.storageUsed
+ };
+ break;
+
+ case 'restoreAllUserData':
+ restoreUserData(request.userData);
+ break;
+
+ case 'resetAllUserData':
+ resetUserData();
+ break;
+
+ default:
+ return vAPI.messaging.UNHANDLED;
+ }
+
+ callback(response);
+};
+
+vAPI.messaging.listen('about.js', onMessage);
+
+/******************************************************************************/
+/******************************************************************************/
+
+// logger-ui.js
+
+(function() {
+
+/******************************************************************************/
+
+var µm = µMatrix,
+ loggerURL = vAPI.getURL('logger-ui.html');
+
+/******************************************************************************/
+
+var onMessage = function(request, sender, callback) {
+ // Async
+ switch ( request.what ) {
+ default:
+ break;
+ }
+
+ // Sync
+ var response;
+
+ switch ( request.what ) {
+ case 'readMany':
+ if (
+ µm.logger.ownerId !== undefined &&
+ request.ownerId !== µm.logger.ownerId
+ ) {
+ response = { unavailable: true };
+ break;
+ }
+ var tabIds = {};
+ for ( var tabId in µm.pageStores ) {
+ var pageStore = µm.pageStoreFromTabId(tabId);
+ if ( pageStore === null ) { continue; }
+ if ( pageStore.rawUrl.startsWith(loggerURL) ) { continue; }
+ tabIds[tabId] = pageStore.title || pageStore.rawUrl;
+ }
+ response = {
+ colorBlind: false,
+ entries: µm.logger.readAll(request.ownerId),
+ maxLoggedRequests: µm.userSettings.maxLoggedRequests,
+ noTabId: vAPI.noTabId,
+ tabIds: tabIds,
+ tabIdsToken: µm.pageStoresToken
+ };
+ break;
+
+ case 'releaseView':
+ if ( request.ownerId === µm.logger.ownerId ) {
+ µm.logger.ownerId = undefined;
+ }
+ break;
+
+ default:
+ return vAPI.messaging.UNHANDLED;
+ }
+
+ callback(response);
+};
+
+vAPI.messaging.listen('logger-ui.js', onMessage);
+
+/******************************************************************************/
+
+})();
+
+/******************************************************************************/
+/******************************************************************************/
+
+})();
+
+/******************************************************************************/