diff --git a/src/js/background.js b/src/js/background.js index fa23ecee01..338e9d9299 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -34,10 +34,19 @@ var incognito = require("incognito"); /** * Privacy Badger initializer. + * + * @param {Boolean} from_qunit don't intercept requests when run by unit tests */ -function Badger() { +function Badger(from_qunit) { let self = this; + // important: must be executed synchronously + // to register a "persistent" onBeforeRequest listener in Firefox + // https://github.com/mdn/sprints/issues/1015 + if (!from_qunit) { + webrequest.startBeforeReadyListener(); + } + self.webRTCAvailable = checkWebRTCBrowserSupport(); self.firstPartyDomainPotentiallyRequired = testCookiesFirstPartyDomain(); @@ -81,6 +90,11 @@ function Badger() { await dntHashesPromise; await tabDataPromise; + if (from_qunit) { + self.INITIALIZED = true; + return; + } + // start the listeners incognito.startListeners(); webrequest.startListeners(); @@ -88,6 +102,8 @@ function Badger() { FirefoxAndroid.startListeners(); startBackgroundListeners(); + webrequest.stopBeforeReadyListener(); + console.log("Privacy Badger is ready to rock!"); console.log("Set DEBUG=1 to view console messages."); self.INITIALIZED = true; @@ -987,4 +1003,4 @@ function startBackgroundListeners() { }); } -var badger = window.badger = new Badger(); +let badger = window.badger = new Badger(document.location.pathname == "/tests/index.html"); diff --git a/src/js/webrequest.js b/src/js/webrequest.js index 9b7b167886..fb4fbed7d4 100644 --- a/src/js/webrequest.js +++ b/src/js/webrequest.js @@ -34,7 +34,8 @@ var incognito = require("incognito"); var utils = require("utils"); /************ Local Variables *****************/ -var temporaryWidgetUnblock = {}; +let temporaryWidgetUnblock = {}; +let pendingTabs = new Set(); /***************** Blocking Listener Functions **************/ @@ -50,6 +51,10 @@ function onBeforeRequest(details) { type = details.type, url = details.url; + if (utils.isRestrictedUrl(url)) { + return {}; + } + if (type == "main_frame") { forgetTab(tab_id); badger.recordFrame(tab_id, frame_id, url); @@ -67,7 +72,7 @@ function onBeforeRequest(details) { return {cancel: true}; } - if (_isTabChromeInternal(tab_id)) { + if (tab_id < 0) { return {}; } @@ -141,8 +146,8 @@ function onBeforeSendHeaders(details) { type = details.type, url = details.url; - if (_isTabChromeInternal(tab_id)) { - // DNT policy requests: strip cookies + if (tab_id < 0 || utils.isRestrictedUrl(url)) { + // strip cookies from DNT policy requests if (type == "xmlhttprequest" && url.endsWith("/.well-known/dnt-policy.txt")) { // remove Cookie headers let newHeaders = []; @@ -157,6 +162,7 @@ function onBeforeSendHeaders(details) { }; } + // ignore otherwise return {}; } @@ -239,8 +245,8 @@ function onHeadersReceived(details) { var tab_id = details.tabId, url = details.url; - if (_isTabChromeInternal(tab_id)) { - // DNT policy responses: strip cookies, reject redirects + if (tab_id < 0 || utils.isRestrictedUrl(url)) { + // strip cookies, reject redirects from DNT policy responses if (details.type == "xmlhttprequest" && url.endsWith("/.well-known/dnt-policy.txt")) { // if it's a redirect, cancel it if (details.statusCode >= 300 && details.statusCode < 400) { @@ -262,6 +268,7 @@ function onHeadersReceived(details) { }; } + // ignore otherwise return {}; } @@ -512,26 +519,6 @@ function checkAction(tabId, requestHost, frameId) { return badger.storage.getBestAction(requestHost); } -/** - * Checks if the tab is chrome internal - * - * @param {Integer} tabId Id of the tab to test - * @returns {boolean} Returns true if the tab is chrome internal - * @private - */ -function _isTabChromeInternal(tabId) { - if (tabId < 0) { - return true; - } - - let frameData = badger.getFrameData(tabId); - if (!frameData || !frameData.url.startsWith("http")) { - return true; - } - - return false; -} - /** * Checks if the tab is a chrome-extension tab * @@ -680,11 +667,6 @@ function dispatcher(request, sender, sendResponse) { return sendResponse(); } - // Ignore requests from internal Chrome tabs. - if (_isTabChromeInternal(sender.tab.id)) { - return sendResponse(); - } - let frame_host = window.extractHostFromURL(request.frameUrl), tab_host = window.extractHostFromURL(sender.tab.url); @@ -1059,17 +1041,57 @@ function dispatcher(request, sender, sendResponse) { } } + +/** + * Cancels all requests, populates list of pending tabs to be reloaded later, + * when Privacy Badger is ready. + * + * @param {Object} details chrome.webRequest request details + * @returns {Object} + */ +function onBeforeReady(details) { + if (!pendingTabs || details.tabId < 0) { + return; + } + + pendingTabs.add(details.tabId); + + return { + cancel: true + }; +} + +/** + * Reloads all tabs that loaded before Privacy Badger was ready. + */ +function reloadPendingTabs() { + for (let tab_id of pendingTabs) { + chrome.tabs.reload(tab_id); + } + pendingTabs = null; +} + + /*************** Event Listeners *********************/ +function startBeforeReadyListener() { + chrome.webRequest.onBeforeRequest.addListener(onBeforeReady, {urls: [""]}, ["blocking"]); +} + +function stopBeforeReadyListener() { + chrome.webRequest.onBeforeRequest.removeListener(onBeforeReady); + reloadPendingTabs(); +} + function startListeners() { chrome.webNavigation.onBeforeNavigate.addListener(onNavigate); - chrome.webRequest.onBeforeRequest.addListener(onBeforeRequest, {urls: ["http://*/*", "https://*/*"]}, ["blocking"]); + chrome.webRequest.onBeforeRequest.addListener(onBeforeRequest, {urls: [""]}, ["blocking"]); let extraInfoSpec = ['requestHeaders', 'blocking']; if (chrome.webRequest.OnBeforeSendHeadersOptions.hasOwnProperty('EXTRA_HEADERS')) { extraInfoSpec.push('extraHeaders'); } - chrome.webRequest.onBeforeSendHeaders.addListener(onBeforeSendHeaders, {urls: ["http://*/*", "https://*/*"]}, extraInfoSpec); + chrome.webRequest.onBeforeSendHeaders.addListener(onBeforeSendHeaders, {urls: [""]}, extraInfoSpec); extraInfoSpec = ['responseHeaders', 'blocking']; if (chrome.webRequest.OnHeadersReceivedOptions.hasOwnProperty('EXTRA_HEADERS')) { @@ -1083,8 +1105,11 @@ function startListeners() { } /************************************** exports */ -var exports = {}; -exports.startListeners = startListeners; +let exports = { + startBeforeReadyListener, + startListeners, + stopBeforeReadyListener, +}; return exports; /************************************** exports */ })(); diff --git a/tests/selenium/pbtest.py b/tests/selenium/pbtest.py index 88a45bcdda..14e4080ff2 100644 --- a/tests/selenium/pbtest.py +++ b/tests/selenium/pbtest.py @@ -320,8 +320,10 @@ def run(self, result=None): # wait for Badger's storage, listeners, ... self.load_url(self.options_url) self.wait_for_script( - "return chrome.extension.getBackgroundPage()." - "badger.INITIALIZED" + "return (" + " chrome.extension &&" + " chrome.extension.getBackgroundPage().badger.INITIALIZED" + ");" ) driver.close() if driver.window_handles: