mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 13:55:43 +00:00
Bug 876397 - Inter-App Communication API (part 3, connect()). r=nsm
This commit is contained in:
parent
a621fc19cd
commit
96cb1d72a8
@ -631,9 +631,18 @@ Services.obs.addObserver(function onSystemMessageOpenApp(subject, topic, data) {
|
||||
shell.openAppForSystemMessage(msg);
|
||||
}, 'system-messages-open-app', false);
|
||||
|
||||
Services.obs.addObserver(function(aSubject, aTopic, aData) {
|
||||
Services.obs.addObserver(function onInterAppCommConnect(subject, topic, data) {
|
||||
data = JSON.parse(data);
|
||||
shell.sendChromeEvent({ type: "inter-app-comm-permission",
|
||||
chromeEventID: data.callerID,
|
||||
manifestURL: data.manifestURL,
|
||||
keyword: data.keyword,
|
||||
peers: data.appsToSelect });
|
||||
}, 'inter-app-comm-select-app', false);
|
||||
|
||||
Services.obs.addObserver(function onFullscreenOriginChange(subject, topic, data) {
|
||||
shell.sendChromeEvent({ type: "fullscreenoriginchange",
|
||||
fullscreenorigin: aData });
|
||||
fullscreenorigin: data });
|
||||
}, "fullscreen-origin-change", false);
|
||||
|
||||
Services.obs.addObserver(function onWebappsStart(subject, topic, data) {
|
||||
@ -700,6 +709,13 @@ var CustomEventManager = {
|
||||
case 'captive-portal-login-cancel':
|
||||
CaptivePortalLoginHelper.handleEvent(detail);
|
||||
break;
|
||||
case 'inter-app-comm-permission':
|
||||
Services.obs.notifyObservers(null, 'inter-app-comm-select-app-result',
|
||||
JSON.stringify({ callerID: detail.chromeEventID,
|
||||
keyword: detail.keyword,
|
||||
manifestURL: detail.manifestURL,
|
||||
selectedApps: detail.peers }));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,13 +8,37 @@ const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/AppsUtils.jsm");
|
||||
|
||||
function debug(aMsg) {
|
||||
// dump("-- InterAppCommService: " + Date.now() + ": " + aMsg + "\n");
|
||||
}
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "appsService",
|
||||
"@mozilla.org/AppsService;1",
|
||||
"nsIAppsService");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
|
||||
"@mozilla.org/parentprocessmessagemanager;1",
|
||||
"nsIMessageBroadcaster");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "UUIDGenerator",
|
||||
"@mozilla.org/uuid-generator;1",
|
||||
"nsIUUIDGenerator");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "messenger",
|
||||
"@mozilla.org/system-message-internal;1",
|
||||
"nsISystemMessagesInternal");
|
||||
|
||||
const kMessages =["Webapps:Connect"];
|
||||
|
||||
function InterAppCommService() {
|
||||
Services.obs.addObserver(this, "xpcom-shutdown", false);
|
||||
Services.obs.addObserver(this, "inter-app-comm-select-app-result", false);
|
||||
|
||||
kMessages.forEach(function(aMsg) {
|
||||
ppmm.addMessageListener(aMsg, this);
|
||||
}, this);
|
||||
|
||||
// This matrix is used for saving the inter-app connection info registered in
|
||||
// the app manifest. The object literal is defined as below:
|
||||
@ -67,6 +91,80 @@ function InterAppCommService() {
|
||||
//
|
||||
// TODO Bug 908999 - Update registered connections when app gets uninstalled.
|
||||
this._registeredConnections = {};
|
||||
|
||||
// This matrix is used for saving the permitted connections, which allows
|
||||
// the messaging between publishers and subscribers. The object literal is
|
||||
// defined as below:
|
||||
//
|
||||
// {
|
||||
// "keyword1": {
|
||||
// "pubAppManifestURL1": [
|
||||
// "subAppManifestURL1",
|
||||
// "subAppManifestURL2",
|
||||
// ...
|
||||
// ],
|
||||
// "pubAppManifestURL2": [
|
||||
// "subAppManifestURL3",
|
||||
// "subAppManifestURL4",
|
||||
// ...
|
||||
// ],
|
||||
// ...
|
||||
// },
|
||||
// "keyword2": {
|
||||
// "pubAppManifestURL3": [
|
||||
// "subAppManifestURL5",
|
||||
// ...
|
||||
// ],
|
||||
// ...
|
||||
// },
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// {
|
||||
// "foo": {
|
||||
// "app://pubApp1.gaiamobile.org/manifest.webapp": [
|
||||
// "app://subApp1.gaiamobile.org/manifest.webapp",
|
||||
// "app://subApp2.gaiamobile.org/manifest.webapp"
|
||||
// ],
|
||||
// "app://pubApp2.gaiamobile.org/manifest.webapp": [
|
||||
// "app://subApp3.gaiamobile.org/manifest.webapp",
|
||||
// "app://subApp4.gaiamobile.org/manifest.webapp"
|
||||
// ]
|
||||
// },
|
||||
// "bar": {
|
||||
// "app://pubApp3.gaiamobile.org/manifest.webapp": [
|
||||
// "app://subApp5.gaiamobile.org/manifest.webapp",
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// TODO Bug 908999 - Update allowed connections when app gets uninstalled.
|
||||
this._allowedConnections = {};
|
||||
|
||||
// This matrix is used for saving the caller info from the content process,
|
||||
// which is indexed by a random UUID, to know where to return the promise
|
||||
// resolvser's callback when the prompt UI for allowing connections returns.
|
||||
// An example of the object literal is shown as below:
|
||||
//
|
||||
// {
|
||||
// "fooID": {
|
||||
// outerWindowID: 12,
|
||||
// requestID: 34,
|
||||
// target: pubAppTarget1
|
||||
// },
|
||||
// "barID": {
|
||||
// outerWindowID: 56,
|
||||
// requestID: 78,
|
||||
// target: pubAppTarget2
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// where |outerWindowID| is the ID of the window requesting the connection,
|
||||
// |requestID| is the ID specifying the promise resolver to return,
|
||||
// |target| is the target of the process requesting the connection.
|
||||
this._promptUICallers = {};
|
||||
}
|
||||
|
||||
InterAppCommService.prototype = {
|
||||
@ -96,10 +194,349 @@ InterAppCommService.prototype = {
|
||||
};
|
||||
},
|
||||
|
||||
_matchMinimumAccessLevel: function(aRules, aAppStatus) {
|
||||
if (!aRules || !aRules.minimumAccessLevel) {
|
||||
debug("rules.minimumAccessLevel is not available. No need to match.");
|
||||
return true;
|
||||
}
|
||||
|
||||
let minAccessLevel = aRules.minimumAccessLevel;
|
||||
switch (minAccessLevel) {
|
||||
case "web":
|
||||
if (aAppStatus == Ci.nsIPrincipal.APP_STATUS_INSTALLED ||
|
||||
aAppStatus == Ci.nsIPrincipal.APP_STATUS_PRIVILEGED ||
|
||||
aAppStatus == Ci.nsIPrincipal.APP_STATUS_CERTIFIED) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case "privileged":
|
||||
if (aAppStatus == Ci.nsIPrincipal.APP_STATUS_PRIVILEGED ||
|
||||
aAppStatus == Ci.nsIPrincipal.APP_STATUS_CERTIFIED) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case "certified":
|
||||
if (aAppStatus == Ci.nsIPrincipal.APP_STATUS_CERTIFIED) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
debug("rules.minimumAccessLevel is not matched! " +
|
||||
"minAccessLevel: " + minAccessLevel + " aAppStatus : " + aAppStatus);
|
||||
return false;
|
||||
},
|
||||
|
||||
_matchManifestURLs: function(aRules, aManifestURL) {
|
||||
if (!aRules || !Array.isArray(aRules.manifestURLs)) {
|
||||
debug("rules.manifestURLs is not available. No need to match.");
|
||||
return true;
|
||||
}
|
||||
|
||||
let manifestURLs = aRules.manifestURLs;
|
||||
if (manifestURLs.indexOf(aManifestURL) != -1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
debug("rules.manifestURLs is not matched! " +
|
||||
"manifestURLs: " + manifestURLs + " aManifestURL : " + aManifestURL);
|
||||
return false;
|
||||
},
|
||||
|
||||
_matchInstallOrigins: function(aRules, aManifestURL) {
|
||||
if (!aRules || !Array.isArray(aRules.installOrigins)) {
|
||||
debug("rules.installOrigins is not available. No need to match.");
|
||||
return true;
|
||||
}
|
||||
|
||||
let installOrigin =
|
||||
appsService.getAppByManifestURL(aManifestURL).installOrigin;
|
||||
|
||||
let installOrigins = aRules.installOrigins;
|
||||
if (installOrigins.indexOf(installOrigin) != -1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
debug("rules.installOrigins is not matched! aManifestURL: " + aManifestURL +
|
||||
" installOrigins: " + installOrigins + " installOrigin : " + installOrigin);
|
||||
return false;
|
||||
},
|
||||
|
||||
_matchRules: function(aPubAppManifestURL, aPubAppStatus, aPubRules,
|
||||
aSubAppManifestURL, aSubAppStatus, aSubRules) {
|
||||
// TODO Bug 907068 In the initiative step, we only expose this API to
|
||||
// certified apps to meet the time line. Eventually, we need to make
|
||||
// it available for the non-certified apps as well. For now, only the
|
||||
// certified apps can match the rules.
|
||||
if (aPubAppStatus != Ci.nsIPrincipal.APP_STATUS_CERTIFIED ||
|
||||
aSubAppStatus != Ci.nsIPrincipal.APP_STATUS_CERTIFIED) {
|
||||
debug("Only certified apps are allowed to do connections.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aPubRules && !aSubRules) {
|
||||
debug("Rules of publisher and subscriber are absent. No need to match.");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check minimumAccessLevel.
|
||||
if (!this._matchMinimumAccessLevel(aPubRules, aSubAppStatus) ||
|
||||
!this._matchMinimumAccessLevel(aSubRules, aPubAppStatus)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check manifestURLs.
|
||||
if (!this._matchManifestURLs(aPubRules, aSubAppManifestURL) ||
|
||||
!this._matchManifestURLs(aSubRules, aPubAppManifestURL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check installOrigins.
|
||||
if (!this._matchInstallOrigins(aPubRules, aSubAppManifestURL) ||
|
||||
!this._matchInstallOrigins(aSubRules, aPubAppManifestURL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check developers.
|
||||
// TODO Do we really want to check this? This one seems naive.
|
||||
|
||||
debug("All rules are matched.");
|
||||
return true;
|
||||
},
|
||||
|
||||
_dispatchMessagePorts: function(aKeyword, aAllowedSubAppManifestURLs,
|
||||
aTarget, aOuterWindowID, aRequestID) {
|
||||
debug("_dispatchMessagePorts: aKeyword: " + aKeyword +
|
||||
" aAllowedSubAppManifestURLs: " + aAllowedSubAppManifestURLs);
|
||||
|
||||
if (aAllowedSubAppManifestURLs.length == 0) {
|
||||
debug("No apps are allowed to connect. Returning.");
|
||||
aTarget.sendAsyncMessage("Webapps:Connect:Return:KO",
|
||||
{ oid: aOuterWindowID, requestID: aRequestID });
|
||||
return;
|
||||
}
|
||||
|
||||
let subAppManifestURLs = this._registeredConnections[aKeyword];
|
||||
if (!subAppManifestURLs) {
|
||||
debug("No apps are subscribed to connect. Returning.");
|
||||
aTarget.sendAsyncMessage("Webapps:Connect:Return:KO",
|
||||
{ oid: aOuterWindowID, requestID: aRequestID });
|
||||
return;
|
||||
}
|
||||
|
||||
let messagePortIDs = [];
|
||||
aAllowedSubAppManifestURLs.forEach(function(aAllowedSubAppManifestURL) {
|
||||
let subscribedInfo = subAppManifestURLs[aAllowedSubAppManifestURL];
|
||||
if (!subscribedInfo) {
|
||||
debug("The sunscribed info is not available. Skipping: " +
|
||||
aAllowedSubAppManifestURL);
|
||||
return;
|
||||
}
|
||||
|
||||
let messagePortID = UUIDGenerator.generateUUID().toString();
|
||||
|
||||
// Fire system message to deliver the message port to the subscriber.
|
||||
messenger.sendMessage("connection",
|
||||
{ keyword: aKeyword,
|
||||
messagePortID: messagePortID },
|
||||
Services.io.newURI(subscribedInfo.pageURL, null, null),
|
||||
Services.io.newURI(subscribedInfo.manifestURL, null, null));
|
||||
|
||||
messagePortIDs.push(messagePortID);
|
||||
});
|
||||
|
||||
if (messagePortIDs.length == 0) {
|
||||
debug("No apps are subscribed to connect. Returning.");
|
||||
aTarget.sendAsyncMessage("Webapps:Connect:Return:KO",
|
||||
{ oid: aOuterWindowID, requestID: aRequestID });
|
||||
return;
|
||||
}
|
||||
|
||||
// Return the message port IDs to open the message ports for the publisher.
|
||||
debug("messagePortIDs: " + messagePortIDs);
|
||||
aTarget.sendAsyncMessage("Webapps:Connect:Return:OK",
|
||||
{ keyword: aKeyword,
|
||||
messagePortIDs: messagePortIDs,
|
||||
oid: aOuterWindowID, requestID: aRequestID });
|
||||
},
|
||||
|
||||
_connect: function(aMessage, aTarget) {
|
||||
let keyword = aMessage.keyword;
|
||||
let pubRules = aMessage.rules;
|
||||
let pubAppManifestURL = aMessage.manifestURL;
|
||||
let outerWindowID = aMessage.outerWindowID;
|
||||
let requestID = aMessage.requestID;
|
||||
let pubAppStatus = aMessage.appStatus;
|
||||
|
||||
let subAppManifestURLs = this._registeredConnections[keyword];
|
||||
if (!subAppManifestURLs) {
|
||||
debug("No apps are subscribed for this connection. Returning.")
|
||||
this._dispatchMessagePorts(keyword, [], aTarget, outerWindowID, requestID);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch the apps that used to be allowed to connect before, so that
|
||||
// users don't need to select/allow them again. That is, we only pop up
|
||||
// the prompt UI for the *new* connections.
|
||||
let allowedSubAppManifestURLs = [];
|
||||
let allowedPubAppManifestURLs = this._allowedConnections[keyword];
|
||||
if (allowedPubAppManifestURLs &&
|
||||
allowedPubAppManifestURLs[pubAppManifestURL]) {
|
||||
allowedSubAppManifestURLs = allowedPubAppManifestURLs[pubAppManifestURL];
|
||||
}
|
||||
|
||||
// Check rules to see if a subscribed app is allowed to connect.
|
||||
let appsToSelect = [];
|
||||
for (let subAppManifestURL in subAppManifestURLs) {
|
||||
if (allowedSubAppManifestURLs.indexOf(subAppManifestURL) != -1) {
|
||||
debug("Don't need to select again. Skipping: " + subAppManifestURL);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only rule-matched publishers/subscribers are allowed to connect.
|
||||
let subscribedInfo = subAppManifestURLs[subAppManifestURL];
|
||||
let subAppStatus = subscribedInfo.appStatus;
|
||||
let subRules = subscribedInfo.rules;
|
||||
|
||||
let matched =
|
||||
this._matchRules(pubAppManifestURL, pubAppStatus, pubRules,
|
||||
subAppManifestURL, subAppStatus, subRules);
|
||||
if (!matched) {
|
||||
debug("Rules are not matched. Skipping: " + subAppManifestURL);
|
||||
continue;
|
||||
}
|
||||
|
||||
appsToSelect.push({
|
||||
manifestURL: subAppManifestURL,
|
||||
description: subscribedInfo.description
|
||||
});
|
||||
}
|
||||
|
||||
if (appsToSelect.length == 0) {
|
||||
debug("No additional apps need to be selected for this connection. " +
|
||||
"Just dispatch message ports for the existing connections.");
|
||||
this._dispatchMessagePorts(keyword, allowedSubAppManifestURLs,
|
||||
aTarget, outerWindowID, requestID);
|
||||
return;
|
||||
}
|
||||
|
||||
// Remember the caller info with an UUID so that we can know where to
|
||||
// return the promise resolver's callback when the prompt UI returns.
|
||||
let callerID = UUIDGenerator.generateUUID().toString();
|
||||
this._promptUICallers[callerID] = {
|
||||
outerWindowID: outerWindowID,
|
||||
requestID: requestID,
|
||||
target: aTarget
|
||||
};
|
||||
|
||||
// TODO Bug 897169 Temporarily disable the notification for popping up
|
||||
// the prompt until the UX/UI for the prompt is confirmed.
|
||||
//
|
||||
// TODO Bug 908191 We need to change the way of interaction between API and
|
||||
// run-time prompt from observer notification to xpcom-interface caller.
|
||||
//
|
||||
/*
|
||||
debug("appsToSelect: " + appsToSelect);
|
||||
Services.obs.notifyObservers(null, "inter-app-comm-select-app",
|
||||
JSON.stringify({ callerID: callerID,
|
||||
manifestURL: pubAppManifestURL,
|
||||
keyword: keyword,
|
||||
appsToSelect: appsToSelect }));
|
||||
*/
|
||||
|
||||
// TODO Bug 897169 Simulate the return of the app-selected result by
|
||||
// the prompt, which always allows the connection. This dummy codes
|
||||
// will be removed when the UX/UI for the prompt is ready.
|
||||
debug("appsToSelect: " + appsToSelect);
|
||||
Services.obs.notifyObservers(null, 'inter-app-comm-select-app-result',
|
||||
JSON.stringify({ callerID: callerID,
|
||||
manifestURL: pubAppManifestURL,
|
||||
keyword: keyword,
|
||||
selectedApps: appsToSelect }));
|
||||
},
|
||||
|
||||
_handleSelectcedApps: function(aData) {
|
||||
let callerID = aData.callerID;
|
||||
let caller = this._promptUICallers[callerID];
|
||||
if (!caller) {
|
||||
debug("Error! Cannot find the caller.");
|
||||
return;
|
||||
}
|
||||
|
||||
delete this._promptUICallers[callerID];
|
||||
|
||||
let outerWindowID = caller.outerWindowID;
|
||||
let requestID = caller.requestID;
|
||||
let target = caller.target;
|
||||
|
||||
let manifestURL = aData.manifestURL;
|
||||
let keyword = aData.keyword;
|
||||
let selectedApps = aData.selectedApps;
|
||||
|
||||
if (selectedApps.length == 0) {
|
||||
debug("No apps are selected to connect.")
|
||||
this._dispatchMessagePorts(keyword, [], target, outerWindowID, requestID);
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the entry of allowed connections to add the selected apps.
|
||||
let allowedPubAppManifestURLs = this._allowedConnections[keyword];
|
||||
if (!allowedPubAppManifestURLs) {
|
||||
allowedPubAppManifestURLs = this._allowedConnections[keyword] = {};
|
||||
}
|
||||
let allowedSubAppManifestURLs = allowedPubAppManifestURLs[manifestURL];
|
||||
if (!allowedSubAppManifestURLs) {
|
||||
allowedSubAppManifestURLs = allowedPubAppManifestURLs[manifestURL] = [];
|
||||
}
|
||||
|
||||
// Add the selected app into the existing set of allowed connections.
|
||||
selectedApps.forEach(function(aSelectedApp) {
|
||||
let allowedSubAppManifestURL = aSelectedApp.manifestURL;
|
||||
if (allowedSubAppManifestURLs.indexOf(allowedSubAppManifestURL) == -1) {
|
||||
allowedSubAppManifestURLs.push(allowedSubAppManifestURL);
|
||||
}
|
||||
});
|
||||
|
||||
// Finally, dispatch the message ports for the allowed connections,
|
||||
// including the old connections and the newly selected connection.
|
||||
this._dispatchMessagePorts(keyword, allowedSubAppManifestURLs,
|
||||
target, outerWindowID, requestID);
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
debug("receiveMessage: name: " + aMessage.name);
|
||||
let message = aMessage.json;
|
||||
let target = aMessage.target;
|
||||
|
||||
// To prevent the hacked child process from sending commands to parent
|
||||
// to do illegal connections, we need to check its manifest URL.
|
||||
if (kMessages.indexOf(aMessage.name) != -1) {
|
||||
if (!target.assertContainApp(message.manifestURL)) {
|
||||
debug("Got message from a child process carrying illegal manifest URL.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
switch (aMessage.name) {
|
||||
case "Webapps:Connect":
|
||||
this._connect(message, target);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
case "xpcom-shutdown":
|
||||
Services.obs.removeObserver(this, "xpcom-shutdown");
|
||||
Services.obs.removeObserver(this, "inter-app-comm-select-app-result");
|
||||
kMessages.forEach(function(aMsg) {
|
||||
ppmm.removeMessageListener(aMsg, this);
|
||||
}, this);
|
||||
ppmm = null;
|
||||
break;
|
||||
case "inter-app-comm-select-app-result":
|
||||
debug("inter-app-comm-select-app-result: " + aData);
|
||||
this._handleSelectcedApps(JSON.parse(aData));
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
@ -26,6 +26,13 @@ InterAppMessagePort.prototype = {
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports]),
|
||||
|
||||
// WebIDL implementation for constructor.
|
||||
__init: function(aKeyword, aMessagePortID, aIsPublisher) {
|
||||
debug("Calling __init(): aKeyword: " + aKeyword +
|
||||
" aMessagePortID: " + aMessagePortID +
|
||||
" aIsPublisher: " + aIsPublisher);
|
||||
},
|
||||
|
||||
postMessage: function(aMessage) {
|
||||
// TODO
|
||||
},
|
||||
|
@ -309,6 +309,8 @@ WebappsApplication.prototype = {
|
||||
|
||||
init: function(aWindow, aApp) {
|
||||
this._window = aWindow;
|
||||
let principal = this._window.document.nodePrincipal;
|
||||
this._appStatus = principal.appStatus;
|
||||
this.origin = aApp.origin;
|
||||
this._manifest = aApp.manifest;
|
||||
this._updateManifest = aApp.updateManifest;
|
||||
@ -342,7 +344,9 @@ WebappsApplication.prototype = {
|
||||
"Webapps:Launch:Return:OK",
|
||||
"Webapps:Launch:Return:KO",
|
||||
"Webapps:PackageEvent",
|
||||
"Webapps:ClearBrowserData:Return"]);
|
||||
"Webapps:ClearBrowserData:Return",
|
||||
"Webapps:Connect:Return:OK",
|
||||
"Webapps:Connect:Return:KO"]);
|
||||
|
||||
cpmm.sendAsyncMessage("Webapps:RegisterForMessages",
|
||||
["Webapps:OfflineCache",
|
||||
@ -461,7 +465,15 @@ WebappsApplication.prototype = {
|
||||
},
|
||||
|
||||
connect: function(aKeyword, aRules) {
|
||||
// TODO
|
||||
return this.createPromise(function (aResolver) {
|
||||
cpmm.sendAsyncMessage("Webapps:Connect",
|
||||
{ keyword: aKeyword,
|
||||
rules: aRules,
|
||||
manifestURL: this.manifestURL,
|
||||
outerWindowID: this._id,
|
||||
appStatus: this._appStatus,
|
||||
requestID: this.getPromiseResolverId(aResolver) });
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
getConnections: function() {
|
||||
@ -487,7 +499,13 @@ WebappsApplication.prototype = {
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
let msg = aMessage.json;
|
||||
let req = this.takeRequest(msg.requestID);
|
||||
let req;
|
||||
if (aMessage.name == "Webapps:Connect:Return:OK" ||
|
||||
aMessage.name == "Webapps:Connect:Return:KO") {
|
||||
req = this.takePromiseResolver(msg.requestID);
|
||||
} else {
|
||||
req = this.takeRequest(msg.requestID);
|
||||
}
|
||||
|
||||
// ondownload* callbacks should be triggered on all app instances
|
||||
if ((msg.oid != this._id || !req) &&
|
||||
@ -611,6 +629,18 @@ WebappsApplication.prototype = {
|
||||
case "Webapps:ClearBrowserData:Return":
|
||||
Services.DOMRequest.fireSuccess(req, null);
|
||||
break;
|
||||
case "Webapps:Connect:Return:OK":
|
||||
let messagePorts = [];
|
||||
msg.messagePortIDs.forEach(function(aPortID) {
|
||||
let port = new this._window.MozInterAppMessagePort(msg.keyword,
|
||||
aPortID, true);
|
||||
messagePorts.push(port);
|
||||
}, this);
|
||||
req.resolve(messagePorts);
|
||||
break;
|
||||
case "Webapps:Connect:Return:KO":
|
||||
req.reject("No connections registered");
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
[HeaderFile="mozilla/dom/InterAppComm.h",
|
||||
Func="mozilla::dom::InterAppComm::EnabledForScope",
|
||||
Constructor(DOMString keyword, DOMString messagePortID, boolean isPublisher),
|
||||
JSImplementation="@mozilla.org/dom/inter-app-message-port;1"]
|
||||
interface MozInterAppMessagePort : EventTarget {
|
||||
void postMessage(any message);
|
||||
|
Loading…
Reference in New Issue
Block a user