mirror of
https://github.com/gorhill/uBlock.git
synced 2024-10-06 09:37:12 +02:00
Merge branch 'master' of https://github.com/gorhill/uBlock
This commit is contained in:
commit
e222ace6ef
@ -2,7 +2,7 @@
|
||||
"manifest_version": 2,
|
||||
|
||||
"name": "µBlock",
|
||||
"version": "0.8.9.1",
|
||||
"version": "0.8.9.2",
|
||||
|
||||
"default_locale": "en",
|
||||
"description": "__MSG_extShortDesc__",
|
||||
|
@ -53,7 +53,6 @@ const contentObserver = {
|
||||
MAIN_FRAME: Ci.nsIContentPolicy.TYPE_DOCUMENT,
|
||||
contentBaseURI: 'chrome://' + hostName + '/content/js/',
|
||||
cpMessageName: hostName + ':shouldLoad',
|
||||
|
||||
ignoredPopups: new WeakMap(),
|
||||
uniqueSandboxId: 1,
|
||||
|
||||
|
@ -549,7 +549,7 @@ vAPI.tabs.get = function(tabId, callback) {
|
||||
}
|
||||
}
|
||||
|
||||
// for internal use
|
||||
// For internal use
|
||||
if ( typeof callback !== 'function' ) {
|
||||
return tab;
|
||||
}
|
||||
@ -565,12 +565,14 @@ vAPI.tabs.get = function(tabId, callback) {
|
||||
|
||||
var browser = getBrowserForTab(tab);
|
||||
var tabBrowser = getTabBrowser(win);
|
||||
var tabIndex = vAPI.fennec
|
||||
? tabBrowser.tabs.indexOf(tab)
|
||||
: tabBrowser.browsers.indexOf(browser);
|
||||
var tabTitle = vAPI.fennec
|
||||
? browser.contentTitle
|
||||
: tab.label;
|
||||
var tabIndex, tabTitle;
|
||||
if ( vAPI.fennec ) {
|
||||
tabIndex = tabBrowser.tabs.indexOf(tab);
|
||||
tabTitle = browser.contentTitle;
|
||||
} else {
|
||||
tabIndex = tabBrowser.browsers.indexOf(browser);
|
||||
tabTitle = tab.label;
|
||||
}
|
||||
|
||||
callback({
|
||||
id: tabId,
|
||||
@ -1022,14 +1024,7 @@ var httpObserver = {
|
||||
12: 'object',
|
||||
14: 'font'
|
||||
},
|
||||
lastRequest: {
|
||||
url: null,
|
||||
type: null,
|
||||
tabId: null,
|
||||
frameId: null,
|
||||
parentFrameId: null,
|
||||
openerURL: null
|
||||
},
|
||||
lastRequest: [{}, {}],
|
||||
|
||||
get componentRegistrar() {
|
||||
return Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
@ -1134,13 +1129,13 @@ var httpObserver = {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( result.redirectUrl ) {
|
||||
/*if ( result.redirectUrl ) {
|
||||
channel.redirectionLimit = 1;
|
||||
channel.redirectTo(
|
||||
Services.io.newURI(result.redirectUrl, null, null)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}*/
|
||||
|
||||
return false;
|
||||
},
|
||||
@ -1159,13 +1154,6 @@ var httpObserver = {
|
||||
}
|
||||
|
||||
try {
|
||||
/*[
|
||||
type,
|
||||
tabId,
|
||||
sourceTabId - given if it was a popup,
|
||||
frameId,
|
||||
parentFrameId
|
||||
]*/
|
||||
channelData = channel.getProperty(this.REQDATAKEY);
|
||||
} catch (ex) {
|
||||
return;
|
||||
@ -1175,7 +1163,7 @@ var httpObserver = {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( (1 << channelData[0] & this.VALID_CSP_TARGETS) === 0 ) {
|
||||
if ( (1 << channelData[4] & this.VALID_CSP_TARGETS) === 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1189,9 +1177,9 @@ var httpObserver = {
|
||||
|
||||
result = vAPI.net.onHeadersReceived.callback({
|
||||
hostname: URI.asciiHost,
|
||||
parentFrameId: channelData[4],
|
||||
parentFrameId: channelData[1],
|
||||
responseHeaders: result ? [{name: topic, value: result}] : [],
|
||||
tabId: channelData[1],
|
||||
tabId: channelData[3],
|
||||
url: URI.asciiSpec
|
||||
});
|
||||
|
||||
@ -1208,13 +1196,36 @@ var httpObserver = {
|
||||
|
||||
// http-on-opening-request
|
||||
|
||||
var lastRequest = this.lastRequest;
|
||||
var lastRequest = this.lastRequest[0];
|
||||
|
||||
if ( lastRequest.url !== URI.spec ) {
|
||||
if ( this.lastRequest[1].url === URI.spec ) {
|
||||
lastRequest = this.lastRequest[1];
|
||||
} else {
|
||||
lastRequest.url = null;
|
||||
}
|
||||
}
|
||||
|
||||
if ( lastRequest.url === null ) {
|
||||
this.handleRequest(channel, URI, {
|
||||
lastRequest.type = channel.loadInfo && channel.loadInfo.contentPolicyType || 1;
|
||||
result = this.handleRequest(channel, URI, {
|
||||
tabId: vAPI.noTabId,
|
||||
type: channel.loadInfo && channel.loadInfo.contentPolicyType || 1
|
||||
type: lastRequest.type
|
||||
});
|
||||
|
||||
if ( result === true ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( channel instanceof Ci.nsIWritablePropertyBag === false ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Carry data for behind-the-scene redirects
|
||||
channel.setProperty(
|
||||
this.REQDATAKEY,
|
||||
[lastRequest.type, vAPI.noTabId, null, 0, -1]
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1222,34 +1233,11 @@ var httpObserver = {
|
||||
// the URL will be the same, so it could fall into an infinite loop
|
||||
lastRequest.url = null;
|
||||
|
||||
var sourceTabId = null;
|
||||
|
||||
// Popup candidate (only for main_frame type)
|
||||
if ( lastRequest.openerURL ) {
|
||||
for ( var tab of vAPI.tabs.getAll() ) {
|
||||
var tabURI = tab.linkedBrowser.currentURI;
|
||||
|
||||
// Probably isn't the best method to identify the source tab
|
||||
if ( tabURI.spec !== lastRequest.openerURL ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sourceTabId = vAPI.tabs.getTabId(tab);
|
||||
|
||||
if ( sourceTabId !== lastRequest.tabId ) {
|
||||
break;
|
||||
}
|
||||
|
||||
sourceTabId = null;
|
||||
}
|
||||
|
||||
if ( this.handlePopup(channel.URI, lastRequest.tabId, sourceTabId) ) {
|
||||
channel.cancel(this.ABORT);
|
||||
return;
|
||||
}
|
||||
if ( this.handleRequest(channel, URI, lastRequest) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( lastRequest.type === this.MAIN_FRAME && lastRequest.frameId === 0 ) {
|
||||
if ( vAPI.fennec && lastRequest.type === this.MAIN_FRAME && lastRequest.frameId === 0 ) {
|
||||
vAPI.tabs.onNavigation({
|
||||
frameId: 0,
|
||||
tabId: lastRequest.tabId,
|
||||
@ -1257,22 +1245,15 @@ var httpObserver = {
|
||||
});
|
||||
}
|
||||
|
||||
if ( this.handleRequest(channel, URI, lastRequest) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If request is not handled we may use the data in on-modify-request
|
||||
if ( channel instanceof Ci.nsIWritablePropertyBag ) {
|
||||
channel.setProperty(
|
||||
this.REQDATAKEY,
|
||||
[
|
||||
lastRequest.type,
|
||||
lastRequest.tabId,
|
||||
sourceTabId,
|
||||
lastRequest.frameId,
|
||||
lastRequest.parentFrameId
|
||||
]
|
||||
);
|
||||
channel.setProperty(this.REQDATAKEY, [
|
||||
lastRequest.frameId,
|
||||
lastRequest.parentFrameId,
|
||||
lastRequest.sourceTabId,
|
||||
lastRequest.tabId,
|
||||
lastRequest.type
|
||||
]);
|
||||
}
|
||||
},
|
||||
|
||||
@ -1282,12 +1263,6 @@ var httpObserver = {
|
||||
|
||||
// If error thrown, the redirect will fail
|
||||
try {
|
||||
// skip internal redirects?
|
||||
/*if ( flags & 4 ) {
|
||||
console.log('internal redirect skipped');
|
||||
return;
|
||||
}*/
|
||||
|
||||
var URI = newChannel.URI;
|
||||
|
||||
if ( !URI.schemeIs('http') && !URI.schemeIs('https') ) {
|
||||
@ -1298,21 +1273,18 @@ var httpObserver = {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: what if a behind-the-scene request is being redirected?
|
||||
// This data is present only for tabbed requests, so if this throws,
|
||||
// the redirection won't be evaluated and canceled (if necessary)
|
||||
var channelData = oldChannel.getProperty(this.REQDATAKEY);
|
||||
|
||||
if ( this.handlePopup(URI, channelData[1], channelData[2]) ) {
|
||||
if ( this.handlePopup(URI, channelData[3], channelData[2]) ) {
|
||||
result = this.ABORT;
|
||||
return;
|
||||
}
|
||||
|
||||
var details = {
|
||||
type: channelData[0],
|
||||
tabId: channelData[1],
|
||||
frameId: channelData[3],
|
||||
parentFrameId: channelData[4]
|
||||
frameId: channelData[0],
|
||||
parentFrameId: channelData[1],
|
||||
tabId: channelData[3],
|
||||
type: channelData[4]
|
||||
};
|
||||
|
||||
if ( this.handleRequest(newChannel, URI, details) ) {
|
||||
@ -1347,13 +1319,46 @@ vAPI.net.registerListeners = function() {
|
||||
var shouldLoadListenerMessageName = location.host + ':shouldLoad';
|
||||
var shouldLoadListener = function(e) {
|
||||
var details = e.data;
|
||||
var tabId = vAPI.tabs.getTabId(e.target);
|
||||
var sourceTabId = null;
|
||||
|
||||
// Popup candidate
|
||||
if ( details.openerURL ) {
|
||||
for ( var tab of vAPI.tabs.getAll() ) {
|
||||
var URI = tab.linkedBrowser.currentURI;
|
||||
|
||||
// Probably isn't the best method to identify the source tab
|
||||
if ( URI.spec !== details.openerURL ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sourceTabId = vAPI.tabs.getTabId(tab);
|
||||
|
||||
if ( sourceTabId === tabId ) {
|
||||
sourceTabId = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
URI = Services.io.newURI(details.url, null, null);
|
||||
|
||||
if ( httpObserver.handlePopup(URI, tabId, sourceTabId) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var lastRequest = httpObserver.lastRequest;
|
||||
lastRequest.url = details.url;
|
||||
lastRequest.type = details.type;
|
||||
lastRequest.tabId = vAPI.tabs.getTabId(e.target);
|
||||
lastRequest.frameId = details.frameId;
|
||||
lastRequest.parentFrameId = details.parentFrameId;
|
||||
lastRequest.openerURL = details.openerURL;
|
||||
lastRequest[1] = lastRequest[0];
|
||||
lastRequest[0] = {
|
||||
frameId: details.frameId,
|
||||
parentFrameId: details.parentFrameId,
|
||||
sourceTabId: sourceTabId,
|
||||
tabId: tabId,
|
||||
type: details.type,
|
||||
url: details.url
|
||||
};
|
||||
};
|
||||
|
||||
vAPI.messaging.globalMessageManager.addMessageListener(
|
||||
@ -1813,7 +1818,7 @@ vAPI.contextMenu.create = function(details, callback) {
|
||||
|
||||
if ( gContextMenu.inFrame ) {
|
||||
details.tagName = 'iframe';
|
||||
// Probably won't work with e01s
|
||||
// Probably won't work with e10s
|
||||
details.frameUrl = gContextMenu.focusedWindow.location.href;
|
||||
} else if ( gContextMenu.onImage ) {
|
||||
details.tagName = 'img';
|
||||
|
@ -27,6 +27,13 @@
|
||||
if(vAPI.vapiClientInjected) {
|
||||
return;
|
||||
}
|
||||
var safari;
|
||||
if(typeof self.safari === "undefined") {
|
||||
safari = self.top.safari;
|
||||
}
|
||||
else {
|
||||
safari = self.safari;
|
||||
}
|
||||
vAPI.vapiClientInjected = true;
|
||||
vAPI.safari = true;
|
||||
vAPI.sessionId = String.fromCharCode(Date.now() % 25 + 97) +
|
||||
@ -71,9 +78,6 @@
|
||||
listeners: {},
|
||||
requestId: 1,
|
||||
setup: function() {
|
||||
if(typeof safari === "undefined") {
|
||||
return;
|
||||
}
|
||||
this.connector = function(msg) {
|
||||
// messages from the background script are sent to every frame,
|
||||
// so we need to check the vAPI.sessionId to accept only
|
||||
@ -107,9 +111,6 @@
|
||||
channelName: channelName,
|
||||
listener: typeof callback === 'function' ? callback : null,
|
||||
send: function(message, callback) {
|
||||
if(typeof safari === "undefined") {
|
||||
return;
|
||||
}
|
||||
if(!vAPI.messaging.connector) {
|
||||
vAPI.messaging.setup();
|
||||
}
|
||||
@ -236,7 +237,6 @@ return e.detail.url === false;\
|
||||
wo = open,\
|
||||
xo = XMLHttpRequest.prototype.open,\
|
||||
img = Image;\
|
||||
_noOP = function(){};\
|
||||
Image = function() {\
|
||||
var x = new img();\
|
||||
Object.defineProperty(x, 'src', {\
|
||||
@ -252,9 +252,9 @@ return x;\
|
||||
open = function(u) {\
|
||||
return block(u, 'popup') ? null : wo.apply(this, arguments);\
|
||||
};\
|
||||
XMLHttpRequest.prototype.open = function(m, u, s) {\
|
||||
if(block(u, 'xmlhttprequest')) return {send: _noOP};\
|
||||
else return xo.apply(this, arguments);\
|
||||
XMLHttpRequest.prototype.open = function(m, u) {\
|
||||
if(block(u, 'xmlhttprequest')) {throw 'InvalidAccessError'; return;}\
|
||||
else {xo.apply(this, arguments); return;}\
|
||||
};";
|
||||
if(frameId === 0) {
|
||||
tmpScript += "\
|
||||
|
@ -85,7 +85,7 @@ return {
|
||||
|
||||
// read-only
|
||||
systemSettings: {
|
||||
compiledMagic: 'iolkecdtfsiy',
|
||||
compiledMagic: 'fkaywfqahncj',
|
||||
selfieMagic: 'spqmeuaftfra'
|
||||
},
|
||||
|
||||
|
@ -93,25 +93,23 @@ var messager = vAPI.messaging.channel('contentscript-end.js');
|
||||
return;
|
||||
}
|
||||
|
||||
//var timer = window.performance || Date;
|
||||
//var tStart = timer.now();
|
||||
|
||||
var queriedSelectors = {};
|
||||
var injectedSelectors = {};
|
||||
var classSelectors = null;
|
||||
var idSelectors = null;
|
||||
var lowGenericSelectors = [];
|
||||
var highGenerics = null;
|
||||
var contextNodes = [document];
|
||||
var nullArray = { push: function(){} };
|
||||
|
||||
var retrieveGenericSelectors = function() {
|
||||
var selectors = classSelectors !== null ? Object.keys(classSelectors) : [];
|
||||
if ( idSelectors !== null ) {
|
||||
selectors = selectors.concat(idSelectors);
|
||||
}
|
||||
if ( selectors.length > 0 || highGenerics === null ) {
|
||||
//console.log('µBlock> ABP cosmetic filters: retrieving CSS rules using %d selectors', selectors.length);
|
||||
if ( lowGenericSelectors.length !== 0 || highGenerics === null ) {
|
||||
//console.log('µBlock> ABP cosmetic filters: retrieving CSS rules using %d selectors', lowGenericSelectors.length);
|
||||
messager.send({
|
||||
what: 'retrieveGenericCosmeticSelectors',
|
||||
pageURL: window.location.href,
|
||||
selectors: selectors,
|
||||
selectors: lowGenericSelectors,
|
||||
highGenerics: highGenerics === null
|
||||
},
|
||||
retrieveHandler
|
||||
@ -122,8 +120,7 @@ var messager = vAPI.messaging.channel('contentscript-end.js');
|
||||
} else {
|
||||
otherRetrieveHandler(null);
|
||||
}
|
||||
idSelectors = null;
|
||||
classSelectors = null;
|
||||
lowGenericSelectors = [];
|
||||
};
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/452
|
||||
@ -139,7 +136,7 @@ var messager = vAPI.messaging.channel('contentscript-end.js');
|
||||
var selectors = vAPI.hideCosmeticFilters;
|
||||
if ( typeof selectors === 'object' ) {
|
||||
injectedSelectors = selectors;
|
||||
hideElements(Object.keys(selectors).join(','));
|
||||
//hideElements(Object.keys(selectors));
|
||||
}
|
||||
// Add exception filters into injected filters collection, in order
|
||||
// to force them to be seen as "already injected".
|
||||
@ -158,6 +155,7 @@ var messager = vAPI.messaging.channel('contentscript-end.js');
|
||||
};
|
||||
|
||||
var otherRetrieveHandler = function(selectors) {
|
||||
//var tStart = timer.now();
|
||||
//console.debug('µBlock> contextNodes = %o', contextNodes);
|
||||
if ( selectors && selectors.highGenerics ) {
|
||||
highGenerics = selectors.highGenerics;
|
||||
@ -196,6 +194,7 @@ var messager = vAPI.messaging.channel('contentscript-end.js');
|
||||
addStyleTag(hideSelectors);
|
||||
}
|
||||
contextNodes.length = 0;
|
||||
//console.debug('%f: uBlock: CSS injection time', timer.now() - tStart);
|
||||
};
|
||||
|
||||
var retrieveHandler = firstRetrieveHandler;
|
||||
@ -206,10 +205,10 @@ var messager = vAPI.messaging.channel('contentscript-end.js');
|
||||
// - Injecting a style tag
|
||||
|
||||
var addStyleTag = function(selectors) {
|
||||
hideElements(selectors);
|
||||
//hideElements(selectors);
|
||||
var style = document.createElement('style');
|
||||
// The linefeed before the style block is very important: do no remove!
|
||||
style.appendChild(document.createTextNode(selectors.join(',\n') + '\n{display:none !important;}'));
|
||||
style.appendChild(document.createTextNode(selectors.toString() + '\n{display:none !important;}'));
|
||||
var parent = document.body || document.documentElement;
|
||||
if ( parent ) {
|
||||
parent.appendChild(style);
|
||||
@ -349,12 +348,26 @@ var messager = vAPI.messaging.channel('contentscript-end.js');
|
||||
// requests to process high-high generics into as few requests as possible.
|
||||
// The gain is *significant* on bloated pages.
|
||||
|
||||
var processHighHighGenericsMisses = 8;
|
||||
var processHighHighGenericsTimer = null;
|
||||
|
||||
var processHighHighGenerics = function() {
|
||||
processHighHighGenericsTimer = null;
|
||||
if ( injectedSelectors.hasOwnProperty('{{highHighGenerics}}') ) { return; }
|
||||
if ( document.querySelector(highGenerics.hideHigh) === null ) { return; }
|
||||
if ( injectedSelectors.hasOwnProperty('{{highHighGenerics}}') ) {
|
||||
return;
|
||||
}
|
||||
//var tStart = timer.now();
|
||||
if ( document.querySelector(highGenerics.hideHigh) === null ) {
|
||||
//console.debug('%f: high-high generic test time', timer.now() - tStart);
|
||||
processHighHighGenericsMisses -= 1;
|
||||
// Too many misses for these nagging highly generic CSS rules,
|
||||
// so we will just skip them from now on.
|
||||
if ( processHighHighGenericsMisses === 0 ) {
|
||||
injectedSelectors['{{highHighGenerics}}'] = true;
|
||||
console.debug('high-high generic: apparently not needed...');
|
||||
}
|
||||
return;
|
||||
}
|
||||
injectedSelectors['{{highHighGenerics}}'] = true;
|
||||
// We need to filter out possible exception cosmetic filters from
|
||||
// high-high generics selectors.
|
||||
@ -388,11 +401,8 @@ var messager = vAPI.messaging.channel('contentscript-end.js');
|
||||
if ( !nodes || !nodes.length ) {
|
||||
return;
|
||||
}
|
||||
if ( idSelectors === null ) {
|
||||
idSelectors = [];
|
||||
}
|
||||
var qq = queriedSelectors;
|
||||
var ii = idSelectors;
|
||||
var ll = lowGenericSelectors;
|
||||
var node, v;
|
||||
var i = nodes.length;
|
||||
while ( i-- ) {
|
||||
@ -404,8 +414,8 @@ var messager = vAPI.messaging.channel('contentscript-end.js');
|
||||
v = v.trim();
|
||||
if ( v === '' ) { continue; }
|
||||
v = '#' + v;
|
||||
if ( qq[v] ) { continue; }
|
||||
ii.push(v);
|
||||
if ( qq.hasOwnProperty(v) ) { continue; }
|
||||
ll.push(v);
|
||||
qq[v] = true;
|
||||
}
|
||||
};
|
||||
@ -417,11 +427,8 @@ var messager = vAPI.messaging.channel('contentscript-end.js');
|
||||
if ( !nodes || !nodes.length ) {
|
||||
return;
|
||||
}
|
||||
if ( classSelectors === null ) {
|
||||
classSelectors = {};
|
||||
}
|
||||
var qq = queriedSelectors;
|
||||
var cc = classSelectors;
|
||||
var ll = lowGenericSelectors;
|
||||
var node, v, vv, j;
|
||||
var i = nodes.length;
|
||||
while ( i-- ) {
|
||||
@ -433,8 +440,8 @@ var messager = vAPI.messaging.channel('contentscript-end.js');
|
||||
v = vv[j];
|
||||
if ( typeof v !== 'string' ) { continue; }
|
||||
v = '.' + v;
|
||||
if ( qq[v] ) { continue; }
|
||||
cc[v] = true;
|
||||
if ( qq.hasOwnProperty(v) ) { continue; }
|
||||
ll.push(v);
|
||||
qq[v] = true;
|
||||
}
|
||||
}
|
||||
@ -446,6 +453,8 @@ var messager = vAPI.messaging.channel('contentscript-end.js');
|
||||
classesFromNodeList(document.querySelectorAll('[class]'));
|
||||
retrieveGenericSelectors();
|
||||
|
||||
//console.debug('%f: uBlock: survey time', timer.now() - tStart);
|
||||
|
||||
// Below this point is the code which takes care to observe changes in
|
||||
// the page and to add if needed relevant CSS rules as a result of the
|
||||
// changes.
|
||||
@ -528,7 +537,6 @@ var messager = vAPI.messaging.channel('contentscript-end.js');
|
||||
(function() {
|
||||
// https://github.com/gorhill/uBlock/issues/683
|
||||
// Instead of a closure we use a map to remember the element to collapse
|
||||
// or hide.
|
||||
var filterRequestId = 1;
|
||||
var filterRequests = {};
|
||||
|
||||
|
@ -1199,7 +1199,7 @@ FilterContainer.prototype.retrieveDomainSelectors = function(request) {
|
||||
/******************************************************************************/
|
||||
|
||||
FilterContainer.prototype.getFilterCount = function() {
|
||||
return this.acceptedCount;
|
||||
return this.acceptedCount - this.duplicateCount;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -59,6 +59,8 @@ var renderURL = function(url, filter) {
|
||||
.replace(/\?/g, '\\?')
|
||||
.replace('||', '')
|
||||
.replace(/\^/g, '.')
|
||||
.replace(/^\|/g, '^')
|
||||
.replace(/\|$/g, '$')
|
||||
.replace(/\*/g, '.*')
|
||||
;
|
||||
}
|
||||
|
@ -575,7 +575,7 @@ PageStore.prototype.disposeFrameStores = function() {
|
||||
/******************************************************************************/
|
||||
|
||||
PageStore.prototype.getFrame = function(frameId) {
|
||||
return this.frames[frameId];
|
||||
return this.frames[frameId] || null;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -158,11 +158,11 @@ var onSystemSettingsReady = function(fetched) {
|
||||
mustSaveSystemSettings = true;
|
||||
}
|
||||
if ( fetched.selfieMagic !== µb.systemSettings.selfieMagic ) {
|
||||
fetched.selfie = null;
|
||||
µb.destroySelfie();
|
||||
mustSaveSystemSettings = true;
|
||||
}
|
||||
if ( mustSaveSystemSettings ) {
|
||||
fetched.selfie = null;
|
||||
µb.destroySelfie();
|
||||
vAPI.storage.set(µb.systemSettings, µb.noopFunc);
|
||||
}
|
||||
};
|
||||
|
@ -19,8 +19,8 @@
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
/* jshint bitwise: false, esnext: true */
|
||||
/* global µBlock */
|
||||
/* jshint bitwise: false, esnext: true, boss: true */
|
||||
/* global punycode, µBlock */
|
||||
|
||||
// Older Safari throws an exception for const when it's used with 'use strict'.
|
||||
// 'use strict';
|
||||
@ -88,9 +88,7 @@ const AllowAnyTypeAnyParty = AllowAction | AnyType | AnyParty;
|
||||
const AllowAnyType = AllowAction | AnyType;
|
||||
const AllowAnyParty = AllowAction | AnyParty;
|
||||
|
||||
var reHostnameRule = /^[0-9a-z][0-9a-z.-]+[0-9a-z]$/;
|
||||
var reHostnameToken = /^[0-9a-z]+/g;
|
||||
var reGoodToken = /[%0-9a-z]{2,}/g;
|
||||
var reHostnameRule = /^[0-9a-z][0-9a-z.-]*[0-9a-z]$/;
|
||||
var reURLPostHostnameAnchors = /[\/?#]/;
|
||||
|
||||
// ABP filters: https://adblockplus.org/en/filters
|
||||
@ -168,6 +166,12 @@ var isFirstParty = function(firstPartyDomain, hostname) {
|
||||
return c === '.' || c === '';
|
||||
};
|
||||
|
||||
var strToRegex = function(prefix, s) {
|
||||
var reStr = s.replace(/([.+?^=!:${}()|\[\]\/\\])/g, '\\$1')
|
||||
.replace(/\*/g, '.*');
|
||||
return new RegExp(prefix + reStr);
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Filters family tree:
|
||||
@ -872,6 +876,51 @@ FilterSingleWildcardRightAnchoredHostname.fromSelfie = function(s) {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Generic filter: hostname-anchored: it has that extra test to find out
|
||||
// whether the start of the match falls within the hostname part of the
|
||||
// URL.
|
||||
|
||||
var FilterGenericHnAnchored = function(s) {
|
||||
this.s = s;
|
||||
this.re = null;
|
||||
};
|
||||
|
||||
FilterGenericHnAnchored.prototype.match = function(url) {
|
||||
if ( this.re === null ) {
|
||||
this.re = strToRegex('', this.s);
|
||||
}
|
||||
// Quick test first
|
||||
if ( this.re.test(url) === false ) {
|
||||
return false;
|
||||
}
|
||||
// Valid only if begininning of match is within the hostname
|
||||
// part of the url
|
||||
var match = this.re.exec(url);
|
||||
var pos = url.indexOf('://');
|
||||
return pos !== -1 &&
|
||||
reURLPostHostnameAnchors.test(url.slice(pos + 3, match.index)) === false;
|
||||
};
|
||||
|
||||
FilterGenericHnAnchored.fid = FilterGenericHnAnchored.prototype.fid = '||_';
|
||||
|
||||
FilterGenericHnAnchored.prototype.toString = function() {
|
||||
return '||' + this.s;
|
||||
};
|
||||
|
||||
FilterGenericHnAnchored.prototype.toSelfie = function() {
|
||||
return this.s;
|
||||
};
|
||||
|
||||
FilterGenericHnAnchored.compile = function(details) {
|
||||
return details.f;
|
||||
};
|
||||
|
||||
FilterGenericHnAnchored.fromSelfie = function(s) {
|
||||
return new FilterGenericHnAnchored(s);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// With many wildcards, a regex is best.
|
||||
|
||||
// Ref: regex escaper taken from:
|
||||
@ -881,10 +930,13 @@ FilterSingleWildcardRightAnchoredHostname.fromSelfie = function(s) {
|
||||
var FilterManyWildcards = function(s, tokenBeg) {
|
||||
this.s = s;
|
||||
this.tokenBeg = tokenBeg;
|
||||
this.re = new RegExp('^' + s.replace(/([.+?^=!:${}()|\[\]\/\\])/g, '\\$1').replace(/\*/g, '.*'));
|
||||
this.re = null;
|
||||
};
|
||||
|
||||
FilterManyWildcards.prototype.match = function(url, tokenBeg) {
|
||||
if ( this.re === null ) {
|
||||
this.re = strToRegex('^', this.s);
|
||||
}
|
||||
return this.re.test(url.slice(tokenBeg - this.tokenBeg));
|
||||
};
|
||||
|
||||
@ -912,13 +964,18 @@ FilterManyWildcards.fromSelfie = function(s) {
|
||||
var FilterManyWildcardsHostname = function(s, tokenBeg, hostname) {
|
||||
this.s = s;
|
||||
this.tokenBeg = tokenBeg;
|
||||
this.re = new RegExp('^' + s.replace(/([.+?^=!:${}()|\[\]\/\\])/g, '\\$1').replace(/\*/g, '.*'));
|
||||
this.re = null;
|
||||
this.hostname = hostname;
|
||||
};
|
||||
|
||||
FilterManyWildcardsHostname.prototype.match = function(url, tokenBeg) {
|
||||
return pageHostnameRegister.slice(-this.hostname.length) === this.hostname &&
|
||||
this.re.test(url.slice(tokenBeg - this.tokenBeg));
|
||||
if ( pageHostnameRegister.slice(-this.hostname.length) !== this.hostname ) {
|
||||
return false;
|
||||
}
|
||||
if ( this.re === null ) {
|
||||
this.re = strToRegex('^', this.s);
|
||||
}
|
||||
return this.re.test(url.slice(tokenBeg - this.tokenBeg));
|
||||
};
|
||||
|
||||
FilterManyWildcardsHostname.fid = FilterManyWildcardsHostname.prototype.fid = '*+h';
|
||||
@ -1316,6 +1373,9 @@ var getFilterClass = function(details) {
|
||||
var s = details.f;
|
||||
var wcOffset = s.indexOf('*');
|
||||
if ( wcOffset !== -1 ) {
|
||||
if ( details.hostnameAnchored ) {
|
||||
return FilterGenericHnAnchored;
|
||||
}
|
||||
if ( s.indexOf('*', wcOffset + 1) !== -1 ) {
|
||||
return details.anchor === 0 ? FilterManyWildcards : null;
|
||||
}
|
||||
@ -1388,47 +1448,6 @@ var getHostnameBasedFilterClass = function(details) {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Given a string, find a good token. Tokens which are too generic, i.e. very
|
||||
// common with a high probability of ending up as a miss, are not
|
||||
// good. Avoid if possible. This has a *significant* positive impact on
|
||||
// performance.
|
||||
// These "bad tokens" are collated manually.
|
||||
|
||||
var badTokens = {
|
||||
'com': true,
|
||||
'http': true,
|
||||
'https': true,
|
||||
'icon': true,
|
||||
'images': true,
|
||||
'img': true,
|
||||
'js': true,
|
||||
'net': true,
|
||||
'news': true,
|
||||
'www': true
|
||||
};
|
||||
|
||||
var findFirstGoodToken = function(s) {
|
||||
reGoodToken.lastIndex = 0;
|
||||
var matches;
|
||||
while ( matches = reGoodToken.exec(s) ) {
|
||||
if ( badTokens[matches[0]] === undefined ) {
|
||||
return matches;
|
||||
}
|
||||
}
|
||||
// No good token found, just return the first token from left
|
||||
reGoodToken.lastIndex = 0;
|
||||
return reGoodToken.exec(s);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var findHostnameToken = function(s) {
|
||||
reHostnameToken.lastIndex = 0;
|
||||
return reHostnameToken.exec(s);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Trim leading/trailing char "c"
|
||||
|
||||
var trimChar = function(s, c) {
|
||||
@ -1690,6 +1709,50 @@ FilterParser.prototype.parse = function(raw) {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Given a string, find a good token. Tokens which are too generic, i.e. very
|
||||
// common with a high probability of ending up as a miss, are not
|
||||
// good. Avoid if possible. This has a *significant* positive impact on
|
||||
// performance.
|
||||
// These "bad tokens" are collated manually.
|
||||
|
||||
var reHostnameToken = /^[0-9a-z]+/g;
|
||||
var reGoodToken = /[%0-9a-z]{2,}/g;
|
||||
|
||||
var badTokens = {
|
||||
'com': true,
|
||||
'http': true,
|
||||
'https': true,
|
||||
'icon': true,
|
||||
'images': true,
|
||||
'img': true,
|
||||
'js': true,
|
||||
'net': true,
|
||||
'news': true,
|
||||
'www': true
|
||||
};
|
||||
|
||||
var findFirstGoodToken = function(s) {
|
||||
reGoodToken.lastIndex = 0;
|
||||
var matches;
|
||||
while ( matches = reGoodToken.exec(s) ) {
|
||||
if ( badTokens.hasOwnProperty(matches[0]) ) {
|
||||
continue;
|
||||
}
|
||||
if ( s.charAt(reGoodToken.lastIndex) === '*' ) {
|
||||
continue;
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
// No good token found, just return the first token from left
|
||||
reGoodToken.lastIndex = 0;
|
||||
return reGoodToken.exec(s);
|
||||
};
|
||||
|
||||
var findHostnameToken = function(s) {
|
||||
reHostnameToken.lastIndex = 0;
|
||||
return reHostnameToken.exec(s);
|
||||
};
|
||||
|
||||
FilterParser.prototype.makeToken = function() {
|
||||
if ( this.isRegex ) {
|
||||
this.token = '*';
|
||||
@ -1698,7 +1761,8 @@ FilterParser.prototype.makeToken = function() {
|
||||
|
||||
var matches;
|
||||
|
||||
if ( this.hostnameAnchored ) {
|
||||
// Hostname-anchored with no wildcard always have a token index of 0.
|
||||
if ( this.hostnameAnchored && this.f.indexOf('*') === -1 ) {
|
||||
matches = findHostnameToken(this.f);
|
||||
if ( !matches || matches[0].length === 0 ) {
|
||||
return;
|
||||
@ -1799,7 +1863,8 @@ FilterContainer.prototype.factories = {
|
||||
'*+h': FilterManyWildcardsHostname,
|
||||
'//': FilterRegex,
|
||||
'//h': FilterRegexHostname,
|
||||
'{h}': FilterHostnameDict
|
||||
'{h}': FilterHostnameDict,
|
||||
'||_': FilterGenericHnAnchored
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -288,7 +288,7 @@
|
||||
if ( µb.remoteBlacklists.hasOwnProperty(path) ) {
|
||||
var entry = µb.remoteBlacklists[path];
|
||||
entry.entryCount = snfe.acceptedCount + cfe.acceptedCount - acceptedCount;
|
||||
entry.entryUsedCount = entry.entryCount - snfe.duplicateCount - cfe.duplicateCount + duplicateCount;
|
||||
entry.entryUsedCount = entry.entryCount - (snfe.duplicateCount + cfe.duplicateCount - duplicateCount);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -100,8 +100,13 @@ var onBeforeRequest = function(details) {
|
||||
//console.debug('traffic.js > onBeforeRequest(): ALLOW "%s" (%o) because "%s"', details.url, details, result);
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/114
|
||||
if ( isFrame && details.frameId > 0 ) {
|
||||
pageStore.setFrame(details.frameId, requestURL);
|
||||
frameId = details.frameId;
|
||||
if ( frameId > 0 ) {
|
||||
if ( isFrame ) {
|
||||
pageStore.setFrame(frameId, requestURL);
|
||||
} else if ( pageStore.getFrame(frameId) === null ) {
|
||||
pageStore.setFrame(frameId, requestURL);
|
||||
}
|
||||
}
|
||||
|
||||
// https://code.google.com/p/chromium/issues/detail?id=387198
|
||||
|
Loading…
Reference in New Issue
Block a user