Bug 1545163 add incognito flag to proxy and webrequest details r=robwu
authorShane Caraveo <scaraveo@mozilla.com>
Mon, 29 Apr 2019 18:00:12 +0000
changeset 471798 7ba49ce135e667a8e97f00889a434965f331bfb8
parent 471797 50b7f764f4afc39d21c1b96c8c11505daaf6e4a4
child 471799 e64b96d4af3d9d98b34541217f61ff138a1c7880
push id35935
push usershindli@mozilla.com
push dateTue, 30 Apr 2019 03:46:04 +0000
treeherdermozilla-central@f3c2a7206699 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrobwu
bugs1545163
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1545163 add incognito flag to proxy and webrequest details r=robwu Differential Revision: https://phabricator.services.mozilla.com/D28925
toolkit/components/extensions/ProxyScriptContext.jsm
toolkit/components/extensions/parent/ext-webRequest.js
toolkit/components/extensions/schemas/proxy.json
toolkit/components/extensions/schemas/web_request.json
toolkit/components/extensions/test/xpcshell/test_ext_webRequest_incognito.js
toolkit/components/extensions/test/xpcshell/test_proxy_incognito.js
toolkit/modules/addons/WebRequest.jsm
--- a/toolkit/components/extensions/ProxyScriptContext.jsm
+++ b/toolkit/components/extensions/ProxyScriptContext.jsm
@@ -253,22 +253,24 @@ class ProxyChannelFilter {
     ProxyService.registerChannelFilter(
       this /* nsIProtocolProxyChannelFilter aFilter */,
       0 /* unsigned long aPosition */
     );
   }
 
   // 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,
 
       frameId: channel.windowId,
       parentFrameId: channel.parentWindowId,
 
       frameAncestors: channel.frameAncestors || undefined,
--- a/toolkit/components/extensions/parent/ext-webRequest.js
+++ b/toolkit/components/extensions/parent/ext-webRequest.js
@@ -19,17 +19,19 @@ function registerEvent(extension, eventN
       return;
     }
     if (filter.windowId != null && browserData.windowId != filter.windowId) {
       return;
     }
 
     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
       // when the background page is started.  Force that to happen here
       // after which we'll have a valid tabParent.
       if (fire.wakeup) {
         await fire.wakeup();
       }
--- a/toolkit/components/extensions/schemas/proxy.json
+++ b/toolkit/components/extensions/schemas/proxy.json
@@ -142,16 +142,17 @@
             "type": "object",
             "name": "details",
             "properties": {
               "requestId": {"type": "string", "description": "The ID of the request. Request IDs are unique within a browser session. As a result, they could be used to relate different events of the same request."},
               "url": {"type": "string"},
               "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 (<code>type</code> is <code>main_frame</code> or <code>sub_frame</code>), <code>frameId</code> 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."},
               "type": {"$ref": "webRequest.ResourceType", "description": "How the requested resource will be used."},
               "timeStamp": {"type": "number", "description": "The time when this signal is triggered, in milliseconds since the epoch."},
               "ip": {"type": "string", "optional": true, "description": "The server IP address that the request was actually sent to. Note that it may be a literal IPv6 address."},
               "fromCache": {"type": "boolean", "description": "Indicates if this response was fetched from disk cache."},
               "requestHeaders": {"$ref": "webRequest.HttpHeaders", "optional": true, "description": "The HTTP request headers that are going to be sent out with this request."}
--- a/toolkit/components/extensions/schemas/web_request.json
+++ b/toolkit/components/extensions/schemas/web_request.json
@@ -420,16 +420,17 @@
             "type": "object",
             "name": "details",
             "properties": {
               "requestId": {"type": "string", "description": "The ID of the request. Request IDs are unique within a browser session. As a result, they could be used to relate different events of the same request."},
               "url": {"type": "string"},
               "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 (<code>type</code> is <code>main_frame</code> or <code>sub_frame</code>), <code>frameId</code> 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": {
                 "type": "object",
                 "optional": true,
                 "description": "Contains the HTTP request body data. Only provided if extraInfoSpec contains 'requestBody'.",
                 "properties": {
                   "error": {"type": "string", "optional": true, "description": "Errors when obtaining request body data."},
@@ -488,16 +489,17 @@
             "type": "object",
             "name": "details",
             "properties": {
               "requestId": {"type": "string", "description": "The ID of the request. Request IDs are unique within a browser session. As a result, they could be used to relate different events of the same request."},
               "url": {"type": "string"},
               "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 (<code>type</code> is <code>main_frame</code> or <code>sub_frame</code>), <code>frameId</code> 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."},
               "type": {"$ref": "ResourceType", "description": "How the requested resource will be used."},
               "timeStamp": {"type": "number", "description": "The time when this signal is triggered, in milliseconds since the epoch."},
               "requestHeaders": {"$ref": "HttpHeaders", "optional": true, "description": "The HTTP request headers that are going to be sent out with this request."}
             }
           }
@@ -533,16 +535,17 @@
             "type": "object",
             "name": "details",
             "properties": {
               "requestId": {"type": "string", "description": "The ID of the request. Request IDs are unique within a browser session. As a result, they could be used to relate different events of the same request."},
               "url": {"type": "string"},
               "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 (<code>type</code> is <code>main_frame</code> or <code>sub_frame</code>), <code>frameId</code> 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."},
               "type": {"$ref": "ResourceType", "description": "How the requested resource will be used."},
               "timeStamp": {"type": "number", "description": "The time when this signal is triggered, in milliseconds since the epoch."},
               "requestHeaders": {"$ref": "HttpHeaders", "optional": true, "description": "The HTTP request headers that have been sent out with this request."}
             }
           }
@@ -573,16 +576,17 @@
             "type": "object",
             "name": "details",
             "properties": {
               "requestId": {"type": "string", "description": "The ID of the request. Request IDs are unique within a browser session. As a result, they could be used to relate different events of the same request."},
               "url": {"type": "string"},
               "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 (<code>type</code> is <code>main_frame</code> or <code>sub_frame</code>), <code>frameId</code> 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."},
               "type": {"$ref": "ResourceType", "description": "How the requested resource will be used."},
               "timeStamp": {"type": "number", "description": "The time when this signal is triggered, in milliseconds since the epoch."},
               "statusLine": {"type": "string", "description": "HTTP status line of the response or the 'HTTP/0.9 200 OK' string for HTTP/0.9 responses (i.e., responses that lack a status line)."},
               "responseHeaders": {"$ref": "HttpHeaders", "optional": true, "description": "The HTTP response headers that have been received with this response."},
               "statusCode": {"type": "integer", "description": "Standard HTTP status code returned by the server."}
@@ -620,16 +624,17 @@
             "type": "object",
             "name": "details",
             "properties": {
               "requestId": {"type": "string", "description": "The ID of the request. Request IDs are unique within a browser session. As a result, they could be used to relate different events of the same request."},
               "url": {"type": "string"},
               "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 (<code>type</code> is <code>main_frame</code> or <code>sub_frame</code>), <code>frameId</code> 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."},
               "type": {"$ref": "ResourceType", "description": "How the requested resource will be used."},
               "timeStamp": {"type": "number", "description": "The time when this signal is triggered, in milliseconds since the epoch."},
               "scheme": {"type": "string", "description": "The authentication scheme, e.g. Basic or Digest."},
               "realm": {"type": "string", "description": "The authentication realm provided by the server, if there is one.", "optional": true},
               "challenger": {"type": "object", "description": "The server requesting authentication.", "properties": {"host": {"type": "string"}, "port": {"type": "integer"}}},
@@ -679,16 +684,17 @@
             "type": "object",
             "name": "details",
             "properties": {
               "requestId": {"type": "string", "description": "The ID of the request. Request IDs are unique within a browser session. As a result, they could be used to relate different events of the same request."},
               "url": {"type": "string"},
               "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 (<code>type</code> is <code>main_frame</code> or <code>sub_frame</code>), <code>frameId</code> 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."},
               "type": {"$ref": "ResourceType", "description": "How the requested resource will be used."},
               "timeStamp": {"type": "number", "description": "The time when this signal is triggered, in milliseconds since the epoch."},
               "ip": {"type": "string", "optional": true, "description": "The server IP address that the request was actually sent to. Note that it may be a literal IPv6 address."},
               "fromCache": {"type": "boolean", "description": "Indicates if this response was fetched from disk cache."},
               "statusCode": {"type": "integer", "description": "Standard HTTP status code returned by the server."},
@@ -723,16 +729,17 @@
             "type": "object",
             "name": "details",
             "properties": {
               "requestId": {"type": "string", "description": "The ID of the request. Request IDs are unique within a browser session. As a result, they could be used to relate different events of the same request."},
               "url": {"type": "string"},
               "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 (<code>type</code> is <code>main_frame</code> or <code>sub_frame</code>), <code>frameId</code> 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."},
               "type": {"$ref": "ResourceType", "description": "How the requested resource will be used."},
               "timeStamp": {"type": "number", "description": "The time when this signal is triggered, in milliseconds since the epoch."},
               "ip": {"type": "string", "optional": true, "description": "The server IP address that the request was actually sent to. Note that it may be a literal IPv6 address."},
               "fromCache": {"type": "boolean", "description": "Indicates if this response was fetched from disk cache."},
               "statusCode": {"type": "integer", "description": "Standard HTTP status code returned by the server."},
@@ -768,16 +775,17 @@
             "type": "object",
             "name": "details",
             "properties": {
               "requestId": {"type": "string", "description": "The ID of the request. Request IDs are unique within a browser session. As a result, they could be used to relate different events of the same request."},
               "url": {"type": "string"},
               "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 (<code>type</code> is <code>main_frame</code> or <code>sub_frame</code>), <code>frameId</code> 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."},
               "type": {"$ref": "ResourceType", "description": "How the requested resource will be used."},
               "timeStamp": {"type": "number", "description": "The time when this signal is triggered, in milliseconds since the epoch."},
               "ip": {"type": "string", "optional": true, "description": "The server IP address that the request was actually sent to. Note that it may be a literal IPv6 address."},
               "fromCache": {"type": "boolean", "description": "Indicates if this response was fetched from disk cache."},
               "statusCode": {"type": "integer", "description": "Standard HTTP status code returned by the server."},
@@ -812,16 +820,17 @@
             "type": "object",
             "name": "details",
             "properties": {
               "requestId": {"type": "string", "description": "The ID of the request. Request IDs are unique within a browser session. As a result, they could be used to relate different events of the same request."},
               "url": {"type": "string"},
               "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 (<code>type</code> is <code>main_frame</code> or <code>sub_frame</code>), <code>frameId</code> 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."},
               "type": {"$ref": "ResourceType", "description": "How the requested resource will be used."},
               "timeStamp": {"type": "number", "description": "The time when this signal is triggered, in milliseconds since the epoch."},
               "ip": {"type": "string", "optional": true, "description": "The server IP address that the request was actually sent to. Note that it may be a literal IPv6 address."},
               "fromCache": {"type": "boolean", "description": "Indicates if this response was fetched from disk cache."},
               "error": {"type": "string", "description": "The error description. This string is <em>not</em> guaranteed to remain backwards compatible between releases. You must not parse and act based upon its content."}
--- a/toolkit/components/extensions/test/xpcshell/test_ext_webRequest_incognito.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_webRequest_incognito.js
@@ -6,28 +6,48 @@ server.registerPathHandler("/dummy", (re
   response.setStatusLine(request.httpVersion, 200, "OK");
   response.setHeader("Content-Type", "text/html", false);
   response.write("<!DOCTYPE html><html></html>");
 });
 
 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", "<all_urls>"],
+    },
+    background() {
+      browser.webRequest.onBeforeRequest.addListener(async (details) => {
+        browser.test.assertTrue(details.incognito, "incognito flag is set");
+        browser.test.notifyPass("webRequest.private");
+      }, {urls: ["<all_urls>"]}, ["blocking"]);
+    },
+  });
+  await pb_extension.startup();
+
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       permissions: ["webRequest", "webRequestBlocking", "<all_urls>"],
     },
     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: ["<all_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();
 
   Services.prefs.clearUserPref("extensions.allowPrivateBrowsingByDefault");
 });
--- a/toolkit/components/extensions/test/xpcshell/test_proxy_incognito.js
+++ b/toolkit/components/extensions/test/xpcshell/test_proxy_incognito.js
@@ -13,60 +13,64 @@ server.registerPathHandler("/dummy", (re
 
 add_task(async function test_incognito_proxy_onRequest_access() {
   // No specific support exists in the proxy api for this test,
   // rather it depends on functionality existing in ChannelWrapper
   // that prevents notification of private channels if the
   // 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", "<all_urls>"],
     },
     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: ["<all_urls>"]});
 
       // Actual call arguments do not matter here.
       await browser.test.assertRejects(
         browser.proxy.settings.set({value: {
           proxyType: "none",
         }}),
         /proxy.settings requires private browsing permission/,
         "proxy.settings requires private browsing permission.");
 
       browser.test.sendMessage("ready");
     },
   });
   await extension.startup();
   await extension.awaitMessage("ready");
 
-  // This extension will succeed if it gets a request
   let pextension = ExtensionTestUtils.loadExtension({
     incognitoOverride: "spanning",
     manifest: {
       permissions: ["proxy", "<all_urls>"],
     },
     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: ["<all_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");
 });
 
 function scriptData(script) {
   return String(script).replace(/^.*?\{([^]*)\}$/, "$1");
 }
--- a/toolkit/modules/addons/WebRequest.jsm
+++ b/toolkit/modules/addons/WebRequest.jsm
@@ -659,23 +659,25 @@ HttpObserverManager = {
       });
     } else if (lastActivity !== this.GOOD_LAST_ACTIVITY &&
                lastActivity !== nsIHttpActivityObserver.ACTIVITY_SUBTYPE_TRANSACTION_CLOSE) {
       channel.lastActivity = activitySubtype;
     }
   },
 
   getRequestData(channel, extraData) {
+    let originAttributes = channel.loadInfo && channel.loadInfo.originAttributes;
     let data = {
       requestId: String(channel.id),
       url: channel.finalURL,
       method: channel.method,
       browser: channel.browserElement,
       type: channel.type,
       fromCache: channel.fromCache,
+      originAttributes,
 
       originUrl: channel.originURL || undefined,
       documentUrl: channel.documentURL || undefined,
 
       windowId: channel.windowId,
       parentWindowId: channel.parentWindowId,
 
       frameAncestors: channel.frameAncestors || undefined,