Bug 1473309 - Move TabContextMenu and stray usercontext-related functions from browser.js to tabbrowser.js. r?bgrins draft
authorDão Gottwald <dao@mozilla.com>
Wed, 04 Jul 2018 16:24:37 +0200
changeset 814118 f83e2c25fea1423d84c0b00f5b9045c90666fe50
parent 814073 a9dc5dc8e2b8513686ad1b1f28c9e4da6de62226
push id115105
push userdgottwald@mozilla.com
push dateWed, 04 Jul 2018 14:25:14 +0000
reviewersbgrins
bugs1473309
milestone63.0a1
Bug 1473309 - Move TabContextMenu and stray usercontext-related functions from browser.js to tabbrowser.js. r?bgrins MozReview-Commit-ID: CA3F65x08Kg
browser/base/content/browser.js
browser/base/content/browser.xul
browser/base/content/tabbrowser.js
browser/base/content/test/sync/browser_contextmenu_sendtab.js
browser/base/content/test/tabs/head.js
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -4550,22 +4550,16 @@ function openNewUserContextTab(event) {
 function updateFileMenuUserContextUIVisibility(id) {
   let menu = document.getElementById(id);
   menu.hidden = !Services.prefs.getBoolPref("privacy.userContext.enabled", false);
   // Visibility of File menu item shouldn't change frequently.
   if (PrivateBrowsingUtils.isWindowPrivate(window)) {
     menu.setAttribute("disabled", "true");
   }
 }
-function updateTabMenuUserContextUIVisibility(id) {
-  let menu = document.getElementById(id);
-  // Visibility of Tab menu item can change frequently.
-  menu.hidden = !Services.prefs.getBoolPref("privacy.userContext.enabled", false) ||
-                PrivateBrowsingUtils.isWindowPrivate(window);
-}
 
 /**
  * Updates the User Context UI indicators if the browser is in a non-default context
  */
 function updateUserContextUIIndicator() {
   let hbox = document.getElementById("userContext-icons");
 
   let userContextId = gBrowser.selectedBrowser.getAttribute("usercontextid");
@@ -4589,54 +4583,16 @@ function updateUserContextUIIndicator() 
 
   let indicator = document.getElementById("userContext-indicator");
   indicator.setAttribute("data-identity-icon", identity.icon);
 
   hbox.hidden = false;
 }
 
 /**
- * Fill 'Reopen in Container' menu.
- */
-function createReopenInContainerMenu(event) {
-  let currentid = TabContextMenu.contextTab.getAttribute("usercontextid");
-
-  return createUserContextMenu(event, {
-    isContextMenu: true,
-    excludeUserContextId: currentid,
-  });
-}
-
-/**
- * Reopen the tab in another container.
- */
-function reopenInContainer(event) {
-  let userContextId = parseInt(event.target.getAttribute("data-usercontextid"));
-  let currentTab = TabContextMenu.contextTab;
-  let isSelected = (gBrowser.selectedTab == currentTab);
-  let uri = currentTab.linkedBrowser.currentURI.spec;
-
-  let newTab = gBrowser.addTab(uri, {
-    userContextId,
-    pinned: currentTab.pinned,
-    index: currentTab._tPos + 1,
-  });
-
-  // Carry over some configuration.
-  if (isSelected) {
-    gBrowser.selectedTab = newTab;
-  }
-  if (currentTab.muted) {
-    if (!newTab.muted) {
-      newTab.toggleMuteAudio(currentTab.muteReason);
-    }
-  }
-}
-
-/**
  * Makes the Character Encoding menu enabled or disabled as appropriate.
  * To be called when the View menu or the app menu is opened.
  */
 function updateCharacterEncodingMenuState() {
   let charsetMenu = document.getElementById("charsetMenu");
   // gBrowser is null on Mac when the menubar shows in the context of
   // non-browser windows. The above elements may be null depending on
   // what parts of the menubar are present. E.g. no app menu on Mac.
@@ -7830,146 +7786,16 @@ var MenuTouchModeObserver = {
     }
   },
 
   uninit() {
     window.removeEventListener("popupshowing", this, true);
   },
 };
 
-var TabContextMenu = {
-  contextTab: null,
-  _updateToggleMuteMenuItems(aTab, aConditionFn) {
-    ["muted", "soundplaying"].forEach(attr => {
-      if (!aConditionFn || aConditionFn(attr)) {
-        if (aTab.hasAttribute(attr)) {
-          aTab.toggleMuteMenuItem.setAttribute(attr, "true");
-          aTab.toggleMultiSelectMuteMenuItem.setAttribute(attr, "true");
-        } else {
-          aTab.toggleMuteMenuItem.removeAttribute(attr);
-          aTab.toggleMultiSelectMuteMenuItem.removeAttribute(attr);
-        }
-      }
-    });
-  },
-  updateContextMenu: function updateContextMenu(aPopupMenu) {
-    this.contextTab = aPopupMenu.triggerNode.localName == "tab" ?
-                      aPopupMenu.triggerNode : gBrowser.selectedTab;
-    let disabled = gBrowser.tabs.length == 1;
-    let multiselectionContext = this.contextTab.multiselected;
-
-    var menuItems = aPopupMenu.getElementsByAttribute("tbattr", "tabbrowser-multiple");
-    for (let menuItem of menuItems)
-      menuItem.disabled = disabled;
-
-    if (this.contextTab.hasAttribute("customizemode"))
-      document.getElementById("context_openTabInWindow").disabled = true;
-
-    disabled = gBrowser.visibleTabs.length == 1;
-    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");
-    contextUnpinSelectedTabs.hidden = !this.contextTab.pinned || !multiselectionContext;
-
-    // Disable "Close Tabs to the Right" if there are no tabs
-    // following it.
-    document.getElementById("context_closeTabsToTheEnd").disabled =
-      gBrowser.getTabsToTheEndFrom(this.contextTab).length == 0;
-
-    // Disable "Close other Tabs" if there are no unpinned tabs.
-    let unpinnedTabsToClose = gBrowser.visibleTabs.length - gBrowser._numPinnedTabs;
-    if (!this.contextTab.pinned) {
-      unpinnedTabsToClose--;
-    }
-    document.getElementById("context_closeOtherTabs").disabled = unpinnedTabsToClose < 1;
-
-    // Only one of close_tab/close_selected_tabs should be visible
-    document.getElementById("context_closeTab").hidden = multiselectionContext;
-    document.getElementById("context_closeSelectedTabs").hidden = !multiselectionContext;
-
-    // Hide "Bookmark All Tabs" for a pinned tab.  Update its state if visible.
-    let bookmarkAllTabs = document.getElementById("context_bookmarkAllTabs");
-    bookmarkAllTabs.hidden = this.contextTab.pinned;
-    if (!bookmarkAllTabs.hidden)
-      PlacesCommandHook.updateBookmarkAllTabsCommand();
-
-    let toggleMute = document.getElementById("context_toggleMuteTab");
-    let toggleMultiSelectMute = document.getElementById("context_toggleMuteSelectedTabs");
-
-    // Only one of mute_unmute_tab/mute_unmute_selected_tabs should be visible
-    toggleMute.hidden = multiselectionContext;
-    toggleMultiSelectMute.hidden = !multiselectionContext;
-
-    // Adjust the state of the toggle mute menu item.
-    if (this.contextTab.hasAttribute("activemedia-blocked")) {
-      toggleMute.label = gNavigatorBundle.getString("playTab.label");
-      toggleMute.accessKey = gNavigatorBundle.getString("playTab.accesskey");
-    } else if (this.contextTab.hasAttribute("muted")) {
-      toggleMute.label = gNavigatorBundle.getString("unmuteTab.label");
-      toggleMute.accessKey = gNavigatorBundle.getString("unmuteTab.accesskey");
-    } else {
-      toggleMute.label = gNavigatorBundle.getString("muteTab.label");
-      toggleMute.accessKey = gNavigatorBundle.getString("muteTab.accesskey");
-    }
-
-    // Adjust the state of the toggle mute menu item for multi-selected tabs.
-    if (this.contextTab.hasAttribute("activemedia-blocked")) {
-      toggleMultiSelectMute.label = gNavigatorBundle.getString("playTabs.label");
-      toggleMultiSelectMute.accessKey = gNavigatorBundle.getString("playTabs.accesskey");
-    } else if (this.contextTab.hasAttribute("muted")) {
-      toggleMultiSelectMute.label = gNavigatorBundle.getString("unmuteSelectedTabs.label");
-      toggleMultiSelectMute.accessKey = gNavigatorBundle.getString("unmuteSelectedTabs.accesskey");
-    } else {
-      toggleMultiSelectMute.label = gNavigatorBundle.getString("muteSelectedTabs.label");
-      toggleMultiSelectMute.accessKey = gNavigatorBundle.getString("muteSelectedTabs.accesskey");
-    }
-
-    this.contextTab.toggleMuteMenuItem = toggleMute;
-    this.contextTab.toggleMultiSelectMuteMenuItem = toggleMultiSelectMute;
-    this._updateToggleMuteMenuItems(this.contextTab);
-
-    this.contextTab.addEventListener("TabAttrModified", this);
-    aPopupMenu.addEventListener("popuphiding", this);
-
-    gSync.updateTabContextMenu(aPopupMenu, this.contextTab);
-
-    updateTabMenuUserContextUIVisibility("context_reopenInContainer");
-  },
-  handleEvent(aEvent) {
-    switch (aEvent.type) {
-      case "popuphiding":
-        gBrowser.removeEventListener("TabAttrModified", this);
-        aEvent.target.removeEventListener("popuphiding", this);
-        break;
-      case "TabAttrModified":
-        let tab = aEvent.target;
-        this._updateToggleMuteMenuItems(tab,
-          attr => aEvent.detail.changed.includes(attr));
-        break;
-    }
-  }
-};
-
 // Prompt user to restart the browser in safe mode
 function safeModeRestart() {
   if (Services.appinfo.inSafeMode) {
     let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].
                      createInstance(Ci.nsISupportsPRBool);
     Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart");
 
     if (cancelQuit.data)
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -118,18 +118,18 @@
                 oncommand="gBrowser.unpinMultiSelectedTabs();"/>
       <menuitem id="context_duplicateTab" label="&duplicateTab.label;"
                 accesskey="&duplicateTab.accesskey;"
                 oncommand="duplicateTabIn(TabContextMenu.contextTab, 'tab');"/>
       <menu id="context_reopenInContainer"
             label="&reopenInContainer.label;"
             accesskey="&reopenInContainer.accesskey;"
             hidden="true">
-        <menupopup oncommand="reopenInContainer(event);"
-                   onpopupshowing="return createReopenInContainerMenu(event);" />
+        <menupopup oncommand="TabContextMenu.reopenInContainer(event);"
+                   onpopupshowing="TabContextMenu.createReopenInContainerMenu(event);"/>
       </menu>
       <menuitem id="context_openTabInWindow" label="&moveToNewWindow.label;"
                 accesskey="&moveToNewWindow.accesskey;"
                 tbattr="tabbrowser-multiple"
                 oncommand="gBrowser.replaceTabWithWindow(TabContextMenu.contextTab);"/>
       <menuseparator id="context_sendTabToDevice_separator" class="sync-ui-item"/>
       <menu id="context_sendTabToDevice" label="&sendTabToDevice.label;"
             class="sync-ui-item"
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -4908,8 +4908,167 @@ var TabBarVisibility = {
 
     document.getElementById("menu_closeWindow").hidden = collapse;
     document.getElementById("menu_close").setAttribute("label",
       gTabBrowserBundle.GetStringFromName(collapse ? "tabs.close" : "tabs.closeTab"));
 
     TabsInTitlebar.allowedBy("tabs-visible", !collapse);
   }
 };
+
+var TabContextMenu = {
+  contextTab: null,
+  _updateToggleMuteMenuItems(aTab, aConditionFn) {
+    ["muted", "soundplaying"].forEach(attr => {
+      if (!aConditionFn || aConditionFn(attr)) {
+        if (aTab.hasAttribute(attr)) {
+          aTab.toggleMuteMenuItem.setAttribute(attr, "true");
+          aTab.toggleMultiSelectMuteMenuItem.setAttribute(attr, "true");
+        } else {
+          aTab.toggleMuteMenuItem.removeAttribute(attr);
+          aTab.toggleMultiSelectMuteMenuItem.removeAttribute(attr);
+        }
+      }
+    });
+  },
+  updateContextMenu(aPopupMenu) {
+    this.contextTab = aPopupMenu.triggerNode.localName == "tab" ?
+                      aPopupMenu.triggerNode : gBrowser.selectedTab;
+    let disabled = gBrowser.tabs.length == 1;
+    let multiselectionContext = this.contextTab.multiselected;
+
+    var menuItems = aPopupMenu.getElementsByAttribute("tbattr", "tabbrowser-multiple");
+    for (let menuItem of menuItems) {
+      menuItem.disabled = disabled;
+    }
+
+    if (this.contextTab.hasAttribute("customizemode")) {
+      document.getElementById("context_openTabInWindow").disabled = true;
+    }
+
+    disabled = gBrowser.visibleTabs.length == 1;
+    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");
+    contextUnpinSelectedTabs.hidden = !this.contextTab.pinned || !multiselectionContext;
+
+    // Disable "Close Tabs to the Right" if there are no tabs
+    // following it.
+    document.getElementById("context_closeTabsToTheEnd").disabled =
+      gBrowser.getTabsToTheEndFrom(this.contextTab).length == 0;
+
+    // Disable "Close other Tabs" if there are no unpinned tabs.
+    let unpinnedTabsToClose = gBrowser.visibleTabs.length - gBrowser._numPinnedTabs;
+    if (!this.contextTab.pinned) {
+      unpinnedTabsToClose--;
+    }
+    document.getElementById("context_closeOtherTabs").disabled = unpinnedTabsToClose < 1;
+
+    // Only one of close_tab/close_selected_tabs should be visible
+    document.getElementById("context_closeTab").hidden = multiselectionContext;
+    document.getElementById("context_closeSelectedTabs").hidden = !multiselectionContext;
+
+    // Hide "Bookmark All Tabs" for a pinned tab.  Update its state if visible.
+    let bookmarkAllTabs = document.getElementById("context_bookmarkAllTabs");
+    bookmarkAllTabs.hidden = this.contextTab.pinned;
+    if (!bookmarkAllTabs.hidden) {
+      PlacesCommandHook.updateBookmarkAllTabsCommand();
+    }
+
+    let toggleMute = document.getElementById("context_toggleMuteTab");
+    let toggleMultiSelectMute = document.getElementById("context_toggleMuteSelectedTabs");
+
+    // Only one of mute_unmute_tab/mute_unmute_selected_tabs should be visible
+    toggleMute.hidden = multiselectionContext;
+    toggleMultiSelectMute.hidden = !multiselectionContext;
+
+    // Adjust the state of the toggle mute menu item.
+    if (this.contextTab.hasAttribute("activemedia-blocked")) {
+      toggleMute.label = gNavigatorBundle.getString("playTab.label");
+      toggleMute.accessKey = gNavigatorBundle.getString("playTab.accesskey");
+    } else if (this.contextTab.hasAttribute("muted")) {
+      toggleMute.label = gNavigatorBundle.getString("unmuteTab.label");
+      toggleMute.accessKey = gNavigatorBundle.getString("unmuteTab.accesskey");
+    } else {
+      toggleMute.label = gNavigatorBundle.getString("muteTab.label");
+      toggleMute.accessKey = gNavigatorBundle.getString("muteTab.accesskey");
+    }
+
+    // Adjust the state of the toggle mute menu item for multi-selected tabs.
+    if (this.contextTab.hasAttribute("activemedia-blocked")) {
+      toggleMultiSelectMute.label = gNavigatorBundle.getString("playTabs.label");
+      toggleMultiSelectMute.accessKey = gNavigatorBundle.getString("playTabs.accesskey");
+    } else if (this.contextTab.hasAttribute("muted")) {
+      toggleMultiSelectMute.label = gNavigatorBundle.getString("unmuteSelectedTabs.label");
+      toggleMultiSelectMute.accessKey = gNavigatorBundle.getString("unmuteSelectedTabs.accesskey");
+    } else {
+      toggleMultiSelectMute.label = gNavigatorBundle.getString("muteSelectedTabs.label");
+      toggleMultiSelectMute.accessKey = gNavigatorBundle.getString("muteSelectedTabs.accesskey");
+    }
+
+    this.contextTab.toggleMuteMenuItem = toggleMute;
+    this.contextTab.toggleMultiSelectMuteMenuItem = toggleMultiSelectMute;
+    this._updateToggleMuteMenuItems(this.contextTab);
+
+    this.contextTab.addEventListener("TabAttrModified", this);
+    aPopupMenu.addEventListener("popuphiding", this);
+
+    gSync.updateTabContextMenu(aPopupMenu, this.contextTab);
+
+    document.getElementById("context_reopenInContainer").hidden =
+      !Services.prefs.getBoolPref("privacy.userContext.enabled", false) ||
+      PrivateBrowsingUtils.isWindowPrivate(window);
+  },
+  handleEvent(aEvent) {
+    switch (aEvent.type) {
+      case "popuphiding":
+        gBrowser.removeEventListener("TabAttrModified", this);
+        aEvent.target.removeEventListener("popuphiding", this);
+        break;
+      case "TabAttrModified":
+        let tab = aEvent.target;
+        this._updateToggleMuteMenuItems(tab,
+          attr => aEvent.detail.changed.includes(attr));
+        break;
+    }
+  },
+  createReopenInContainerMenu(event) {
+    createUserContextMenu(event, {
+      isContextMenu: true,
+      excludeUserContextId: this.contextTab.getAttribute("usercontextid"),
+    });
+  },
+  reopenInContainer(event) {
+    let newTab = gBrowser.addTab(this.contextTab.linkedBrowser.currentURI.spec, {
+      userContextId: parseInt(event.target.getAttribute("data-usercontextid")),
+      pinned: this.contextTab.pinned,
+      index: this.contextTab._tPos + 1,
+    });
+
+    if (gBrowser.selectedTab == this.contextTab) {
+      gBrowser.selectedTab = newTab;
+    }
+    if (this.contextTab.muted) {
+      if (!newTab.muted) {
+        newTab.toggleMuteAudio(this.contextTab.muteReason);
+      }
+    }
+  }
+};
+
--- a/browser/base/content/test/sync/browser_contextmenu_sendtab.js
+++ b/browser/base/content/test/sync/browser_contextmenu_sendtab.js
@@ -13,17 +13,17 @@ let [testTab] = gBrowser.visibleTabs;
 
 function updateTabContextMenu(tab) {
   let menu = document.getElementById("tabContextMenu");
   if (!tab)
     tab = gBrowser.selectedTab;
   var evt = new Event("");
   tab.dispatchEvent(evt);
   menu.openPopup(tab, "end_after", 0, 0, true, false, evt);
-  is(TabContextMenu.contextTab, tab, "TabContextMenu context is the expected tab");
+  is(window.TabContextMenu.contextTab, tab, "TabContextMenu context is the expected tab");
   menu.hidePopup();
 }
 
 add_task(async function setup() {
   await promiseSyncReady();
   // gSync.init() is called in a requestIdleCallback. Force its initialization.
   gSync.init();
   is(gBrowser.visibleTabs.length, 1, "there is one visible tab");
--- a/browser/base/content/test/tabs/head.js
+++ b/browser/base/content/test/tabs/head.js
@@ -1,16 +1,16 @@
 function updateTabContextMenu(tab) {
   let menu = document.getElementById("tabContextMenu");
   if (!tab)
     tab = gBrowser.selectedTab;
   var evt = new Event("");
   tab.dispatchEvent(evt);
   menu.openPopup(tab, "end_after", 0, 0, true, false, evt);
-  is(TabContextMenu.contextTab, tab, "TabContextMenu context is the expected tab");
+  is(window.TabContextMenu.contextTab, tab, "TabContextMenu context is the expected tab");
   menu.hidePopup();
 }
 
 function triggerClickOn(target, options) {
   let promise = BrowserTestUtils.waitForEvent(target, "click");
   if (AppConstants.platform == "macosx") {
       options = {
           metaKey: options.ctrlKey,