Bug 1458061 - Implement ability to reload a selection of tabs. r=Gijs draft multiselect_reload
authorAbdoulaye O. Ly <ablayelyfondou@gmail.com>
Fri, 29 Jun 2018 02:39:18 +0000
branchmultiselect_reload
changeset 813166 0ba69495eea0a1f815543d886442d904d9c8b76e
parent 812944 23885c14f025b61bb74d85845ac4018f05eb39f8
push id114812
push userbmo:ablayelyfondou@gmail.com
push dateMon, 02 Jul 2018 17:48:04 +0000
reviewersGijs
bugs1458061
milestone63.0a1
Bug 1458061 - Implement ability to reload a selection of tabs. r=Gijs MozReview-Commit-ID: CyJLk7pxGRr
browser/base/content/browser.js
browser/base/content/browser.xul
browser/base/content/tabbrowser.js
browser/base/content/test/tabs/browser.ini
browser/base/content/test/tabs/browser_multiselect_tabs_reload.js
browser/locales/en-US/chrome/browser/browser.dtd
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -7859,16 +7859,20 @@ var TabContextMenu = {
     menuItems = aPopupMenu.getElementsByAttribute("tbattr", "tabbrowser-multiple-visible");
     for (let menuItem of menuItems)
       menuItem.disabled = disabled;
 
     // Session store
     document.getElementById("context_undoCloseTab").disabled =
       SessionStore.getClosedTabCount(window) == 0;
 
+    // Only one of Reload_Tab/Reload_Selected_Tabs should be visible.
+    document.getElementById("context_reloadTab").hidden = multiselectionContext;
+    document.getElementById("context_reloadSelectedTabs").hidden = !multiselectionContext;
+
     // Only one of pin/unpin/multiselect-pin/multiselect-unpin should be visible
     let contextPinTab = document.getElementById("context_pinTab");
     contextPinTab.hidden = this.contextTab.pinned || multiselectionContext;
     let contextUnpinTab = document.getElementById("context_unpinTab");
     contextUnpinTab.hidden = !this.contextTab.pinned || multiselectionContext;
     let contextPinSelectedTabs = document.getElementById("context_pinSelectedTabs");
     contextPinSelectedTabs.hidden = this.contextTab.pinned || !multiselectionContext;
     let contextUnpinSelectedTabs = document.getElementById("context_unpinSelectedTabs");
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -94,16 +94,19 @@
 #undef FULL_BROWSER_WINDOW
 
   <popupset id="mainPopupSet">
     <menupopup id="tabContextMenu"
                onpopupshowing="if (event.target == this) TabContextMenu.updateContextMenu(this);"
                onpopuphidden="if (event.target == this) TabContextMenu.contextTab = null;">
       <menuitem id="context_reloadTab" label="&reloadTab.label;" accesskey="&reloadTab.accesskey;"
                 oncommand="gBrowser.reloadTab(TabContextMenu.contextTab);"/>
+      <menuitem id="context_reloadSelectedTabs" label="&reloadSelectedTabs.label;" hidden="true"
+                accesskey="&reloadSelectedTabs.accesskey;"
+                oncommand="gBrowser.reloadMultiSelectedTabs();"/>
       <menuitem id="context_toggleMuteTab" oncommand="TabContextMenu.contextTab.toggleMuteAudio();"/>
       <menuitem id="context_toggleMuteSelectedTabs" hidden="true"
                 oncommand="gBrowser.toggleMuteAudioOnMultiSelectedTabs(TabContextMenu.contextTab);"/>
       <menuseparator/>
       <menuitem id="context_pinTab" label="&pinTab.label;"
                 accesskey="&pinTab.accesskey;"
                 oncommand="gBrowser.pinTab(TabContextMenu.contextTab);"/>
       <menuitem id="context_unpinTab" label="&unpinTab.label;" hidden="true"
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -3254,21 +3254,27 @@ window._gBrowser = {
       delete aOtherBrowser.registeredOpenURI;
     }
     if (tmp) {
       aOtherBrowser.registeredOpenURI = tmp;
     }
   },
 
   reloadAllTabs() {
-    let tabs = this.visibleTabs;
-    let l = tabs.length;
-    for (var i = 0; i < l; i++) {
+    this.reloadTabs(this.visibleTabs);
+  },
+
+  reloadMultiSelectedTabs() {
+    this.reloadTabs(this.selectedTabs);
+  },
+
+  reloadTabs(tabs) {
+    for (let tab of tabs) {
       try {
-        this.getBrowserForTab(tabs[i]).reload();
+        this.getBrowserForTab(tab).reload();
       } catch (e) {
         // ignore failure to reload so others will be reloaded
       }
     }
   },
 
   reloadTab(aTab) {
     let browser = this.getBrowserForTab(aTab);
--- a/browser/base/content/test/tabs/browser.ini
+++ b/browser/base/content/test/tabs/browser.ini
@@ -20,16 +20,17 @@ support-files =
   test_bug1358314.html
 [browser_isLocalAboutURI.js]
 [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_reload.js]
 [browser_multiselect_tabs_using_Ctrl.js]
 [browser_multiselect_tabs_using_Shift.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
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabs/browser_multiselect_tabs_reload.js
@@ -0,0 +1,50 @@
+const PREF_MULTISELECT_TABS = "browser.tabs.multiselect";
+
+async function tabLoaded(tab) {
+    const browser = gBrowser.getBrowserForTab(tab);
+    await BrowserTestUtils.browserLoaded(browser);
+    return true;
+}
+
+add_task(async function setPref() {
+    await SpecialPowers.pushPrefEnv({
+        set: [[PREF_MULTISELECT_TABS, true]]
+    });
+});
+
+add_task(async function test() {
+    let tab1 = await addTab();
+    let tab2 = await addTab();
+    let tab3 = await addTab();
+
+    let menuItemReloadTab = document.getElementById("context_reloadTab");
+    let menuItemReloadSelectedTabs = document.getElementById("context_reloadSelectedTabs");
+
+    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");
+
+    updateTabContextMenu(tab3);
+    is(menuItemReloadTab.hidden, false, "Reload Tab is visible");
+    is(menuItemReloadSelectedTabs.hidden, true, "Reload Selected Tabs is hidden");
+
+    updateTabContextMenu(tab2);
+    is(menuItemReloadTab.hidden, true, "Reload Tab is hidden");
+    is(menuItemReloadSelectedTabs.hidden, false, "Reload Selected Tabs is visible");
+
+    let tab1Loaded = tabLoaded(tab1);
+    let tab2Loaded = tabLoaded(tab2);
+    menuItemReloadSelectedTabs.click();
+    await tab1Loaded;
+    await tab2Loaded;
+
+    // We got here because tab1 and tab2 are reloaded. Otherwise the test would have timed out and failed.
+    ok(true, "Tab1 and Tab2 are reloaded");
+
+    BrowserTestUtils.removeTab(tab1);
+    BrowserTestUtils.removeTab(tab2);
+    BrowserTestUtils.removeTab(tab3);
+});
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -40,16 +40,20 @@ left instead of right. -->
 <!ENTITY  pinSelectedTabs.label              "Pin Tabs">
 <!-- Pin Tab and Pin Selected Tabs have the same accesskey
 but will never be visible at the same time. -->
 <!ENTITY  pinSelectedTabs.accesskey          "P">
 <!ENTITY  unpinSelectedTabs.label            "Unpin Tabs">
 <!-- Unpin Tab and Unpin Selected Tabs have the same accesskey
 but will never be visible at the same time. -->
 <!ENTITY  unpinSelectedTabs.accesskey        "b">
+<!-- Reload Tab and Reload Selected Tabs have the same accesskey
+but will never be visible at the same time. -->
+<!ENTITY  reloadSelectedTabs.label           "Reload Selected Tabs">
+<!ENTITY  reloadSelectedTabs.accesskey       "R">
 
 <!-- LOCALIZATION NOTE (pinTab.label, unpinTab.label): "Pin" is being
 used as a metaphor for expressing the fact that these tabs are "pinned" to the
 left edge of the tabstrip. Really we just want the string to express the idea
 that this is a lightweight and reversible action that keeps your tab where you
 can reach it easily. -->
 <!ENTITY  pinTab.label                       "Pin Tab">
 <!ENTITY  pinTab.accesskey                   "P">