Bug 1267916 - Open about preferences #containers in any existing menu (except context menu) draft
authorJonathan Kingston <jkt@mozilla.com>
Mon, 31 Oct 2016 14:03:47 +0000
changeset 431737 ef2fa2af66269d9d3cc813103cc65c7ed0290fbb
parent 431736 45e2f5ced9fb1d7611ef6117bb24dc7a2607dd22
child 432324 c4ce44084568af4d2c32daea37b071f7c29f30ea
push id34098
push userjkingston@mozilla.com
push dateMon, 31 Oct 2016 14:04:23 +0000
bugs1267916
milestone52.0a1
Bug 1267916 - Open about preferences #containers in any existing menu (except context menu) MozReview-Commit-ID: CyUJHc3uZmc
browser/base/content/browser-sets.inc
browser/base/content/nsContextMenu.js
browser/base/content/utilityOverlay.js
browser/components/customizableui/CustomizableWidgets.jsm
browser/locales/en-US/chrome/browser/browser.properties
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -88,16 +88,17 @@
     <command id="cmd_fullZoomReset"   oncommand="FullZoom.reset()"/>
     <command id="cmd_fullZoomToggle"  oncommand="ZoomManager.toggleZoom();"/>
     <command id="cmd_gestureRotateLeft" oncommand="gGestureSupport.rotate(event.sourceEvent)"/>
     <command id="cmd_gestureRotateRight" oncommand="gGestureSupport.rotate(event.sourceEvent)"/>
     <command id="cmd_gestureRotateEnd" oncommand="gGestureSupport.rotateEnd()"/>
     <command id="Browser:OpenLocation" oncommand="openLocation();"/>
     <command id="Browser:RestoreLastSession" oncommand="restoreLastSession();" disabled="true"/>
     <command id="Browser:NewUserContextTab" oncommand="openNewUserContextTab(event.sourceEvent);" reserved="true"/>
+    <command id="Browser:OpenAboutContainers" oncommand="openPreferences('paneContainers');"/>
 
     <command id="Tools:Search" oncommand="BrowserSearch.webSearch();"/>
     <command id="Tools:Downloads" oncommand="BrowserDownloadsUI();"/>
     <command id="Tools:Addons" oncommand="BrowserOpenAddonsMgr();"/>
     <command id="Tools:Sanitize"
      oncommand="Cc['@mozilla.org/browser/browserglue;1'].getService(Ci.nsIBrowserGlue).sanitize(window);"/>
     <command id="Tools:PrivateBrowsing"
       oncommand="OpenBrowserWindow({private: true});" reserved="true"/>
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -1862,12 +1862,12 @@ nsContextMenu.prototype = {
   _checkTelemetryForMenu: function(aXulMenu) {
     this._telemetryClickID = null;
     this._telemetryPageContext = this._getTelemetryPageContextInfo();
     this._telemetryHadCustomItems = this.hasPageMenu;
     this._getTelemetryClickInfo(aXulMenu);
   },
 
   createContainerMenu: function(aEvent) {
-    return createUserContextMenu(aEvent, false,
+    return createUserContextMenu(aEvent, true,
                                  gContextMenuContentData.userContextId);
   },
 };
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -433,36 +433,35 @@ function checkForMiddleClick(node, event
 
     // If the middle-click was on part of a menu, close the menu.
     // (Menus close automatically with left-click but not with middle-click.)
     closeMenus(event.target);
   }
 }
 
 // Populate a menu with user-context menu items. This method should be called
-// by onpopupshowing passing the event as first argument. addCommandAttribute
-// param is used to set the 'command' attribute in the new menuitem elements.
-function createUserContextMenu(event, addCommandAttribute = true, excludeUserContextId = 0) {
+// by onpopupshowing passing the event as first argument.
+function createUserContextMenu(event, isContextMenu = false, excludeUserContextId = 0) {
   while (event.target.hasChildNodes()) {
     event.target.removeChild(event.target.firstChild);
   }
 
   let bundle = document.getElementById("bundle_browser");
   let docfrag = document.createDocumentFragment();
 
   // If we are excluding a userContextId, we want to add a 'no-container' item.
   if (excludeUserContextId) {
     let menuitem = document.createElement("menuitem");
     menuitem.setAttribute("data-usercontextid", "0");
     menuitem.setAttribute("label", bundle.getString("userContextNone.label"));
     menuitem.setAttribute("accesskey", bundle.getString("userContextNone.accesskey"));
 
-    // We don't set an oncommand/command attribute attribute because if we have
+    // We don't set an oncommand/command attribute because if we have
     // to exclude a userContextId we are generating the contextMenu and
-    // addCommandAttribute will be false.
+    // isContextMenu will be true.
 
     docfrag.appendChild(menuitem);
 
     let menuseparator = document.createElement("menuseparator");
     docfrag.appendChild(menuseparator);
   }
 
   ContextualIdentityService.getIdentities().forEach(identity => {
@@ -476,25 +475,37 @@ function createUserContextMenu(event, ad
 
     if (identity.accessKey) {
       menuitem.setAttribute("accesskey", bundle.getString(identity.accessKey));
     }
 
     menuitem.classList.add("menuitem-iconic");
     menuitem.setAttribute("data-identity-color", identity.color);
 
-    if (addCommandAttribute) {
+    if (!isContextMenu) {
       menuitem.setAttribute("command", "Browser:NewUserContextTab");
     }
 
     menuitem.setAttribute("data-identity-icon", identity.icon);
 
     docfrag.appendChild(menuitem);
   });
 
+  if (!isContextMenu) {
+    docfrag.appendChild(document.createElement("menuseparator"));
+
+    let menuitem = document.createElement("menuitem");
+    menuitem.setAttribute("label",
+                          bundle.getString("userContext.aboutPage.label"));
+    menuitem.setAttribute("accesskey",
+                          bundle.getString("userContext.aboutPage.accesskey"));
+    menuitem.setAttribute("command", "Browser:OpenAboutContainers");
+    docfrag.appendChild(menuitem);
+  }
+
   event.target.appendChild(docfrag);
   return true;
 }
 
 // Closes all popups that are ancestors of the node.
 function closeMenus(node)
 {
   if ("tagName" in node) {
--- a/browser/components/customizableui/CustomizableWidgets.jsm
+++ b/browser/components/customizableui/CustomizableWidgets.jsm
@@ -1103,18 +1103,20 @@ const CustomizableWidgets = [
     hasObserver: false,
     onCreated: function(aNode) {
       let doc = aNode.ownerDocument;
       let win = doc.defaultView;
       let items = doc.getElementById("PanelUI-containersItems");
 
       let onItemCommand = function (aEvent) {
         let item = aEvent.target;
-        let userContextId = parseInt(item.getAttribute("usercontextid"));
-        win.openUILinkIn(win.BROWSER_NEW_TAB_URL, "tab", {userContextId});
+        if (item.hasAttribute("usercontextid")) {
+          let userContextId = parseInt(item.getAttribute("usercontextid"));
+          win.openUILinkIn(win.BROWSER_NEW_TAB_URL, "tab", {userContextId});
+        }
       };
       items.addEventListener("command", onItemCommand);
 
       if (PrivateBrowsingUtils.isWindowPrivate(win)) {
         aNode.setAttribute("disabled", "true");
       }
 
       this.updateVisibility(aNode);
@@ -1129,31 +1131,39 @@ const CustomizableWidgets = [
 
       let items = doc.getElementById("PanelUI-containersItems");
 
       while (items.firstChild) {
         items.firstChild.remove();
       }
 
       let fragment = doc.createDocumentFragment();
+      let bundle = doc.getElementById("bundle_browser");
 
       ContextualIdentityService.getIdentities().forEach(identity => {
-        let bundle = doc.getElementById("bundle_browser");
         let label = ContextualIdentityService.getUserContextLabel(identity.userContextId);
 
         let item = doc.createElementNS(kNSXUL, "toolbarbutton");
         item.setAttribute("label", label);
         item.setAttribute("usercontextid", identity.userContextId);
         item.setAttribute("class", "subviewbutton");
         item.setAttribute("data-identity-color", identity.color);
         item.setAttribute("data-identity-icon", identity.icon);
 
         fragment.appendChild(item);
       });
 
+      fragment.appendChild(doc.createElementNS(kNSXUL, "menuseparator"));
+
+      let item = doc.createElementNS(kNSXUL, "toolbarbutton");
+      item.setAttribute("label", bundle.getString("userContext.aboutPage.label"));
+      item.setAttribute("command", "Browser:OpenAboutContainers");
+      item.setAttribute("class", "subviewbutton");
+      fragment.appendChild(item);
+
       items.appendChild(fragment);
     },
 
     updateVisibility(aNode) {
       aNode.hidden = !Services.prefs.getBoolPref("privacy.userContext.enabled");
     },
 
     observe(aSubject, aTopic, aData) {
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -689,16 +689,19 @@ userContextShopping.label = Shopping
 userContextNone.label = No Container
 
 userContextPersonal.accesskey = P
 userContextWork.accesskey = W
 userContextBanking.accesskey = B
 userContextShopping.accesskey = S
 userContextNone.accesskey = N
 
+userContext.aboutPage.label = Manage containers
+userContext.aboutPage.accesskey = O
+
 userContextOpenLink.label = Open Link in New %S Tab
 
 muteTab.label = Mute Tab
 muteTab.accesskey = M
 unmuteTab.label = Unmute Tab
 unmuteTab.accesskey = M
 
 # LOCALIZATION NOTE (weakCryptoOverriding.message): %S is brandShortName