From cc5c4bb32e986bcbab30e25c9bccb59c1f529951 Mon Sep 17 00:00:00 2001 From: gorhill Date: Sun, 1 Mar 2015 08:57:43 -0500 Subject: [PATCH 01/20] mind pipe anchors when highlighting as per filter --- src/js/devtool-log.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/js/devtool-log.js b/src/js/devtool-log.js index e7075521b..5a2435283 100644 --- a/src/js/devtool-log.js +++ b/src/js/devtool-log.js @@ -59,6 +59,8 @@ var renderURL = function(url, filter) { .replace(/\?/g, '\\?') .replace('||', '') .replace(/\^/g, '.') + .replace(/^\|/g, '^') + .replace(/\$$/g, '$') .replace(/\*/g, '.*') ; } From 092bfbd274f7c0e868fa9f297fd08c79b8ca663b Mon Sep 17 00:00:00 2001 From: gorhill Date: Sun, 1 Mar 2015 11:20:30 -0500 Subject: [PATCH 02/20] oops --- src/js/devtool-log.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/devtool-log.js b/src/js/devtool-log.js index 5a2435283..29a8ae0df 100644 --- a/src/js/devtool-log.js +++ b/src/js/devtool-log.js @@ -60,7 +60,7 @@ var renderURL = function(url, filter) { .replace('||', '') .replace(/\^/g, '.') .replace(/^\|/g, '^') - .replace(/\$$/g, '$') + .replace(/\|$/g, '$') .replace(/\*/g, '.*') ; } From da3586adde9d19d943e64d865847ab08bb75581f Mon Sep 17 00:00:00 2001 From: Deathamns Date: Sun, 1 Mar 2015 20:21:05 +0100 Subject: [PATCH 03/20] Firefox/Fennec fixes --- platform/firefox/frameModule.js | 1 - platform/firefox/vapi-background.js | 28 +++++++++++++++++++++------- src/js/tab.js | 2 +- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/platform/firefox/frameModule.js b/platform/firefox/frameModule.js index 363f76faf..3a16c70a7 100644 --- a/platform/firefox/frameModule.js +++ b/platform/firefox/frameModule.js @@ -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, diff --git a/platform/firefox/vapi-background.js b/platform/firefox/vapi-background.js index a35cde7ed..bed630bfd 100644 --- a/platform/firefox/vapi-background.js +++ b/platform/firefox/vapi-background.js @@ -364,10 +364,15 @@ var tabWatcher = { return; } + var loc = win.location; + /*if ( loc.protocol === 'http' || loc.protocol === 'https' ) { + return; + }*/ + vAPI.tabs.onNavigation({ frameId: 0, - tabId: getOwnerWindow(win).getTabForWindow(win).id, - url: Services.io.newURI(win.location.href, null, null).asciiSpec + tabId: getOwnerWindow(win).BrowserApp.getTabForWindow(win).id, + url: Services.io.newURI(loc.href, null, null).asciiSpec }); } }; @@ -464,7 +469,7 @@ vAPI.tabs.registerListeners = function() { } var URI = browser.currentURI; if ( URI.schemeIs('chrome') && URI.host === location.host ) { - vAPI.tabs._remove(tab, win); + vAPI.tabs._remove(tab, getTabBrowser(win)); } } } @@ -482,7 +487,7 @@ vAPI.tabs.getTabId = function(target) { for ( var win of this.getWindows() ) { var tab = win.BrowserApp.getTabForBrowser(target); - if ( tab && tab.id ) { + if ( tab && tab.id !== undefined ) { return tab.id; } } @@ -1023,6 +1028,7 @@ var httpObserver = { classDescription: 'net-channel-event-sinks for ' + location.host, classID: Components.ID('{dc8d6319-5f6e-4438-999e-53722db99e84}'), contractID: '@' + location.host + '/net-channel-event-sinks;1', + REQDATAKEY: location.host + 'reqdata', ABORT: Components.results.NS_BINDING_ABORTED, ACCEPT: Components.results.NS_SUCCEEDED, // Request types: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIContentPolicy#Constants @@ -1185,7 +1191,7 @@ var httpObserver = { frameId, parentFrameId ]*/ - channelData = channel.getProperty(location.host + 'reqdata'); + channelData = channel.getProperty(this.REQDATAKEY); } catch (ex) { return; } @@ -1272,10 +1278,18 @@ var httpObserver = { return; } + /*if ( vAPI.fennec && lastRequest.type === this.MAIN_FRAME ) { + vAPI.tabs.onNavigation({ + frameId: 0, + tabId: lastRequest.tabId, + url: URI.asciiSpec + }); + }*/ + // If request is not handled we may use the data in on-modify-request if ( channel instanceof Ci.nsIWritablePropertyBag ) { channel.setProperty( - location.host + 'reqdata', + this.REQDATAKEY, [ lastRequest.type, lastRequest.tabId, @@ -1735,7 +1749,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'; diff --git a/src/js/tab.js b/src/js/tab.js index dbdb45b18..1c1945561 100644 --- a/src/js/tab.js +++ b/src/js/tab.js @@ -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 ) { From 9dbb00819f0a0f05206af815bf5ed9b527e6f775 Mon Sep 17 00:00:00 2001 From: Deathamns Date: Sun, 1 Mar 2015 21:38:51 +0100 Subject: [PATCH 04/20] Fennec: fix tab title --- platform/firefox/vapi-background.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/platform/firefox/vapi-background.js b/platform/firefox/vapi-background.js index bed630bfd..4c824544c 100644 --- a/platform/firefox/vapi-background.js +++ b/platform/firefox/vapi-background.js @@ -579,7 +579,7 @@ vAPI.tabs.get = function(tabId, callback) { } } - // for internal use + // For internal use if ( typeof callback !== 'function' ) { return tab; } @@ -595,9 +595,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 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, @@ -605,7 +610,7 @@ vAPI.tabs.get = function(tabId, callback) { windowId: windows.indexOf(win), active: tab === tabBrowser.selectedTab, url: browser.currentURI.asciiSpec, - title: tab.label + title: tabTitle }); }; From c28568f9b0f7082ca2131e3a77065800773b79b7 Mon Sep 17 00:00:00 2001 From: gorhill Date: Sun, 1 Mar 2015 17:25:48 -0500 Subject: [PATCH 05/20] support 2-letter hostname, for when using TLD alone --- src/js/background.js | 2 +- src/js/start.js | 4 ++-- src/js/static-net-filtering.js | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/js/background.js b/src/js/background.js index aa8033fad..9d84845ea 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -85,7 +85,7 @@ return { // read-only systemSettings: { - compiledMagic: 'iolkecdtfsiy', + compiledMagic: 'umxqgjonkvtf', selfieMagic: 'spqmeuaftfra' }, diff --git a/src/js/start.js b/src/js/start.js index de71253bb..bca966bb0 100644 --- a/src/js/start.js +++ b/src/js/start.js @@ -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); } }; diff --git a/src/js/static-net-filtering.js b/src/js/static-net-filtering.js index 792d130d4..d9eb6b638 100644 --- a/src/js/static-net-filtering.js +++ b/src/js/static-net-filtering.js @@ -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,7 +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 reHostnameRule = /^[0-9a-z][0-9a-z.-]*[0-9a-z]$/; var reHostnameToken = /^[0-9a-z]+/g; var reGoodToken = /[%0-9a-z]{2,}/g; var reURLPostHostnameAnchors = /[\/?#]/; From fc981aef29e82f8b8fea190e6fe67a96a63609a1 Mon Sep 17 00:00:00 2001 From: gorhill Date: Sun, 1 Mar 2015 19:25:36 -0500 Subject: [PATCH 06/20] speed boost for processing high-high generics --- src/js/contentscript-end.js | 85 ++++++++++++++++++++++++------------- 1 file changed, 56 insertions(+), 29 deletions(-) diff --git a/src/js/contentscript-end.js b/src/js/contentscript-end.js index a1ecfbc50..db3682cbb 100644 --- a/src/js/contentscript-end.js +++ b/src/js/contentscript-end.js @@ -93,25 +93,22 @@ var messager = vAPI.messaging.channel('contentscript-end.js'); return; } + //var tStart = window.performance.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 +119,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 +135,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 +154,7 @@ var messager = vAPI.messaging.channel('contentscript-end.js'); }; var otherRetrieveHandler = function(selectors) { + //var tStart = window.performance.now(); //console.debug('µBlock> contextNodes = %o', contextNodes); if ( selectors && selectors.highGenerics ) { highGenerics = selectors.highGenerics; @@ -196,6 +193,7 @@ var messager = vAPI.messaging.channel('contentscript-end.js'); addStyleTag(hideSelectors); } contextNodes.length = 0; + //console.debug('%f: uBlock: CSS injection time', window.performance.now() - tStart); }; var retrieveHandler = firstRetrieveHandler; @@ -206,10 +204,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 +347,46 @@ 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. + // Speed boost (uBlock 0.8.9.2+): + // Element.matches is MUCH faster than document.querySelector(). + // + // Example: + // gmail.com, a page rich in mutation events, which causes many calls + // to processHighHighGenerics(). Cumulative time of 24 calls to + // matchesSelector() (default filter lists): + // Chromium 40: + // - document.querySelector() = 44.79 ms + // - document.body.matches() = 6.06 ms + // Firefox 36: + // - document.querySelector() = 14.23 ms + // - document.body.matches() = 2.97 ms + // + // However, Element.matches() is available from Chromium 34/Firefox 34. So + // we fall back to slower document.querySelector() when Element.matches() + // is not available. + var matchesSelector = (function() { + if ( document.body && document.body.matches ) { + return function(selector) { + return document.body.matches(selector); + }; + } + return function(selector) { + return document.querySelector(selector) !== null; + }; + })(); + 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 = window.performance.now(); + if ( matchesSelector(highGenerics.hideHigh) === false ) { + //console.debug('%f: uBlock: high-high generic time', window.performance.now() - tStart); + return; + } injectedSelectors['{{highHighGenerics}}'] = true; // We need to filter out possible exception cosmetic filters from // high-high generics selectors. @@ -388,11 +420,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 +433,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 +446,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 +459,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 +472,8 @@ var messager = vAPI.messaging.channel('contentscript-end.js'); classesFromNodeList(document.querySelectorAll('[class]')); retrieveGenericSelectors(); + //console.debug('%f: uBlock: survey time', window.performance.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 +556,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 = {}; From 817c497a6b5422b523636c61e66ed98bfd1d5cf4 Mon Sep 17 00:00:00 2001 From: gorhill Date: Sun, 1 Mar 2015 19:25:56 -0500 Subject: [PATCH 07/20] interim version for dev build --- platform/chromium/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/chromium/manifest.json b/platform/chromium/manifest.json index 57ff1ab15..51bf2e590 100644 --- a/platform/chromium/manifest.json +++ b/platform/chromium/manifest.json @@ -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__", From caa1256e7004ff64d5f424911cbe5c2f99801511 Mon Sep 17 00:00:00 2001 From: gorhill Date: Sun, 1 Mar 2015 19:33:20 -0500 Subject: [PATCH 08/20] re-benchmarked using same settings as Chromium --- src/js/contentscript-end.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/js/contentscript-end.js b/src/js/contentscript-end.js index db3682cbb..076986c0f 100644 --- a/src/js/contentscript-end.js +++ b/src/js/contentscript-end.js @@ -358,8 +358,8 @@ var messager = vAPI.messaging.channel('contentscript-end.js'); // - document.querySelector() = 44.79 ms // - document.body.matches() = 6.06 ms // Firefox 36: - // - document.querySelector() = 14.23 ms - // - document.body.matches() = 2.97 ms + // - document.querySelector() = 27.10 ms + // - document.body.matches() = 3.50 ms // // However, Element.matches() is available from Chromium 34/Firefox 34. So // we fall back to slower document.querySelector() when Element.matches() From b0108c92233f280f46cb0892ce5e282343f6b8e4 Mon Sep 17 00:00:00 2001 From: gorhill Date: Sun, 1 Mar 2015 19:43:42 -0500 Subject: [PATCH 09/20] code review --- src/js/contentscript-end.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/contentscript-end.js b/src/js/contentscript-end.js index 076986c0f..d383283ea 100644 --- a/src/js/contentscript-end.js +++ b/src/js/contentscript-end.js @@ -103,7 +103,7 @@ var messager = vAPI.messaging.channel('contentscript-end.js'); var nullArray = { push: function(){} }; var retrieveGenericSelectors = function() { - if ( lowGenericSelectors.length > 0 || highGenerics === null ) { + if ( lowGenericSelectors.length !== 0 || highGenerics === null ) { //console.log('µBlock> ABP cosmetic filters: retrieving CSS rules using %d selectors', lowGenericSelectors.length); messager.send({ what: 'retrieveGenericCosmeticSelectors', From b6f1aa263c25749f41a2c913425a75c8b717b2f9 Mon Sep 17 00:00:00 2001 From: gorhill Date: Sun, 1 Mar 2015 19:54:17 -0500 Subject: [PATCH 10/20] I misunderstood Element.matches(), reverting --- src/js/contentscript-end.js | 30 +----------------------------- 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/src/js/contentscript-end.js b/src/js/contentscript-end.js index d383283ea..f8f028fa0 100644 --- a/src/js/contentscript-end.js +++ b/src/js/contentscript-end.js @@ -347,34 +347,6 @@ 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. - // Speed boost (uBlock 0.8.9.2+): - // Element.matches is MUCH faster than document.querySelector(). - // - // Example: - // gmail.com, a page rich in mutation events, which causes many calls - // to processHighHighGenerics(). Cumulative time of 24 calls to - // matchesSelector() (default filter lists): - // Chromium 40: - // - document.querySelector() = 44.79 ms - // - document.body.matches() = 6.06 ms - // Firefox 36: - // - document.querySelector() = 27.10 ms - // - document.body.matches() = 3.50 ms - // - // However, Element.matches() is available from Chromium 34/Firefox 34. So - // we fall back to slower document.querySelector() when Element.matches() - // is not available. - var matchesSelector = (function() { - if ( document.body && document.body.matches ) { - return function(selector) { - return document.body.matches(selector); - }; - } - return function(selector) { - return document.querySelector(selector) !== null; - }; - })(); - var processHighHighGenericsTimer = null; var processHighHighGenerics = function() { @@ -383,7 +355,7 @@ var messager = vAPI.messaging.channel('contentscript-end.js'); return; } //var tStart = window.performance.now(); - if ( matchesSelector(highGenerics.hideHigh) === false ) { + if ( document.querySelector(highGenerics.hideHigh) === null ) { //console.debug('%f: uBlock: high-high generic time', window.performance.now() - tStart); return; } From bd0e07bef2e7abb8e771ad8375a9d8a8082ca515 Mon Sep 17 00:00:00 2001 From: gorhill Date: Sun, 1 Mar 2015 20:26:33 -0500 Subject: [PATCH 11/20] high-high generic: do not try forever --- src/js/contentscript-end.js | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/js/contentscript-end.js b/src/js/contentscript-end.js index f8f028fa0..d67be9b22 100644 --- a/src/js/contentscript-end.js +++ b/src/js/contentscript-end.js @@ -93,7 +93,8 @@ var messager = vAPI.messaging.channel('contentscript-end.js'); return; } - //var tStart = window.performance.now(); + //var timer = window.performance || Date; + //var tStart = timer.now(); var queriedSelectors = {}; var injectedSelectors = {}; @@ -154,7 +155,7 @@ var messager = vAPI.messaging.channel('contentscript-end.js'); }; var otherRetrieveHandler = function(selectors) { - //var tStart = window.performance.now(); + //var tStart = timer.now(); //console.debug('µBlock> contextNodes = %o', contextNodes); if ( selectors && selectors.highGenerics ) { highGenerics = selectors.highGenerics; @@ -193,7 +194,7 @@ var messager = vAPI.messaging.channel('contentscript-end.js'); addStyleTag(hideSelectors); } contextNodes.length = 0; - //console.debug('%f: uBlock: CSS injection time', window.performance.now() - tStart); + //console.debug('%f: uBlock: CSS injection time', timer.now() - tStart); }; var retrieveHandler = firstRetrieveHandler; @@ -347,6 +348,7 @@ 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 = 0; var processHighHighGenericsTimer = null; var processHighHighGenerics = function() { @@ -354,9 +356,16 @@ var messager = vAPI.messaging.channel('contentscript-end.js'); if ( injectedSelectors.hasOwnProperty('{{highHighGenerics}}') ) { return; } - //var tStart = window.performance.now(); + //var tStart = timer.now(); if ( document.querySelector(highGenerics.hideHigh) === null ) { - //console.debug('%f: uBlock: high-high generic time', window.performance.now() - tStart); + //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 >= 8 ) { + injectedSelectors['{{highHighGenerics}}'] = true; + console.debug('high-high generic: clearly not needed...'); + } return; } injectedSelectors['{{highHighGenerics}}'] = true; @@ -444,7 +453,7 @@ var messager = vAPI.messaging.channel('contentscript-end.js'); classesFromNodeList(document.querySelectorAll('[class]')); retrieveGenericSelectors(); - //console.debug('%f: uBlock: survey time', window.performance.now() - tStart); + //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 From 83975124a41e135374f1555f241525b12b5b53a6 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 1 Mar 2015 21:09:28 -0700 Subject: [PATCH 12/20] Safari: XHR should explicitly fail. Fixes #878 --- platform/safari/vapi-client.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/platform/safari/vapi-client.js b/platform/safari/vapi-client.js index a6d5d1481..6e0eacf79 100644 --- a/platform/safari/vapi-client.js +++ b/platform/safari/vapi-client.js @@ -236,7 +236,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 +251,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 += "\ From 91c764821267e17b02a09a26ac2130db500e744f Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 1 Mar 2015 21:39:15 -0700 Subject: [PATCH 13/20] Safari: minor scoping tweaks --- platform/safari/vapi-client.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/platform/safari/vapi-client.js b/platform/safari/vapi-client.js index 6e0eacf79..59c08de4b 100644 --- a/platform/safari/vapi-client.js +++ b/platform/safari/vapi-client.js @@ -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(); } From 8bedabb5ef23db6c0deab54b9ed718b4c8b2d4f3 Mon Sep 17 00:00:00 2001 From: Deathamns Date: Mon, 2 Mar 2015 12:52:04 +0100 Subject: [PATCH 14/20] Firefox: handle behind-the-scene redirects --- platform/firefox/vapi-background.js | 57 ++++++++++++++++------------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/platform/firefox/vapi-background.js b/platform/firefox/vapi-background.js index 4c824544c..6a7f3b295 100644 --- a/platform/firefox/vapi-background.js +++ b/platform/firefox/vapi-background.js @@ -1164,13 +1164,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; }, @@ -1241,10 +1241,28 @@ var httpObserver = { var lastRequest = this.lastRequest; if ( lastRequest.url === null ) { - this.handleRequest(channel, URI, { + result = this.handleRequest(channel, URI, { tabId: vAPI.noTabId, - type: channel.loadInfo && channel.loadInfo.contentPolicyType || 1 + type: channel.loadInfo && channel.loadInfo.contentPolicyType }); + + if ( result === true ) { + return; + } + + if ( channel instanceof Ci.nsIWritablePropertyBag === false ) { + return; + } + + // Carry data for behind-the-scene redirects + channelData = [ + channel.loadInfo && channel.loadInfo.contentPolicyType || 1, + vAPI.noTabId, + null, + 0, + -1 + ]; + channel.setProperty(this.REQDATAKEY, channelData); return; } @@ -1293,16 +1311,14 @@ var httpObserver = { // 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 - ] - ); + channelData = [ + lastRequest.type, + lastRequest.tabId, + sourceTabId, + lastRequest.frameId, + lastRequest.parentFrameId + ]; + channel.setProperty(this.REQDATAKEY, channelData); } }, @@ -1312,12 +1328,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') ) { @@ -1328,10 +1338,7 @@ 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(location.host + 'reqdata'); + var channelData = oldChannel.getProperty(this.REQDATAKEY); if ( this.handlePopup(URI, channelData[1], channelData[2]) ) { result = this.ABORT; @@ -1352,7 +1359,7 @@ var httpObserver = { // Carry the data on in case of multiple redirects if ( newChannel instanceof Ci.nsIWritablePropertyBag ) { - newChannel.setProperty(location.host + 'reqdata', channelData); + newChannel.setProperty(this.REQDATAKEY, channelData); } } catch (ex) { // console.error(ex); From 1136734e339f52008c5900e06a3dccd84d8b4a19 Mon Sep 17 00:00:00 2001 From: gorhill Date: Mon, 2 Mar 2015 10:41:51 -0500 Subject: [PATCH 15/20] this fixes #915 --- src/js/background.js | 2 +- src/js/pagestore.js | 2 +- src/js/static-net-filtering.js | 163 +++++++++++++++++++++++---------- src/js/traffic.js | 9 +- 4 files changed, 123 insertions(+), 53 deletions(-) diff --git a/src/js/background.js b/src/js/background.js index 9d84845ea..d9bb7c91d 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -85,7 +85,7 @@ return { // read-only systemSettings: { - compiledMagic: 'umxqgjonkvtf', + compiledMagic: 'fkaywfqahncj', selfieMagic: 'spqmeuaftfra' }, diff --git a/src/js/pagestore.js b/src/js/pagestore.js index 09dc1934f..a8cb32dbd 100644 --- a/src/js/pagestore.js +++ b/src/js/pagestore.js @@ -575,7 +575,7 @@ PageStore.prototype.disposeFrameStores = function() { /******************************************************************************/ PageStore.prototype.getFrame = function(frameId) { - return this.frames[frameId]; + return this.frames[frameId] || null; }; /******************************************************************************/ diff --git a/src/js/static-net-filtering.js b/src/js/static-net-filtering.js index d9eb6b638..a68e347dc 100644 --- a/src/js/static-net-filtering.js +++ b/src/js/static-net-filtering.js @@ -89,8 +89,6 @@ 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 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 }; /******************************************************************************/ diff --git a/src/js/traffic.js b/src/js/traffic.js index ed1eb63d7..a17d8e467 100644 --- a/src/js/traffic.js +++ b/src/js/traffic.js @@ -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 From 09740463a71bec2b3d689f7a039cabfdedf5608c Mon Sep 17 00:00:00 2001 From: gorhill Date: Mon, 2 Mar 2015 10:54:15 -0500 Subject: [PATCH 16/20] code review --- src/js/contentscript-end.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/js/contentscript-end.js b/src/js/contentscript-end.js index d67be9b22..5efbeb797 100644 --- a/src/js/contentscript-end.js +++ b/src/js/contentscript-end.js @@ -348,7 +348,7 @@ 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 = 0; + var processHighHighGenericsMisses = 8; var processHighHighGenericsTimer = null; var processHighHighGenerics = function() { @@ -359,12 +359,12 @@ var messager = vAPI.messaging.channel('contentscript-end.js'); //var tStart = timer.now(); if ( document.querySelector(highGenerics.hideHigh) === null ) { //console.debug('%f: high-high generic test time', timer.now() - tStart); - processHighHighGenericsMisses += 1; + processHighHighGenericsMisses -= 1; // Too many misses for these nagging highly generic CSS rules, // so we will just skip them from now on. - if ( processHighHighGenericsMisses >= 8 ) { + if ( processHighHighGenericsMisses === 0 ) { injectedSelectors['{{highHighGenerics}}'] = true; - console.debug('high-high generic: clearly not needed...'); + console.debug('high-high generic: apparently not needed...'); } return; } From aaddab2023f0da305cc383c515c5c4f3fcaf5ea8 Mon Sep 17 00:00:00 2001 From: gorhill Date: Mon, 2 Mar 2015 11:01:21 -0500 Subject: [PATCH 17/20] this fixes #916 --- src/js/cosmetic-filtering.js | 2 +- src/js/storage.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/js/cosmetic-filtering.js b/src/js/cosmetic-filtering.js index 1f54e0b79..e4b66eb6f 100644 --- a/src/js/cosmetic-filtering.js +++ b/src/js/cosmetic-filtering.js @@ -1199,7 +1199,7 @@ FilterContainer.prototype.retrieveDomainSelectors = function(request) { /******************************************************************************/ FilterContainer.prototype.getFilterCount = function() { - return this.acceptedCount; + return this.acceptedCount - this.duplicateCount; }; /******************************************************************************/ diff --git a/src/js/storage.js b/src/js/storage.js index f3d358966..beb3edeed 100644 --- a/src/js/storage.js +++ b/src/js/storage.js @@ -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); } }; From 4a9e6c22ccaa4967d1aecd93b681cb3d0c7538ff Mon Sep 17 00:00:00 2001 From: gorhill Date: Mon, 2 Mar 2015 11:25:45 -0500 Subject: [PATCH 18/20] code review --- src/js/static-net-filtering.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/static-net-filtering.js b/src/js/static-net-filtering.js index a68e347dc..8faf9dd28 100644 --- a/src/js/static-net-filtering.js +++ b/src/js/static-net-filtering.js @@ -904,7 +904,7 @@ FilterGenericHnAnchored.prototype.match = function(url) { FilterGenericHnAnchored.fid = FilterGenericHnAnchored.prototype.fid = '||_'; FilterGenericHnAnchored.prototype.toString = function() { - return this.s; + return '||' + this.s; }; FilterGenericHnAnchored.prototype.toSelfie = function() { From cc47d13207657ebee2ab68b4211c311589c598a1 Mon Sep 17 00:00:00 2001 From: Deathamns Date: Mon, 2 Mar 2015 17:49:25 +0100 Subject: [PATCH 19/20] Firefox: workaround for #886 --- platform/firefox/vapi-background.js | 54 ++++++++++++++--------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/platform/firefox/vapi-background.js b/platform/firefox/vapi-background.js index 6a7f3b295..b6f3f7410 100644 --- a/platform/firefox/vapi-background.js +++ b/platform/firefox/vapi-background.js @@ -1052,14 +1052,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); @@ -1238,12 +1231,21 @@ 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 ) { + lastRequest.type = channel.loadInfo && channel.loadInfo.contentPolicyType || 1; result = this.handleRequest(channel, URI, { tabId: vAPI.noTabId, - type: channel.loadInfo && channel.loadInfo.contentPolicyType + type: lastRequest.type }); if ( result === true ) { @@ -1255,14 +1257,10 @@ var httpObserver = { } // Carry data for behind-the-scene redirects - channelData = [ - channel.loadInfo && channel.loadInfo.contentPolicyType || 1, - vAPI.noTabId, - null, - 0, - -1 - ]; - channel.setProperty(this.REQDATAKEY, channelData); + channel.setProperty( + this.REQDATAKEY, + [lastRequest.type, vAPI.noTabId, null, 0, -1] + ); return; } @@ -1311,14 +1309,13 @@ var httpObserver = { // If request is not handled we may use the data in on-modify-request if ( channel instanceof Ci.nsIWritablePropertyBag ) { - channelData = [ + channel.setProperty(this.REQDATAKEY, [ lastRequest.type, lastRequest.tabId, sourceTabId, lastRequest.frameId, lastRequest.parentFrameId - ]; - channel.setProperty(this.REQDATAKEY, channelData); + ]); } }, @@ -1385,12 +1382,15 @@ vAPI.net.registerListeners = function() { var shouldLoadListener = function(e) { var details = e.data; 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] = { + url: details.url, + type: details.type, + tabId: vAPI.tabs.getTabId(e.target), + frameId: details.frameId, + parentFrameId: details.parentFrameId, + openerURL: details.openerURL + }; }; vAPI.messaging.globalMessageManager.addMessageListener( From 1d3205ea817ccb8a2f03bbaecc9daf19440e300b Mon Sep 17 00:00:00 2001 From: Deathamns Date: Mon, 2 Mar 2015 18:36:04 +0100 Subject: [PATCH 20/20] Firefox: block popups earlier --- platform/firefox/vapi-background.js | 96 ++++++++++++++--------------- 1 file changed, 46 insertions(+), 50 deletions(-) diff --git a/platform/firefox/vapi-background.js b/platform/firefox/vapi-background.js index b6f3f7410..ed74663f6 100644 --- a/platform/firefox/vapi-background.js +++ b/platform/firefox/vapi-background.js @@ -1182,13 +1182,6 @@ var httpObserver = { } try { - /*[ - type, - tabId, - sourceTabId - given if it was a popup, - frameId, - parentFrameId - ]*/ channelData = channel.getProperty(this.REQDATAKEY); } catch (ex) { return; @@ -1198,7 +1191,7 @@ var httpObserver = { return; } - if ( (1 << channelData[0] & this.VALID_CSP_TARGETS) === 0 ) { + if ( (1 << channelData[4] & this.VALID_CSP_TARGETS) === 0 ) { return; } @@ -1212,9 +1205,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 }); @@ -1268,33 +1261,6 @@ 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; } @@ -1310,11 +1276,11 @@ var httpObserver = { // 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 + lastRequest.parentFrameId, + lastRequest.sourceTabId, + lastRequest.tabId, + lastRequest.type ]); } }, @@ -1337,16 +1303,16 @@ var httpObserver = { 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) ) { @@ -1381,15 +1347,45 @@ 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[1] = lastRequest[0]; lastRequest[0] = { - url: details.url, - type: details.type, - tabId: vAPI.tabs.getTabId(e.target), frameId: details.frameId, parentFrameId: details.parentFrameId, - openerURL: details.openerURL + sourceTabId: sourceTabId, + tabId: tabId, + type: details.type, + url: details.url }; };