mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 11:55:49 +00:00
Bug 1018320 - RequestSync API - patch 3 - a Promise return value from sendAsyncMessage, r=fabrice
This commit is contained in:
parent
717717cd09
commit
b052341e26
@ -46,6 +46,7 @@ const kMessages =["SystemMessageManager:GetPendingMessages",
|
||||
"SystemMessageManager:Message:Return:OK",
|
||||
"SystemMessageManager:AskReadyToRegister",
|
||||
"SystemMessageManager:HandleMessagesDone",
|
||||
"SystemMessageManager:HandleMessageDone",
|
||||
"child-process-shutdown"]
|
||||
|
||||
function debug(aMsg) {
|
||||
@ -84,6 +85,8 @@ function SystemMessageInternal() {
|
||||
|
||||
this._configurators = {};
|
||||
|
||||
this._pendingPromises = new Map();
|
||||
|
||||
Services.obs.addObserver(this, "xpcom-shutdown", false);
|
||||
Services.obs.addObserver(this, "webapps-registry-start", false);
|
||||
Services.obs.addObserver(this, "webapps-registry-ready", false);
|
||||
@ -176,6 +179,14 @@ SystemMessageInternal.prototype = {
|
||||
},
|
||||
|
||||
sendMessage: function(aType, aMessage, aPageURI, aManifestURI, aExtra) {
|
||||
return new Promise((aResolve, aReject) => {
|
||||
this.sendMessageInternal(aType, aMessage, aPageURI, aManifestURI, aExtra,
|
||||
aResolve, aReject);
|
||||
});
|
||||
},
|
||||
|
||||
sendMessageInternal: function(aType, aMessage, aPageURI, aManifestURI,
|
||||
aExtra, aResolvePromiseCb, aRejectPromiseCb) {
|
||||
// Buffer system messages until the webapps' registration is ready,
|
||||
// so that we can know the correct pages registered to be sent.
|
||||
if (!this._webappsRegistryReady) {
|
||||
@ -184,15 +195,22 @@ SystemMessageInternal.prototype = {
|
||||
msg: aMessage,
|
||||
pageURI: aPageURI,
|
||||
manifestURI: aManifestURI,
|
||||
extra: aExtra });
|
||||
extra: aExtra,
|
||||
resolvePromiseCb: aResolvePromiseCb,
|
||||
rejectPromiseCb: aRejectPromiseCb });
|
||||
return;
|
||||
}
|
||||
|
||||
// Give this message an ID so that we can identify the message and
|
||||
// clean it up from the pending message queue when apps receive it.
|
||||
let messageID = gUUIDGenerator.generateUUID().toString();
|
||||
|
||||
let manifestURL = aManifestURI.spec;
|
||||
|
||||
let pendingPromise = { resolvePromiseCb: aResolvePromiseCb,
|
||||
rejectPromiseCb: aRejectPromiseCb,
|
||||
manifestURL: manifestURL,
|
||||
counter: 0 };
|
||||
|
||||
let pageURLs = [];
|
||||
if (aPageURI) {
|
||||
pageURLs.push(aPageURI.spec);
|
||||
@ -226,6 +244,9 @@ SystemMessageInternal.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
// For each page we must receive a confirm.
|
||||
++pendingPromise.counter;
|
||||
|
||||
let page = this._findPage(aType, aPageURL, manifestURL);
|
||||
if (page) {
|
||||
// Queue this message in the corresponding pages.
|
||||
@ -233,7 +254,12 @@ SystemMessageInternal.prototype = {
|
||||
|
||||
this._openAppPage(page, aMessage, aExtra, result);
|
||||
}
|
||||
|
||||
}, this);
|
||||
|
||||
if (pendingPromise.counter) {
|
||||
this._pendingPromises.set(messageID, pendingPromise);
|
||||
}
|
||||
},
|
||||
|
||||
broadcastMessage: function(aType, aMessage, aExtra) {
|
||||
@ -393,7 +419,8 @@ SystemMessageInternal.prototype = {
|
||||
"SystemMessageManager:GetPendingMessages",
|
||||
"SystemMessageManager:HasPendingMessages",
|
||||
"SystemMessageManager:Message:Return:OK",
|
||||
"SystemMessageManager:HandleMessagesDone"].indexOf(aMessage.name) != -1) {
|
||||
"SystemMessageManager:HandleMessagesDone",
|
||||
"SystemMessageManager:HandleMessageDone"].indexOf(aMessage.name) != -1) {
|
||||
if (!aMessage.target.assertContainApp(msg.manifestURL)) {
|
||||
debug("Got message from a child process containing illegal manifest URL.");
|
||||
return null;
|
||||
@ -442,6 +469,8 @@ SystemMessageInternal.prototype = {
|
||||
manifestURL,
|
||||
true,
|
||||
null);
|
||||
|
||||
this._rejectPendingPromises(manifestURL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -453,6 +482,7 @@ SystemMessageInternal.prototype = {
|
||||
msg.manifestURL,
|
||||
false,
|
||||
msg.pageURL);
|
||||
this._rejectPendingPromises(msg.manifestURL);
|
||||
break;
|
||||
}
|
||||
case "SystemMessageManager:GetPendingMessages":
|
||||
@ -520,6 +550,21 @@ SystemMessageInternal.prototype = {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "SystemMessageManager:HandleMessageDone":
|
||||
{
|
||||
debug("received SystemMessageManager:HandleMessageDone " + msg.type +
|
||||
" with msgID " + msg.msgID + " for " + msg.pageURL +
|
||||
" @ " + msg.manifestURL);
|
||||
|
||||
// Maybe this should resolve a pending promise.
|
||||
this._resolvePendingPromises(msg.msgID);
|
||||
|
||||
// A page has finished handling some of its system messages, so we try
|
||||
// to release the CPU wake lock we acquired on behalf of that page.
|
||||
this._releaseCpuWakeLock(this._createKeyForPage(msg), 1);
|
||||
break;
|
||||
}
|
||||
|
||||
case "SystemMessageManager:HandleMessagesDone":
|
||||
{
|
||||
debug("received SystemMessageManager:HandleMessagesDone " + msg.type +
|
||||
@ -547,6 +592,7 @@ SystemMessageInternal.prototype = {
|
||||
ppmm = null;
|
||||
this._pages = null;
|
||||
this._bufferedSysMsgs = null;
|
||||
this._pendingPromises.clear();
|
||||
break;
|
||||
case "webapps-registry-start":
|
||||
this._webappsRegistryReady = false;
|
||||
@ -558,9 +604,10 @@ SystemMessageInternal.prototype = {
|
||||
this._bufferedSysMsgs.forEach(function(aSysMsg) {
|
||||
switch (aSysMsg.how) {
|
||||
case "send":
|
||||
this.sendMessage(
|
||||
this.sendMessageInternal(
|
||||
aSysMsg.type, aSysMsg.msg,
|
||||
aSysMsg.pageURI, aSysMsg.manifestURI, aSysMsg.extra);
|
||||
aSysMsg.pageURI, aSysMsg.manifestURI, aSysMsg.extra,
|
||||
aSysMsg.resolvePromiseCb, aSysMsg.rejectPromiseCb);
|
||||
break;
|
||||
case "broadcast":
|
||||
this.broadcastMessage(aSysMsg.type, aSysMsg.msg, aSysMsg.extra);
|
||||
@ -596,6 +643,9 @@ SystemMessageInternal.prototype = {
|
||||
" from registered pages due to app uninstallation.");
|
||||
}
|
||||
}
|
||||
|
||||
this._rejectPendingPromises(manifestURL);
|
||||
|
||||
debug("Finish updating registered pages for an uninstalled app.");
|
||||
break;
|
||||
}
|
||||
@ -692,9 +742,10 @@ SystemMessageInternal.prototype = {
|
||||
|
||||
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.
|
||||
// we'll receive a "SystemMessageManager:HandleMessagesDone" or a
|
||||
// "SystemMessageManager:HandleMessageDone" 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
|
||||
@ -714,8 +765,9 @@ SystemMessageInternal.prototype = {
|
||||
// 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
|
||||
// pending messages. At that point, we'll release the lock we acquired.
|
||||
// or a "SystemMessageManager:HandleMessageDone" message when the page
|
||||
// finishes handling the system message with other pending messages. At
|
||||
// that point, we'll release the lock we acquired.
|
||||
this._acquireCpuWakeLock(pageKey);
|
||||
return MSG_SENT_FAILURE_APP_NOT_RUNNING;
|
||||
} else {
|
||||
@ -724,6 +776,28 @@ SystemMessageInternal.prototype = {
|
||||
|
||||
},
|
||||
|
||||
_resolvePendingPromises: function(aMessageID) {
|
||||
if (!this._pendingPromises.has(aMessageID)) {
|
||||
debug("Unknown pendingPromise messageID. This seems a bug!!");
|
||||
return;
|
||||
}
|
||||
|
||||
let obj = this._pendingPromises.get(aMessageID);
|
||||
if (!--obj.counter) {
|
||||
obj.resolvePromiseCb();
|
||||
this._pendingPromises.delete(aMessageID);
|
||||
}
|
||||
},
|
||||
|
||||
_rejectPendingPromises: function(aManifestURL) {
|
||||
for (var [i, obj] of this._pendingPromises) {
|
||||
if (obj.manifestURL == aManifestURL) {
|
||||
obj.rejectPromiseCb();
|
||||
this._pendingPromises.delete(i);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
classID: Components.ID("{70589ca5-91ac-4b9e-b839-d6a88167d714}"),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsISystemMessagesInternal,
|
||||
|
@ -57,7 +57,7 @@ function SystemMessageManager() {
|
||||
SystemMessageManager.prototype = {
|
||||
__proto__: DOMRequestIpcHelper.prototype,
|
||||
|
||||
_dispatchMessage: function(aType, aDispatcher, aMessage) {
|
||||
_dispatchMessage: function(aType, aDispatcher, aMessage, aMessageID) {
|
||||
if (aDispatcher.isHandling) {
|
||||
// Queue up the incomming message if we're currently dispatching a
|
||||
// message; we'll send the message once we finish with the current one.
|
||||
@ -66,7 +66,7 @@ SystemMessageManager.prototype = {
|
||||
// event loop from within a system message handler (e.g. via alert()),
|
||||
// and we can then try to send the page another message while it's
|
||||
// inside this nested event loop.
|
||||
aDispatcher.messages.push(aMessage);
|
||||
aDispatcher.messages.push({ message: aMessage, messageID: aMessageID });
|
||||
return;
|
||||
}
|
||||
|
||||
@ -96,16 +96,17 @@ SystemMessageManager.prototype = {
|
||||
|
||||
// We need to notify the parent one of the system messages has been handled,
|
||||
// so the parent can release the CPU wake lock it took on our behalf.
|
||||
cpmm.sendAsyncMessage("SystemMessageManager:HandleMessagesDone",
|
||||
cpmm.sendAsyncMessage("SystemMessageManager:HandleMessageDone",
|
||||
{ type: aType,
|
||||
manifestURL: this._manifestURL,
|
||||
pageURL: this._pageURL,
|
||||
handledCount: 1 });
|
||||
msgID: aMessageID });
|
||||
|
||||
aDispatcher.isHandling = false;
|
||||
|
||||
if (aDispatcher.messages.length > 0) {
|
||||
this._dispatchMessage(aType, aDispatcher, aDispatcher.messages.shift());
|
||||
let msg = aDispatcher.messages.shift();
|
||||
this._dispatchMessage(aType, aDispatcher, msg.message, msg.messageID);
|
||||
} else {
|
||||
// No more messages that need to be handled, we can notify the
|
||||
// ContentChild to release the CPU wake lock grabbed by the ContentParent
|
||||
@ -236,8 +237,9 @@ SystemMessageManager.prototype = {
|
||||
}
|
||||
|
||||
messages.forEach(function(aMsg) {
|
||||
this._dispatchMessage(msg.type, dispatcher, aMsg);
|
||||
this._dispatchMessage(msg.type, dispatcher, aMsg, msg.msgID);
|
||||
}, this);
|
||||
|
||||
} else {
|
||||
// Since no handlers are registered, we need to notify the parent as if
|
||||
// all the queued system messages have been handled (notice |handledCount:
|
||||
|
@ -9,7 +9,7 @@ interface nsIDOMWindow;
|
||||
|
||||
// Implemented by the contract id @mozilla.org/system-message-internal;1
|
||||
|
||||
[scriptable, uuid(6296a314-2abf-4cd0-9097-5e81ee6832e2)]
|
||||
[scriptable, uuid(54c8e274-decb-4258-9a24-4ebfcbf3d00a)]
|
||||
interface nsISystemMessagesInternal : nsISupports
|
||||
{
|
||||
/*
|
||||
@ -22,8 +22,11 @@ interface nsISystemMessagesInternal : nsISupports
|
||||
* @param manifestURI The webapp's manifest URI.
|
||||
* @param extra Extra opaque information that will be passed around in the observer
|
||||
* notification to open the page.
|
||||
* returns a Promise
|
||||
*/
|
||||
void sendMessage(in DOMString type, in jsval message, in nsIURI pageURI, in nsIURI manifestURI, [optional] in jsval extra);
|
||||
nsISupports sendMessage(in DOMString type, in jsval message,
|
||||
in nsIURI pageURI, in nsIURI manifestURI,
|
||||
[optional] in jsval extra);
|
||||
|
||||
/*
|
||||
* Allow any internal user to broadcast a message of a given type.
|
||||
|
Loading…
Reference in New Issue
Block a user