1
0
mirror of https://github.com/gorhill/uBlock.git synced 2024-07-08 12:57:57 +02:00
This commit is contained in:
AlexVallat 2015-03-02 19:08:05 +00:00
commit e222ace6ef
14 changed files with 278 additions and 194 deletions

View File

@ -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__",

View File

@ -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,

View File

@ -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';

View File

@ -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 += "\

View File

@ -85,7 +85,7 @@ return {
// read-only
systemSettings: {
compiledMagic: 'iolkecdtfsiy',
compiledMagic: 'fkaywfqahncj',
selfieMagic: 'spqmeuaftfra'
},

View File

@ -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 = {};

View File

@ -1199,7 +1199,7 @@ FilterContainer.prototype.retrieveDomainSelectors = function(request) {
/******************************************************************************/
FilterContainer.prototype.getFilterCount = function() {
return this.acceptedCount;
return this.acceptedCount - this.duplicateCount;
};
/******************************************************************************/

View File

@ -59,6 +59,8 @@ var renderURL = function(url, filter) {
.replace(/\?/g, '\\?')
.replace('||', '')
.replace(/\^/g, '.')
.replace(/^\|/g, '^')
.replace(/\|$/g, '$')
.replace(/\*/g, '.*')
;
}

View File

@ -575,7 +575,7 @@ PageStore.prototype.disposeFrameStores = function() {
/******************************************************************************/
PageStore.prototype.getFrame = function(frameId) {
return this.frames[frameId];
return this.frames[frameId] || null;
};
/******************************************************************************/

View File

@ -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);
}
};

View File

@ -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
};
/******************************************************************************/

View File

@ -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);
}
};

View File

@ -47,7 +47,7 @@ vAPI.tabs.onNavigation = function(details) {
// The hostname of the bound document must always be present in the
// mini-matrix. That's the best place I could find for the fix, all other
// options had bad side-effects or complications.
// TODO: Evantually, we will have to use an API to check whether a scheme
// TODO: Evantually, we will have to use an API to check whether a scheme
// is supported as I suspect we are going to start to see `ws`, `wss`
// as well soon.
if ( pageStore && details.url.lastIndexOf('http', 0) === 0 ) {

View File

@ -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