Bug 798445 - Send a ChromeEvent when the web activities is completed. r=vingtetun, a=blocking-basecamp
authorFabrice Desré <fabrice@mozilla.com>
Mon, 15 Oct 2012 12:26:49 -0700
changeset 113416 10a4db1a1d8e84bca9d44981a99f1a1c1bf7d87e
parent 113415 de000386f8bf10f4a603cbd4b8e02521611abda9
child 113417 cbfef8616b633b460987030a1b6798b1869e769b
push id2342
push userryanvm@gmail.com
push dateWed, 17 Oct 2012 00:45:56 +0000
treeherdermozilla-aurora@cbfef8616b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvingtetun, blocking-basecamp
bugs798445
milestone18.0a2
Bug 798445 - Send a ChromeEvent when the web activities is completed. r=vingtetun, a=blocking-basecamp
b2g/chrome/content/shell.js
dom/activities/src/ActivitiesService.jsm
dom/activities/src/ActivityProxy.js
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -850,8 +850,18 @@ window.addEventListener('ContentStart', 
 (function volumeStateTracker() {
   Services.obs.addObserver(function(aSubject, aTopic, aData) {
     shell.sendChromeEvent({
       type: 'volume-state-changed',
       active: (aData == 'Shared')
     });
 }, 'volume-state-changed', false);
 })();
+
+Services.obs.addObserver(function(aSubject, aTopic, aData) {
+  let data = JSON.parse(aData);
+  shell.sendChromeEvent({
+    type: "activity-done",
+    success: data.success,
+    manifestURL: data.manifestURL,
+    pageURL: data.pageURL
+  });
+}, "activity-done", false);
--- a/dom/activities/src/ActivitiesService.jsm
+++ b/dom/activities/src/ActivitiesService.jsm
@@ -162,17 +162,17 @@ let Activities = {
     this.messages.forEach(function(msgName) {
       ppmm.addMessageListener(msgName, this);
     }, this);
 
     Services.obs.addObserver(this, "xpcom-shutdown", false);
 
     this.db = new ActivitiesDb();
     this.db.init();
-    this.mm = {};
+    this.callers = {};
   },
 
   observe: function activities_observe(aSubject, aTopic, aData) {
     this.messages.forEach(function(msgName) {
       ppmm.removeMessageListener(msgName, this);
     }, this);
     ppmm = null;
 
@@ -189,34 +189,34 @@ let Activities = {
   startActivity: function activities_startActivity(aMsg) {
     debug("StartActivity: " + JSON.stringify(aMsg));
 
     let successCb = function successCb(aResults) {
       debug(JSON.stringify(aResults));
 
       // We have no matching activity registered, let's fire an error.
       if (aResults.options.length === 0) {
-        Activities.mm[aMsg.id].sendAsyncMessage("Activity:FireError", {
+        Activities.callers[aMsg.id].mm.sendAsyncMessage("Activity:FireError", {
           "id": aMsg.id,
           "error": "NO_PROVIDER"
         });
-        delete Activities.mm[aMsg.id];
+        delete Activities.callers[aMsg.id];
         return;
       }
 
       function getActivityChoice(aChoice) {
         debug("Activity choice: " + aChoice);
 
         // The user has cancelled the choice, fire an error.
         if (aChoice === -1) {
-          Activities.mm[aMsg.id].sendAsyncMessage("Activity:FireError", {
+          Activities.callers[aMsg.id].mm.sendAsyncMessage("Activity:FireError", {
             "id": aMsg.id,
             "error": "USER_ABORT"
           });
-          delete Activities.mm[aMsg.id];
+          delete Activities.callers[aMsg.id];
           return;
         }
 
         let sysmm = Cc["@mozilla.org/system-message-internal;1"]
                       .getService(Ci.nsISystemMessagesInternal);
         if (!sysmm) {
           // System message is not present, what should we do?
           return;
@@ -228,21 +228,23 @@ let Activities = {
             "id": aMsg.id,
             "payload": aMsg.options,
             "target": result.description
           },
           Services.io.newURI(result.description.href, null, null),
           Services.io.newURI(result.manifest, null, null));
 
         if (!result.description.returnValue) {
-          Activities.mm[aMsg.id].sendAsyncMessage("Activity:FireSuccess", {
+          Activities.callers[aMsg.id].mm.sendAsyncMessage("Activity:FireSuccess", {
             "id": aMsg.id,
             "result": null
           });
-          delete Activities.mm[aMsg.id];
+          // No need to notify observers, since we don't want the caller
+          // to be raised on the foreground that quick.
+          delete Activities.callers[aMsg.id];
         }
       };
 
       let glue = Cc["@mozilla.org/dom/activities/ui-glue;1"]
                    .createInstance(Ci.nsIActivityUIGlue);
       glue.chooseActivity(aResults.name, aResults.options, getActivityChoice);
     };
 
@@ -266,29 +268,47 @@ let Activities = {
     };
 
     this.db.find(aMsg, successCb, errorCb, matchFunc);
   },
 
   receiveMessage: function activities_receiveMessage(aMessage) {
     let mm = aMessage.target;
     let msg = aMessage.json;
+
+    let caller;
+    let obsData;
+
+    if (aMessage.name == "Activity:FireSuccess" ||
+        aMessage.name == "Activity:FireError") {
+      caller = this.callers[msg.id];
+      if (caller) {
+        obsData = JSON.stringify({ manifestURL: caller.manifestURL,
+                                   pageURL: caller.pageURL,
+                                   success: aMessage.name == "Activity:FireSuccess" });
+      }
+    }
+
     switch(aMessage.name) {
       case "Activity:Start":
-        this.mm[msg.id] = aMessage.target;
+        this.callers[msg.id] = { mm: aMessage.target,
+                                 manifestURL: msg.manifestURL,
+                                 pageURL: msg.pageURL };
         this.startActivity(msg);
         break;
 
       case "Activity:PostResult":
-        this.mm[msg.id].sendAsyncMessage("Activity:FireSuccess", msg);
-        delete this.mm[msg.id];
+        caller.mm.sendAsyncMessage("Activity:FireSuccess", msg);
+        Services.obs.notifyObservers(null, "activity-done", obsData);
+        delete this.callers[msg.id];
         break;
       case "Activity:PostError":
-        this.mm[msg.id].sendAsyncMessage("Activity:FireError", msg);
-        delete this.mm[msg.id];
+        caller.mm.sendAsyncMessage("Activity:FireError", msg);
+        Services.obs.notifyObservers(null, "activity-done", obsData);
+        delete this.callers[msg.id];
         break;
 
       case "Activities:Register":
         this.db.add(msg, function onSuccess(aEvent) {
           mm.sendAsyncMessage("Activities:Register:OK", msg);
         },
         function onError(aEvent) {
           msg.error = "REGISTER_ERROR";
--- a/dom/activities/src/ActivityProxy.js
+++ b/dom/activities/src/ActivityProxy.js
@@ -6,16 +6,17 @@
 
 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");
 Cu.import("resource://gre/modules/ObjectWrapper.jsm");
+Cu.import("resource://gre/modules/Webapps.jsm");
 
 XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
                                    "@mozilla.org/childprocessmessagemanager;1",
                                    "nsISyncMessageSender");
 
 function debug(aMsg) {
   //dump("-- ActivityProxy " + Date.now() + " : " + aMsg + "\n");
 }
@@ -35,17 +36,28 @@ ActivityProxy.prototype = {
   startActivity: function actProxy_startActivity(aActivity, aOptions, aWindow) {
     debug("startActivity");
 
     this.window = aWindow;
     this.activity = aActivity;
     this.id = Cc["@mozilla.org/uuid-generator;1"]
                 .getService(Ci.nsIUUIDGenerator)
                 .generateUUID().toString();
-    cpmm.sendAsyncMessage("Activity:Start", { id: this.id, options: aOptions });
+    // Retrieve the app's manifest url from the principal, so that we can
+    // later notify when the activity handler called postResult or postError
+    let principal = aWindow.document.nodePrincipal;
+    let appId = principal.appId;
+    let manifestURL = (appId != Ci.nsIScriptSecurityManager.NO_APP_ID &&
+                       appId != Ci.nsIScriptSecurityManager.UNKNOWN_APP_ID)
+                        ? DOMApplicationRegistry.getManifestURLByLocalId(appId)
+                        : null;
+    cpmm.sendAsyncMessage("Activity:Start", { id: this.id,
+                                              options: aOptions,
+                                              manifestURL: manifestURL,
+                                              pageURL: aWindow.document.location.href });
 
     cpmm.addMessageListener("Activity:FireSuccess", this);
     cpmm.addMessageListener("Activity:FireError", this);
   },
 
   receiveMessage: function actProxy_receiveMessage(aMessage) {
     debug("Got message: " + aMessage.name);
     let msg = aMessage.json;