Bug 896945 - Allow System Messages to inform gaia they should bring up the receiving app in a configurable way. r=gene,fabrice a=leo+
authorAntonio M. Amaya <amac@tid.es>
Thu, 25 Jul 2013 14:36:15 +0200
changeset 152607 6f6a4ea042c096d36fe308ba5f84c72ddcde4e35
parent 152606 b0e6fbbd444f44052c843a3b8a59f704e91917ab
child 152608 70cfa13bf2b0bb87488e35f94afc456368e634f6
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgene, fabrice, leo
bugs896945
milestone25.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 896945 - Allow System Messages to inform gaia they should bring up the receiving app in a configurable way. r=gene,fabrice a=leo+
b2g/chrome/content/shell.js
dom/activities/src/ActivityMessageConfigurator.js
dom/messages/SystemMessageInternal.js
dom/messages/interfaces/nsISystemMessagesInternal.idl
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -550,16 +550,18 @@ var shell = {
 
   openAppForSystemMessage: function shell_openAppForSystemMessage(msg) {
     let origin = Services.io.newURI(msg.manifest, null, null).prePath;
     this.sendChromeEvent({
       type: 'open-app',
       url: msg.uri,
       manifestURL: msg.manifest,
       isActivity: (msg.type == 'activity'),
+      onlyShowApp: msg.onlyShowApp,
+      showApp: msg.showApp,
       target: msg.target,
       expectingSystemMessage: true,
       extra: msg.extra
     });
   },
 
   receiveMessage: function shell_receiveMessage(message) {
     var activities = { 'content-handler': { name: 'view', response: null },
--- a/dom/activities/src/ActivityMessageConfigurator.js
+++ b/dom/activities/src/ActivityMessageConfigurator.js
@@ -16,18 +16,18 @@ function debug(aMsg) {
 /**
   * nsISystemMessagesConfigurator implementation.
   */
 function ActivityMessageConfigurator() {
   debug("ActivityMessageConfigurator");
 }
 
 ActivityMessageConfigurator.prototype = {
-  get safeToSendBeforeRunningApp() {
-    debug("safeToSendBeforeRunningApp returning false");
-    return false;
+  get mustShowRunningApp() {
+    debug("mustShowRunningApp returning true");
+    return true;
   },
 
   classID: Components.ID("{d2296daa-c406-4c5e-b698-e5f2c1715798}"),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsISystemMessagesConfigurator])
 }
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ActivityMessageConfigurator]);
--- a/dom/messages/SystemMessageInternal.js
+++ b/dom/messages/SystemMessageInternal.js
@@ -44,18 +44,18 @@ const kMessages =["SystemMessageManager:
                   "child-process-shutdown"]
 
 function debug(aMsg) {
   // dump("-- SystemMessageInternal " + Date.now() + " : " + aMsg + "\n");
 }
 
 
 let defaultMessageConfigurator = {
-  get safeToSendBeforeRunningApp() {
-    return true;
+  get mustShowRunningApp() {
+    return false;
   }
 };
 
 const MSG_SENT_SUCCESS = 0;
 const MSG_SENT_FAILURE_PERM_DENIED = 1;
 const MSG_SENT_FAILURE_APP_NOT_RUNNING = 2;
 
 // Implementation of the component used by internal users.
@@ -203,20 +203,17 @@ SystemMessageInternal.prototype = {
       return;
     }
 
     let page = this._findPage(aType, aPageURI.spec, aManifestURI.spec);
     if (page) {
       // Queue this message in the corresponding pages.
       this._queueMessage(page, aMessage, messageID);
 
-      if (result === MSG_SENT_FAILURE_APP_NOT_RUNNING) {
-        // Don't open the page again if we already sent the message to it.
-        this._openAppPage(page, aMessage, aExtra);
-      }
+      this._openAppPage(page, aMessage, aExtra, result);
     }
   },
 
   broadcastMessage: function broadcastMessage(aType, aMessage, aExtra) {
     // Buffer system messages until the webapps' registration is ready,
     // so that we can know the correct pages registered to be broadcasted.
     if (!this._webappsRegistryReady) {
       this._bufferedSysMsgs.push({ how: "broadcast",
@@ -248,20 +245,17 @@ SystemMessageInternal.prototype = {
         // which was not allowed to be sent.
         if (result === MSG_SENT_FAILURE_PERM_DENIED) {
           return;
         }
 
         // Queue this message in the corresponding pages.
         this._queueMessage(aPage, aMessage, messageID);
 
-        if (result === MSG_SENT_FAILURE_APP_NOT_RUNNING) {
-          // Open app pages to handle their pending messages.
-          this._openAppPage(aPage, aMessage, aExtra);
-        }
+        this._openAppPage(aPage, aMessage, aExtra, result);
       }
     }, this);
   },
 
   registerPage: function registerPage(aType, aPageURI, aManifestURI) {
     if (!aPageURI || !aManifestURI) {
       throw Cr.NS_ERROR_INVALID_ARG;
     }
@@ -525,23 +519,38 @@ SystemMessageInternal.prototype = {
     // Queue the message for this page because we've never known if an app is
     // opened or not. We'll clean it up when the app has already received it.
     aPage.pendingMessages.push({ msg: aMessage, msgID: aMessageID });
     if (aPage.pendingMessages.length > kMaxPendingMessages) {
       aPage.pendingMessages.splice(0, 1);
     }
   },
 
-  _openAppPage: function _openAppPage(aPage, aMessage, aExtra) {
+  _openAppPage: function _openAppPage(aPage, aMessage, aExtra, aMsgSentStatus) {
+    // This means the app must be brought to the foreground.
+    let showApp = this._getMessageConfigurator(aPage.type).mustShowRunningApp;
+
+    // We should send the open-app message if the system message was
+    // not sent, or if it was sent but we should show the app anyway.
+    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 = { uri: aPage.uri,
                  manifest: aPage.manifest,
                  type: aPage.type,
                  extra: aExtra,
-                 target: aMessage.target };
+                 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));
   },
 
   _isPageMatched: function _isPageMatched(aPage, aType, aPageURI, aManifestURI) {
     return (aPage.type === aType &&
             aPage.manifest === aManifestURI &&
             aPage.uri === aPageURI)
@@ -575,50 +584,44 @@ SystemMessageInternal.prototype = {
       return MSG_SENT_FAILURE_PERM_DENIED;
     }
 
     let appPageIsRunning = false;
     let pageKey = this._createKeyForPage({ type: aType,
                                            manifest: aManifestURI,
                                            uri: aPageURI });
 
-    // Tries to send the message to a previously opened app only if it's safe
-    // to do so. Generically, it's safe to send the message if the app isn't
-    // going to be reloaded. And it's not safe otherwise
-    if (this._getMessageConfigurator(aType).safeToSendBeforeRunningApp) {
-
-      let targets = this._listeners[aManifestURI];
-      if (targets) {
-        for (let index = 0; index < targets.length; ++index) {
-          let target = targets[index];
-          // We only need to send the system message to the targets (processes)
-          // which contain the window page that matches the manifest/page URL of
-          // the destination of system message.
-          if (target.winCounts[aPageURI] === undefined) {
-            continue;
-          }
+    let targets = this._listeners[aManifestURI];
+    if (targets) {
+      for (let index = 0; index < targets.length; ++index) {
+        let target = targets[index];
+        // We only need to send the system message to the targets (processes)
+        // which contain the window page that matches the manifest/page URL of
+        // the destination of system message.
+        if (target.winCounts[aPageURI] === undefined) {
+          continue;
+        }
 
-          appPageIsRunning = true;
-          // We need to acquire a CPU wake lock for that page and expect that
-          // we'll receive a "SystemMessageManager:HandleMessagesDone" message
-          // when the page finishes handling the system message. At that point,
-          // we'll release the lock we acquired.
-          this._acquireCpuWakeLock(pageKey);
+        appPageIsRunning = true;
+        // We need to acquire a CPU wake lock for that page and expect that
+        // we'll receive a "SystemMessageManager:HandleMessagesDone" message
+        // when the page finishes handling the system message. At that point,
+        // we'll release the lock we acquired.
+        this._acquireCpuWakeLock(pageKey);
 
-          // Multiple windows can share the same target (process), the content
-          // window needs to check if the manifest/page URL is matched. Only
-          // *one* window should handle the system message.
-          let manager = target.target;
-          manager.sendAsyncMessage("SystemMessageManager:Message",
-                                   { type: aType,
-                                     msg: aMessage,
-                                     manifest: aManifestURI,
-                                     uri: aPageURI,
-                                     msgID: aMessageID });
-        }
+        // Multiple windows can share the same target (process), the content
+        // window needs to check if the manifest/page URL is matched. Only
+        // *one* window should handle the system message.
+        let manager = target.target;
+        manager.sendAsyncMessage("SystemMessageManager:Message",
+                                 { type: aType,
+                                   msg: aMessage,
+                                   manifest: aManifestURI,
+                                   uri: aPageURI,
+                                   msgID: aMessageID });
       }
     }
 
     if (!appPageIsRunning) {
       // The app page isn't running and relies on the 'open-app' chrome event to
       // wake it up. We still need to acquire a CPU wake lock for that page and
       // expect that we will receive a "SystemMessageManager:HandleMessagesDone"
       // message when the page finishes handling the system message with other
--- a/dom/messages/interfaces/nsISystemMessagesInternal.idl
+++ b/dom/messages/interfaces/nsISystemMessagesInternal.idl
@@ -51,18 +51,17 @@ interface nsISystemMessagesWrapper: nsIS
    */
   jsval wrapMessage(in jsval message, in nsIDOMWindow window);
 };
 
 /*
  * Implements an interface to allow specific message types to
  * configure some behaviors
  */
-[scriptable, uuid(8a71981b-a462-4697-b63c-925997f9d47b)]
+[scriptable, uuid(a0e970f6-faa9-4605-89d6-fafae8b10a80)]
 interface nsISystemMessagesConfigurator: nsISupports
 {
   /*
-   * Will be true if this type of system messages is safe to send
-   * before the frontend has activated the app to process it.
-   * The default value (if there's no overriding class) is true
+   * Will be true if this type of system messages assumes/requires
+   * that the app will be brought to the front always.
    */
-  readonly attribute boolean safeToSendBeforeRunningApp;
+  readonly attribute boolean mustShowRunningApp;
 };