From 4deef5ca41a6a60597881ee69f5fc9fac86cd9c1 Mon Sep 17 00:00:00 2001 From: Josh Dover Date: Fri, 25 Apr 2014 16:29:00 +0200 Subject: [PATCH] Bug 776027 - Allow nsIActivityUIGlueCallback to handle native and web activities. r=fabrice --- b2g/components/ActivitiesGlue.js | 9 +- .../interfaces/nsIActivityUIGlue.idl | 30 ++++- dom/activities/src/ActivitiesService.jsm | 110 ++++++++++-------- 3 files changed, 95 insertions(+), 54 deletions(-) diff --git a/b2g/components/ActivitiesGlue.js b/b2g/components/ActivitiesGlue.js index 9c631f457af8..d1c741fa58a9 100644 --- a/b2g/components/ActivitiesGlue.js +++ b/b2g/components/ActivitiesGlue.js @@ -48,7 +48,8 @@ ActivitiesDialog.prototype = { return; SystemAppProxy.removeEventListener("mozContentEvent", act_getChoice); - activity.callback.handleEvent(evt.detail.value !== undefined + activity.callback.handleEvent(Ci.nsIActivityUIGlueCallback.WEBAPPS_ACTIVITY, + evt.detail.value !== undefined ? evt.detail.value : -1); }); @@ -57,6 +58,12 @@ ActivitiesDialog.prototype = { }, chooseActivity: function ap_chooseActivity(aOptions, aActivities, aCallback) { + // B2G does not have an alternate activity system, make no choice and return. + if (aActivities.length === 0) { + aCallback(Ci.nsIActivityUIGlueCallback.WEBAPPS_ACTIVITY, -1); + return; + } + this.activities.push({ name: aOptions.name, list: aActivities, diff --git a/dom/activities/interfaces/nsIActivityUIGlue.idl b/dom/activities/interfaces/nsIActivityUIGlue.idl index 4b16e1c6a140..8e3a4751f1bb 100644 --- a/dom/activities/interfaces/nsIActivityUIGlue.idl +++ b/dom/activities/interfaces/nsIActivityUIGlue.idl @@ -4,22 +4,42 @@ #include "nsISupports.idl" -[scriptable, function, uuid(7a16feb4-5a78-4589-9174-b728f26942e2)] +[scriptable, function, uuid(674b6e69-05f0-41da-aabd-4184ea85c9d8)] interface nsIActivityUIGlueCallback : nsISupports { - void handleEvent(in long choice); + /** + * The activity service should start the activity at the specified index. + */ + const short WEBAPPS_ACTIVITY = 0; + + /** + * The activity service should deliver the specified result to the MozActivity callback. + */ + const short NATIVE_ACTIVITY = 1; + + /** + * Called if the user picked an activitiy to launch. + * @param resultType Inidcates that {@code result} is an index or a native activity result. + * @param result If WEBAPPS_ACTIVITY, the index of the chosen activity. Send '-1' if no choice is made. + If NATIVE_ACTIVITY, the return value to be sent to the MozActivity. + */ + void handleEvent(in short resultType, in jsval result); }; /** * To be implemented by @mozilla.org/dom/activities/ui-glue;1 */ -[scriptable, uuid(03e6743c-2fc3-43fa-bcb3-0476947c8ac5)] +[scriptable, uuid(3caef69f-3569-4b19-bcea-1cfb0fee4466)] interface nsIActivityUIGlue : nsISupports { /** + * This method is called even if the size of {@code activities} is 0 so that the callee can + * decide whether or not to defer the request to an alternate activity system. + * * @param options The ActivityOptions object in the form of { name: "send", data: { ... } } * @param activities A json blob which is an array of { "title":"...", "icon":"..." }. - * @param onresult The callback to send the index of the choosen activity. Send -1 if no choice is made. + * @param callback The callback to send the index of the choosen activity, or the result. */ - void chooseActivity(in jsval options, in jsval activities, in nsIActivityUIGlueCallback onresult); + void chooseActivity(in jsval options, in jsval activities, + in nsIActivityUIGlueCallback callback); }; diff --git a/dom/activities/src/ActivitiesService.jsm b/dom/activities/src/ActivitiesService.jsm index bee5a8024f04..a3ae207424ec 100644 --- a/dom/activities/src/ActivitiesService.jsm +++ b/dom/activities/src/ActivitiesService.jsm @@ -206,59 +206,73 @@ let Activities = { 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.callers[aMsg.id].mm.sendAsyncMessage("Activity:FireError", { - "id": aMsg.id, - "error": "NO_PROVIDER" - }); - delete Activities.callers[aMsg.id]; - return; - } + function getActivityChoice(aResultType, aResult) { + switch(aResultType) { + case Ci.nsIActivityUIGlueCallback.NATIVE_ACTIVITY: { + Activities.callers[aMsg.id].mm.sendAsyncMessage("Activity:FireSuccess", { + "id": aMsg.id, + "result": aResult + }); + break; + } + case Ci.nsIActivityUIGlueCallback.WEBAPPS_ACTIVITY: { + debug("Activity choice: " + aResult); - function getActivityChoice(aChoice) { - debug("Activity choice: " + aChoice); + // We have no matching activity registered, let's fire an error. + // Don't do this check until we have passed to UIGlue so the glue can choose to launch + // its own activity if needed. + if (aResults.options.length === 0) { + Activities.callers[aMsg.id].mm.sendAsyncMessage("Activity:FireError", { + "id": aMsg.id, + "error": "NO_PROVIDER" + }); + delete Activities.callers[aMsg.id]; + return; + } - // The user has cancelled the choice, fire an error. - if (aChoice === -1) { - Activities.callers[aMsg.id].mm.sendAsyncMessage("Activity:FireError", { - "id": aMsg.id, - "error": "ActivityCanceled" - }); - delete Activities.callers[aMsg.id]; - return; - } + // The user has cancelled the choice, fire an error. + if (aResult === -1) { + Activities.callers[aMsg.id].mm.sendAsyncMessage("Activity:FireError", { + "id": aMsg.id, + "error": "ActivityCanceled" + }); + 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? - 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? + delete Activities.callers[aMsg.id]; + return; + } - debug("Sending system message..."); - let result = aResults.options[aChoice]; - sysmm.sendMessage("activity", { - "id": aMsg.id, - "payload": aMsg.options, - "target": result.description - }, - Services.io.newURI(result.description.href, null, null), - Services.io.newURI(result.manifest, null, null), - { - "manifestURL": Activities.callers[aMsg.id].manifestURL, - "pageURL": Activities.callers[aMsg.id].pageURL - }); + debug("Sending system message..."); + let result = aResults.options[aResult]; + sysmm.sendMessage("activity", { + "id": aMsg.id, + "payload": aMsg.options, + "target": result.description + }, + Services.io.newURI(result.description.href, null, null), + Services.io.newURI(result.manifest, null, null), + { + "manifestURL": Activities.callers[aMsg.id].manifestURL, + "pageURL": Activities.callers[aMsg.id].pageURL + }); - if (!result.description.returnValue) { - Activities.callers[aMsg.id].mm.sendAsyncMessage("Activity:FireSuccess", { - "id": aMsg.id, - "result": null - }); - // 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]; + if (!result.description.returnValue) { + Activities.callers[aMsg.id].mm.sendAsyncMessage("Activity:FireSuccess", { + "id": aMsg.id, + "result": null + }); + // 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]; + } + break; + } } };