Bug 1319452: Part 2 - Don't expose extension views that the caller cannot access. r?billm draft
authorKris Maglione <maglione.k@gmail.com>
Tue, 22 Nov 2016 12:31:37 -0800
changeset 442589 29de2f953174adce56efd5f260c881a593f9526e
parent 442588 c5537344fe6bffede6869fa9c6bd385855795d95
child 537829 3201b9100a8977df1853844f083ff647e4e451c7
push id36742
push usermaglione.k@gmail.com
push dateTue, 22 Nov 2016 20:34:55 +0000
reviewersbillm
bugs1319452
milestone53.0a1
Bug 1319452: Part 2 - Don't expose extension views that the caller cannot access. r?billm MozReview-Commit-ID: IS7mpOnQ8y0
browser/components/extensions/test/browser/browser-common.ini
browser/components/extensions/test/browser/browser_ext_incognito_views.js
toolkit/components/extensions/ext-c-backgroundPage.js
toolkit/components/extensions/ext-c-extension.js
--- a/browser/components/extensions/test/browser/browser-common.ini
+++ b/browser/components/extensions/test/browser/browser-common.ini
@@ -36,16 +36,17 @@ support-files =
 [browser_ext_contextMenus_checkboxes.js]
 [browser_ext_contextMenus_icons.js]
 [browser_ext_contextMenus_onclick.js]
 [browser_ext_contextMenus_radioGroups.js]
 [browser_ext_contextMenus_uninstall.js]
 [browser_ext_contextMenus_urlPatterns.js]
 [browser_ext_currentWindow.js]
 [browser_ext_getViews.js]
+[browser_ext_incognito_views.js]
 [browser_ext_incognito_popup.js]
 [browser_ext_lastError.js]
 [browser_ext_optionsPage_privileges.js]
 [browser_ext_pageAction_context.js]
 [browser_ext_pageAction_popup.js]
 [browser_ext_pageAction_popup_resize.js]
 [browser_ext_pageAction_simple.js]
 [browser_ext_pageAction_title.js]
copy from browser/components/extensions/test/browser/browser_ext_incognito_popup.js
copy to browser/components/extensions/test/browser/browser_ext_incognito_views.js
--- a/browser/components/extensions/test/browser/browser_ext_incognito_popup.js
+++ b/browser/components/extensions/test/browser/browser_ext_incognito_views.js
@@ -1,25 +1,24 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
-add_task(function* testIncognitoPopup() {
+add_task(function* testIncognitoViews() {
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "permissions": ["tabs"],
       "browser_action": {
         "default_popup": "popup.html",
       },
-      "page_action": {
-        "default_popup": "popup.html",
-      },
     },
 
     background: async function() {
+      window.isBackgroundPage = true;
+
       let resolveMessage;
       browser.runtime.onMessage.addListener(msg => {
         if (resolveMessage && msg.message == "popup-details") {
           resolveMessage(msg);
         }
       });
 
       let awaitPopup = windowId => {
@@ -27,27 +26,19 @@ add_task(function* testIncognitoPopup() 
           resolveMessage = resolve;
         }).then(msg => {
           browser.test.assertEq(windowId, msg.windowId, "Got popup message from correct window");
           return msg;
         });
       };
 
       let testWindow = async window => {
-        let [tab] = await browser.tabs.query({active: true, windowId: window.id});
-
-        await browser.pageAction.show(tab.id);
-        browser.test.sendMessage("click-pageAction");
+        browser.test.sendMessage("click-browserAction");
 
         let msg = await awaitPopup(window.id);
-        browser.test.assertEq(window.incognito, msg.incognito, "Correct incognito status in pageAction popup");
-
-        browser.test.sendMessage("click-browserAction");
-
-        msg = await awaitPopup(window.id);
         browser.test.assertEq(window.incognito, msg.incognito, "Correct incognito status in browserAction popup");
       };
 
       const URL = "http://example.com/incognito";
       let windowReady = new Promise(resolve => {
         browser.tabs.onUpdated.addListener(function listener(tabId, changed, tab) {
           if (changed.status == "complete" && tab.url == URL) {
             browser.tabs.onUpdated.removeListener(listener);
@@ -67,42 +58,64 @@ add_task(function* testIncognitoPopup() 
           let window = await browser.windows.create({incognito: true, url: URL});
           await windowReady;
 
           await testWindow(window);
 
           await browser.windows.remove(window.id);
         }
 
-        browser.test.notifyPass("incognito");
+        browser.test.notifyPass("incognito-views");
       } catch (error) {
         browser.test.fail(`Error: ${error} :: ${error.stack}`);
-        browser.test.notifyFail("incognito");
+        browser.test.notifyFail("incognito-views");
       }
     },
 
     files: {
       "popup.html": '<html><head><meta charset="utf-8"><script src="popup.js"></script></head></html>',
 
       "popup.js": async function() {
+        let views = browser.extension.getViews();
+
+        if (browser.extension.inIncognitoContext) {
+          let bgPage = browser.extension.getBackgroundPage();
+          browser.test.assertEq(null, bgPage, "Should not be able to access background page in incognito context");
+
+          bgPage = await browser.runtime.getBackgroundPage();
+          browser.test.assertEq(null, bgPage, "Should not be able to access background page in incognito context");
+
+          browser.test.assertEq(1, views.length, "Should only see one view in incognito popup");
+          browser.test.assertEq(window, views[0], "This window should be the only view");
+        } else {
+          let bgPage = browser.extension.getBackgroundPage();
+          browser.test.assertEq(true, bgPage.isBackgroundPage,
+                                "Should be able to access background page in non-incognito context");
+
+          bgPage = await browser.runtime.getBackgroundPage();
+          browser.test.assertEq(true, bgPage.isBackgroundPage,
+                                "Should be able to access background page in non-incognito context");
+
+          browser.test.assertEq(2, views.length, "Should only two views in non-incognito popup");
+          browser.test.assertEq(bgPage, views[0], "The background page should be the first view");
+          browser.test.assertEq(window, views[1], "This window should be the second view");
+        }
+
         let win = await browser.windows.getCurrent();
         browser.runtime.sendMessage({
           message: "popup-details",
           windowId: win.id,
           incognito: browser.extension.inIncognitoContext,
         });
+
         window.close();
       },
     },
   });
 
   extension.onMessage("click-browserAction", () => {
     clickBrowserAction(extension, Services.wm.getMostRecentWindow("navigator:browser"));
   });
 
-  extension.onMessage("click-pageAction", () => {
-    clickPageAction(extension, Services.wm.getMostRecentWindow("navigator:browser"));
-  });
-
   yield extension.startup();
-  yield extension.awaitFinish("incognito");
+  yield extension.awaitFinish("incognito-views");
   yield extension.unload();
 });
--- a/toolkit/components/extensions/ext-c-backgroundPage.js
+++ b/toolkit/components/extensions/ext-c-backgroundPage.js
@@ -20,20 +20,21 @@ global.initializeBackgroundPage = (conte
     contentWindow.console.log(text);
   };
   Cu.exportFunction(alertOverwrite, contentWindow, {defineAs: "alert"});
 };
 
 extensions.registerSchemaAPI("extension", "addon_child", context => {
   function getBackgroundPage() {
     for (let view of context.extension.views) {
-      if (view.viewType == "background") {
+      if (view.viewType == "background" && context.principal.subsumes(view.principal)) {
         return view.contentWindow;
       }
     }
+    return null;
   }
   return {
     extension: {
       getBackgroundPage,
     },
 
     runtime: {
       getBackgroundPage() {
--- a/toolkit/components/extensions/ext-c-extension.js
+++ b/toolkit/components/extensions/ext-c-extension.js
@@ -29,16 +29,20 @@ extensions.registerSchemaAPI("extension"
     extension: {
       getViews: function(fetchProperties) {
         let result = Cu.cloneInto([], context.cloneScope);
 
         for (let view of context.extension.views) {
           if (!view.active) {
             continue;
           }
+          if (!context.principal.subsumes(view.principal)) {
+            continue;
+          }
+
           if (fetchProperties !== null) {
             if (fetchProperties.type !== null && view.viewType != fetchProperties.type) {
               continue;
             }
 
             if (fetchProperties.windowId !== null && view.windowId != fetchProperties.windowId) {
               continue;
             }