Bug 1220124 - Add support for chrome.tabs.onhighlight. r=kmag
authorMatthew Wein <mwein@mozilla.com>
Sun, 07 Feb 2016 18:35:22 -0800
changeset 286027 57774ff596857a1567ff5e40ce44cbbe2ec8308a
parent 286026 e3f38a0b663f2c0aeb5bef33cf7e79868d7d4853
child 286028 4245d4c579beb4be51281240b8cef73cdccb0400
push id17892
push usermaglione.k@gmail.com
push dateMon, 29 Feb 2016 21:52:21 +0000
treeherderfx-team@57774ff59685 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskmag
bugs1220124
milestone47.0a1
Bug 1220124 - Add support for chrome.tabs.onhighlight. r=kmag MozReview-Commit-ID: BB6vJl8qV4l
browser/components/extensions/ext-tabs.js
browser/components/extensions/test/browser/browser.ini
browser/components/extensions/test/browser/browser_ext_tabs_onHighlighted.js
--- a/browser/components/extensions/ext-tabs.js
+++ b/browser/components/extensions/ext-tabs.js
@@ -149,16 +149,29 @@ extensions.registerSchemaAPI("tabs", nul
         WindowListManager.addOpenListener(windowListener);
         AllWindowEvents.addListener("TabOpen", listener);
         return () => {
           WindowListManager.removeOpenListener(windowListener);
           AllWindowEvents.removeListener("TabOpen", listener);
         };
       }).api(),
 
+      /**
+       * Since multiple tabs currently can't be highlighted, onHighlighted
+       * essentially acts an alias for self.tabs.onActivated but returns
+       * the tabId in an array to match the API.
+       * @see  https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/Tabs/onHighlighted
+      */
+      onHighlighted: new WindowEventManager(context, "tabs.onHighlighted", "TabSelect", (fire, event) => {
+        let tab = event.originalTarget;
+        let tabIds = [TabManager.getId(tab)];
+        let windowId = WindowManager.getId(tab.ownerDocument.defaultView);
+        fire({tabIds, windowId});
+      }).api(),
+
       onAttached: new EventManager(context, "tabs.onAttached", fire => {
         let fireForTab = tab => {
           let newWindowId = WindowManager.getId(tab.ownerDocument.defaultView);
           fire(TabManager.getId(tab), {newWindowId, newPosition: tab._tPos});
         };
 
         let listener = event => {
           if (event.detail.adoptedTab) {
--- a/browser/components/extensions/test/browser/browser.ini
+++ b/browser/components/extensions/test/browser/browser.ini
@@ -39,13 +39,14 @@ support-files =
 [browser_ext_tabs_create_invalid_url.js]
 [browser_ext_tabs_duplicate.js]
 [browser_ext_tabs_update.js]
 [browser_ext_tabs_update_url.js]
 [browser_ext_tabs_onUpdated.js]
 [browser_ext_tabs_sendMessage.js]
 [browser_ext_tabs_move.js]
 [browser_ext_tabs_move_window.js]
+[browser_ext_tabs_onHighlighted.js]
 [browser_ext_windows_create_tabId.js]
 [browser_ext_windows_update.js]
 [browser_ext_contentscript_connect.js]
 [browser_ext_tab_runtimeConnect.js]
 [browser_ext_webNavigation_getFrames.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_tabs_onHighlighted.js
@@ -0,0 +1,118 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+add_task(function* testTabEvents() {
+  function background() {
+    /** The list of active tab ID's */
+    let tabIds = [];
+
+    /**
+     * Stores the events that fire for each tab.
+     *
+     * events {
+     *   tabId1: [event1, event2, ...],
+     *   tabId2: [event1, event2, ...],
+     * }
+     */
+    let events = {};
+
+    browser.tabs.onActivated.addListener((info) => {
+      if (info.tabId in events) {
+        events[info.tabId].push("onActivated");
+      } else {
+        events[info.tabId] = ["onActivated"];
+      }
+    });
+
+    browser.tabs.onHighlighted.addListener((info) => {
+      if (info.tabIds[0] in events) {
+        events[info.tabIds[0]].push("onHighlighted");
+      } else {
+        events[info.tabIds[0]] = ["onHighlighted"];
+      }
+    });
+
+    /**
+     * Asserts that the expected events are fired for the tab with id = tabId.
+     * The events associated to the specified tab are removed after this check is made.
+     */
+    function expectEvents(tabId, expectedEvents) {
+      browser.test.log(`Expecting events: ${expectedEvents.join(", ")}`);
+
+      return new Promise(resolve => {
+        setTimeout(resolve, 0);
+      }).then(() => {
+        browser.test.assertEq(expectedEvents.length, events[tabId].length,
+         `Got expected number of events for ${tabId}`);
+        for (let [i, name] of expectedEvents.entries()) {
+          browser.test.assertEq(name, i in events[tabId] && events[tabId][i],
+                                `Got expected ${name} event`);
+        }
+        delete events[tabId];
+      });
+    }
+
+    /**
+     * Opens a new tab and asserts that the correct events are fired.
+     */
+    function openTab(windowId) {
+      return browser.tabs.create({windowId}).then(tab => {
+        tabIds.push(tab.id);
+        browser.test.log(`Opened tab ${tab.id}`);
+        return expectEvents(tab.id, [
+          "onActivated",
+          "onHighlighted",
+        ]);
+      });
+    }
+
+    /**
+     * Highlights an existing tab and asserts that the correct events are fired.
+     */
+    function highlightTab(tabId) {
+      browser.test.log(`Highlighting tab ${tabId}`);
+      return browser.tabs.update(tabId, {active: true}).then(tab => {
+        browser.test.assertEq(tab.id, tabId, `Tab ${tab.id} highlighted`);
+        return expectEvents(tab.id, [
+          "onActivated",
+          "onHighlighted",
+        ]);
+      });
+    }
+
+    /**
+     * The main entry point to the tests.
+     */
+    browser.tabs.query({active: true, currentWindow: true}, tabs => {
+      let activeWindow = tabs[0].windowId;
+      Promise.all([
+        openTab(activeWindow),
+        openTab(activeWindow),
+        openTab(activeWindow),
+      ]).then(() => {
+        return Promise.all([
+          highlightTab(tabIds[0]),
+          highlightTab(tabIds[1]),
+          highlightTab(tabIds[2]),
+        ]);
+      }).then(() => {
+        return Promise.all(tabIds.map(id => browser.tabs.remove(id)));
+      }).then(() => {
+        browser.test.notifyPass("tabs.highlight");
+      });
+    });
+  }
+
+  let extension = ExtensionTestUtils.loadExtension({
+    manifest: {
+      "permissions": ["tabs"],
+    },
+
+    background,
+  });
+
+  yield extension.startup();
+  yield extension.awaitFinish("tabs.highlight");
+  yield extension.unload();
+});