Bug 1229933: create the Loop menu item in the browser Tools menu dynamically from the extension and remove it from core browser code. r=Standard8
authorMike de Boer <mdeboer@mozilla.com>
Wed, 16 Dec 2015 16:34:26 +0100
changeset 315848 ac9c0f02ef3357c1a6b7ca8f43781e9f15f86d63
parent 315847 48d56e89c4828d82a255c37bb045710d4c1bab25
child 315849 8f1c046303f0e1d1ffe8f5c59fa96b8c36ac5f3b
push id8469
push userbgrinstead@mozilla.com
push dateWed, 16 Dec 2015 19:53:11 +0000
reviewersStandard8
bugs1229933
milestone46.0a1
Bug 1229933: create the Loop menu item in the browser Tools menu dynamically from the extension and remove it from core browser code. r=Standard8
browser/base/content/browser-menubar.inc
browser/extensions/loop/bootstrap.js
browser/locales/en-US/chrome/browser/browser.dtd
browser/locales/en-US/chrome/browser/loop/loop.properties
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -499,21 +499,16 @@
                         accesskey="&addons.accesskey;"
                         key="key_openAddons"
                         command="Tools:Addons"/>
               <menuitem id="menu_openApps"
                         label="&webapps.label;"
                         accesskey="&webapps.accesskey;"
                         oncommand="BrowserOpenApps();"/>
 
-              <menuitem id="menu_openLoop"
-                        label="&loopMenuItem.label;"
-                        accesskey = "&loopMenuItem.accesskey;"
-                        oncommand="LoopUI.togglePanel();"/>
-
               <!-- only one of sync-setup, sync-syncnowitem or sync-reauthitem will be showing at once -->
               <menuitem id="sync-setup"
                         label="&syncSignIn.label;"
                         accesskey="&syncSignIn.accesskey;"
                         observes="sync-setup-state"
                         oncommand="gSyncUI.openSetup(null, 'menubar')"/>
               <menuitem id="sync-syncnowitem"
                         label="&syncSyncNowItem.label;"
--- a/browser/extensions/loop/bootstrap.js
+++ b/browser/extensions/loop/bootstrap.js
@@ -30,16 +30,17 @@ var WindowListener = {
    *
    * @param {Object} window The window to inject the integration into.
    */
   setupBrowserUI: function(window) {
     let document = window.document;
     let gBrowser = window.gBrowser;
     let xhrClass = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"];
     let FileReader = window.FileReader;
+    let menuItem = null;
 
     // the "exported" symbols
     var LoopUI = {
       /**
        * @var {XULWidgetSingleWrapper} toolbarButton Getter for the Loop toolbarbutton
        *                                             instance for this window. This should
        *                                             not be used in the hidden window.
        */
@@ -65,30 +66,16 @@ var WindowListener = {
         if (browser) {
           delete this.browser;
           this.browser = browser;
         }
         return browser;
       },
 
       /**
-       * @var {String|null} selectedTab Getter for the name of the currently selected
-       *                                tab inside the Loop panel. Will be NULL if
-       *                                the panel hasn't loaded yet.
-       */
-      get selectedTab() {
-        if (!this.browser) {
-          return null;
-        }
-
-        let selectedTab = this.browser.contentDocument.querySelector(".tab-view > .selected");
-        return selectedTab && selectedTab.getAttribute("data-tab-name");
-      },
-
-      /**
        * @return {Promise}
        */
       promiseDocumentVisible(aDocument) {
         if (!aDocument.hidden) {
           return Promise.resolve(aDocument);
         }
 
         return new Promise((resolve) => {
@@ -273,32 +260,63 @@ var WindowListener = {
         this.MozLoopService.initialize().catch(ex => {
           if (!ex.message ||
               (!ex.message.contains("not enabled") &&
                !ex.message.contains("not needed"))) {
             console.error(ex);
           }
         });
 
+        this.addMenuItem();
+
         // Don't do the rest if this is for the hidden window - we don't
         // have a toolbar there.
         if (window == Services.appShell.hiddenDOMWindow) {
           return;
         }
 
         // Cleanup when the window unloads.
         window.addEventListener("unload", () => {
           Services.obs.removeObserver(this, "loop-status-changed");
         });
 
         Services.obs.addObserver(this, "loop-status-changed", false);
 
         this.updateToolbarState();
       },
 
+      /**
+       * Adds a menu item to the browsers' Tools menu that open the Loop panel
+       * when selected.
+       */
+      addMenuItem: function() {
+        let menu = document.getElementById("menu_ToolsPopup");
+        if (!menu || menuItem) {
+          return;
+        }
+
+        menuItem = document.createElementNS(kNSXUL, "menuitem");
+        menuItem.setAttribute("id", "menu_openLoop");
+        menuItem.setAttribute("label", this._getString("loopMenuItem_label"));
+        menuItem.setAttribute("accesskey", this._getString("loopMenuItem_accesskey"));
+
+        menuItem.addEventListener("command", () => this.togglePanel());
+
+        menu.insertBefore(menuItem, document.getElementById("sync-setup"));
+      },
+
+      /**
+       * Removes the menu item from the browsers' Tools menu.
+       */
+      removeMenuItem: function() {
+        if (menuItem) {
+          menuItem.parentNode.removeChild(menuItem);
+        }
+      },
+
       // Implements nsIObserver
       observe: function(subject, topic, data) {
         if (topic != "loop-status-changed") {
           return;
         }
         this.updateToolbarState(data);
       },
 
@@ -669,17 +687,20 @@ var WindowListener = {
     window.LoopUI = LoopUI;
   },
 
   tearDownBrowserUI: function(window) {
     let document = window.document;
 
     // Take any steps to remove UI or anything from the browser window
     // document.getElementById() etc. will work here
-    // XXX Add in tear-down of the panel.
+    if (window.LoopUI) {
+      window.LoopUI.removeMenuItem();
+      // XXX Add in tear-down of the panel.
+    }
   },
 
   // nsIWindowMediatorListener functions.
   onOpenWindow: function(xulWindow) {
     // A new window has opened.
     let domWindow = xulWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                              .getInterface(Ci.nsIDOMWindow);
 
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -247,18 +247,16 @@ These should match what Safari and other
 <!ENTITY downloads.accesskey          "D">
 <!ENTITY downloads.commandkey         "j">
 <!ENTITY downloadsUnix.commandkey     "y">
 <!ENTITY addons.label                 "Add-ons">
 <!ENTITY addons.accesskey             "A">
 <!ENTITY addons.commandkey            "A">
 <!ENTITY webapps.label                "Apps">
 <!ENTITY webapps.accesskey            "p">
-<!ENTITY loopMenuItem.label           "Start a conversation…">
-<!ENTITY loopMenuItem.accesskey       "t">
 
 <!ENTITY webDeveloperMenu.label       "Web Developer">
 <!ENTITY webDeveloperMenu.accesskey   "W">
 
 <!ENTITY devToolsCmd.keycode          "VK_F12">
 <!ENTITY devToolsCmd.keytext          "F12">
 
 <!ENTITY devtoolsConnect.label        "Connect…">
--- a/browser/locales/en-US/chrome/browser/loop/loop.properties
+++ b/browser/locales/en-US/chrome/browser/loop/loop.properties
@@ -4,16 +4,22 @@
 
 # Panel Strings
 
 ## LOCALIZATION NOTE(clientShortname2): This should not be localized and
 ## should remain "Firefox Hello" for all locales.
 clientShortname2=Firefox Hello
 clientSuperShortname=Hello
 
+## LOCALIZATION_NOTE(loopMenuItem_label): Label of the menu item that is placed
+## inside the browser 'Tools' menu. Use the unicode ellipsis char, \u2026, or
+## use "..." if \u2026 doesn't suit traditions in your locale.
+loopMenuItem_label=Start a conversation…
+loopMenuItem_accesskey=t
+
 ## LOCALIZATION_NOTE(sign_in_again_title_line_one, sign_in_again_title_line_two2):
 ## These are displayed together at the top of the panel when a user is needed to
 ## sign-in again. The emphesis is on the first line to get the user to sign-in again,
 ## and this is displayed in slightly larger font. Please arrange as necessary for
 ## your locale.
 ## {{clientShortname2}} will be replaced by the brand name for either string.
 sign_in_again_title_line_one=Please sign in again
 sign_in_again_title_line_two2=to continue using {{clientShortname2}}