Bug 1472305 - browser.tabs.highlight() with single tab should not set multiselected=true
MozReview-Commit-ID: 8cvtMkHoRxD
--- 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;
}
};