Bug 1504277 - Open new tabs at the end of a multiselection of tabs if the New Tab button is ctrl-clicked. r=dao
authorJared Wein <jwein@mozilla.com>
Sun, 18 Nov 2018 22:26:52 +0000
changeset 503374 b42ccd72214c31ff454a56436321cecc6cc8416a
parent 503373 7e9cac76980a2a4a10898c721c4a054db831ab4a
child 503375 eb04ab1f698a06f6f9eb58b212dab59d5e1828cd
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [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,102 @@
+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 metaKeyEvent = AppConstants.platform == "macosx" ? {metaKey: true} : {ctrlKey: true};
+
+  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, metaKeyEvent);
+  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, metaKeyEvent);
+  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, metaKeyEvent);
+  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);
+});