Bug 1521923 - Preserve lazyness of the first inactive tab moved into a new window. r=jaws CLOSED TREE
authorOriol Brufau <oriol-bugzilla@hotmail.com>
Thu, 28 Feb 2019 23:21:40 +0000
changeset 519734 ab719ccd5501eab69ec791da3a7edd939227e743
parent 519733 1003ed8243c5633f9a67a0e1323f6faf0abd067a
child 519735 7c3df2c8c8a7283fd33f055a7e504b777ef9380d
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 CLOSED TREE 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);
 });