Bug 1106932 - allow opening the loop panel from the menu, focus the panel immediately, r=mikedeboer
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Thu, 01 Oct 2015 15:56:41 -0400
changeset 265801 58acf8a0176e5cc381e33814140750fb781b72be
parent 265800 616c04d4e5a1d7e46033447078bb73bb17e3a653
child 265831 2308353160d2c7b75d6471874af62c965159e2ee
child 265871 10aec9211e477521da35fa265777d8ecd732a18d
push id66032
push userkwierso@gmail.com
push dateFri, 02 Oct 2015 20:43:24 +0000
treeherdermozilla-inbound@03e8acfc181f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmikedeboer
bugs1106932
milestone44.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 1106932 - allow opening the loop panel from the menu, focus the panel immediately, r=mikedeboer
browser/base/content/browser-loop.js
browser/base/content/browser-menubar.inc
browser/locales/en-US/chrome/browser/browser.dtd
--- a/browser/base/content/browser-loop.js
+++ b/browser/base/content/browser-loop.js
@@ -55,45 +55,59 @@ var LoopUI;
       return selectedTab && selectedTab.getAttribute("data-tab-name");
     },
 
     /**
      * @return {Promise}
      */
     promiseDocumentVisible(aDocument) {
       if (!aDocument.hidden) {
-        return Promise.resolve();
+        return Promise.resolve(aDocument);
       }
 
       return new Promise((resolve) => {
         aDocument.addEventListener("visibilitychange", function onVisibilityChanged() {
           aDocument.removeEventListener("visibilitychange", onVisibilityChanged);
-          resolve();
+          resolve(aDocument);
         });
       });
     },
 
     /**
      * Toggle between opening or hiding the Loop panel.
      *
      * @param {DOMEvent} [event] Optional event that triggered the call to this
      *                           function.
      * @param {String}   [tabId] Optional name of the tab to select after the panel
      *                           has opened. Does nothing when the panel is hidden.
      * @return {Promise}
      */
     togglePanel: function(event, tabId = null) {
+      if (!this.panel) {
+        // We're on the hidden window! What fun!
+        let obs = win => {
+          Services.obs.removeObserver(obs, "browser-delayed-startup-finished");
+          win.LoopUI.togglePanel(event, tabId);
+        };
+        Services.obs.addObserver(obs, "browser-delayed-startup-finished", false);
+        return OpenBrowserWindow();
+      }
       if (this.panel.state == "open") {
         return new Promise(resolve => {
           this.panel.hidePopup();
           resolve();
         });
       }
 
-      return this.openCallPanel(event, tabId);
+      return this.openCallPanel(event, tabId).then(doc => {
+        let fm = Services.focus;
+        fm.moveFocus(doc.defaultView, null, fm.MOVEFOCUS_FIRST, fm.FLAG_NOSCROLL);
+      }).catch(err => {
+        Cu.reportError(x);
+      });
     },
 
     /**
      * Opens the panel for Loop and sizes it appropriately.
      *
      * @param {event}  event   The event opening the panel, used to anchor
      *                         the panel to the button which triggers it.
      * @param {String} [tabId] Identifier of the tab to select when the panel is
@@ -125,40 +139,42 @@ var LoopUI;
           // for the content to load - because it's already there.
           if (("contentWindow" in iframe) && iframe.contentWindow.document.readyState == "complete") {
             showTab();
             return;
           }
 
           let documentDOMLoaded = () => {
             iframe.removeEventListener("DOMContentLoaded", documentDOMLoaded, true);
-  	    this.injectLoopAPI(iframe.contentWindow);
-  	    iframe.contentWindow.addEventListener("loopPanelInitialized", function loopPanelInitialized() {
+            this.injectLoopAPI(iframe.contentWindow);
+            iframe.contentWindow.addEventListener("loopPanelInitialized", function loopPanelInitialized() {
               iframe.contentWindow.removeEventListener("loopPanelInitialized",
-                                                       loopPanelInitialized);
+                loopPanelInitialized);
               showTab();
-	    });
-	  };
-	  iframe.addEventListener("DOMContentLoaded", documentDOMLoaded, true); 
+            });
+          };
+          iframe.addEventListener("DOMContentLoaded", documentDOMLoaded, true);
         };
 
         // Used to clear the temporary "login" state from the button.
         Services.obs.notifyObservers(null, "loop-status-changed", null);
 
         this.shouldResumeTour().then((resume) => {
           if (resume) {
             // Assume the conversation with the visitor wasn't open since we would
             // have resumed the tour as soon as the visitor joined if it was (and
             // the pref would have been set to false already.
             this.MozLoopService.resumeTour("waiting");
             resolve();
             return;
           }
 
-          this.PanelFrame.showPopup(window, event ? event.target : this.toolbarButton.node,
+          let anchor = event ? event.target : this.toolbarButton.anchor;
+
+          this.PanelFrame.showPopup(window, anchor,
             "loop", null, "about:looppanel",
             // Loop wants a fixed size for the panel. This also stops it dynamically resizing.
             { width: 330, height: 410 },
             callback);
         });
       });
     },
 
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -502,16 +502,22 @@
                         label="&addons.label;"
                         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();"/>
+
 #ifdef MOZ_SERVICES_SYNC
               <!-- 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"
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -224,16 +224,18 @@ 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…">