Bug 1220124 - Add support for chrome.tabs.onhighlight. r=kmag
☠☠ backed out by 7882aa8df614 ☠ ☠
authorMatthew Wein <mwein@mozilla.com>
Sun, 07 Feb 2016 18:35:22 -0800
changeset 285910 90494d4d76ab4587805ad27cc663fa7407b04450
parent 285909 3a116d8cb42f45daf1467692c91afc2a2c7f0985
child 285911 648ed13cecacb7ea511d019e02c6dddc7649b94e
push id72576
push userryanvm@gmail.com
push dateSun, 28 Feb 2016 22:43:36 +0000
treeherdermozilla-inbound@3374f3adff0d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskmag
bugs1220124
milestone47.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 1220124 - Add support for chrome.tabs.onhighlight. r=kmag
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
@@ -3,44 +3,45 @@ support-files =
   head.js
   context.html
   ctxmenu-image.png
   context_tabs_onUpdated_page.html
   context_tabs_onUpdated_iframe.html
   file_popup_api_injection_a.html
   file_popup_api_injection_b.html
 
-[browser_ext_simple.js]
-[browser_ext_commands.js]
-[browser_ext_currentWindow.js]
-[browser_ext_browserAction_simple.js]
-[browser_ext_browserAction_pageAction_icon.js]
 [browser_ext_browserAction_context.js]
 [browser_ext_browserAction_disabled.js]
+[browser_ext_browserAction_pageAction_icon.js]
+[browser_ext_browserAction_popup.js]
+[browser_ext_browserAction_simple.js]
+[browser_ext_commands.js]
+[browser_ext_contentscript_connect.js]
+[browser_ext_contextMenus.js]
+[browser_ext_currentWindow.js]
+[browser_ext_getViews.js]
+[browser_ext_lastError.js]
 [browser_ext_pageAction_context.js]
 [browser_ext_pageAction_popup.js]
-[browser_ext_browserAction_popup.js]
 [browser_ext_popup_api_injection.js]
-[browser_ext_contextMenus.js]
-[browser_ext_getViews.js]
-[browser_ext_lastError.js]
 [browser_ext_runtime_setUninstallURL.js]
+[browser_ext_simple.js]
+[browser_ext_tab_runtimeConnect.js]
 [browser_ext_tabs_audio.js]
 [browser_ext_tabs_captureVisibleTab.js]
-[browser_ext_tabs_events.js]
-[browser_ext_tabs_executeScript.js]
-[browser_ext_tabs_executeScript_good.js]
-[browser_ext_tabs_executeScript_bad.js]
-[browser_ext_tabs_insertCSS.js]
-[browser_ext_tabs_query.js]
-[browser_ext_tabs_getCurrent.js]
 [browser_ext_tabs_create.js]
 [browser_ext_tabs_duplicate.js]
-[browser_ext_tabs_update.js]
-[browser_ext_tabs_onUpdated.js]
-[browser_ext_tabs_sendMessage.js]
+[browser_ext_tabs_events.js]
+[browser_ext_tabs_executeScript.js]
+[browser_ext_tabs_executeScript_bad.js]
+[browser_ext_tabs_executeScript_good.js]
+[browser_ext_tabs_getCurrent.js]
+[browser_ext_tabs_insertCSS.js]
 [browser_ext_tabs_move.js]
 [browser_ext_tabs_move_window.js]
+[browser_ext_tabs_onHighlighted.js]
+[browser_ext_tabs_onUpdated.js]
+[browser_ext_tabs_query.js]
+[browser_ext_tabs_sendMessage.js]
+[browser_ext_tabs_update.js]
+[browser_ext_webNavigation_getFrames.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]
\ No newline at end of file
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();
+});