diff --git a/toolkit/components/extensions/ProxyScriptContext.jsm b/toolkit/components/extensions/ProxyScriptContext.jsm
index 8e2ea2ce5140..a9770eea24ba 100644
--- a/toolkit/components/extensions/ProxyScriptContext.jsm
+++ b/toolkit/components/extensions/ProxyScriptContext.jsm
@@ -258,12 +258,14 @@ class ProxyChannelFilter {
// Copy from WebRequest.jsm with small changes.
getRequestData(channel, extraData) {
+ let originAttributes = channel.loadInfo && channel.loadInfo.originAttributes;
let data = {
requestId: String(channel.id),
url: channel.finalURL,
method: channel.method,
type: channel.type,
fromCache: !!channel.fromCache,
+ incognito: originAttributes && originAttributes.privateBrowsingId > 0,
originUrl: channel.originURL || undefined,
documentUrl: channel.documentURL || undefined,
diff --git a/toolkit/components/extensions/parent/ext-webRequest.js b/toolkit/components/extensions/parent/ext-webRequest.js
index a3293c3bf235..b07dad8c2dc4 100644
--- a/toolkit/components/extensions/parent/ext-webRequest.js
+++ b/toolkit/components/extensions/parent/ext-webRequest.js
@@ -24,7 +24,9 @@ function registerEvent(extension, eventName, fire, filter, info, remoteTab = nul
let event = data.serialize(eventName);
event.tabId = browserData.tabId;
-
+ if (data.originAttributes) {
+ event.incognito = data.originAttributes.privateBrowsingId > 0;
+ }
if (data.registerTraceableChannel) {
// If this is a primed listener, no tabParent was passed in here,
// but the convert() callback later in this function will be called
diff --git a/toolkit/components/extensions/schemas/proxy.json b/toolkit/components/extensions/schemas/proxy.json
index b1596de3648b..4ce910e5b0b7 100644
--- a/toolkit/components/extensions/schemas/proxy.json
+++ b/toolkit/components/extensions/schemas/proxy.json
@@ -147,6 +147,7 @@
"method": {"type": "string", "description": "Standard HTTP method."},
"frameId": {"type": "integer", "description": "The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in which the request happens. If the document of a (sub-)frame is loaded (type
is main_frame
or sub_frame
), frameId
indicates the ID of this frame, not the ID of the outer frame. Frame IDs are unique within a tab."},
"parentFrameId": {"type": "integer", "description": "ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists."},
+ "incognito": {"type": "boolean", "optional": true, "description": "True for private browsing requests."},
"originUrl": {"type": "string", "optional": true, "description": "URL of the resource that triggered this request."},
"documentUrl": {"type": "string", "optional": true, "description": "URL of the page into which the requested resource will be loaded."},
"tabId": {"type": "integer", "description": "The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab."},
diff --git a/toolkit/components/extensions/schemas/web_request.json b/toolkit/components/extensions/schemas/web_request.json
index b6d7e311495d..f3c6b2893951 100644
--- a/toolkit/components/extensions/schemas/web_request.json
+++ b/toolkit/components/extensions/schemas/web_request.json
@@ -425,6 +425,7 @@
"method": {"type": "string", "description": "Standard HTTP method."},
"frameId": {"type": "integer", "description": "The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in which the request happens. If the document of a (sub-)frame is loaded (type
is main_frame
or sub_frame
), frameId
indicates the ID of this frame, not the ID of the outer frame. Frame IDs are unique within a tab."},
"parentFrameId": {"type": "integer", "description": "ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists."},
+ "incognito": {"type": "boolean", "optional": true, "description": "True for private browsing requests."},
"originUrl": {"type": "string", "optional": true, "description": "URL of the resource that triggered this request."},
"documentUrl": {"type": "string", "optional": true, "description": "URL of the page into which the requested resource will be loaded."},
"requestBody": {
@@ -493,6 +494,7 @@
"method": {"type": "string", "description": "Standard HTTP method."},
"frameId": {"type": "integer", "description": "The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in which the request happens. If the document of a (sub-)frame is loaded (type
is main_frame
or sub_frame
), frameId
indicates the ID of this frame, not the ID of the outer frame. Frame IDs are unique within a tab."},
"parentFrameId": {"type": "integer", "description": "ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists."},
+ "incognito": {"type": "boolean", "optional": true, "description": "True for private browsing requests."},
"originUrl": {"type": "string", "optional": true, "description": "URL of the resource that triggered this request."},
"documentUrl": {"type": "string", "optional": true, "description": "URL of the page into which the requested resource will be loaded."},
"tabId": {"type": "integer", "description": "The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab."},
@@ -538,6 +540,7 @@
"method": {"type": "string", "description": "Standard HTTP method."},
"frameId": {"type": "integer", "description": "The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in which the request happens. If the document of a (sub-)frame is loaded (type
is main_frame
or sub_frame
), frameId
indicates the ID of this frame, not the ID of the outer frame. Frame IDs are unique within a tab."},
"parentFrameId": {"type": "integer", "description": "ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists."},
+ "incognito": {"type": "boolean", "optional": true, "description": "True for private browsing requests."},
"originUrl": {"type": "string", "optional": true, "description": "URL of the resource that triggered this request."},
"documentUrl": {"type": "string", "optional": true, "description": "URL of the page into which the requested resource will be loaded."},
"tabId": {"type": "integer", "description": "The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab."},
@@ -578,6 +581,7 @@
"method": {"type": "string", "description": "Standard HTTP method."},
"frameId": {"type": "integer", "description": "The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in which the request happens. If the document of a (sub-)frame is loaded (type
is main_frame
or sub_frame
), frameId
indicates the ID of this frame, not the ID of the outer frame. Frame IDs are unique within a tab."},
"parentFrameId": {"type": "integer", "description": "ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists."},
+ "incognito": {"type": "boolean", "optional": true, "description": "True for private browsing requests."},
"originUrl": {"type": "string", "optional": true, "description": "URL of the resource that triggered this request."},
"documentUrl": {"type": "string", "optional": true, "description": "URL of the page into which the requested resource will be loaded."},
"tabId": {"type": "integer", "description": "The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab."},
@@ -625,6 +629,7 @@
"method": {"type": "string", "description": "Standard HTTP method."},
"frameId": {"type": "integer", "description": "The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in which the request happens. If the document of a (sub-)frame is loaded (type
is main_frame
or sub_frame
), frameId
indicates the ID of this frame, not the ID of the outer frame. Frame IDs are unique within a tab."},
"parentFrameId": {"type": "integer", "description": "ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists."},
+ "incognito": {"type": "boolean", "optional": true, "description": "True for private browsing requests."},
"originUrl": {"type": "string", "optional": true, "description": "URL of the resource that triggered this request."},
"documentUrl": {"type": "string", "optional": true, "description": "URL of the page into which the requested resource will be loaded."},
"tabId": {"type": "integer", "description": "The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab."},
@@ -684,6 +689,7 @@
"method": {"type": "string", "description": "Standard HTTP method."},
"frameId": {"type": "integer", "description": "The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in which the request happens. If the document of a (sub-)frame is loaded (type
is main_frame
or sub_frame
), frameId
indicates the ID of this frame, not the ID of the outer frame. Frame IDs are unique within a tab."},
"parentFrameId": {"type": "integer", "description": "ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists."},
+ "incognito": {"type": "boolean", "optional": true, "description": "True for private browsing requests."},
"originUrl": {"type": "string", "optional": true, "description": "URL of the resource that triggered this request."},
"documentUrl": {"type": "string", "optional": true, "description": "URL of the page into which the requested resource will be loaded."},
"tabId": {"type": "integer", "description": "The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab."},
@@ -728,6 +734,7 @@
"method": {"type": "string", "description": "Standard HTTP method."},
"frameId": {"type": "integer", "description": "The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in which the request happens. If the document of a (sub-)frame is loaded (type
is main_frame
or sub_frame
), frameId
indicates the ID of this frame, not the ID of the outer frame. Frame IDs are unique within a tab."},
"parentFrameId": {"type": "integer", "description": "ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists."},
+ "incognito": {"type": "boolean", "optional": true, "description": "True for private browsing requests."},
"originUrl": {"type": "string", "optional": true, "description": "URL of the resource that triggered this request."},
"documentUrl": {"type": "string", "optional": true, "description": "URL of the page into which the requested resource will be loaded."},
"tabId": {"type": "integer", "description": "The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab."},
@@ -773,6 +780,7 @@
"method": {"type": "string", "description": "Standard HTTP method."},
"frameId": {"type": "integer", "description": "The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in which the request happens. If the document of a (sub-)frame is loaded (type
is main_frame
or sub_frame
), frameId
indicates the ID of this frame, not the ID of the outer frame. Frame IDs are unique within a tab."},
"parentFrameId": {"type": "integer", "description": "ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists."},
+ "incognito": {"type": "boolean", "optional": true, "description": "True for private browsing requests."},
"originUrl": {"type": "string", "optional": true, "description": "URL of the resource that triggered this request."},
"documentUrl": {"type": "string", "optional": true, "description": "URL of the page into which the requested resource will be loaded."},
"tabId": {"type": "integer", "description": "The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab."},
@@ -817,6 +825,7 @@
"method": {"type": "string", "description": "Standard HTTP method."},
"frameId": {"type": "integer", "description": "The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in which the request happens. If the document of a (sub-)frame is loaded (type
is main_frame
or sub_frame
), frameId
indicates the ID of this frame, not the ID of the outer frame. Frame IDs are unique within a tab."},
"parentFrameId": {"type": "integer", "description": "ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists."},
+ "incognito": {"type": "boolean", "optional": true, "description": "True for private browsing requests."},
"originUrl": {"type": "string", "optional": true, "description": "URL of the resource that triggered this request."},
"documentUrl": {"type": "string", "optional": true, "description": "URL of the page into which the requested resource will be loaded."},
"tabId": {"type": "integer", "description": "The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab."},
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_webRequest_incognito.js b/toolkit/components/extensions/test/xpcshell/test_ext_webRequest_incognito.js
index 8762094836d8..f306350e4357 100644
--- a/toolkit/components/extensions/test/xpcshell/test_ext_webRequest_incognito.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_webRequest_incognito.js
@@ -11,21 +11,41 @@ server.registerPathHandler("/dummy", (request, response) => {
add_task(async function test_incognito_webrequest_access() {
Services.prefs.setBoolPref("extensions.allowPrivateBrowsingByDefault", false);
- // This extension will fail if it gets a request
+ let pb_extension = ExtensionTestUtils.loadExtension({
+ incognitoOverride: "spanning",
+ manifest: {
+ permissions: ["webRequest", "webRequestBlocking", ""],
+ },
+ background() {
+ browser.webRequest.onBeforeRequest.addListener(async (details) => {
+ browser.test.assertTrue(details.incognito, "incognito flag is set");
+ browser.test.notifyPass("webRequest.private");
+ }, {urls: [""]}, ["blocking"]);
+ },
+ });
+ await pb_extension.startup();
+
let extension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["webRequest", "webRequestBlocking", ""],
},
background() {
browser.webRequest.onBeforeRequest.addListener(async (details) => {
- browser.test.fail("webrequest received incognito request");
+ browser.test.assertFalse(details.incognito, "incognito flag is not set");
+ browser.test.notifyPass("webRequest");
}, {urls: [""]}, ["blocking"]);
},
});
+ // Load non-incognito extension to check that private requests are invisible to it.
await extension.startup();
let contentPage = await ExtensionTestUtils.loadContentPage("http://example.com/dummy", {privateBrowsing: true});
+ await pb_extension.awaitFinish("webRequest.private");
+ await pb_extension.unload();
+ await contentPage.close();
+ contentPage = await ExtensionTestUtils.loadContentPage("http://example.com/dummy");
+ await extension.awaitFinish("webRequest");
await extension.unload();
await contentPage.close();
diff --git a/toolkit/components/extensions/test/xpcshell/test_proxy_incognito.js b/toolkit/components/extensions/test/xpcshell/test_proxy_incognito.js
index 072643605fcc..b7df6b2205f8 100644
--- a/toolkit/components/extensions/test/xpcshell/test_proxy_incognito.js
+++ b/toolkit/components/extensions/test/xpcshell/test_proxy_incognito.js
@@ -18,14 +18,15 @@ add_task(async function test_incognito_proxy_onRequest_access() {
// extension does not have permission.
Services.prefs.setBoolPref("extensions.allowPrivateBrowsingByDefault", false);
- // This extension will fail if it gets a request
+ // This extension will fail if it gets a private request.
let extension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["proxy", ""],
},
async background() {
browser.proxy.onRequest.addListener(async (details) => {
- browser.test.fail("proxy.onRequest received incognito request");
+ browser.test.assertFalse(details.incognito, "incognito flag is not set");
+ browser.test.notifyPass("proxy.onRequest");
}, {urls: [""]});
// Actual call arguments do not matter here.
@@ -42,7 +43,6 @@ add_task(async function test_incognito_proxy_onRequest_access() {
await extension.startup();
await extension.awaitMessage("ready");
- // This extension will succeed if it gets a request
let pextension = ExtensionTestUtils.loadExtension({
incognitoOverride: "spanning",
manifest: {
@@ -50,18 +50,22 @@ add_task(async function test_incognito_proxy_onRequest_access() {
},
background() {
browser.proxy.onRequest.addListener(async (details) => {
- browser.test.notifyPass("proxy.onRequest");
+ browser.test.assertTrue(details.incognito, "incognito flag is set");
+ browser.test.notifyPass("proxy.onRequest.private");
}, {urls: [""]});
},
});
await pextension.startup();
- let finished = pextension.awaitFinish("proxy.onRequest");
let contentPage = await ExtensionTestUtils.loadContentPage("http://example.com/dummy", {privateBrowsing: true});
- await finished;
+ await pextension.awaitFinish("proxy.onRequest.private");
+ await pextension.unload();
+ await contentPage.close();
+
+ contentPage = await ExtensionTestUtils.loadContentPage("http://example.com/dummy");
+ await extension.awaitFinish("proxy.onRequest");
await extension.unload();
- await pextension.unload();
await contentPage.close();
Services.prefs.clearUserPref("extensions.allowPrivateBrowsingByDefault");
diff --git a/toolkit/modules/addons/WebRequest.jsm b/toolkit/modules/addons/WebRequest.jsm
index bed5d06fd5e4..4022fd892b87 100644
--- a/toolkit/modules/addons/WebRequest.jsm
+++ b/toolkit/modules/addons/WebRequest.jsm
@@ -664,6 +664,7 @@ HttpObserverManager = {
},
getRequestData(channel, extraData) {
+ let originAttributes = channel.loadInfo && channel.loadInfo.originAttributes;
let data = {
requestId: String(channel.id),
url: channel.finalURL,
@@ -671,6 +672,7 @@ HttpObserverManager = {
browser: channel.browserElement,
type: channel.type,
fromCache: channel.fromCache,
+ originAttributes,
originUrl: channel.originURL || undefined,
documentUrl: channel.documentURL || undefined,