Bug 1013671 - Use SystemAppProxy to fire "system-messages-open-app" from SystemMessageInternal.js. r=gene
authorSean Lin <selin@mozilla.com>
Fri, 30 May 2014 15:48:25 +0800
changeset 205700 10869fc4d7e776ece46f35181ee59c3f26caddaa
parent 205699 2a4cde9c1130172be110db8438a6e7a8e9793a5a
child 205701 e11d8753edc0dd1a454c384d79a441193fd5d6be
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgene
bugs1013671, 793420
milestone32.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 1013671 - Use SystemAppProxy to fire "system-messages-open-app" from SystemMessageInternal.js. r=gene Bug 793420 - Remove the waiting timer for the open-app mozChromeEvents requested by System Message. r=gene, fabrice
b2g/chrome/content/shell.js
b2g/components/B2GComponents.manifest
b2g/components/SystemAppProxy.jsm
b2g/components/SystemMessageGlue.js
b2g/components/moz.build
b2g/installer/package-manifest.in
dom/messages/SystemMessageInternal.js
dom/messages/interfaces/moz.build
dom/messages/interfaces/nsISystemMessageGlue.idl
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -365,20 +365,16 @@ var shell = {
     window.removeEventListener('keydown', this, true);
     window.removeEventListener('keypress', this, true);
     window.removeEventListener('keyup', this, true);
     window.removeEventListener('MozApplicationManifest', this);
     window.removeEventListener('mozfullscreenchange', this);
     window.removeEventListener('sizemodechange', this);
     this.contentBrowser.removeEventListener('mozbrowserloadstart', this, true);
     ppmm.removeMessageListener("content-handler", this);
-    if (this.timer) {
-      this.timer.cancel();
-      this.timer = null;
-    }
 
     UserAgentOverrides.uninit();
     IndexedDBPromptHelper.uninit();
   },
 
   // If this key event actually represents a hardware button, filter it here
   // and send a mozChromeEvent with detail.type set to xxx-button-press or
   // xxx-button-release instead.
@@ -470,19 +466,16 @@ var shell = {
     // FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=761067
     if (type !== this.lastHardwareButtonEventType) {
       this.lastHardwareButtonEventType = type;
       this.sendChromeEvent({type: type});
     }
   },
 
   lastHardwareButtonEventType: null, // property for the hack above
-  needBufferOpenAppReq: true,
-  bufferedOpenAppReqs: [],
-  timer: null,
   visibleNormalAudioActive: false,
 
   handleEvent: function shell_handleEvent(evt) {
     let content = this.contentBrowser.contentWindow;
     switch (evt.type) {
       case 'keydown':
       case 'keyup':
       case 'keypress':
@@ -590,30 +583,16 @@ var shell = {
       this.pendingChromeEvents.push(details);
       return;
     }
 
     this.sendEvent(getContentWindow(), "mozChromeEvent",
                    Cu.cloneInto(details, getContentWindow()));
   },
 
-  openAppForSystemMessage: function shell_openAppForSystemMessage(msg) {
-    let payload = {
-      url: msg.pageURL,
-      manifestURL: msg.manifestURL,
-      isActivity: (msg.type == 'activity'),
-      onlyShowApp: msg.onlyShowApp,
-      showApp: msg.showApp,
-      target: msg.target,
-      expectingSystemMessage: true,
-      extra: msg.extra
-    }
-    this.sendCustomEvent('open-app', payload);
-  },
-
   receiveMessage: function shell_receiveMessage(message) {
     var activities = { 'content-handler': { name: 'view', response: null },
                        'dial-handler':    { name: 'dial', response: null },
                        'mail-handler':    { name: 'new',  response: null },
                        'sms-handler':     { name: 'new',  response: null },
                        'file-picker':     { name: 'pick', response: 'file-picked' } };
 
     if (!(message.name in activities))
@@ -672,28 +651,16 @@ var shell = {
       if ('pendingChromeEvents' in shell) {
         shell.pendingChromeEvents.forEach((shell.sendChromeEvent).bind(shell));
       }
       delete shell.pendingChromeEvents;
     });
   }
 };
 
-// Listen for the request of opening app and relay them to Gaia.
-Services.obs.addObserver(function onSystemMessageOpenApp(subject, topic, data) {
-  let msg = JSON.parse(data);
-  // Buffer non-activity request until content starts to load for 10 seconds.
-  // We'll revisit this later if new kind of requests don't need to be cached.
-  if (shell.needBufferOpenAppReq && msg.type !== 'activity') {
-    shell.bufferedOpenAppReqs.push(msg);
-    return;
-  }
-  shell.openAppForSystemMessage(msg);
-}, 'system-messages-open-app', false);
-
 Services.obs.addObserver(function onFullscreenOriginChange(subject, topic, data) {
   shell.sendChromeEvent({ type: "fullscreenoriginchange",
                           fullscreenorigin: data });
 }, "fullscreen-origin-change", false);
 
 DOMApplicationRegistry.registryStarted.then(function () {
   shell.sendChromeEvent({ type: 'webapps-registry-start' });
 });
@@ -712,31 +679,16 @@ Services.obs.addObserver(function(subjec
   shell.sendCustomEvent('mozmemorypressure');
 }, 'memory-pressure', false);
 
 var CustomEventManager = {
   init: function custevt_init() {
     window.addEventListener("ContentStart", (function(evt) {
       let content = shell.contentBrowser.contentWindow;
       content.addEventListener("mozContentEvent", this, false, true);
-
-      // After content starts to load for 10 seconds, send and
-      // clean up the buffered open-app requests if there is any.
-      //
-      // TODO: Bug 793420 - Remove the waiting timer for the 'open-app'
-      //                    mozChromeEvents requested by System Message
-      shell.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-      shell.timer.initWithCallback(function timerCallback() {
-        shell.bufferedOpenAppReqs.forEach(function bufferOpenAppReq(msg) {
-          shell.openAppForSystemMessage(msg);
-        });
-        shell.bufferedOpenAppReqs.length = 0;
-        shell.needBufferOpenAppReq = false;
-        shell.timer = null;
-      }, 10000, Ci.nsITimer.TYPE_ONE_SHOT);
     }).bind(this), false);
   },
 
   handleEvent: function custevt_handleEvent(evt) {
     let detail = evt.detail;
     dump('XXX FIXME : Got a mozContentEvent: ' + detail.type + "\n");
 
     switch(detail.type) {
--- a/b2g/components/B2GComponents.manifest
+++ b/b2g/components/B2GComponents.manifest
@@ -23,16 +23,20 @@ category xpcom-directory-providers b2g-d
 # ActivitiesGlue.js
 component {3a54788b-48cc-4ab4-93d6-0d6a8ef74f8e} ActivitiesGlue.js
 contract @mozilla.org/dom/activities/ui-glue;1 {3a54788b-48cc-4ab4-93d6-0d6a8ef74f8e}
 
 # InterAppCommUIGlue.js
 component {879ee66c-e246-11e3-9910-74d02b97e723} InterAppCommUIGlue.js
 contract @mozilla.org/dom/apps/inter-app-comm-ui-glue;1 {879ee66c-e246-11e3-9910-74d02b97e723}
 
+# SystemMessageGlue.js
+component {2846f034-e614-11e3-93cd-74d02b97e723} SystemMessageGlue.js
+contract @mozilla.org/dom/messages/system-message-glue;1 {2846f034-e614-11e3-93cd-74d02b97e723}
+
 # ProcessGlobal.js
 component {1a94c87a-5ece-4d11-91e1-d29c29f21b28} ProcessGlobal.js
 contract @mozilla.org/b2g-process-global;1 {1a94c87a-5ece-4d11-91e1-d29c29f21b28}
 category app-startup ProcessGlobal service,@mozilla.org/b2g-process-global;1
 
 # PaymentGlue.js
 component {8b83eabc-7929-47f4-8b48-4dea8d887e4b} PaymentGlue.js
 contract @mozilla.org/payment/ui-glue;1 {8b83eabc-7929-47f4-8b48-4dea8d887e4b}
--- a/b2g/components/SystemAppProxy.jsm
+++ b/b2g/components/SystemAppProxy.jsm
@@ -47,23 +47,28 @@ let SystemAppProxy = {
    * Common way to send an event to the system app.
    *
    * // In gecko code:
    *   SystemAppProxy.sendCustomEvent('foo', { data: 'bar' });
    * // In system app:
    *   window.addEventListener('foo', function (event) {
    *     event.details == 'bar'
    *   });
+   *
+   *   @param type      The custom event type.
+   *   @param details   The event details.
+   *   @param noPending Set to true to emit this event even before the system
+   *                    app is ready.
    */
-  _sendCustomEvent: function systemApp_sendCustomEvent(type, details) {
+  _sendCustomEvent: function systemApp_sendCustomEvent(type, details, noPending) {
     let content = this._frame ? this._frame.contentWindow : null;
 
     // If the system app isn't ready yet,
-    // queue events until someone calls setIsLoaded
-    if (!this._isReady || !content) {
+    // queue events until someone calls setIsReady
+    if (!content || (!this._isReady && !noPending)) {
       this._pendingEvents.push([type, details]);
       return null;
     }
 
     let event = content.document.createEvent('CustomEvent');
 
     let payload;
     // If the root object already has __exposedProps__,
new file mode 100644
--- /dev/null
+++ b/b2g/components/SystemMessageGlue.js
@@ -0,0 +1,42 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict"
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "SystemAppProxy",
+                                  "resource://gre/modules/SystemAppProxy.jsm");
+
+function SystemMessageGlue() {
+}
+
+SystemMessageGlue.prototype = {
+  openApp: function(aPageURL, aManifestURL, aType, aTarget, aShowApp,
+                    aOnlyShowApp, aExtra) {
+    let payload = { url: aPageURL,
+                    manifestURL: aManifestURL,
+                    isActivity: (aType == "activity"),
+                    target: aTarget,
+                    showApp: aShowApp,
+                    onlyShowApp: aOnlyShowApp,
+                    expectingSystemMessage: true,
+                    extra: aExtra };
+
+    // |SystemAppProxy| will queue "open-app" events for non-activity system
+    // messages without actually sending them until the system app is ready.
+    SystemAppProxy._sendCustomEvent("open-app", payload, (aType == "activity"));
+  },
+
+  classID: Components.ID("{2846f034-e614-11e3-93cd-74d02b97e723}"),
+
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISystemMessageGlue])
+};
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SystemMessageGlue]);
--- a/b2g/components/moz.build
+++ b/b2g/components/moz.build
@@ -13,16 +13,17 @@ EXTRA_COMPONENTS += [
     'ContentPermissionPrompt.js',
     'FilePicker.js',
     'HelperAppDialog.js',
     'InterAppCommUIGlue.js',
     'MailtoProtocolHandler.js',
     'PaymentGlue.js',
     'ProcessGlobal.js',
     'SmsProtocolHandler.js',
+    'SystemMessageGlue.js',
     'TelProtocolHandler.js',
     'WebappsUpdateTimer.js',
     'YoutubeProtocolHandler.js',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk':
     EXTRA_COMPONENTS += [
       'OopCommandLine.js',
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -797,16 +797,17 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DL
 @BINPATH@/components/MailtoProtocolHandler.js
 @BINPATH@/components/SmsProtocolHandler.js
 @BINPATH@/components/TelProtocolHandler.js
 @BINPATH@/components/B2GAboutRedirector.js
 @BINPATH@/components/FilePicker.js
 @BINPATH@/components/HelperAppDialog.js
 @BINPATH@/components/DownloadsUI.js
 @BINPATH@/components/InterAppCommUIGlue.js
+@BINPATH@/components/SystemMessageGlue.js
 
 #ifndef MOZ_WIDGET_GONK
 @BINPATH@/components/SimulatorScreen.js
 #endif
 
 #ifdef MOZ_SERVICES_FXACCOUNTS
 @BINPATH@/components/FxAccountsUIGlue.js
 @BINPATH@/components/services_fxaccounts.xpt
--- a/dom/messages/SystemMessageInternal.js
+++ b/dom/messages/SystemMessageInternal.js
@@ -580,28 +580,30 @@ SystemMessageInternal.prototype = {
     if ((aMsgSentStatus === MSG_SENT_SUCCESS) && !showApp) {
       return;
     }
 
     // This flag means the app must *only* be brought to the foreground
     // and we don't need to load the app to handle messages.
     let onlyShowApp = (aMsgSentStatus === MSG_SENT_SUCCESS) && showApp;
 
-    // We don't need to send the full object to observers.
-    let page = { pageURL: aPage.pageURL,
-                 manifestURL: aPage.manifestURL,
-                 type: aPage.type,
-                 extra: aExtra,
-                 target: aMessage.target,
-                 onlyShowApp: onlyShowApp,
-                 showApp: showApp };
-    debug("Asking to open " + JSON.stringify(page));
-    Services.obs.notifyObservers(this,
-                                 "system-messages-open-app",
-                                 JSON.stringify(page));
+    debug("Asking to open pageURL: " + aPage.pageURL +
+          ", manifestURL: " + aPage.manifestURL + ", type: " + aPage.type +
+          ", target: " + JSON.stringify(aMessage.target) +
+          ", showApp: " + showApp + ", onlyShowApp: " + onlyShowApp +
+          ", extra: " + JSON.stringify(aExtra));
+
+    let glue = Cc["@mozilla.org/dom/messages/system-message-glue;1"]
+                 .createInstance(Ci.nsISystemMessageGlue);
+    if (glue) {
+      glue.openApp(aPage.pageURL, aPage.manifestURL, aPage.type, aMessage.target,
+                   showApp, onlyShowApp, aExtra);
+    } else {
+      debug("Error! The UI glue component is not implemented.");
+    }
   },
 
   _isPageMatched: function(aPage, aType, aPageURL, aManifestURL) {
     return (aPage.type === aType &&
             aPage.manifestURL === aManifestURL &&
             aPage.pageURL === aPageURL)
   },
 
--- a/dom/messages/interfaces/moz.build
+++ b/dom/messages/interfaces/moz.build
@@ -1,13 +1,14 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 XPIDL_SOURCES += [
     'nsIDOMNavigatorSystemMessages.idl',
+    'nsISystemMessageGlue.idl',
     'nsISystemMessagesInternal.idl',
 ]
 
 XPIDL_MODULE = 'dom_messages'
 
new file mode 100644
--- /dev/null
+++ b/dom/messages/interfaces/nsISystemMessageGlue.idl
@@ -0,0 +1,31 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "domstubs.idl"
+
+// Implemented by the contract id @mozilla.org/dom/messages/system-message-glue;1
+
+[scriptable, uuid(b5d98286-e7cc-11e3-92fb-74d02b97e723)]
+interface nsISystemMessageGlue : nsISupports
+{
+    /* Notify the system app to open the target app.
+     *
+     * @param pageURL     The URL of the page that will be opened.
+     * @param manifestURL The webapp's manifest URL.
+     * @param type        The message type.
+     * @param target      The target which the message is associated with.
+     * @param showApp     This flag indicates the app must be brought to the
+     *                    foreground.
+     * @param onlyShowApp This flag indicates the app must be *only* brought to
+     *                    the foreground without loading to handle messages.
+     * @param extra       Extra opaque info to pass around for opening the page.
+     */
+    void openApp(in DOMString pageURL,
+                 in DOMString manifestURL,
+                 in DOMString type,
+                 in jsval target,
+                 in boolean showApp,
+                 in boolean onlyShowApp,
+                 [optional] in jsval extra);
+};