aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlessio Vanni <vannilla@firemail.cc>2020-08-24 14:34:54 +0200
committerJesús <heckyel@hyperbola.info>2022-04-06 04:39:51 +0800
commitb769343d0511aa444a6bf9fd601f0f97dea27cab (patch)
tree70cbea11cb43455e246dc3b75cb3759903f786c0
parentf7ee828e1c624be7429f8d986612c600d3eefd3b (diff)
downloadematrix-b769343d0511aa444a6bf9fd601f0f97dea27cab.tar.lz
ematrix-b769343d0511aa444a6bf9fd601f0f97dea27cab.tar.xz
ematrix-b769343d0511aa444a6bf9fd601f0f97dea27cab.zip
Rewrite messaging.js
Before, it was a series of switch statements that did stuff based on the content of a field of the request object; the new implementation does dynamic dispatching of "methods" (just some functions in a table) instead. Signed-off-by: Jesús <heckyel@hyperbola.info>
-rw-r--r--js/messaging.js1540
1 files changed, 738 insertions, 802 deletions
diff --git a/js/messaging.js b/js/messaging.js
index 90c5c5f..63e1c92 100644
--- a/js/messaging.js
+++ b/js/messaging.js
@@ -17,849 +17,785 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see {http://www.gnu.org/licenses/}.
- Home: https://libregit.spks.xyz/heckyel/ematrix
+ Home: https://notabug.org/heckyel/ematrix
uMatrix Home: https://github.com/gorhill/uMatrix
*/
'use strict';
-// Default handler
(function () {
+ Cu.import('chrome://ematrix/content/lib/UriTools.jsm');
Cu.import('chrome://ematrix/content/lib/Tools.jsm');
+ Cu.import('chrome://ematrix/content/lib/RowSnapshot.jsm');
let η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
- let 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':
- Tools.gotoExtensionURL({
- api: vAPI,
- details: request,
- matrix: ηm,
- });
- break;
- case 'gotoURL':
- Tools.gotoURL({
- api: vAPI,
- details: 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
-
- let ηm = ηMatrix;
-
- // Constructor is faster than object literal
- // ηMatrix: really? I'll take your word for it...
- let 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 () {
- let aa = [];
- let n = ηm.Matrix.columnHeaderIndices.size
-
- for (let i=0; i<n; ++i) {
- aa[i] = 0;
- }
-
- return aa;
- })();
-
- let matrixSnapshot = function (pageStore, details) {
- let ηmuser = ηm.userSettings;
- let headerIndices = ηm.Matrix.columnHeaderIndices;
-
- let 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 (let 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;
-
- let anyIndex = headerIndices.get('*');
- for (let entry of pageStore.hostnameTypeCells) {
- let pos = entry[0].indexOf(' ');
- let reqHostname = entry[0].slice(0, pos);
- let 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;
- }
-
- let reqDomain =
- UriTools.domainFromHostname(reqHostname) || reqHostname;
-
- // We want rows of self and ancestors
- let 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);
- }
-
- let count = entry[1].size;
- let typeIndex = headerIndices.get(reqType);
-
- let 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;
- };
-
- let matrixSnapshotFromTabId = function (details, callback) {
- let matrixSnapshotIf = function (tabId, details) {
- let 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
- let onTabReady = function (tab) {
- if (tab instanceof Object === false) {
- callback('ENOTFOUND');
- return;
- }
-
- // Allow examination of behind-the-scene requests
- let tabId =
- tab.url.lastIndexOf(vAPI.getURL('dashboard.html'), 0) !== 0 ?
- tab.id :
- vAPI.noTabId;
- matrixSnapshotIf(tabId, details);
- };
-
- vAPI.tabs.get(null, onTabReady);
- };
-
- let onMessage = function (request, sender, callback) {
- // Async
- switch (request.what) {
- case 'matrixSnapshot':
- matrixSnapshotFromTabId(request, callback);
- return;
- default:
- break;
- }
-
- // Sync
- let response;
- switch (request.what) {
- case 'toggleMatrixSwitch':
- let switchZ = ηm.tMatrix.evaluateSwitchZ(request.switchName,
- request.srcHostname)
- ηm.tMatrix.setSwitchZ(request.switchName,
- request.srcHostname,
- switchZ === 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 () {
-
- let ηm = ηMatrix;
-
- let foundInlineCode = function (tabId, pageStore, details, type) {
- if (pageStore === null) {
- return;
- }
-
- let pageHostname = pageStore.pageHostname;
- let ηmuri = UriTools.set(details.documentURI);
- let frameURL = UriTools.normalizedURI();
-
- let blocked = details.blocked;
- if (blocked === undefined) {
- blocked = ηm.mustBlock(pageHostname, ηmuri.hostname, type);
- }
-
- let mapTo = {
- css: 'style',
- script: 'script',
- };
-
- // https://github.com/gorhill/httpswitchboard/issues/333
- // Look-up here whether inline scripting is blocked for the frame.
- let url = frameURL + '{inline_' + mapTo[type] + '}';
- pageStore.recordRequest(type, url, blocked);
- ηm.logger.writeOne(tabId, 'net', pageHostname, url, type, blocked);
+ // I personally find this method better than a giant (or multiple
+ // giant) switch statement(s), but all things considered it's not
+ // as nice as when the language has proper macros. The idea is to
+ // make a more flexible system, at the cost of a slightly more
+ // verbose code and a bit more memory usage due to the new
+ // function objects.
+
+ // Method tables.
+ // "Early" is for those methods that do not call the callback.
+ let methods = {};
+ let methodsEarly = {};
+
+ // The message queue callback.
+ let dispatchMethod = function (request, sender, cb) {
+ let f = methods[request.what];
+ let early = false;
+ if (!f) {
+ f = methodsEarly[request.what];
+ if (!f) {
+ return vAPI.messaging.UNHANDLED;
+ }
+ early = true;
+ }
+
+ let response = f(request, sender, cb);
+ if (early === true) {
+ return response;
+ }
+
+ cb(response);
};
- let contentScriptLocalStorageHandler = function (tabId, originURL) {
- let tabContext = ηm.tabContextManager.lookup(tabId);
- if (tabContext === null) {
- return;
- }
+ // Used here to add dispatchable functions
+ let addMethod = function (name, f, /* &optional */ early) {
+ if (early) {
+ methodsEarly[name] = f;
+ } else {
+ methods[name] = f;
+ }
+ }
- let blocked = ηm.mustBlock(tabContext.rootHostname,
- UriTools.hostnameFromURI(originURL),
- 'cookie');
+ // Default
+ addMethod('getAssetContent', function (request, sender, cb) {
+ ηm.assets.get(request.url, {
+ dontCache: true,
+ }, cb);
+ return undefined;
+ }, true);
+
+ addMethod('selectHostsFiles', function (request, sender, cb) {
+ ηm.selectHostsFiles(request, cb);
+ return undefined;
+ }, true);
+
+ addMethod('forceReloadTab', function (request, sender, cb) {
+ ηm.forceReload(request.tabId, request.bypassCache);
+ return undefined;
+ });
+
+ addMethod('forceUpdateAssets', function (request, sender, cb) {
+ ηm.scheduleAssetUpdater(0);
+ ηm.assets.updateStart({
+ delay: 1000,
+ });
+ return undefined;
+ });
+
+ addMethod('getUserSettings', function (request, sender, cb) {
+ let pmat = ηm.pMatrix;
+ return {
+ userSettings: ηm.userSettings,
+ matrixSwitches: {
+ 'https-strict': (pmat.evaluateSwitch('https-strict', '*')
+ === 1),
+ 'referrer-spoof': (pmat.evaluateSwitch('referrer-spoof', '*')
+ === 1),
+ 'noscript-spoof': (pmat.evaluateSwitch('noscript-spoof', '*')
+ === 1),
+ },
+ };
+ });
+
+ addMethod('gotoExtensionURL', function (request, sender, cb) {
+ Tools.gotoExtensionURL({
+ api: vAPI,
+ details: request,
+ matrix: ηm,
+ });
+ return undefined;
+ });
+
+ addMethod('gotoURL', function (request, sender, cb) {
+ Tools.gotoURL({
+ api: vAPI,
+ details: request,
+ });
+ return undefined;
+ });
+
+ addMethod('mustBlock', function (request, sender, cb) {
+ return ηm.mustBlock(request.scope,
+ request.hostname,
+ request.type);
+ });
+
+ addMethod('readRawSettings', function (request, sender, cb) {
+ return ηm.stringFromRawSettings();
+ });
+
+ addMethod('writeRawSettings', function (request, sender, cb) {
+ ηm.rawSettingsFromString(request.content);
+ return undefined;
+ });
+
+ addMethod('reloadHostsFiles', function (request, sender, cb) {
+ ηm.reloadHostsFiles();
+ return undefined;
+ });
+
+ addMethod('setMatrixSwitch', function (request, sender, cb) {
+ ηm.tMatrix.setSwitch(request.switchName, '*', request.state);
+ if (ηm.pMatrix.setSwitch(request.swtichName, '*', request.state)) {
+ ηm.saveMatrix();
+ }
+ return undefined;
+ });
+
+ addMethod('userSettings', function (request, sender, cb) {
+ if (request.hasOwnProperty('value') === false) {
+ request.value = undefined;
+ }
+ return ηm.changeUserSettings(request.name, request.value);
+ });
+
+ vAPI.messaging.setup(dispatchMethod);
+
+ // popup.js begins here
+ addMethod('matrixSnapshot', function (request, sender, cb) {
+ let snapShot = function (store, details) {
+ let user = ηm.userSettings;
+ let indices = ηm.Matrix.columnHeaderIndices;
+
+ let r = {
+ appVersion: vAPI.app.version,
+ blockedCount: store.requestStats.blocked.all,
+ collapseAllDomains: user.popupCollapseAllDomains,
+ collapseBlacklistedDomains: user.popupCollapseBlacklistedDomains,
+ diff: [],
+ domain: store.pageDomain,
+ has3pReferrer: store.has3pReferrer,
+ hasMixedContent: store.hasMixedContent,
+ hasNoscriptTags: store.hasNoscriptTags,
+ hasWebWorkers: store.hasWebWorkers,
+ headerIndices: Array.from(indices),
+ hostname: store.pageHostname,
+ mtxContentModified: (store.mtxContentModifiedTime
+ !== details.mtxContentModifiedTime),
+ mtxCountModified: (store.mtxCountModifiedTime
+ !== details.mtxCountModifiedTime),
+ mtxContentModifiedTime: store.mtxContentModifiedTime,
+ mtxCountModifiedTime: store.mtxCountModifiedTime,
+ pMatrixModified: (ηm.pMatrix.modifiedTime
+ !== details.pMatrixModifiedTime),
+ pMatrixModifiedTime: ηm.pMatrix.modifiedTime,
+ pSwitches: {},
+ rows: {},
+ rowCount: 0,
+ scope: '*',
+ tabId: store.tabId,
+ tMatrixModified: (ηm.tMatrix.modifiedTime
+ !== details.tMatrixModifiedTime),
+ tMatrixModifiedTime: ηm.tMatrix.modifiedTime,
+ tSwitches: {},
+ url: store.pageUrl,
+ userSettings: {
+ colorBlindFriendly: user.colorBlindFriendly,
+ displayTextSize: user.displayTextSize,
+ popupScopeLevel: user.popupScopeLevel,
+ },
+ };
+
+ if (typeof details.scope === 'string') {
+ r.scope = details.scope;
+ } else if (user.popupScopeLevel === 'site') {
+ r.scope = r.hostname;
+ } else if (user.popupScopeLevel === 'domain') {
+ r.scope = r.domain;
+ }
+
+ for (let s of ηm.Matrix.switchNames) {
+ r.tSwitches[s] = ηm.tMatrix.evaluateSwitchZ(s, r.scope);
+ r.pSwitches[s] = ηm.pMatrix.evaluateSwitchZ(s, r.scope);
+ }
+
+ r.rows['*'] = new RowSnapshot(ηm, r.scope, '*', '*');
+ r.rows['1st-party'] = new RowSnapshot(ηm, r.scope,
+ '1st-party', '1st-party');
+ r.rowCount += 1;
+
+ let any = indices.get('*');
+ for (let e of store.hostnameTypeCells) {
+ let pos = e[0].indexOf(' ');
+ let reqhn = e[0].slice(0, pos);
+ let reqt = e[0].slice(pos+1);
+
+ // Hostname can be empty in some cases
+ // (reported from uMatrix)
+ if (reqhn === '') {
+ reqhn = store.pageHostname;
+ }
+
+ let reqd = UriTools.domainFromHostname(reqhn) || reqhn;
+
+ let desthn = reqhn;
+ while (true) {
+ if (r.rows.hasOwnProperty(desthn) !== false) {
+ break;
+ }
+
+ r.rows[desthn] = new RowSnapshot(ηm,
+ r.scope,
+ desthn,
+ reqd);
+ r.rowCount += 1;
+
+ if (desthn === reqd) {
+ break;
+ }
+
+ pos = desthn.indexOf('.');
+ if (pos === -1) {
+ break;
+ }
+
+ desthn = desthn.slice(pos + 1);
+ }
+
+ let count = e[1].size;
+ let tindex = indices.get(reqt);
+
+ let row = r.rows[reqhn];
+ row.counts[tindex] += count;
+ row.counts[any] += count;
+
+ row = r.rows[reqd];
+ row.totals[tindex] += count;
+ row.totals[any] += count;
+
+ row = r.rows['*'];
+ row.totals[tindex] += count;
+ row.totals[any] += count;
+ }
+
+ r.diff = ηm.tMatrix.diff(ηm.pMatrix,
+ r.hostname,
+ Object.keys(r.rows));
+
+ return r;
+ };
+
+ let snapFromId = function (details, cb) {
+ let snapIf = function (id, details) {
+ let store = ηm.pageStoreFromTabId(id);
+ if (store === null) {
+ cb('ENOTFOUND');
+ return;
+ }
+
+ let tmat = ηm.tMatrix;
+ let pmat = ηm.pMatrix;
+ let mtx = details.mtxContentModifiedTime;
+
+ if (tmat.modifiedTime === details.tMatrixModifiedTime
+ && pmat.modifiedTime === details.pMatrixModifiedTime
+ && store.mtxContentModifiedTime === mtx
+ && store.mtxCountModifiedTime === mtx) {
+ cb('ENOCHANGE');
+ return;
+ }
+
+ cb(snapShot(store, details));
+ };
+
+ if (details.tabId) {
+ snapIf(details.tabId, details);
+ return;
+ }
+
+ let onReady = function (tab) {
+ if (tab instanceof Object === false) {
+ cb('ENOTFOUND');
+ return;
+ }
+
+ let id =
+ tab.url.lastIndexOf(vAPI.getURL('dashboard.html'), 0) !== 0
+ ? tab.id
+ : vAPI.noTabId;
+
+ snapIf(id, details);
+ };
+
+ vAPI.tabs.get(null, onReady);
+ };
+
+ snapFromId(request, cb);
+ return undefined;
+ }, true);
+
+ addMethod('toggleMatrixSwitch', function (request, sender, cb) {
+ let sz = ηm.tMatrix.evaluateSwitchZ(request.switchName,
+ request.srcHostname);
+ ηm.tMatrix.setSwitchZ(request.switchName,
+ request.scrHostname,
+ sz === false);
+ return undefined;
+ });
+
+ addMethod('blacklistMatrixCell', function (request, sender, cb) {
+ ηm.tMatrix.blacklistCell(request.srcHostname,
+ request.desHostname,
+ request.type);
+ return undefined;
+ });
+
+ addMethod('whitelistMatrixCell', function (request, sender, cb) {
+ ηm.tMatrix.whitelistCell(request.srcHostname,
+ request.desHostname,
+ request.type);
+ return undefined;
+ });
+
+ addMethod('graylistMatrixCell', function (request, sender, cb) {
+ ηm.tMatrix.graylistCell(request.srcHostname,
+ request.desHostname,
+ request.type);
+ return undefined;
+ });
+
+ addMethod('applyDiffToPermanentMatrix', function (request, sender, cb) {
+ if (ηm.pMatrix.applyDiff(request.diff, ηm.tMatrix)) {
+ ηm.saveMatrix();
+ }
+ return undefined;
+ });
+
+ addMethod('applyDiffToTemporaryMatrix', function (request, sender, cb) {
+ ηm.tMatrix.applyDiff(request.diff, ηm.pMatrix);
+ return undefined;
+ });
+
+ addMethod('revertTemporaryMatrix', function (request, sender, cb) {
+ ηm.tMatrix.assign(ηm.pMatrix);
+ return undefined;
+ });
+
+ vAPI.messaging.listen('popup.js', dispatchMethod);
+
+ // Content scripts handling begins here
+ let placeholders = undefined;
+ let phReadTime = 0;
+
+ addMethod('contentScriptHasLocalStorage', function (request, sender, cb) {
+ let contentScriptLocalStorageHandler = function (id, originURL) {
+ let tabContext = ηm.tabContextManager.lookup(id);
+ if (tabContext === null) {
+ return;
+ }
+
+ let blocked = ηm.mustBlock(tabContext.rootHostname,
+ UriTools.hostnameFromURI(originURL),
+ 'cookie');
+
+ let store = ηm.pageStoreFromTabId(id);
+ if (store !== null) {
+ let requestURL = originURL + '/{localStorage}';
+ store.recordRequest('cookie', requestURL, blocked);
+ ηm.logger.writeOne(id, 'net', tabContext.rootHostname,
+ requestURL, 'cookie', blocked);
+ }
+
+ let removeStorage = blocked && ηm.userSettings.deleteLocalStorage;
+ if (removeStorage) {
+ ηm.localStorageRemovedCounter++;
+ }
+
+ return removeStorage;
+ };
+
+ let tabId = sender && sender.tab ? sender.tab.id || 0 : 0;
+ return contentScriptLocalStorageHandler(tabId, request.originURL);
+ });
+
+ addMethod('lookupBlockedCollapsibles', function (request, sender, cb) {
+ let lookupBlockedCollapsibles = function (id, requests) {
+ if (phReadTime < ηm.rawSettingsWriteTime) {
+ placeholders = undefined;
+ }
+
+ if (placeholders === undefined) {
+ placeholders = {
+ frame: ηm.rawSettings.framePlaceholder,
+ image: ηm.rawSettings.imagePlaceholder,
+ };
+
+ if (placeholders.frame) {
+ let doc = ηm.rawSettings.framePlaceholderDocument;
+ let bg = ηm.rawSettings.framePlaceholderBackground;
+
+ placeholders.frameDocument =
+ doc.replace('{{bg}}',
+ bg !== 'default'
+ ? bg
+ : η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;
+ }
+
+ phReadTime = Date.now();
+ }
+
+ let response = {
+ blockedResources: [],
+ hash: requests.hash,
+ id: requests.id,
+ placeholders: placeholders,
+ };
+
+ let context = ηm.tabContextManager.lookup(id);
+ if (context === null) {
+ return response;
+ }
+
+ let store = ηm.pageStoreFromTabId(id);
+ if (store !== null) {
+ store.lookupBlockedCollapsibles(requests, response);
+ }
+
+ return response;
+ };
+
+ let tabId = sender && sender.tab ? sender.tab.id || 0 : 0;
+ return lookupBlockedCollapsibles(tabId, request);
+ });
+
+ addMethod('mustRenderNoscriptTags?', function (request, sender, cb) {
+ let tabId = sender && sender.tab ? sender.tab.id || 0 : 0;
+ let tabContext = ηm.tabContextManager.lookup(tabId);
+ let rootHostname = tabContext && tabContext.rootHostname;
+ let pageStore = ηm.pageStoreFromTabId(tabId);
+
+ if (tabContext === null) {
+ return undefined;
+ }
+
+ let response =
+ ηm.tMatrix.mustBlock(rootHostname, rootHostname, 'script')
+ && ηm.tMatrix.evaluateSwitchZ('noscript-spoof', rootHostname);
- let pageStore = ηm.pageStoreFromTabId(tabId);
if (pageStore !== null) {
- let requestURL = originURL + '/{localStorage}';
- pageStore.recordRequest('cookie', requestURL, blocked);
- ηm.logger.writeOne(tabId, 'net', tabContext.rootHostname,
- requestURL, 'cookie', blocked);
+ pageStore.hasNoscriptTags = true;
}
- let removeStorage = blocked && ηm.userSettings.deleteLocalStorage;
- if (removeStorage) {
- ηm.localStorageRemovedCounter++;
+ // 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);
+
+ return response;
+ });
+
+ addMethod('securityPolicyViolation', function (request, sender, cb) {
+ let foundInlineCode = function (id, store, details, type) {
+ if (store === null) {
+ return;
+ }
+
+ let pageHostname = store.pageHostname;
+ let uri = UriTools.set(details.documentURI);
+ let frameURL = UriTools.normalizedURI();
+
+ let blocked = details.blocked;
+ if (blocked === undefined) {
+ blocked = ηm.mustBlock(pageHostname, uri.hostname, type);
+ }
+
+ let mapTo = {
+ css: 'style',
+ script: 'script',
+ };
+
+ // https://github.com/gorhill/httpswitchboard/issues/333
+ // Look-up here whether inline scripting is blocked for the frame.
+ let url = frameURL + '{inline_' + mapTo[type] + '}';
+ store.recordRequest(type, url, blocked);
+ ηm.logger.writeOne(id, 'net', pageHostname, url, type, blocked);
+ };
+
+ let tabId = sender && sender.tab ? sender.tab.id || 0 : 0;
+ let tabContext = ηm.tabContextManager.lookup(tabId);
+ let rootHostname = tabContext && tabContext.rootHostname;
+ let pageStore = ηm.pageStoreFromTabId(tabId);
+
+ if (request.directive === 'worker-src') {
+ let url = UriTools.hostnameFromURI(request.blockedURI) !== ''
+ ? request.blockedURI
+ : request.documentURI;
+
+ if (pageStore !== null) {
+ pageStore.hasWebWorkers = true;
+ pageStore.recordRequest('script', url, request.blocked);
+ }
+
+ 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');
}
- return removeStorage;
- };
+ return undefined;
+ });
- // Evaluate many URLs against the matrix.
- let lookupBlockedCollapsibles = function (tabId, requests) {
- if (placeholdersReadTime < ηm.rawSettingsWriteTime) {
- placeholders = undefined;
- }
+ addMethod('shutdown?', function (request, sender, cb) {
+ let tabId = sender && sender.tab ? sender.tab.id || 0 : 0;
+ let tabContext = ηm.tabContextManager.lookup(tabId);
+ let rootHostname = tabContext && tabContext.rootHostname;
- 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();
+ let response = undefined;
+ if (tabContext !== null) {
+ response =
+ ηm.tMatrix.evaluateSwitchZ('matrixb-off', rootHostname);
}
-
- let response = {
- blockedResources: [],
- hash: requests.hash,
- id: requests.id,
- placeholders: placeholders,
+ return response;
+ });
+
+ vAPI.messaging.listen('contentscript.js', dispatchMethod);
+
+ // cloud-ui.js begins here
+ addMethod('cloudGetOptions', function (request, sender, cb) {
+ vAPI.cloud.getOptions(function (options) {
+ options.enabled = ηm.userSettings.cloudStorageEnabled === true;
+ cb(options);
+ });
+ return undefined;
+ }, true);
+
+ addMethod('cloudSetOptions', function (request, sender, cb) {
+ vAPI.cloud.setOptions(request.options, cb);
+ return undefined;
+ }, true);
+
+ addMethod('cloudPull', function (request, sender, cb) {
+ return vAPI.cloud.pull(request.datakey, cb);
+ }, true);
+
+ addMethod('cloudPush', function (request, sender, cb) {
+ return vAPI.cloud.push(request.datakey, request.data, cb);
+ }, true);
+
+ vAPI.messaging.listen('cloud-ui.js', dispatchMethod);
+
+ // user-rules.js begins here
+ addMethod('getUserRules', function (request, sender, cb) {
+ return {
+ temporaryRules: ηm.tMatrix.toString(),
+ permanentRules: ηm.pMatrix.toString(),
};
+ });
- let tabContext = ηm.tabContextManager.lookup(tabId);
- if (tabContext === null) {
- return response;
- }
-
- let pageStore = ηm.pageStoreFromTabId(tabId);
- if (pageStore !== null) {
- pageStore.lookupBlockedCollapsibles(requests, response);
- }
-
- return response;
- };
-
- let placeholders;
- let placeholdersReadTime = 0;
-
- let onMessage = function (request, sender, callback) {
- // Async
- switch (request.what) {
- default:
- break;
- }
-
- let tabId = sender && sender.tab ? sender.tab.id || 0 : 0;
- let tabContext = ηm.tabContextManager.lookup(tabId);
- let rootHostname = tabContext && tabContext.rootHostname;
- let pageStore = ηm.pageStoreFromTabId(tabId);
-
- // Sync
- let 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') {
- let url = UriTools.hostnameFromURI(request.blockedURI) !== '' ?
- request.blockedURI :
- request.documentURI;
-
- if (pageStore !== null) {
- pageStore.hasWebWorkers = true;
- pageStore.recordRequest('script', url, request.blocked);
- }
-
- 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('matrixb-off', rootHostname);
- }
- break;
- default:
- return vAPI.messaging.UNHANDLED;
- }
-
- callback(response);
- };
-
- vAPI.messaging.listen('contentscript.js', onMessage);
-})();
-
-// cloud-ui.js
-(function () {
-
- let ηm = ηMatrix;
-
- let 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
- let 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 () {
-
- let ηm = ηMatrix;
-
- let onMessage = function (request, sender, callback) {
- // Async
- switch (request.what) {
- default:
- break;
+ addMethod('setUserRules', function (request, sender, cb) {
+ if (typeof request.temporaryRules === 'string') {
+ ηm.tMatrix.fromString(request.temporaryRules);
}
-
- // Sync
- let 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 () {
-
- let ηm = ηMatrix;
-
- let prepEntries = function (entries) {
- let ηmuri = UriTools;
- let entry;
- for (let 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);
- }
+ if (typeof request.permanentRules === 'string') {
+ ηm.pMatrix.fromString(request.permanentRules);
+ ηm.saveMatrix();
}
- };
-
- let getLists = function (callback) {
- let r = {
- autoUpdate: ηm.userSettings.autoUpdate,
- available: null,
- cache: null,
- current: ηm.liveHostsFiles,
- blockedHostnameCount: ηm.ubiquitousBlacklist.count,
- };
-
- let onMetadataReady = function (entries) {
- r.cache = entries;
- prepEntries(r.cache);
- callback(r);
- };
-
- let onAvailableHostsFilesReady = function (lists) {
- r.available = lists;
- prepEntries(r.available);
- ηm.assets.metadata(onMetadataReady);
+ return {
+ temporaryRules: ηm.tMatrix.toString(),
+ permanentRules: ηm.pMatrix.toString(),
};
-
- ηm.getAvailableHostsFiles(onAvailableHostsFilesReady);
- };
-
- let onMessage = function (request, sender, callback) {
- let ηm = ηMatrix;
-
- // Async
- switch (request.what) {
- case 'getLists':
- return getLists(callback);
- default:
- break;
- }
-
- // Sync
- let 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;
+ });
+
+ vAPI.messaging.listen('user-rules.js', dispatchMethod);
+
+ // hosts-files.js begins here
+ addMethod('getLists', function (request, sender, cb) {
+ let prepare = function (entries) {
+ for (let e in entries) {
+ if (entries.hasOwnProperty(e) === false) {
+ continue;
+ }
+
+ let entry = entries[e];
+
+ if (typeof entry.homeURL === 'string') {
+ let homehost = UriTools.hostnameFromURI(entry.homeURL);
+ entry.homeHostname = homehost
+ entry.homeDomain = UriTools.domainFromHostname(homehost);
+ }
+ }
+ };
+
+ let getLists = function (cb) {
+ let r = {
+ autoUpdate: ηm.userSettings.autoUpdate,
+ available: null,
+ cache: null,
+ current: ηm.liveHostsFiles,
+ blockedHostnameCount: ηm.ubiquitousBlacklist.count,
+ };
+
+ let onMetadataReady = function (entries) {
+ r.cache = entries;
+ prepare(r.cache);
+ cb(r);
+ };
+
+ let onHostsReady = function (lists) {
+ r.available = lists;
+ prepare(r.available);
+ ηm.assets.metadata(onMetadataReady);
+ };
+
+ ηm.getAvailableHostsFiles(onHostsReady);
+ };
+
+ return getLists(cb);
+ }, true);
+
+ addMethod('purgeCache', function (request, sender, cb) {
+ ηm.assets.purge(request.assetKey);
+ ηm.assets.remove('compiled/' + request.assetKey);
+ return undefined;
+ });
+
+ addMethod('purgeAllCaches', function (request, sender, cb) {
+ if (request.hard) {
+ ηm.assets.remove(/./);
+ } else {
+ ηm.assets.purge(/./, 'public_suffix_list.dat');
}
-
- callback(response);
- };
-
- vAPI.messaging.listen('hosts-files.js', onMessage);
-})();
-
-// about.js
-(function () {
-
- let ηm = ηMatrix;
-
- let restoreUserData = function (userData) {
- let countdown = 4;
- let onCountdown = function () {
- countdown -= 1;
- if (countdown === 0) {
- vAPI.app.restart();
- }
+ return undefined;
+ });
+
+ vAPI.messaging.listen('hosts-files.js', dispatchMethod);
+
+ // about.js begins here
+ addMethod('getAllUserData', function (request, sender, cb) {
+ return {
+ app: vAPI.app.name,
+ version: vAPI.app.version,
+ when: Date.now(),
+ settings: ηm.userSettings,
+ rules: ηm.pMatrix.toString(),
+ hostsFiles: ηm.liveHostsFiles,
+ rawSettings: ηm.rawSettings,
};
+ });
- let 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);
- }
+ addMethod('getSomeStats', function (request, sender, cb) {
+ return {
+ version: vAPI.app.version,
+ storageUsed: ηm.storageUsed
};
-
- // If we are going to restore all, might as well wipe out
- // clean local storage
- ηm.XAL.keyvalRemoveAll(onAllRemoved);
- };
-
- let resetUserData = function () {
- let onAllRemoved = function () {
+ });
+
+ addMethod('restoreAllUserData', function (request, sender, cb) {
+ let restoreData = function (data) {
+ let countdown = 4;
+ let onCountdown = function () {
+ countdown -= 1;
+ if (countdown === 0) {
+ vAPI.app.restart();
+ }
+ };
+
+ let 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);
+ };
+
+ restoreUserData(request.userData);
+ return undefined;
+ });
+
+ addMethod('resetAllUserData', function (request, sender, cb) {
+ let onAllRemoved = function () {
vAPI.app.restart();
- };
- ηm.XAL.keyvalRemoveAll(onAllRemoved);
- };
+ };
- let onMessage = function (request, sender, callback) {
- // Async
- switch (request.what) {
- default:
- break;
- }
+ ηm.XAL.keyvalRemoveAll(onAllRemoved);
+ return undefined;
+ });
- // Sync
- let 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;
- }
+ vAPI.messaging.listen('about.js', dispatchMethod);
- callback(response);
- };
+ // logger-ui.js begins here
+ let loggerURL = vAPI.getURL('logger-ui.html');
- vAPI.messaging.listen('about.js', onMessage);
-})();
+ addMethod('readMany', function (request, sender, cb) {
+ if (ηm.logger.ownerId !== undefined
+ && request.ownerId !== ηm.logger.ownerId) {
+ return {
+ unavailable: true,
+ };
+ }
-// logger-ui.js
-(function () {
+ let tabIds = {};
+ for (let id in ηm.pageStores) {
+ let store = ηm.pageStoreFromTabId(tabId);
- let ηm = ηMatrix;
- let loggerURL = vAPI.getURL('logger-ui.html');
+ if (store === null) {
+ continue;
+ }
+ if (store.rawUrl.startsWith(loggerURL)) {
+ continue;
+ }
- let onMessage = function (request, sender, callback) {
- // Async
- switch (request.what) {
- default:
- break;
+ tabIds[id] = store.title || store.rawUrl;
}
- // Sync
- let response;
- switch (request.what) {
- case 'readMany':
- if (ηm.logger.ownerId !== undefined
- && request.ownerId !== ηm.logger.ownerId) {
- response = {
- unavailable: true,
- };
- break;
- }
- let tabIds = {};
- for (let tabId in ηm.pageStores) {
- let 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;
- }
+ return {
+ colorBlind: false,
+ entries: ηm.logger.readAll(request.ownerId),
+ maxLoggedRequests: ηm.userSettings.maxLoggedRequests,
+ noTabId: vAPI.noTabId,
+ tabIds: tabIds,
+ tabIdsToken: ηm.pageStoresToken,
+ };
+ });
- callback(response);
- };
+ addMethod('releaseView', function (request, sender, cb) {
+ if (request.ownerId === ηm.logger.ownerId) {
+ ηm.logger.ownerId = undefined;
+ }
+ return undefined;
+ });
- vAPI.messaging.listen('logger-ui.js', onMessage);
+ vAPI.messaging.listen('logger-ui.js', dispatchMethod);
})();