Bug 1472305 - browser.tabs.highlight() with single tab should not set multiselected=true draft
authorOriol Brufau <oriol-bugzilla@hotmail.com>
Sat, 30 Jun 2018 17:27:12 +0200
changeset 813248 08bab79b37a0b13b60ba41f41a9307b84f0ebe7e
parent 812944 23885c14f025b61bb74d85845ac4018f05eb39f8
push id114840
push userbmo:oriol-bugzilla@hotmail.com
push dateMon, 02 Jul 2018 20:36:54 +0000
bugs1472305
milestone63.0a1
Bug 1472305 - browser.tabs.highlight() with single tab should not set multiselected=true MozReview-Commit-ID: 8cvtMkHoRxD
browser/base/content/tabbrowser.js
browser/base/content/test/tabs/browser.ini
browser/base/content/test/tabs/browser_multiselect_tabs_using_selectedTabs.js
browser/components/extensions/parent/ext-tabs.js
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -3631,16 +3631,27 @@ window._gBrowser = {
       tab.removeAttribute("multiselected");
     }
     this._multiSelectedTabsSet = new WeakSet();
     if (updatePositionalAttributes) {
       this.tabContainer._setPositionalAttributes();
     }
   },
 
+  set selectedTabs(tabs) {
+    this.clearMultiSelectedTabs(false);
+    this.selectedTab = tabs[0];
+    if (tabs.length > 1) {
+      for (let tab of tabs) {
+        this.addToMultiSelectedTabs(tab, true);
+      }
+    }
+    this.tabContainer._setPositionalAttributes();
+  },
+
   get selectedTabs() {
     let {selectedTab, _multiSelectedTabsSet} = this;
     let tabs = ChromeUtils.nondeterministicGetWeakSetKeys(_multiSelectedTabsSet)
       .filter(tab => tab.isConnected && !tab.closing);
     if (!_multiSelectedTabsSet.has(selectedTab)) {
       tabs.push(selectedTab);
     }
     return tabs;
--- a/browser/base/content/test/tabs/browser.ini
+++ b/browser/base/content/test/tabs/browser.ini
@@ -22,16 +22,17 @@ support-files =
 [browser_multiselect_tabs_active_tab_selected_by_default.js]
 [browser_multiselect_tabs_close_using_shortcuts.js]
 [browser_multiselect_tabs_close.js]
 [browser_multiselect_tabs_mute_unmute.js]
 [browser_multiselect_tabs_pin_unpin.js]
 [browser_multiselect_tabs_positional_attrs.js]
 [browser_multiselect_tabs_using_Ctrl.js]
 [browser_multiselect_tabs_using_Shift.js]
+[browser_multiselect_tabs_using_selectedTabs.js]
 [browser_navigatePinnedTab.js]
 [browser_new_file_whitelisted_http_tab.js]
 skip-if = !e10s # Test only relevant for e10s.
 [browser_new_tab_insert_position.js]
 skip-if = (debug && os == 'linux' && bits == 32) #Bug 1455882, disabled on Linux32 for almost permafailing
 support-files = file_new_tab_page.html
 [browser_new_tab_in_privileged_process_pref.js]
 skip-if = !e10s # Pref and test only relevant for e10s.
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabs/browser_multiselect_tabs_using_selectedTabs.js
@@ -0,0 +1,48 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+const PREF_MULTISELECT_TABS = "browser.tabs.multiselect";
+
+add_task(async function() {
+  await SpecialPowers.pushPrefEnv({
+    set: [
+      [PREF_MULTISELECT_TABS, true]
+    ]
+  });
+
+  function testSelectedTabs(tabs) {
+    gBrowser.selectedTabs = tabs;
+    let {selectedTab, selectedTabs, _multiSelectedTabsSet} = gBrowser;
+    is(selectedTab, tabs[0], "The selected tab should be the expected one");
+    if (tabs.length == 1) {
+      ok(!selectedTab.multiselected, "Selected tab shouldn't be multi-selected because we are not in multi-select context yet");
+      ok(!_multiSelectedTabsSet.has(selectedTab), "Selected tab shouldn't be in _multiSelectedTabsSet");
+      is(selectedTabs.length, 1, "selectedTabs should contain a single tab");
+      is(selectedTabs[0], selectedTab, "selectedTabs should contain the selected tab");
+    } else {
+      ok(selectedTabs.length, tabs.length, "Check number of selected tabs");
+      for (let tab of tabs) {
+        ok(tab.multiselected, "Tab should be multi-selected");
+        ok(_multiSelectedTabsSet.has(tab), "Tab should be in _multiSelectedTabsSet");
+        ok(selectedTabs.includes(tab), "Tab should be in selectedTabs");
+      }
+    }
+  }
+
+  const tab1 = await addTab();
+  const tab2 = await addTab();
+  const tab3 = await addTab();
+
+  testSelectedTabs([tab1]);
+  testSelectedTabs([tab2]);
+  testSelectedTabs([tab2, tab1]);
+  testSelectedTabs([tab1, tab2]);
+  testSelectedTabs([tab3, tab2]);
+  testSelectedTabs([tab3, tab1]);
+  testSelectedTabs([tab1, tab2, tab1]);
+
+  BrowserTestUtils.removeTab(tab1);
+  BrowserTestUtils.removeTab(tab2);
+  BrowserTestUtils.removeTab(tab3);
+});
--- a/browser/components/extensions/parent/ext-tabs.js
+++ b/browser/components/extensions/parent/ext-tabs.js
@@ -19,16 +19,18 @@ XPCOMUtils.defineLazyGetter(this, "strBu
   return Services.strings.createBundle("chrome://global/locale/extensions.properties");
 });
 
 var {
   ExtensionError,
 } = ExtensionUtils;
 
 const TABHIDE_PREFNAME = "extensions.webextensions.tabhide.enabled";
+const MULTISELECT_PREFNAME = "browser.tabs.multiselect";
+XPCOMUtils.defineLazyPreferenceGetter(this, "gMultiSelectEnabled", MULTISELECT_PREFNAME, false);
 
 const TAB_HIDE_CONFIRMED_TYPE = "tabHideNotification";
 
 
 XPCOMUtils.defineLazyGetter(this, "tabHidePopup", () => {
   return new ExtensionControlledPopup({
     confirmedType: TAB_HIDE_CONFIRMED_TYPE,
     anchorId: "alltabs-button",
@@ -1233,40 +1235,35 @@ this.tabs = class extends ExtensionAPI {
           if (hidden.length > 0) {
             let win = Services.wm.getMostRecentWindow("navigator:browser");
             tabHidePopup.open(win, extension.id);
           }
           return hidden;
         },
 
         highlight(highlightInfo) {
-          if (!Services.prefs.getBoolPref("browser.tabs.multiselect")) {
-            throw new ExtensionError("Multiple tab selection is not enabled.");
+          if (!gMultiSelectEnabled) {
+            throw new ExtensionError(`tabs.highlight is currently experimental and must be enabled with the ${MULTISELECT_PREFNAME} preference.`);
           }
           let {windowId, tabs} = highlightInfo;
           if (windowId == null) {
             windowId = Window.WINDOW_ID_CURRENT;
           }
           let window = windowTracker.getWindow(windowId, context);
           if (!Array.isArray(tabs)) {
             tabs = [tabs];
           } else if (tabs.length == 0) {
             throw new ExtensionError("No highlighted tab.");
           }
-          tabs = tabs.map((tabIndex) => {
+          window.gBrowser.selectedTabs = tabs.map((tabIndex) => {
             let tab = window.gBrowser.tabs[tabIndex];
             if (!tab) {
               throw new ExtensionError("No tab at index: " + tabIndex);
             }
             return tab;
           });
-          window.gBrowser.clearMultiSelectedTabs();
-          window.gBrowser.selectedTab = tabs[0];
-          for (let tab of tabs) {
-            window.gBrowser.addToMultiSelectedTabs(tab);
-          }
           return windowManager.convert(window, {populate: true});
         },
       },
     };
     return self;
   }
 };