Bug 1504277 - Open new tabs at the end of a multiselection of tabs if the New Tab button is ctrl-clicked. r=dao
☠☠ backed out by 65384cee04da ☠ ☠
authorJared Wein <jwein@mozilla.com>
Fri, 16 Nov 2018 20:41:57 +0000
changeset 446836 988fd6689153a86f6f4410c1d1fe46eaff036afb
parent 446835 4dcf88b1fabcfb7fb0e4c87aec107f09e81a200b
child 446837 dad98317fee0ff692f30d6f0c845a9241f0d5de4
push id35052
push userapavel@mozilla.com
push dateSat, 17 Nov 2018 11:25:40 +0000
treeherdermozilla-central@efc1da42132b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdao
bugs1504277
milestone65.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 1504277 - Open new tabs at the end of a multiselection of tabs if the New Tab button is ctrl-clicked. r=dao Differential Revision: https://phabricator.services.mozilla.com/D11376
browser/base/content/tabbrowser.js
browser/base/content/test/tabs/browser.ini
browser/base/content/test/tabs/browser_multiselect_tabs_open_related.js
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -2377,17 +2377,22 @@ window._gBrowser = {
       if (typeof index != "number") {
         // Move the new tab after another tab if needed.
         if (!bulkOrderedOpen &&
             ((openerTab &&
               Services.prefs.getBoolPref("browser.tabs.insertRelatedAfterCurrent")) ||
              Services.prefs.getBoolPref("browser.tabs.insertAfterCurrent"))) {
 
           let lastRelatedTab = openerTab && this._lastRelatedTabMap.get(openerTab);
-          index = (lastRelatedTab || openerTab || this.selectedTab)._tPos + 1;
+          let previousTab = (lastRelatedTab || openerTab || this.selectedTab);
+          if (previousTab.multiselected) {
+            index = this.selectedTabs[this.selectedTabs.length - 1]._tPos + 1;
+          } else {
+            index = previousTab._tPos + 1;
+          }
 
           if (lastRelatedTab) {
             lastRelatedTab.owner = null;
           } else if (openerTab) {
             t.owner = openerTab;
           }
           // Always set related map if opener exists.
           if (openerTab) {
--- a/browser/base/content/test/tabs/browser.ini
+++ b/browser/base/content/test/tabs/browser.ini
@@ -28,16 +28,17 @@ support-files =
 [browser_multiselect_tabs_close.js]
 [browser_multiselect_tabs_copy_through_drag_and_drop.js]
 [browser_multiselect_tabs_drag_to_bookmarks_toolbar.js]
 [browser_multiselect_tabs_duplicate.js]
 [browser_multiselect_tabs_event.js]
 [browser_multiselect_tabs_move_to_another_window_drag.js]
 [browser_multiselect_tabs_move_to_new_window_contextmenu.js]
 [browser_multiselect_tabs_mute_unmute.js]
+[browser_multiselect_tabs_open_related.js]
 [browser_multiselect_tabs_pin_unpin.js]
 [browser_multiselect_tabs_positional_attrs.js]
 [browser_multiselect_tabs_reload.js]
 [browser_multiselect_tabs_reopen_in_container.js]
 [browser_multiselect_tabs_reorder.js]
 [browser_multiselect_tabs_using_Ctrl.js]
 [browser_multiselect_tabs_using_keyboard.js]
 skip-if = os == 'mac' # Skipped because macOS keyboard support requires changing system settings
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabs/browser_multiselect_tabs_open_related.js
@@ -0,0 +1,99 @@
+const PREF_MULTISELECT_TABS = "browser.tabs.multiselect";
+
+add_task(async function test() {
+  await SpecialPowers.pushPrefEnv({
+    set: [
+      [PREF_MULTISELECT_TABS, true],
+    ],
+  });
+
+  let tab1 = await addTab("http://example.com/1");
+  let tab2 = await addTab("http://example.com/2");
+  let tab3 = await addTab("http://example.com/3");
+
+  await BrowserTestUtils.switchTab(gBrowser, tab1);
+  await triggerClickOn(tab2, { ctrlKey: true });
+
+  ok(tab1.multiselected, "Tab1 is multi-selected");
+  ok(tab2.multiselected, "Tab2 is multi-selected");
+  ok(!tab3.multiselected, "Tab3 is not multi-selected");
+
+  let tabs = document.getElementById("tabbrowser-tabs");
+  let newTabButton = document.getAnonymousElementByAttribute(tabs, "anonid", "tabs-newtab-button");
+  let promiseTabOpened = BrowserTestUtils.waitForEvent(gBrowser.tabContainer, "TabOpen");
+  EventUtils.synthesizeMouseAtCenter(newTabButton, {ctrlKey: true});
+  let openEvent = await promiseTabOpened;
+  let newTab = openEvent.target;
+
+  is(newTab.previousElementSibling, tab2,
+    "New tab should be opened after tab2 when tab1 and tab2 are multiselected");
+  is(newTab.nextElementSibling, tab3,
+    "New tab should be opened before tab3 when tab1 and tab2 are multiselected");
+  BrowserTestUtils.removeTab(newTab);
+
+  await BrowserTestUtils.switchTab(gBrowser, tab1);
+  ok(!tab1.multiselected, "Tab1 is not multi-selected");
+  ok(!tab2.multiselected, "Tab2 is not multi-selected");
+  ok(!tab3.multiselected, "Tab3 is not multi-selected");
+
+  promiseTabOpened = BrowserTestUtils.waitForEvent(gBrowser.tabContainer, "TabOpen");
+  EventUtils.synthesizeMouseAtCenter(newTabButton, {ctrlKey: true});
+  openEvent = await promiseTabOpened;
+  newTab = openEvent.target;
+  is(newTab.previousElementSibling, tab1,
+    "New tab should be opened after tab1 when only tab1 is selected");
+  is(newTab.nextElementSibling, tab2,
+    "New tab should be opened before tab2 when only tab1 is selected");
+  BrowserTestUtils.removeTab(newTab);
+
+  await BrowserTestUtils.switchTab(gBrowser, tab1);
+  await triggerClickOn(tab3, { ctrlKey: true });
+  ok(tab1.multiselected, "Tab1 is multi-selected");
+  ok(!tab2.multiselected, "Tab2 is not multi-selected");
+  ok(tab3.multiselected, "Tab3 is multi-selected");
+
+  promiseTabOpened = BrowserTestUtils.waitForEvent(gBrowser.tabContainer, "TabOpen");
+  EventUtils.synthesizeMouseAtCenter(newTabButton, {ctrlKey: true});
+  openEvent = await promiseTabOpened;
+  newTab = openEvent.target;
+  is(newTab.previousElementSibling, tab3,
+    "New tab should be opened after tab3 when tab1 and tab3 are selected");
+  is(newTab.nextElementSibling, null,
+    "New tab should be opened at the end of the tabstrip when tab1 and tab3 are selected");
+  BrowserTestUtils.removeTab(newTab);
+
+  await BrowserTestUtils.switchTab(gBrowser, tab1);
+  ok(!tab1.multiselected, "Tab1 is not multi-selected");
+  ok(!tab2.multiselected, "Tab2 is not multi-selected");
+  ok(!tab3.multiselected, "Tab3 is not multi-selected");
+
+  promiseTabOpened = BrowserTestUtils.waitForEvent(gBrowser.tabContainer, "TabOpen");
+  EventUtils.synthesizeMouseAtCenter(newTabButton, {});
+  openEvent = await promiseTabOpened;
+  newTab = openEvent.target;
+  is(newTab.previousElementSibling, tab3,
+    "New tab should be opened after tab3 when ctrlKey is not used without multiselection");
+  is(newTab.nextElementSibling, null,
+    "New tab should be opened at the end of the tabstrip when ctrlKey is not used without multiselection");
+  BrowserTestUtils.removeTab(newTab);
+
+  await BrowserTestUtils.switchTab(gBrowser, tab1);
+  await triggerClickOn(tab2, { ctrlKey: true });
+  ok(tab1.multiselected, "Tab1 is multi-selected");
+  ok(tab2.multiselected, "Tab2 is multi-selected");
+  ok(!tab3.multiselected, "Tab3 is not multi-selected");
+
+  promiseTabOpened = BrowserTestUtils.waitForEvent(gBrowser.tabContainer, "TabOpen");
+  EventUtils.synthesizeMouseAtCenter(newTabButton, {});
+  openEvent = await promiseTabOpened;
+  newTab = openEvent.target;
+  is(newTab.previousElementSibling, tab3,
+    "New tab should be opened after tab3 when ctrlKey is not used with multiselection");
+  is(newTab.nextElementSibling, null,
+    "New tab should be opened at the end of the tabstrip when ctrlKey is not used with multiselection");
+  BrowserTestUtils.removeTab(newTab);
+
+  BrowserTestUtils.removeTab(tab1);
+  BrowserTestUtils.removeTab(tab2);
+  BrowserTestUtils.removeTab(tab3);
+});