Permalink
Browse files

Reworked to handle Activities API rev. 2

  • Loading branch information...
1 parent 60e6310 commit a2a69dc0160d2097bb38718b239f4ec26342665f mhanson@gmail.com committed Aug 25, 2011
@@ -23,7 +23,8 @@ function Service(svcinfo, iframe) {
unsafeWindow.Service = Service;
Service.prototype = {
- call: function(activity, args, cb, cberr) {
+ call: function(activity, message, cb, cberr) {
+ dump("mediatorAPI service call invoked with activity "+ JSON.stringify(activity) +" action " + activity.action + "\n")
function cbshim(result) {
cb(JSON.parse(result));
}
@@ -33,7 +34,7 @@ Service.prototype = {
}
}
// Need to use unsafeWindow here for some reason.
- unsafeWindow.navigator.apps.mediation._invokeService(this.iframe.contentWindow, this.service, activity, args, cbshim, cberrshim);
+ unsafeWindow.navigator.apps.mediation._startActivity(this.iframe.contentWindow, activity, message, cbshim, cberrshim);
},
// Get the closest icon that is equal to or larger than the requested size,
@@ -105,7 +106,7 @@ window.navigator.apps.mediation.ready = function(invocationHandler) {
services.push(svcob);
allServices[svc.url] = svcob;
}
- invocationHandler(msg.method, msg.args, services);
+ invocationHandler(msg.activity, services);
self.port.once("reconfigure", function() {
// nuke all iframes.
for (let url in allServices) {
@@ -148,15 +149,15 @@ window.navigator.apps.mediation.emit = function(event, args) {
unsafeWindow.navigator.apps.mediation.emit = window.navigator.apps.mediation.emit;
-window.navigator.apps.mediation.invokeService = function(iframe, method, activity, args, callback) {
+window.navigator.apps.mediation.startActivity = function(iframe, activity, message, callback) {//XX error cb?
function callbackShim(result) {
dump("mediator shim got" + (typeof result) + "\n");
callback(JSON.parse(result));
}
// ideally we could use the port mechanism, but this is stymied by the
// inability to pass iframe or iframe.contentWindow in args to emit().
// Need to use unsafeWindow here for some reason.
- unsafeWindow.navigator.apps.mediation._invokeService(iframe.contentWindow, method, activity, args, callbackShim);
+ unsafeWindow.navigator.apps.mediation._startActivity(iframe.contentWindow, activity, message, callbackShim);
};
-unsafeWindow.navigator.apps.mediation.invokeService = window.navigator.apps.mediation.invokeService;
+unsafeWindow.navigator.apps.mediation.startActivity = window.navigator.apps.mediation.startActivity;
@@ -43,16 +43,16 @@ function renderRequestExplanation(requestMethod, args)
}
}
-function handleSetup(method, args, serviceList)
+function handleSetup(activity, serviceList)
{
$("#requestDescription").empty().
append($("<div>Some page is asking for something from you. Perhaps we could provide some more details about what is being requested here.</div>")).
- append($("<div>Method name: " + method + "</div>")).
- append($("<div>Arguments: " + args + "</div>"));
+ append($("<div>Method name: " + activity.action + "</div>")).
+ append($("<div>Arguments: " + activity.data + "</div>"));
gServiceList = serviceList;
- renderRequestExplanation(method, args);
+ renderRequestExplanation(activity.action, activity.data);
$("#servicebox").append($("<div id='services'></div>"));
$("#services").append($("<ul id='services-tabs'></ul>"));
@@ -107,7 +107,7 @@ function handleSetup(method, args, serviceList)
// and then the "add services" tab
svcDiv = createServiceTab(addServicesService);
var serviceFinder = document.createElement("iframe");
- serviceFinder.src = "http://localhost:8420/" + method + ".html";
+ serviceFinder.src = "http://localhost:8420/" + activity.action + ".html";
serviceFinder.classList.add("serviceFrame");
svcDiv.appendChild(serviceFinder);
@@ -149,7 +149,7 @@ $(function() {
});
window.navigator.apps.mediation.ready(
- function(method, args, services) {
+ function(activity, services) {
$("#services").remove();// this will remove old iframes from DOM
for (var i = 0; i < services.length; i++) {
var service = services[i];
@@ -160,6 +160,6 @@ window.navigator.apps.mediation.ready(
})
});
}
- handleSetup(method, args, services);
+ handleSetup(activity, services);
}
);
View
@@ -158,10 +158,10 @@ openwebapps.prototype = {
});
win.appinjector.register({
- apibase: "navigator.apps", name: "invokeService", script: null,
+ apibase: "navigator.apps", name: "startActivity", script: null,
getapi: function (contentWindowRef) {
- return function (methodName, args, successCB, errorCB) {
- self._services.invoke(contentWindowRef, methodName, args, successCB, errorCB);
+ return function (methodName, activity, successCB, errorCB) {
+ self._services.invoke(contentWindowRef, activity, successCB, errorCB);
}
}
});
@@ -170,11 +170,14 @@ openwebapps.prototype = {
// pass a content object (eg, the iframe or the frame's content window).
// Attempting to pass it via self.emit() fails...
win.appinjector.register({
- apibase: "navigator.apps.mediation", name: "_invokeService", script: null,
+ apibase: "navigator.apps.mediation", name: "_startActivity", script: null,
getapi: function (contentWindowRef) {
- return function (iframe, activity, message, args, cb, cberr) {
- args = JSON.parse(JSON.stringify(args));
- self._services.invokeService(iframe.wrappedJSObject, activity, message, args, cb, cberr)
+ return function (iframe, activity, message, cb, cberr) {
+ activity.message = message; // XX remove?
+ if (activity.data) {
+ activity.data = JSON.parse(JSON.stringify(activity.data)); // flatten and reinflate...
+ }
+ self._services.invokeService(iframe.wrappedJSObject, activity, cb, cberr);
}
}
});
@@ -192,8 +195,8 @@ openwebapps.prototype = {
win.appinjector.register({
apibase: "navigator.apps.services", name: "registerHandler", script: null,
getapi: function(contentWindowRef) {
- return function(activity, message, func) {
- self._services.registerServiceHandler(contentWindowRef.wrappedJSObject, activity, message, func);
+ return function(activity, func) {
+ self._services.registerServiceHandler(contentWindowRef.wrappedJSObject, activity, func);
}
}
});
@@ -62,15 +62,16 @@ var nextinvocationid = 0;
* This class controls the mediator panel UI. There is one per tab
* per mediator, created only when needed.
*/
-function MediatorPanel(window, contentWindowRef, methodName, args, successCB, errorCB) {
+function MediatorPanel(window, contentWindowRef, activity, successCB, errorCB) {
this.window = window; // the window the panel is attached to
this.contentWindow = contentWindowRef; // ???
- this.methodName = methodName;
+ this.methodName = activity.action;
+ this.activity = activity;
this.successCB = successCB;
this.errorCB = errorCB;
// Update the content for the new invocation
- this.args = this.updateargs(args);
+ this.args = this.updateargs(activity.data);
this.mediator = mediators[this.methodName];
this.panel = null;
@@ -131,8 +132,7 @@ MediatorPanel.prototype = {
onReady: function(msg) {
FFRepoImplService.findServices(this.methodName, function(serviceList) {
this.panel.port.emit("setup", {
- method: this.methodName,
- args: this.args,
+ activity: this.activity,
serviceList: serviceList,
caller: this.contentWindow.location.href,
invocationid: this.invocationid
@@ -279,7 +279,20 @@ serviceInvocationHandler.prototype = {
*
*/
registerMediator: function(methodName, mediator) {
+ // need to nuke any cached mediators here?
mediators[methodName] = mediator;
+
+ let newPopups = [];
+ for each (let popupCheck in this._popups) {
+ if (popupCheck.methodName === methodName) {
+ // this popup record must die.
+ let nukePanel = popupCheck.panel;
+ nukePanel.destroy();
+ } else {
+ newPopups.push(popupCheck);
+ }
+ }
+ this._popups = newPopups;
},
/**
@@ -363,7 +376,7 @@ serviceInvocationHandler.prototype = {
},
// when an app registers a service handler
- registerServiceHandler: function(contentWindowRef, activity, message, func) {
+ registerServiceHandler: function(contentWindowRef, action, func) {
// check that this is indeed an app
FFRepoImplService.getAppByUrl(contentWindowRef.location, function(app) {
@@ -375,67 +388,70 @@ serviceInvocationHandler.prototype = {
var theWindow = contentWindowRef;
if (!theWindow._MOZ_NOAPP_SERVICES)
theWindow._MOZ_NOAPP_SERVICES = {};
- if (!theWindow._MOZ_NOAPP_SERVICES[activity])
- theWindow._MOZ_NOAPP_SERVICES[activity] = {};
- theWindow._MOZ_NOAPP_SERVICES[activity][message] = func;
+ if (!theWindow._MOZ_NOAPP_SERVICES[action])
+ theWindow._MOZ_NOAPP_SERVICES[action] = {};
+ theWindow._MOZ_NOAPP_SERVICES[action] = func;
return;
}
// make sure the app supports this activity
- if (!(app.services && app.services[activity])) {
- console.log("app attempted to register handler for activity " + activity + " but not declared in manifest");
+ if (!(app.services && app.services[action])) {
+ console.log("app attempted to register handler for activity action " + action + " but not declared in manifest");
return;
}
- //console.log("Registering handler for " + app.origin + " " + activity + " / " + message);
+ //console.log("Registering handler for " + app.origin + " " + activity;
if (!theWindow._MOZ_SERVICES)
theWindow._MOZ_SERVICES = {};
- if (!theWindow._MOZ_SERVICES[activity])
- theWindow._MOZ_SERVICES[activity] = {};
+ if (!theWindow._MOZ_SERVICES[action])
+ theWindow._MOZ_SERVICES[action] = {};
- theWindow._MOZ_SERVICES[activity][message] = func;
+ theWindow._MOZ_SERVICES[action]= func;
});
},
// this call means to invoke a specific call within a given app
- invokeService: function(contentWindow, activity, message, args, cb, cberr, privileged) {
+ invokeService: function(contentWindow, activity, cb, cberr, privileged) {
+ dump("invokeService invoked for " + activity.action + "; message is " + activity.message + "\n")
FFRepoImplService.getAppByUrl(contentWindow.location, function(app) {
var theWindow = contentWindow;
if (!app) {
if (privileged) {
try {
- theWindow._MOZ_NOAPP_SERVICES[activity][message](args, cb);
+ theWindow._MOZ_NOAPP_SERVICES[activity.action](activity);
} catch (e) {
- console.log("error invoking " + activity + "/" + message + " in privileged invocation\n" + e.toString());
+ console.log("error invoking " + activity.action + "/" + message + " in privileged invocation\n" + e.toString());
}
}
return;
}
// make sure the app supports this activity
- if (!(app.services && app.services[activity])) {
- console.log("attempted to send message to app for activity " + activity + " but app doesn't support it");
+ if (!(app.services && app.services[activity.action])) {
+ console.log("attempted to send message to app for activity " + activity.action + " but app doesn't support it");
return;
}
let cbshim = function(result) {
+ dump("cbshim was invoked inside invokeService\n")
cb(JSON.stringify(result));
};
- let cberrshim = function(code, message) {
+ let cberrshim = function(code, errmsg) {
// Following the lead from jschannel, the errback might be invoked
- // as either: errback(code, message) or errback({code: "code", message: message})
+ // as either: errback(code, errmsg) or errback({code: "code", message: errmsg})
+ dump("cberrshim was invoked inside invokeService\n")
let errob;
- if (typeof message === 'undefined') {
+ if (typeof errmsg === 'undefined') {
if (typeof code === 'string') {
errob = {code: code};
} else {
errob = code;
}
} else {
// 2 params - must be explicit code/message params.
- errob = {code: code, message: message};
+ errob = {code: code, message: errmsg};
}
if (cberr) {
cberr(JSON.stringify(errob));
@@ -444,9 +460,11 @@ serviceInvocationHandler.prototype = {
}
}
try {
- theWindow._MOZ_SERVICES[activity][message](args, cbshim, cberrshim);
+ activity.postResult = cbshim;
+ activity.postException = cberrshim;
+ theWindow._MOZ_SERVICES[activity.action](activity);
} catch (e) {
- console.log("error invoking " + activity + "/" + message + " on app " + app.origin + ": " + e.toString());
+ console.log("error invoking " + activity.action + "/" + activity.message + " on app " + app.origin + ": " + e.toString());
// invoke the callback with an error object the content can see.
cberrshim("runtime_error", e.toString());
}
@@ -479,15 +497,15 @@ serviceInvocationHandler.prototype = {
this._popups = newPopups;
},
- get: function(contentWindowRef, methodName, args, successCB, errorCB) {
+ get: function(contentWindowRef, activity, successCB, errorCB) {
for each (let popupCheck in this._popups) {
- if (contentWindowRef == popupCheck.contentWindow && methodName == popupCheck.methodName) {
+ if (contentWindowRef == popupCheck.contentWindow && activity.action == popupCheck.methodName) {
return popupCheck;
}
}
// if we didn't find it, create it
- let agent = agentCreators[methodName] ? agentCreators[methodName] : MediatorPanel;
- let panel = new agent(this._window, contentWindowRef, methodName, args, successCB, errorCB);
+ let agent = agentCreators[activity.action] ? agentCreators[activity.action] : MediatorPanel;
+ let panel = new agent(this._window, contentWindowRef, activity, successCB, errorCB);
// attach our response listeners
panel.attachHandlers();
this._popups.push(panel);
@@ -502,10 +520,10 @@ serviceInvocationHandler.prototype = {
*
* show the panel for a mediator, creating one if necessary.
*/
- invoke: function(contentWindowRef, methodName, args, successCB, errorCB) {
+ invoke: function(contentWindowRef, activity, successCB, errorCB) {
try {
// Do we already have a panel for this service for this content window?
- let panel = this.get(contentWindowRef, methodName, args, successCB, errorCB);
+ let panel = this.get(contentWindowRef, activity, successCB, errorCB);
panel.hideErrorNotification();
panel.show();
} catch (e) {
@@ -1,25 +1,29 @@
// A simple web-app implementing the 'test.basic' service.
-navigator.apps.services.registerHandler('test.basic', 'echoArgs',
- function(args, cb, cberr) {
- cb(args);
- }
-);
+navigator.apps.services.registerHandler('test.basic',
+ function(activity) {
-navigator.apps.services.registerHandler('test.basic', 'testErrors',
- function(args, cb, cberr) {
- if (args.type === "explicit_errob") {
- cberr({code: "testable_error", message: "a testable error"});
- } else if (args.type === "explicit_params") {
- cberr("testable_error", "a testable error");
- } else if (args.type === "implicit_string_exception") {
- throw "a testable error";
+ dump("Basic app test.basic handler invoked - message is " + activity.message + "\n")
+ if (activity.message === "echoArgs") {
+ // just bounce the data back
+ activity.postResult(activity.data);
+
+ } else if (activity.message === "testErrors") {
+ dump("Got testErrors\n")
+ if (activity.data.type === "explicit_errob") {
+ activity.postException({code: "testable_error", message: "a testable error"});
+ } else if (activity.data.type === "explicit_params") {
+ activity.postException("testable_error", "a testable error 2");
+ } else if (activity.data.type === "implicit_string_exception") {
+ throw "a testable error 3";
+ } else {
+ dump("testErrors doesn't know what to do!\n");
+ // and just let things timeout...
+ }
} else {
- dump("testErrors doesn't know what to do!\n");
- // and just let things timeout...
+ activity.postException({code:"unknown_action"});
}
}
);
-
navigator.apps.services.ready();
Oops, something went wrong.

0 comments on commit a2a69dc

Please sign in to comment.