Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cancel requests before Badger is ready #2566

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions src/js/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -81,13 +90,20 @@ function Badger() {
await dntHashesPromise;
await tabDataPromise;

if (from_qunit) {
self.INITIALIZED = true;
return;
}

// start the listeners
incognito.startListeners();
webrequest.startListeners();
HeuristicBlocking.startListeners();
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;
Expand Down Expand Up @@ -987,4 +1003,4 @@ function startBackgroundListeners() {
});
}

var badger = window.badger = new Badger();
let badger = window.badger = new Badger(document.location.pathname == "/tests/index.html");
95 changes: 60 additions & 35 deletions src/js/webrequest.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 **************/

Expand All @@ -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);
Expand All @@ -67,7 +72,7 @@ function onBeforeRequest(details) {
return {cancel: true};
}

if (_isTabChromeInternal(tab_id)) {
if (tab_id < 0) {
return {};
}

Expand Down Expand Up @@ -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 = [];
Expand All @@ -157,6 +162,7 @@ function onBeforeSendHeaders(details) {
};
}

// ignore otherwise
return {};
}

Expand Down Expand Up @@ -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) {
Expand All @@ -262,6 +268,7 @@ function onHeadersReceived(details) {
};
}

// ignore otherwise
return {};
}

Expand Down Expand Up @@ -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
*
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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: ["<all_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: ["<all_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: ["<all_urls>"]}, extraInfoSpec);

extraInfoSpec = ['responseHeaders', 'blocking'];
if (chrome.webRequest.OnHeadersReceivedOptions.hasOwnProperty('EXTRA_HEADERS')) {
Expand All @@ -1083,8 +1105,11 @@ function startListeners() {
}

/************************************** exports */
var exports = {};
exports.startListeners = startListeners;
let exports = {
startBeforeReadyListener,
startListeners,
stopBeforeReadyListener,
};
return exports;
/************************************** exports */
})();
6 changes: 4 additions & 2 deletions tests/selenium/pbtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down