uBlock/src/js/messaging.js

1398 lines
39 KiB
JavaScript
Raw Normal View History

2014-06-24 00:42:43 +02:00
/*******************************************************************************
2015-05-19 19:59:53 +02:00
uBlock - a browser extension to block requests.
Copyright (C) 2014-2015 Raymond Hill
2014-06-24 00:42:43 +02:00
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/}.
Home: https://github.com/gorhill/uBlock
*/
2015-03-09 17:57:52 +01:00
/* global µBlock, vAPI */
/******************************************************************************/
/******************************************************************************/
// Default handler
(function() {
2014-12-17 14:04:21 +01:00
'use strict';
/******************************************************************************/
var µb = µBlock;
/******************************************************************************/
var getDomainNames = function(targets) {
var out = [];
var µburi = µb.URI;
var target, domain;
for ( var i = 0; i < targets.length; i++ ) {
target = targets[i];
if ( target.indexOf('/') !== -1 ) {
domain = µburi.domainFromURI(target) || '';
} else {
domain = µburi.domainFromHostname(target) || target;
}
out.push(domain);
}
return out;
};
/******************************************************************************/
var onMessage = function(request, sender, callback) {
// Async
switch ( request.what ) {
case 'getAssetContent':
// https://github.com/chrisaljoudi/uBlock/issues/417
µb.assets.get(request.url, callback);
return;
case 'reloadAllFilters':
µb.reloadAllFilters(callback);
return;
2015-03-11 04:46:18 +01:00
default:
break;
}
var tabId = sender && sender.tab ? sender.tab.id : 0;
// Sync
var response;
switch ( request.what ) {
case 'contextMenuEvent':
µb.contextMenuClientX = request.clientX;
µb.contextMenuClientY = request.clientY;
break;
case 'cosmeticFiltersInjected':
µb.cosmeticFilteringEngine.addToSelectorCache(request);
/* falls through */
case 'cosmeticFiltersActivated':
// Net-based cosmetic filters are of no interest for logging purpose.
2015-05-19 19:59:53 +02:00
if ( µb.logger.isEnabled() && request.type !== 'net' ) {
µb.logCosmeticFilters(tabId);
}
break;
2015-03-11 04:46:18 +01:00
case 'createUserFilter':
µb.appendUserFilters(request.filters);
break;
case 'forceUpdateAssets':
µb.assetUpdater.force();
break;
2014-12-01 17:25:33 +01:00
case 'getAppData':
response = {name: vAPI.app.name, version: vAPI.app.version};
break;
case 'getDomainNames':
response = getDomainNames(request.targets);
break;
case 'getUserSettings':
response = µb.userSettings;
break;
case 'launchElementPicker':
// Launched from some auxiliary pages, clear context menu coords.
µb.contextMenuClientX = µb.contextMenuClientY = -1;
µb.elementPickerExec(request.tabId, request.targetURL);
break;
case 'gotoURL':
vAPI.tabs.open(request.details);
break;
case 'scriptletGotoImageURL':
µb.scriptletGotoImageURL(request);
break;
case 'reloadTab':
if ( vAPI.isBehindTheSceneTabId(request.tabId) === false ) {
vAPI.tabs.reload(request.tabId);
if ( request.select && vAPI.tabs.select ) {
vAPI.tabs.select(request.tabId);
}
}
break;
case 'selectFilterLists':
µb.selectFilterLists(request.switches);
break;
2015-03-11 04:46:18 +01:00
case 'toggleHostnameSwitch':
µb.toggleHostnameSwitch(request);
break;
2015-03-27 18:00:55 +01:00
case 'userSettings':
response = µb.changeUserSettings(request.name, request.value);
break;
default:
return vAPI.messaging.UNHANDLED;
}
callback(response);
};
vAPI.messaging.setup(onMessage);
/******************************************************************************/
})();
2014-09-14 22:20:40 +02:00
/******************************************************************************/
2014-06-24 00:42:43 +02:00
/******************************************************************************/
2014-09-28 18:05:46 +02:00
// popup.js
2014-06-24 00:42:43 +02:00
(function() {
2014-12-17 14:04:21 +01:00
'use strict';
2014-09-28 18:05:46 +02:00
/******************************************************************************/
var µb = µBlock;
2014-06-24 00:42:43 +02:00
/******************************************************************************/
2014-12-30 22:36:29 +01:00
var getHostnameDict = function(hostnameToCountMap) {
2015-02-17 03:15:09 +01:00
var r = {}, de;
2015-01-08 16:37:19 +01:00
var domainFromHostname = µb.URI.domainFromHostname;
2015-02-17 03:15:09 +01:00
var domain, counts, blockCount, allowCount;
2014-12-30 22:36:29 +01:00
for ( var hostname in hostnameToCountMap ) {
if ( hostnameToCountMap.hasOwnProperty(hostname) === false ) {
continue;
}
if ( r.hasOwnProperty(hostname) ) {
continue;
}
2015-01-11 15:47:14 +01:00
domain = domainFromHostname(hostname) || hostname;
2014-12-30 22:36:29 +01:00
counts = hostnameToCountMap[domain] || 0;
2015-02-17 03:15:09 +01:00
blockCount = counts & 0xFFFF;
allowCount = counts >>> 16 & 0xFFFF;
if ( r.hasOwnProperty(domain) === false ) {
de = r[domain] = {
domain: domain,
blockCount: blockCount,
allowCount: allowCount,
totalBlockCount: 0,
totalAllowCount: 0
};
} else {
de = r[domain];
}
counts = hostnameToCountMap[hostname] || 0;
blockCount = counts & 0xFFFF;
allowCount = counts >>> 16 & 0xFFFF;
de.totalBlockCount += blockCount;
de.totalAllowCount += allowCount;
2014-12-30 22:36:29 +01:00
if ( hostname === domain ) {
continue;
}
r[hostname] = {
domain: domain,
2015-02-17 03:15:09 +01:00
blockCount: blockCount,
allowCount: allowCount
2014-12-30 22:36:29 +01:00
};
}
return r;
};
/******************************************************************************/
var getFirewallRules = function(srcHostname, desHostnames) {
var r = {};
2015-05-21 20:15:17 +02:00
var df = µb.sessionFirewall;
r['/ * *'] = df.evaluateCellZY('*', '*', '*').toFilterString();
r['/ * image'] = df.evaluateCellZY('*', '*', 'image').toFilterString();
r['/ * 3p'] = df.evaluateCellZY('*', '*', '3p').toFilterString();
r['/ * inline-script'] = df.evaluateCellZY('*', '*', 'inline-script').toFilterString();
r['/ * 1p-script'] = df.evaluateCellZY('*', '*', '1p-script').toFilterString();
r['/ * 3p-script'] = df.evaluateCellZY('*', '*', '3p-script').toFilterString();
r['/ * 3p-frame'] = df.evaluateCellZY('*', '*', '3p-frame').toFilterString();
2014-12-30 22:36:29 +01:00
if ( typeof srcHostname !== 'string' ) {
return r;
}
2015-05-21 20:15:17 +02:00
r['. * *'] = df.evaluateCellZY(srcHostname, '*', '*').toFilterString();
r['. * image'] = df.evaluateCellZY(srcHostname, '*', 'image').toFilterString();
r['. * 3p'] = df.evaluateCellZY(srcHostname, '*', '3p').toFilterString();
r['. * inline-script'] = df.evaluateCellZY(srcHostname, '*', 'inline-script').toFilterString();
r['. * 1p-script'] = df.evaluateCellZY(srcHostname, '*', '1p-script').toFilterString();
r['. * 3p-script'] = df.evaluateCellZY(srcHostname, '*', '3p-script').toFilterString();
r['. * 3p-frame'] = df.evaluateCellZY(srcHostname, '*', '3p-frame').toFilterString();
2014-12-30 22:36:29 +01:00
for ( var desHostname in desHostnames ) {
if ( desHostnames.hasOwnProperty(desHostname) ) {
2015-05-21 20:15:17 +02:00
r['/ ' + desHostname + ' *'] = df.evaluateCellZY('*', desHostname, '*').toFilterString();
r['. ' + desHostname + ' *'] = df.evaluateCellZY(srcHostname, desHostname, '*').toFilterString();
2014-12-30 22:36:29 +01:00
}
}
return r;
2014-10-06 20:02:44 +02:00
};
/******************************************************************************/
2015-05-18 16:39:20 +02:00
var popupDataFromTabId = function(tabId, tabTitle) {
2015-04-09 00:46:08 +02:00
var tabContext = µb.tabContextManager.lookup(tabId);
2014-06-24 00:42:43 +02:00
var r = {
advancedUserEnabled: µb.userSettings.advancedUserEnabled,
2014-12-01 17:25:33 +01:00
appName: vAPI.app.name,
appVersion: vAPI.app.version,
colorBlindFriendly: µb.userSettings.colorBlindFriendly,
cosmeticFilteringSwitch: false,
dfEnabled: µb.userSettings.dynamicFilteringEnabled,
2015-02-17 03:15:09 +01:00
firewallPaneMinimized: µb.userSettings.firewallPaneMinimized,
2014-06-24 00:42:43 +02:00
globalAllowedRequestCount: µb.localSettings.allowedRequestCount,
globalBlockedRequestCount: µb.localSettings.blockedRequestCount,
netFilteringSwitch: false,
2015-04-09 00:46:08 +02:00
rawURL: tabContext.rawURL,
pageURL: tabContext.normalURL,
pageHostname: tabContext.rootHostname,
pageDomain: tabContext.rootDomain,
2014-06-24 00:42:43 +02:00
pageAllowedRequestCount: 0,
pageBlockedRequestCount: 0,
2015-03-02 19:49:34 +01:00
tabId: tabId,
tabTitle: tabTitle
2014-06-24 00:42:43 +02:00
};
2015-04-09 00:46:08 +02:00
2014-12-30 22:36:29 +01:00
var pageStore = µb.pageStoreFromTabId(tabId);
2014-06-24 00:42:43 +02:00
if ( pageStore ) {
r.pageBlockedRequestCount = pageStore.perLoadBlockedRequestCount;
r.pageAllowedRequestCount = pageStore.perLoadAllowedRequestCount;
2014-08-02 17:40:27 +02:00
r.netFilteringSwitch = pageStore.getNetFilteringSwitch();
2014-12-30 22:36:29 +01:00
r.hostnameDict = getHostnameDict(pageStore.hostnameToCountMap);
2015-01-10 17:23:28 +01:00
r.contentLastModified = pageStore.contentLastModified;
2015-04-09 00:46:08 +02:00
r.firewallRules = getFirewallRules(tabContext.rootHostname, r.hostnameDict);
r.canElementPicker = tabContext.rootHostname.indexOf('.') !== -1;
r.noPopups = µb.hnSwitches.evaluateZ('no-popups', tabContext.rootHostname);
r.noStrictBlocking = µb.hnSwitches.evaluateZ('no-strict-blocking', tabContext.rootHostname);
r.noCosmeticFiltering = µb.hnSwitches.evaluateZ('no-cosmetic-filtering', tabContext.rootHostname);
r.noRemoteFonts = µb.hnSwitches.evaluateZ('no-remote-fonts', tabContext.rootHostname);
r.remoteFontCount = pageStore.remoteFontCount;
2014-12-30 22:36:29 +01:00
} else {
r.hostnameDict = {};
r.firewallRules = getFirewallRules();
}
2015-04-09 00:46:08 +02:00
r.matrixIsDirty = !µb.sessionFirewall.hasSameRules(
µb.permanentFirewall,
tabContext.rootHostname,
r.hostnameDict
);
2014-06-24 00:42:43 +02:00
return r;
};
/******************************************************************************/
2015-05-18 16:39:20 +02:00
var popupDataFromRequest = function(request, callback) {
if ( request.tabId ) {
callback(popupDataFromTabId(request.tabId, ''));
return;
}
2015-01-21 17:13:32 +01:00
2015-05-18 16:39:20 +02:00
// Still no target tab id? Use currently selected tab.
vAPI.tabs.get(null, function(tab) {
var tabId = '';
var tabTitle = '';
if ( tab ) {
tabId = tab.id;
tabTitle = tab.title || '';
}
callback(popupDataFromTabId(tabId, tabTitle));
});
};
/******************************************************************************/
var getPopupDataLazy = function(tabId, callback) {
var r = {
hiddenElementCount: ''
};
var pageStore = µb.pageStoreFromTabId(tabId);
if ( !pageStore ) {
callback(r);
return;
}
µb.surveyCosmeticFilters(tabId, function() {
r.hiddenElementCount = pageStore.hiddenElementCount;
callback(r);
});
};
/******************************************************************************/
2014-06-24 00:42:43 +02:00
var onMessage = function(request, sender, callback) {
// Async
switch ( request.what ) {
2015-04-24 14:36:19 +02:00
case 'getPopupDataLazy':
getPopupDataLazy(request.tabId, callback);
return;
2015-04-24 14:36:19 +02:00
case 'getPopupData':
2015-05-18 16:39:20 +02:00
popupDataFromRequest(request, callback);
2015-04-24 14:36:19 +02:00
return;
2015-04-24 14:36:19 +02:00
default:
break;
2014-06-24 00:42:43 +02:00
}
// Sync
2015-03-09 17:57:52 +01:00
var pageStore;
2014-06-24 00:42:43 +02:00
var response;
switch ( request.what ) {
2015-04-24 14:36:19 +02:00
case 'hasPopupContentChanged':
pageStore = µb.pageStoreFromTabId(request.tabId);
var lastModified = pageStore ? pageStore.contentLastModified : 0;
response = lastModified !== request.contentLastModified;
break;
case 'revertFirewallRules':
µb.sessionFirewall.copyRules(
µb.permanentFirewall,
request.srcHostname,
request.desHostnames
);
2015-05-09 14:25:05 +02:00
// https://github.com/gorhill/uBlock/issues/188
µb.cosmeticFilteringEngine.removeFromSelectorCache(request.srcHostname, 'net');
2015-05-18 16:39:20 +02:00
response = popupDataFromTabId(request.tabId);
2015-04-24 14:36:19 +02:00
break;
case 'saveFirewallRules':
µb.permanentFirewall.copyRules(
µb.sessionFirewall,
request.srcHostname,
request.desHostnames
);
µb.savePermanentFirewallRules();
break;
case 'toggleFirewallRule':
µb.toggleFirewallRule(request);
2015-05-18 16:39:20 +02:00
response = popupDataFromTabId(request.tabId);
2015-04-24 14:36:19 +02:00
break;
case 'toggleNetFiltering':
pageStore = µb.pageStoreFromTabId(request.tabId);
if ( pageStore ) {
pageStore.toggleNetFilteringSwitch(request.url, request.scope, request.state);
µb.updateBadgeAsync(request.tabId);
}
break;
2014-06-24 00:42:43 +02:00
2015-04-24 14:36:19 +02:00
default:
return vAPI.messaging.UNHANDLED;
2014-06-24 00:42:43 +02:00
}
callback(response);
};
vAPI.messaging.listen('popup.js', onMessage);
2014-09-28 18:05:46 +02:00
/******************************************************************************/
2014-06-24 00:42:43 +02:00
})();
2014-09-14 22:20:40 +02:00
/******************************************************************************/
2014-06-24 00:42:43 +02:00
/******************************************************************************/
2014-06-27 23:06:42 +02:00
// contentscript-start.js
2014-06-24 00:42:43 +02:00
(function() {
2014-12-17 14:04:21 +01:00
'use strict';
2014-09-28 18:05:46 +02:00
/******************************************************************************/
2014-08-02 17:40:27 +02:00
var µb = µBlock;
2014-09-28 18:05:46 +02:00
/******************************************************************************/
2014-06-24 00:42:43 +02:00
var onMessage = function(request, sender, callback) {
// Async
switch ( request.what ) {
2015-05-19 19:59:53 +02:00
default:
break;
2014-06-24 00:42:43 +02:00
}
// Sync
var response;
2014-06-24 01:23:36 +02:00
var pageStore;
if ( sender && sender.tab ) {
2014-08-02 17:40:27 +02:00
pageStore = µb.pageStoreFromTabId(sender.tab.id);
2014-06-24 01:23:36 +02:00
}
2014-06-24 00:42:43 +02:00
switch ( request.what ) {
2015-05-19 19:59:53 +02:00
case 'retrieveDomainCosmeticSelectors':
if ( pageStore && pageStore.getSpecificCosmeticFilteringSwitch() ) {
response = µb.cosmeticFilteringEngine.retrieveDomainSelectors(request);
}
break;
2015-05-19 19:59:53 +02:00
default:
return vAPI.messaging.UNHANDLED;
2014-06-27 23:06:42 +02:00
}
callback(response);
};
vAPI.messaging.listen('contentscript-start.js', onMessage);
2014-06-27 23:06:42 +02:00
2014-09-28 18:05:46 +02:00
/******************************************************************************/
2014-06-27 23:06:42 +02:00
})();
2014-09-14 22:20:40 +02:00
/******************************************************************************/
2014-06-27 23:06:42 +02:00
/******************************************************************************/
// contentscript-end.js
(function() {
2014-12-17 14:04:21 +01:00
'use strict';
2014-09-28 18:05:46 +02:00
/******************************************************************************/
2014-08-02 17:40:27 +02:00
var µb = µBlock;
2014-09-14 22:20:40 +02:00
/******************************************************************************/
var tagNameToRequestTypeMap = {
'embed': 'object',
'iframe': 'sub_frame',
'img': 'image',
'object': 'object'
};
/******************************************************************************/
// Evaluate many requests
var filterRequests = function(pageStore, details) {
2015-03-29 18:13:28 +02:00
var requests = details.requests;
if ( µb.userSettings.collapseBlocked === false ) {
return requests;
}
//console.debug('messaging.js/contentscript-end.js: processing %d requests', requests.length);
var µburi = µb.URI;
2015-01-22 19:00:59 +01:00
var isBlockResult = µb.isBlockResult;
// Create evaluation context
2015-04-09 00:46:08 +02:00
var context = pageStore.createContextFromFrameHostname(details.pageHostname);
2015-03-29 18:13:28 +02:00
2015-01-22 19:00:59 +01:00
var request;
2015-03-29 18:13:28 +02:00
var i = requests.length;
2014-09-14 22:20:40 +02:00
while ( i-- ) {
2015-03-29 18:13:28 +02:00
request = requests[i];
context.requestURL = vAPI.punycodeURL(request.url);
context.requestHostname = µburi.hostnameFromURI(request.url);
context.requestType = tagNameToRequestTypeMap[request.tagName];
if ( isBlockResult(pageStore.filterRequest(context)) ) {
request.collapse = true;
2014-09-14 22:20:40 +02:00
}
}
2015-03-29 18:13:28 +02:00
return requests;
2014-09-14 22:20:40 +02:00
};
/******************************************************************************/
var onMessage = function(request, sender, callback) {
2014-06-27 23:06:42 +02:00
// Async
switch ( request.what ) {
default:
break;
2014-06-27 23:06:42 +02:00
}
// Sync
var response;
var pageStore;
if ( sender && sender.tab ) {
2014-08-02 17:40:27 +02:00
pageStore = µb.pageStoreFromTabId(sender.tab.id);
2014-06-27 23:06:42 +02:00
}
switch ( request.what ) {
case 'retrieveGenericCosmeticSelectors':
response = {
shutdown: !pageStore || !pageStore.getNetFilteringSwitch(),
result: null
};
if ( !response.shutdown && pageStore.getGenericCosmeticFilteringSwitch() ) {
response.result = µb.cosmeticFilteringEngine.retrieveGenericSelectors(request);
}
break;
2014-06-27 23:06:42 +02:00
case 'filterRequests':
response = {
shutdown: !pageStore || !pageStore.getNetFilteringSwitch(),
result: null
};
if ( !response.shutdown ) {
response.result = filterRequests(pageStore, request);
}
break;
default:
return vAPI.messaging.UNHANDLED;
}
2014-06-24 00:42:43 +02:00
callback(response);
};
vAPI.messaging.listen('contentscript-end.js', onMessage);
/******************************************************************************/
})();
/******************************************************************************/
/******************************************************************************/
// element-picker.js
(function() {
2014-12-17 14:04:21 +01:00
'use strict';
/******************************************************************************/
2014-09-28 18:05:46 +02:00
var µb = µBlock;
/******************************************************************************/
var onMessage = function(request, sender, callback) {
// Async
switch ( request.what ) {
2015-05-19 19:59:53 +02:00
case 'elementPickerArguments':
var xhr = new XMLHttpRequest();
xhr.open('GET', 'epicker.html', true);
xhr.overrideMimeType('text/html;charset=utf-8');
xhr.responseType = 'text';
xhr.onload = function() {
this.onload = null;
var i18n = {
bidi_dir: document.body.getAttribute('dir'),
create: vAPI.i18n('pickerCreate'),
pick: vAPI.i18n('pickerPick'),
quit: vAPI.i18n('pickerQuit'),
netFilters: vAPI.i18n('pickerNetFilters'),
cosmeticFilters: vAPI.i18n('pickerCosmeticFilters'),
cosmeticFiltersHint: vAPI.i18n('pickerCosmeticFiltersHint')
};
var reStrings = /\{\{(\w+)\}\}/g;
var replacer = function(a0, string) {
return i18n[string];
2014-07-13 02:32:44 +02:00
};
2015-05-19 19:59:53 +02:00
callback({
frameContent: this.responseText.replace(reStrings, replacer),
target: µb.epickerTarget,
2015-05-19 19:59:53 +02:00
clientX: µb.contextMenuClientX,
clientY: µb.contextMenuClientY,
eprom: µb.epickerEprom
});
µb.epickerTarget = '';
2015-05-19 19:59:53 +02:00
µb.contextMenuClientX = -1;
µb.contextMenuClientY = -1;
};
xhr.send();
return;
default:
break;
}
2014-07-13 02:32:44 +02:00
// Sync
var response;
switch ( request.what ) {
2015-05-19 19:59:53 +02:00
case 'elementPickerEprom':
µb.epickerEprom = request;
break;
2015-05-19 19:59:53 +02:00
default:
return vAPI.messaging.UNHANDLED;
2014-07-13 02:32:44 +02:00
}
callback(response);
};
vAPI.messaging.listen('element-picker.js', onMessage);
2014-09-28 18:05:46 +02:00
/******************************************************************************/
2014-06-24 00:42:43 +02:00
})();
2014-09-14 22:20:40 +02:00
/******************************************************************************/
2014-06-24 00:42:43 +02:00
/******************************************************************************/
// 3p-filters.js
(function() {
2014-12-17 14:04:21 +01:00
'use strict';
2014-09-28 18:05:46 +02:00
/******************************************************************************/
var µb = µBlock;
/******************************************************************************/
var prepEntries = function(entries) {
var µburi = µb.URI;
var entry, hn;
for ( var k in entries ) {
if ( entries.hasOwnProperty(k) === false ) {
continue;
}
entry = entries[k];
if ( typeof entry.supportURL === 'string' && entry.supportURL !== '' ) {
entry.supportName = µburi.hostnameFromURI(entry.supportURL);
} else if ( typeof entry.homeURL === 'string' && entry.homeURL !== '' ) {
hn = µburi.hostnameFromURI(entry.homeURL);
entry.supportURL = 'http://' + hn + '/';
entry.supportName = µburi.domainFromHostname(hn);
}
}
};
/******************************************************************************/
2014-07-25 22:12:20 +02:00
var getLists = function(callback) {
2014-07-26 22:10:20 +02:00
var r = {
2015-03-11 04:46:18 +01:00
autoUpdate: µb.userSettings.autoUpdate,
2014-07-26 22:10:20 +02:00
available: null,
2015-03-11 04:46:18 +01:00
cache: null,
2014-07-26 22:10:20 +02:00
cosmetic: µb.userSettings.parseAllABPHideFilters,
2014-09-08 23:46:58 +02:00
cosmeticFilterCount: µb.cosmeticFilteringEngine.getFilterCount(),
2015-03-11 04:46:18 +01:00
current: µb.remoteBlacklists,
manualUpdate: false,
netFilterCount: µb.staticNetFilteringEngine.getFilterCount(),
userFiltersPath: µb.userFiltersPath
2014-07-26 22:10:20 +02:00
};
var onMetadataReady = function(entries) {
2014-07-26 22:10:20 +02:00
r.cache = entries;
2015-03-11 04:46:18 +01:00
r.manualUpdate = µb.assetUpdater.manualUpdate;
r.manualUpdateProgress = µb.assetUpdater.manualUpdateProgress;
prepEntries(r.cache);
2014-09-09 01:45:22 +02:00
callback(r);
2014-07-26 22:10:20 +02:00
};
var onLists = function(lists) {
r.available = lists;
prepEntries(r.available);
2014-09-09 01:45:22 +02:00
µb.assets.metadata(onMetadataReady);
2014-07-25 22:12:20 +02:00
};
2014-07-26 22:10:20 +02:00
µb.getAvailableLists(onLists);
2014-07-25 22:12:20 +02:00
};
/******************************************************************************/
2014-06-24 00:42:43 +02:00
var onMessage = function(request, sender, callback) {
// Async
switch ( request.what ) {
2015-05-19 19:59:53 +02:00
case 'getLists':
return getLists(callback);
2014-07-25 22:12:20 +02:00
2015-05-19 19:59:53 +02:00
case 'purgeAllCaches':
return µb.assets.purgeAll(callback);
2014-06-24 00:42:43 +02:00
2015-05-19 19:59:53 +02:00
default:
break;
2014-06-24 00:42:43 +02:00
}
// Sync
var response;
switch ( request.what ) {
2015-05-19 19:59:53 +02:00
case 'purgeCache':
µb.assets.purge(request.path);
break;
2014-07-26 22:10:20 +02:00
2015-05-19 19:59:53 +02:00
default:
return vAPI.messaging.UNHANDLED;
2014-06-24 00:42:43 +02:00
}
callback(response);
};
vAPI.messaging.listen('3p-filters.js', onMessage);
2014-09-28 18:05:46 +02:00
/******************************************************************************/
2014-06-24 00:42:43 +02:00
})();
2014-09-14 22:20:40 +02:00
/******************************************************************************/
2014-06-24 00:42:43 +02:00
/******************************************************************************/
// 1p-filters.js
(function() {
2014-12-17 14:04:21 +01:00
'use strict';
2014-09-28 18:05:46 +02:00
/******************************************************************************/
2014-06-24 00:42:43 +02:00
2014-09-28 18:05:46 +02:00
var µb = µBlock;
/******************************************************************************/
var onMessage = function(request, sender, callback) {
2014-06-24 00:42:43 +02:00
// Async
switch ( request.what ) {
2015-05-19 19:59:53 +02:00
case 'readUserFilters':
return µb.assets.get(µb.userFiltersPath, callback);
2014-06-24 00:42:43 +02:00
2015-05-19 19:59:53 +02:00
case 'writeUserFilters':
return µb.assets.put(µb.userFiltersPath, request.content, callback);
2014-06-24 00:42:43 +02:00
2015-05-19 19:59:53 +02:00
default:
break;
2014-06-24 00:42:43 +02:00
}
// Sync
var response;
switch ( request.what ) {
2015-05-19 19:59:53 +02:00
default:
return vAPI.messaging.UNHANDLED;
2014-06-24 00:42:43 +02:00
}
callback(response);
};
vAPI.messaging.listen('1p-filters.js', onMessage);
2014-09-28 18:05:46 +02:00
/******************************************************************************/
2014-06-24 00:42:43 +02:00
})();
2014-09-14 22:20:40 +02:00
/******************************************************************************/
2014-06-24 00:42:43 +02:00
/******************************************************************************/
// dyna-rules.js
(function() {
'use strict';
/******************************************************************************/
var µb = µBlock;
/******************************************************************************/
var getRules = function() {
2015-02-11 17:34:51 +01:00
return {
2015-05-21 20:15:17 +02:00
permanentRules: µb.permanentFirewall.toString() + '\n' + µb.permanentURLFiltering.toString(),
sessionRules: µb.sessionFirewall.toString() + '\n' + µb.sessionURLFiltering.toString(),
hnSwitches: µb.hnSwitches.toString()
};
};
2015-05-21 20:15:17 +02:00
// Untangle firewall rules, url rules and switches.
var untangle = function(s) {
var textEnd = s.length;
var lineBeg = 0, lineEnd;
var line;
2015-05-21 20:15:17 +02:00
var firewallRules = [];
var urlRules = [];
var switches = [];
while ( lineBeg < textEnd ) {
lineEnd = s.indexOf('\n', lineBeg);
if ( lineEnd < 0 ) {
lineEnd = s.indexOf('\r', lineBeg);
if ( lineEnd < 0 ) {
lineEnd = textEnd;
}
}
line = s.slice(lineBeg, lineEnd).trim();
lineBeg = lineEnd + 1;
2015-05-21 20:15:17 +02:00
if ( line.indexOf('://') !== -1 ) {
urlRules.push(line);
} else if ( line.indexOf(':') === -1 ) {
firewallRules.push(line);
} else {
switches.push(line);
}
}
return {
2015-05-21 20:15:17 +02:00
firewallRules: firewallRules.join('\n'),
urlRules: urlRules.join('\n'),
switches: switches.join('\n')
2015-02-11 17:34:51 +01:00
};
};
/******************************************************************************/
var onMessage = function(request, sender, callback) {
// Async
switch ( request.what ) {
default:
break;
}
// Sync
var r;
var response;
switch ( request.what ) {
2015-05-21 20:15:17 +02:00
case 'getRules':
response = getRules();
break;
2015-05-21 20:15:17 +02:00
case 'setSessionRules':
// https://github.com/chrisaljoudi/uBlock/issues/772
µb.cosmeticFilteringEngine.removeFromSelectorCache('*');
r = untangle(request.rules);
2015-05-21 20:15:17 +02:00
µb.sessionFirewall.fromString(r.firewallRules);
µb.sessionURLFiltering.fromString(r.urlRules);
µb.hnSwitches.fromString(r.switches);
µb.saveHostnameSwitches();
response = getRules();
break;
2015-05-21 20:15:17 +02:00
case 'setPermanentRules':
r = untangle(request.rules);
2015-05-21 20:15:17 +02:00
µb.permanentFirewall.fromString(r.firewallRules);
µb.savePermanentFirewallRules();
2015-05-21 20:15:17 +02:00
µb.permanentURLFiltering.fromString(r.urlRules);
µb.savePermanentURLFilteringRules();
µb.hnSwitches.fromString(r.switches);
µb.saveHostnameSwitches();
response = getRules();
break;
default:
return vAPI.messaging.UNHANDLED;
}
callback(response);
};
vAPI.messaging.listen('dyna-rules.js', onMessage);
/******************************************************************************/
})();
/******************************************************************************/
/******************************************************************************/
2014-07-17 16:52:43 +02:00
// whitelist.js
(function() {
2014-12-17 14:04:21 +01:00
'use strict';
2014-09-28 18:05:46 +02:00
/******************************************************************************/
2014-07-17 16:52:43 +02:00
2014-09-28 18:05:46 +02:00
var µb = µBlock;
/******************************************************************************/
var onMessage = function(request, sender, callback) {
2014-07-17 16:52:43 +02:00
// Async
switch ( request.what ) {
2015-05-19 19:59:53 +02:00
default:
break;
2014-07-17 16:52:43 +02:00
}
// Sync
var response;
switch ( request.what ) {
2015-05-19 19:59:53 +02:00
case 'getWhitelist':
response = µb.stringFromWhitelist(µb.netWhitelist);
break;
2014-07-17 16:52:43 +02:00
2015-05-19 19:59:53 +02:00
case 'setWhitelist':
µb.netWhitelist = µb.whitelistFromString(request.whitelist);
µb.saveWhitelist();
break;
2014-07-17 16:52:43 +02:00
2015-05-19 19:59:53 +02:00
default:
return vAPI.messaging.UNHANDLED;
2014-07-17 16:52:43 +02:00
}
callback(response);
};
vAPI.messaging.listen('whitelist.js', onMessage);
2014-09-28 18:05:46 +02:00
/******************************************************************************/
2014-07-17 16:52:43 +02:00
})();
2014-07-02 18:02:29 +02:00
2014-09-14 22:20:40 +02:00
/******************************************************************************/
2014-07-02 18:02:29 +02:00
/******************************************************************************/
// settings.js
2014-06-24 00:42:43 +02:00
(function() {
2014-12-17 14:04:21 +01:00
'use strict';
2014-09-28 18:05:46 +02:00
/******************************************************************************/
2014-06-24 00:42:43 +02:00
2014-09-28 18:05:46 +02:00
var µb = µBlock;
/******************************************************************************/
2015-03-07 05:36:09 +01:00
var getLocalData = function(callback) {
var onStorageInfoReady = function(bytesInUse) {
var o = µb.restoreBackupSettings;
2014-10-07 14:59:35 +02:00
callback({
2015-03-07 05:36:09 +01:00
storageUsed: bytesInUse,
lastRestoreFile: o.lastRestoreFile,
lastRestoreTime: o.lastRestoreTime,
lastBackupFile: o.lastBackupFile,
lastBackupTime: o.lastBackupTime
2014-10-07 14:59:35 +02:00
});
};
2015-03-07 05:36:09 +01:00
µb.getBytesInUse(onStorageInfoReady);
};
/******************************************************************************/
var backupUserData = function(callback) {
2015-04-16 18:14:43 +02:00
var userData = {
timeStamp: Date.now(),
version: vAPI.app.version,
userSettings: µb.userSettings,
filterLists: {},
netWhitelist: µb.stringFromWhitelist(µb.netWhitelist),
dynamicFilteringString: µb.permanentFirewall.toString(),
2015-05-21 20:15:17 +02:00
urlFilteringString: µb.permanentURLFiltering.toString(),
2015-04-16 18:14:43 +02:00
hostnameSwitchesString: µb.hnSwitches.toString(),
userFilters: ''
};
var onSelectedListsReady = function(filterLists) {
userData.filterLists = filterLists;
2015-03-07 05:36:09 +01:00
var now = new Date();
var filename = vAPI.i18n('aboutBackupFilename')
.replace('{{datetime}}', now.toLocaleString())
.replace(/ +/g, '_');
vAPI.download({
'url': 'data:text/plain;charset=utf-8,' + encodeURIComponent(JSON.stringify(userData, null, ' ')),
'filename': filename
});
µb.restoreBackupSettings.lastBackupFile = filename;
µb.restoreBackupSettings.lastBackupTime = Date.now();
2015-04-10 15:52:16 +02:00
vAPI.storage.set(µb.restoreBackupSettings);
2015-03-07 05:36:09 +01:00
getLocalData(callback);
};
2015-04-16 18:14:43 +02:00
var onUserFiltersReady = function(details) {
userData.userFilters = details.content;
µb.extractSelectedFilterLists(onSelectedListsReady);
};
2014-10-07 14:59:35 +02:00
µb.assets.get('assets/user/filters.txt', onUserFiltersReady);
};
/******************************************************************************/
2015-03-07 05:36:09 +01:00
var restoreUserData = function(request) {
var userData = request.userData;
2015-05-21 20:15:17 +02:00
var countdown = 8;
2014-10-11 22:44:56 +02:00
var onCountdown = function() {
countdown -= 1;
if ( countdown === 0 ) {
vAPI.app.restart();
2014-10-11 22:44:56 +02:00
}
};
var onAllRemoved = function() {
// Be sure to adjust `countdown` if adding/removing anything below
2015-04-10 08:17:12 +02:00
µb.keyvalSetOne('version', userData.version);
2015-03-11 16:05:13 +01:00
µBlock.saveLocalSettings(true);
2015-04-10 15:52:16 +02:00
vAPI.storage.set(userData.userSettings, onCountdown);
2015-04-10 08:17:12 +02:00
µb.keyvalSetOne('remoteBlacklists', userData.filterLists, onCountdown);
µb.keyvalSetOne('netWhitelist', userData.netWhitelist || '', onCountdown);
2015-03-07 05:36:09 +01:00
2015-03-27 18:00:55 +01:00
// With versions 0.9.2.4-, dynamic rules were saved within the
// `userSettings` object. No longer the case.
var s = userData.dynamicFilteringString || userData.userSettings.dynamicFilteringString || '';
2015-04-10 08:17:12 +02:00
µb.keyvalSetOne('dynamicFilteringString', s, onCountdown);
2015-03-27 18:00:55 +01:00
2015-05-21 20:15:17 +02:00
µb.keyvalSetOne('urlFilteringString', userData.urlFilteringString || '', onCountdown);
2015-04-10 08:17:12 +02:00
µb.keyvalSetOne('hostnameSwitchesString', userData.hostnameSwitchesString || '', onCountdown);
2015-03-27 18:00:55 +01:00
µb.assets.put('assets/user/filters.txt', userData.userFilters, onCountdown);
2015-04-10 15:52:16 +02:00
vAPI.storage.set({
2015-03-07 05:36:09 +01:00
lastRestoreFile: request.file || '',
lastRestoreTime: Date.now(),
lastBackupFile: '',
lastBackupTime: 0
}, onCountdown);
2014-10-11 22:44:56 +02:00
};
2015-04-07 03:26:05 +02:00
// https://github.com/chrisaljoudi/uBlock/issues/1102
2015-03-27 14:50:31 +01:00
// Ensure all currently cached assets are flushed from storage AND memory.
µb.assets.rmrf();
2014-10-07 16:46:10 +02:00
// If we are going to restore all, might as well wipe out clean local
// storage
2015-04-10 08:17:12 +02:00
vAPI.storage.clear(onAllRemoved);
2014-10-07 14:59:35 +02:00
};
/******************************************************************************/
var resetUserData = function() {
2015-04-10 08:17:12 +02:00
vAPI.storage.clear();
2015-03-11 16:05:13 +01:00
2014-10-07 14:59:35 +02:00
// Keep global counts, people can become quite attached to numbers
2015-03-11 16:05:13 +01:00
µb.saveLocalSettings(true);
vAPI.app.restart();
2014-10-07 14:59:35 +02:00
};
/******************************************************************************/
2014-09-28 18:05:46 +02:00
var onMessage = function(request, sender, callback) {
2014-06-24 00:42:43 +02:00
// Async
switch ( request.what ) {
2015-05-19 19:59:53 +02:00
case 'backupUserData':
return backupUserData(callback);
2015-03-07 05:36:09 +01:00
2015-05-19 19:59:53 +02:00
case 'getLocalData':
return getLocalData(callback);
2014-06-24 00:42:43 +02:00
2015-05-19 19:59:53 +02:00
default:
break;
2014-06-24 00:42:43 +02:00
}
// Sync
var response;
switch ( request.what ) {
2015-05-19 19:59:53 +02:00
case 'restoreUserData':
restoreUserData(request);
break;
2014-10-07 14:59:35 +02:00
2015-05-19 19:59:53 +02:00
case 'resetUserData':
resetUserData();
break;
2015-05-19 19:59:53 +02:00
default:
return vAPI.messaging.UNHANDLED;
2014-06-24 00:42:43 +02:00
}
callback(response);
};
vAPI.messaging.listen('settings.js', onMessage);
2014-09-28 18:05:46 +02:00
/******************************************************************************/
2014-06-24 00:42:43 +02:00
})();
/******************************************************************************/
/******************************************************************************/
2015-05-09 00:28:01 +02:00
// logger-ui.js
(function() {
'use strict';
/******************************************************************************/
var µb = µBlock;
/******************************************************************************/
2015-05-21 20:15:17 +02:00
var getURLFilteringData = function(details) {
var colors = {};
var response = {
dirty: false,
colors: colors
};
var suf = µb.sessionURLFiltering;
var puf = µb.permanentURLFiltering;
var urls = details.urls,
context = details.context,
type = details.type;
var url, colorEntry;
var i = urls.length;
while ( i-- ) {
url = urls[i];
colorEntry = colors[url] = { r: 0, own: false };
if ( suf.evaluateZ(context, url, type).r !== 0 ) {
colorEntry.r = suf.r;
colorEntry.own = suf.context === context && suf.url === url && suf.type === type;
}
if ( response.dirty ) {
continue;
}
puf.evaluateZ(context, url, type);
response.dirty = colorEntry.own !== (puf.context === context && puf.url === url && puf.type === type);
}
return response;
};
/******************************************************************************/
var onMessage = function(request, sender, callback) {
// Async
switch ( request.what ) {
2015-05-19 19:59:53 +02:00
default:
break;
}
// Sync
var response;
switch ( request.what ) {
2015-05-19 19:59:53 +02:00
case 'readAll':
var tabIds = {}, pageStore;
var loggerURL = vAPI.getURL('logger-ui.html');
for ( var tabId in µb.pageStores ) {
pageStore = µb.pageStoreFromTabId(tabId);
if ( pageStore === null ) {
continue;
2015-05-09 00:28:01 +02:00
}
2015-05-19 19:59:53 +02:00
if ( pageStore.rawURL.lastIndexOf(loggerURL, 0) === 0 ) {
continue;
}
tabIds[tabId] = pageStore.title;
}
response = {
colorBlind: µb.userSettings.colorBlindFriendly,
entries: µb.logger.readAll(),
maxEntries: µb.userSettings.requestLogMaxEntries,
noTabId: vAPI.noTabId,
tabIds: tabIds,
tabIdsToken: µb.pageStoresToken
};
break;
2015-05-21 20:15:17 +02:00
case 'saveURLFilteringRules':
2015-05-22 14:05:55 +02:00
response = µb.permanentURLFiltering.copyRules(
µb.sessionURLFiltering,
request.context,
request.urls,
request.type
);
if ( response ) {
2015-05-21 20:15:17 +02:00
µb.savePermanentURLFilteringRules();
}
break;
case 'setURLFilteringRule':
µb.toggleURLFilteringRule(request);
break;
case 'getURLFilteringData':
response = getURLFilteringData(request);
break;
2015-05-19 19:59:53 +02:00
default:
return vAPI.messaging.UNHANDLED;
}
callback(response);
};
2015-05-09 00:28:01 +02:00
vAPI.messaging.listen('logger-ui.js', onMessage);
/******************************************************************************/
})();
// https://www.youtube.com/watch?v=3_WcygKJP1k
2014-06-24 00:42:43 +02:00
/******************************************************************************/
2015-03-09 17:57:52 +01:00
/******************************************************************************/
// subscriber.js
(function() {
'use strict';
/******************************************************************************/
var onMessage = function(request, sender, callback) {
// Async
switch ( request.what ) {
default:
break;
}
// Sync
var response;
switch ( request.what ) {
2015-05-19 19:59:53 +02:00
case 'subscriberData':
response = {
confirmStr: vAPI.i18n('subscriberConfirm'),
externalLists: µBlock.userSettings.externalLists
};
break;
2015-03-09 17:57:52 +01:00
2015-05-19 19:59:53 +02:00
default:
return vAPI.messaging.UNHANDLED;
2015-03-09 17:57:52 +01:00
}
callback(response);
};
vAPI.messaging.listen('subscriber.js', onMessage);
/******************************************************************************/
})();
2015-03-26 00:28:22 +01:00
/******************************************************************************/
/******************************************************************************/
// document-blocked.js
(function() {
'use strict';
/******************************************************************************/
var onMessage = function(request, sender, callback) {
// Async
switch ( request.what ) {
2015-05-19 19:59:53 +02:00
default:
break;
2015-03-26 00:28:22 +01:00
}
// Sync
var response;
switch ( request.what ) {
2015-05-19 19:59:53 +02:00
case 'temporarilyWhitelistDocument':
µBlock.webRequest.temporarilyWhitelistDocument(request.hostname);
break;
2015-03-26 00:28:22 +01:00
2015-05-19 19:59:53 +02:00
default:
return vAPI.messaging.UNHANDLED;
2015-03-26 00:28:22 +01:00
}
callback(response);
};
vAPI.messaging.listen('document-blocked.js', onMessage);
/******************************************************************************/
})();
2015-03-09 17:57:52 +01:00
/******************************************************************************/
/******************************************************************************/
// scriptlets
(function() {
'use strict';
/******************************************************************************/
var µb = µBlock;
/******************************************************************************/
var logCosmeticFilters = function(tabId, details) {
if ( µb.logger.isEnabled() === false ) {
return;
}
var selectors = details.matchedSelectors;
selectors.sort();
for ( var i = 0; i < selectors.length; i++ ) {
µb.logger.writeOne(
tabId,
'cosmetic',
'cb:##' + selectors[i],
'dom',
details.pageURL
);
}
};
/******************************************************************************/
var onMessage = function(request, sender, callback) {
// Async
switch ( request.what ) {
default:
break;
}
// Sync
var response;
var tabId = sender && sender.tab ? sender.tab.id : 0;
switch ( request.what ) {
case 'gotoImageURL':
response = µb.scriptlets.gotoImageURL;
break;
case 'liveCosmeticFilteringData':
var pageStore = µb.pageStoreFromTabId(tabId);
if ( pageStore ) {
pageStore.hiddenElementCount = request.filteredElementCount;
}
break;
case 'logCosmeticFilteringData':
logCosmeticFilters(tabId, request);
break;
default:
return vAPI.messaging.UNHANDLED;
}
callback(response);
};
vAPI.messaging.listen('scriptlets', onMessage);
/******************************************************************************/
})();
/******************************************************************************/