Bug 1521923 - Preserve lazyness of the first inactive tab moved into a new window. r=jaws
☠☠ backed out by 6b8e4909d303 ☠ ☠
authorOriol Brufau <oriol-bugzilla@hotmail.com>
Thu, 28 Feb 2019 23:21:40 +0000
changeset 519724 51ffa59f14882531251a889b57ed73530c8997ac
parent 519723 62d4e16fbb2b655a82418553929c9883279273a5
child 519725 345dfcf7d76f3ad82f46903e30b65c889cdbf310
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws
bugs1521923
milestone67.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 1521923 - Preserve lazyness of the first inactive tab moved into a new window. r=jaws Differential Revision: https://phabricator.services.mozilla.com/D20100
browser/base/content/browser.js
browser/base/content/tabbrowser.js
browser/base/content/test/tabs/browser_multiselect_tabs_move_to_new_window_contextmenu.js
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1403,16 +1403,19 @@ var gBrowserInit = {
     }
 
     gRemoteControl.updateVisualCue(Marionette.running);
 
     // If we are given a tab to swap in, take care of it before first paint to
     // avoid an about:blank flash.
     let tabToAdopt = this.getTabToAdopt();
     if (tabToAdopt) {
+      let evt = new CustomEvent("before-initial-tab-adopted", { bubbles: true });
+      gBrowser.tabpanels.dispatchEvent(evt);
+
       // Stop the about:blank load
       gBrowser.stop();
       // make sure it has a docshell
       gBrowser.docShell;
 
       // Remove the speculative focus from the urlbar to let the url be formatted.
       gURLBar.removeAttribute("focused");
 
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -3698,59 +3698,47 @@ window._gBrowser = {
     if (this.tabs.length == tabs.length) {
       return null;
     }
 
     if (tabs.length == 1) {
       return this.replaceTabWithWindow(tabs[0], aOptions);
     }
 
-    // The order of the tabs is preserved.
-    // To avoid multiple tab-switch, the active tab is "moved" last, if applicable.
-    // If applicable, the active tab remains active in the new window.
-    let activeTab = gBrowser.selectedTab;
-    let inactiveTabs = tabs.filter(t => t != activeTab);
-    let activeTabNewIndex = tabs.indexOf(activeTab);
-
     // Play the closing animation for all selected tabs to give
     // immediate feedback while waiting for the new window to appear.
     if (this.animationsEnabled) {
       for (let tab of tabs) {
         tab.style.maxWidth = ""; // ensure that fade-out transition happens
         tab.removeAttribute("fadein");
       }
     }
 
-    let win;
-    let firstInactiveTab = inactiveTabs[0];
-
-    let adoptRemainingTabs = () => {
-      for (let i = 1; i < inactiveTabs.length; i++) {
-        win.gBrowser.adoptTab(inactiveTabs[i], i);
+    // Create a new window and make it adopt the tabs, preserving their relative order.
+    // The initial tab of the new window will be selected, so it should adopt the
+    // selected tab of the original window, if applicable, or else the first moving tab.
+    // This avoids tab-switches in the new window, preserving tab laziness.
+    // However, to avoid multiple tab-switches in the original window, the other tabs
+    // should be adopted before the selected one.
+    let selectedTabIndex = Math.max(0, tabs.indexOf(gBrowser.selectedTab));
+    let selectedTab = tabs[selectedTabIndex];
+    let win = this.replaceTabWithWindow(selectedTab, aOptions);
+    win.addEventListener("before-initial-tab-adopted", () => {
+      for (let i = 0; i < tabs.length; ++i) {
+        if (i != selectedTabIndex) {
+          win.gBrowser.adoptTab(tabs[i], i);
+        }
       }
-
-      if (activeTabNewIndex > -1) {
-        win.gBrowser.adoptTab(activeTab, activeTabNewIndex, true /* aSelectTab */);
-      }
-
       // Restore tab selection
       let winVisibleTabs = win.gBrowser.visibleTabs;
       let winTabLength = winVisibleTabs.length;
       win.gBrowser.addRangeToMultiSelectedTabs(winVisibleTabs[0],
                                                winVisibleTabs[winTabLength - 1]);
-    };
-
-    // Pending tabs don't get their docshell swapped, wait for their TabClose
-    if (firstInactiveTab.hasAttribute("pending")) {
-      firstInactiveTab.addEventListener("TabClose", adoptRemainingTabs, {once: true});
-    } else {
-      firstInactiveTab.linkedBrowser.addEventListener("EndSwapDocShells", adoptRemainingTabs, {once: true});
-    }
-
-    win = this.replaceTabWithWindow(firstInactiveTab, aOptions);
+      win.gBrowser.lockClearMultiSelectionOnce();
+    }, {once: true});
     return win;
   },
 
   _updateTabsAfterInsert() {
     for (let i = 0; i < this.tabs.length; i++) {
       this.tabs[i]._tPos = i;
       this.tabs[i]._selected = false;
     }
--- a/browser/base/content/test/tabs/browser_multiselect_tabs_move_to_new_window_contextmenu.js
+++ b/browser/base/content/test/tabs/browser_multiselect_tabs_move_to_new_window_contextmenu.js
@@ -90,25 +90,25 @@ add_task(async function testLazyTabs() {
       }
     });
   });
   let newWindow = gBrowser.replaceTabsWithWindow(oldTabs[0]);
   await tabsMoved;
   let newTabs = newWindow.gBrowser.tabs;
 
   isnot(newTabs[0].linkedPanel, "", `New tab 0 should continue not being lazy`);
-  // FIXME: bug 1521923 - First inactive tab to be moved into another window loses laziness
-  todo_is(newTabs[1].linkedPanel, "", `New tab 1 should continue being lazy`);
-  for (let i = 2; i < numTabs; ++i) {
+  for (let i = 1; i < numTabs; ++i) {
     is(newTabs[i].linkedPanel, "", `New tab ${i} should continue being lazy`);
   }
 
   is(newTabs[0].linkedBrowser.currentURI.spec, `http://example.com/?0`,
     `New tab 0 should have the right URL`);
-  todo_is(SessionStore.getLazyTabValue(newTabs[1], "url"), `http://example.com/?1`,
-    `New tab 1 should have the right lazy URL`);
-  for (let i = 2; i < numTabs; ++i) {
+  for (let i = 1; i < numTabs; ++i) {
     is(SessionStore.getLazyTabValue(newTabs[i], "url"), `http://example.com/?${i}`,
       `New tab ${i} should have the right lazy URL`);
   }
 
+  for (let i = 0; i < numTabs; ++i) {
+    ok(newTabs[i].multiselected, `New tab ${i} should be multiselected`);
+  }
+
   BrowserTestUtils.closeWindow(newWindow);
 });