Bug 1443221 - Do not send a webNavigation API event for a browser which is adopting an existent tab in a new window. draft
authorLuca Greco <lgreco@mozilla.com>
Mon, 09 Apr 2018 15:39:49 +0200
changeset 780964 4e4073eb1a1e232b610fd884abda5ec3c4fa9d1a
parent 780803 88f297d206a65910871de724e9c8bb462f04d792
push id106173
push userluca.greco@alcacoop.it
push dateThu, 12 Apr 2018 10:07:21 +0000
bugs1443221
milestone61.0a1
Bug 1443221 - Do not send a webNavigation API event for a browser which is adopting an existent tab in a new window. MozReview-Commit-ID: GG9cSB5hdhA
browser/components/extensions/test/browser/browser_ext_windows_create_tabId.js
toolkit/components/extensions/parent/ext-webNavigation.js
--- a/browser/components/extensions/test/browser/browser_ext_windows_create_tabId.js
+++ b/browser/components/extensions/test/browser/browser_ext_windows_create_tabId.js
@@ -133,8 +133,93 @@ add_task(async function testWindowCreate
 
     background,
   });
 
   await extension.startup();
   await extension.awaitFinish("window-create");
   await extension.unload();
 });
+
+add_task(async function testWebNavigationOnWindowCreateTabId() {
+  async function background() {
+    const webNavEvents = [];
+    const onceTabsAttached = [];
+
+    let promiseTabAttached = (tab) => {
+      return new Promise(resolve => {
+        browser.tabs.onAttached.addListener(function listener(tabId) {
+          if (tabId !== tab.id) {
+            return;
+          }
+          browser.tabs.onAttached.removeListener(listener);
+          resolve();
+        });
+      });
+    };
+
+    // Listen to webNavigation.onCompleted events to ensure that
+    // it is not going to be fired when we move the existent tabs
+    // to new windows.
+    browser.webNavigation.onCompleted.addListener((data) => {
+      webNavEvents.push(data);
+    });
+
+    // Wait for the list of urls needed to select the test tabs,
+    // and then move these tabs to a new window and assert that
+    // no webNavigation.onCompleted events should be received
+    // while the tabs are being adopted into the new windows.
+    browser.test.onMessage.addListener(async (msg, testTabURLs) => {
+      if (msg !== "testTabURLs") {
+        return;
+      }
+
+      // Retrieve the tabs list and filter out the tabs that should
+      // not be moved into a new window.
+      let allTabs = await browser.tabs.query({});
+      let testTabs = allTabs.filter(tab => {
+        return testTabURLs.includes(tab.url);
+      });
+
+      browser.test.assertEq(2, testTabs.length, "Got the expected number of test tabs");
+
+      for (let tab of testTabs) {
+        onceTabsAttached.push(promiseTabAttached(tab));
+        await browser.windows.create({tabId: tab.id});
+      }
+
+      // Wait the tabs to have been attached to the new window and then assert that no
+      // webNavigation.onCompleted event has been received.
+      browser.test.log("Waiting tabs move to new window to be attached");
+      await Promise.all(onceTabsAttached);
+
+      browser.test.assertEq("[]", JSON.stringify(webNavEvents),
+                            "No webNavigation.onCompleted event should have been received");
+
+      // Remove all the test tabs before exiting the test successfully.
+      for (let tab of testTabs) {
+        await browser.tabs.remove(tab.id);
+      }
+
+      browser.test.notifyPass("webNavigation-on-window-create-tabId");
+    });
+  }
+
+  const testURLs = ["http://example.com/", "http://example.org/"];
+
+  for (let url of testURLs) {
+    await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
+  }
+
+  let extension = ExtensionTestUtils.loadExtension({
+    manifest: {
+      "permissions": ["tabs", "webNavigation"],
+    },
+    background,
+  });
+
+  await extension.startup();
+
+  await extension.sendMessage("testTabURLs", testURLs);
+
+  await extension.awaitFinish("webNavigation-on-window-create-tabId");
+  await extension.unload();
+});
--- a/toolkit/components/extensions/parent/ext-webNavigation.js
+++ b/toolkit/components/extensions/parent/ext-webNavigation.js
@@ -115,16 +115,24 @@ class WebNavigationEventManager extends 
           data2.frameId = data.frameId;
           data2.parentFrameId = data.parentFrameId;
         }
 
         if (data.sourceFrameId != undefined) {
           data2.sourceFrameId = data.sourceFrameId;
         }
 
+        // Do not send a webNavigation event when the data.browser is related to a tab from a
+        // new window opened to adopt an existent tab (See Bug 1443221 for a rationale).
+        const chromeWin = data.browser.ownerGlobal;
+        if (chromeWin && chromeWin.arguments && chromeWin.arguments[0] instanceof chromeWin.XULElement &&
+            chromeWin.gBrowser.selectedBrowser === data.browser) {
+          return;
+        }
+
         // Fills in tabId typically.
         Object.assign(data2, tabTracker.getBrowserData(data.browser));
         if (data2.tabId < 0) {
           return;
         }
 
         if (data.sourceTabBrowser) {
           data2.sourceTabId = tabTracker.getBrowserData(data.sourceTabBrowser).tabId;