diff --git a/dom/activities/src/ActivityProxy.js b/dom/activities/src/ActivityProxy.js index 7476197681e0..4d48fd1ce8ed 100644 --- a/dom/activities/src/ActivityProxy.js +++ b/dom/activities/src/ActivityProxy.js @@ -54,7 +54,10 @@ ActivityProxy.prototype = { ? DOMApplicationRegistry.getManifestURLByLocalId(appId) : null; cpmm.sendAsyncMessage("Activity:Start", { id: this.id, - options: aOptions, + options: { + name: aOptions.name, + data: aOptions.data + }, manifestURL: manifestURL, pageURL: aWindow.document.location.href }); diff --git a/dom/base/ObjectWrapper.jsm b/dom/base/ObjectWrapper.jsm index 1f16e07e1398..b3563a181e2d 100644 --- a/dom/base/ObjectWrapper.jsm +++ b/dom/base/ObjectWrapper.jsm @@ -4,7 +4,7 @@ "use strict" -const Cu = Components.utils; +const Cu = Components.utils; const Cc = Components.classes; const Ci = Components.interfaces; @@ -13,25 +13,59 @@ const EXPORTED_SYMBOLS = ["ObjectWrapper"]; // Makes sure that we expose correctly chrome JS objects to content. let ObjectWrapper = { + getObjectKind: function objWrapper_getobjectkind(aObject) { + if (!aObject) { + return "null"; + } + + if (Array.isArray(aObject)) { + return "array"; + } else if (aObject.mozSlice && (typeof aObject.mozSlice == "function")) { + return "blob"; + } else if (typeof aObject == "object") { + return "object"; + } else { + return "primitive"; + } + }, + wrap: function objWrapper_wrap(aObject, aCtxt) { + if (!aObject) { + return null; + } + + // First check wich kind of object we have. + let kind = this.getObjectKind(aObject); + if (kind == "array") { + let res = Cu.createArrayIn(aCtxt); + aObject.forEach(function(aObj) { + res.push(this.wrap(aObj, aCtxt)); + }, this); + return res; + } else if (kind == "blob") { + return new aCtxt.Blob([aObject]); + } else if (kind == "primitive") { + return aObject; + } + + // Fall-through, we now have a dictionnary object. let res = Cu.createObjectIn(aCtxt); let propList = { }; for (let prop in aObject) { let value; - if (Array.isArray(aObject[prop])) { + let objProp = aObject[prop]; + let propKind = this.getObjectKind(objProp); + if (propKind == "array") { value = Cu.createArrayIn(aCtxt); - aObject[prop].forEach(function(aObj) { - // Only wrap objects. - if (typeof aObj == "object") { - value.push(objWrapper_wrap(aObj, aCtxt)); - } else { - value.push(aObj); - } - }); - } else if (typeof(aObject[prop]) == "object") { - value = objWrapper_wrap(aObject[prop], aCtxt); + objProp.forEach(function(aObj) { + value.push(this.wrap(aObj, aCtxt)); + }, this); + } else if (propKind == "blob") { + value = new aCtxt.Blob([objProp]); + } else if (propKind == "object") { + value = this.wrap(objProp, aCtxt); } else { - value = aObject[prop]; + value = objProp; } propList[prop] = { enumerable: true, diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 7271f501a5e5..ac3732918d03 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -1228,7 +1228,9 @@ ContentParent::GetOrCreateActorForBlob(nsIDOMBlob* aBlob) static_cast(remoteBlob->GetPBlob())); NS_ASSERTION(actor, "Null actor?!"); - return actor; + if (actor->Manager() == this) { + return actor; + } } // XXX This is only safe so long as all blob implementations in our tree diff --git a/dom/messages/SystemMessageInternal.js b/dom/messages/SystemMessageInternal.js index 9e22c9842002..aa942c63bea6 100644 --- a/dom/messages/SystemMessageInternal.js +++ b/dom/messages/SystemMessageInternal.js @@ -30,6 +30,7 @@ try { } const kMessages =["SystemMessageManager:GetPendingMessages", + "SystemMessageManager:HasPendingMessages", "SystemMessageManager:Register", "SystemMessageManager:Message:Return:OK", "SystemMessageManager:AskReadyToRegister", @@ -209,7 +210,7 @@ SystemMessageInternal.prototype = { return page !== null; }, this); if (!page) { - return null; + return; } // Return the |msg| of each pending message (drop the |msgID|). @@ -222,7 +223,33 @@ SystemMessageInternal.prototype = { // pending messages in the content process (|SystemMessageManager|). page.pendingMessages.length = 0; - return pendingMessages; + // Send the array of pending messages. + aMessage.target.sendAsyncMessage("SystemMessageManager:GetPendingMessages:Return", + { type: msg.type, + manifest: msg.manifest, + uri: msg.uri, + msgQueue: pendingMessages }); + break; + } + case "SystemMessageManager:HasPendingMessages": + { + debug("received SystemMessageManager:HasPendingMessages " + msg.type + + " for " + msg.uri + " @ " + msg.manifest); + + // This is a sync call used to return if a page has pending messages. + // Find the right page to get its corresponding pending messages. + let page = null; + this._pages.some(function(aPage) { + if (this._isPageMatched(aPage, msg.type, msg.uri, msg.manifest)) { + page = aPage; + } + return page !== null; + }, this); + if (!page) { + return false; + } + + return page.pendingMessages.length != 0; break; } case "SystemMessageManager:Message:Return:OK": diff --git a/dom/messages/SystemMessageManager.js b/dom/messages/SystemMessageManager.js index 43a678b794f0..837d3ec86bc3 100644 --- a/dom/messages/SystemMessageManager.js +++ b/dom/messages/SystemMessageManager.js @@ -19,15 +19,6 @@ XPCOMUtils.defineLazyServiceGetter(this, "cpmm", "@mozilla.org/childprocessmessagemanager;1", "nsISyncMessageSender"); -// Limit the number of pending messages for a given type. -let kMaxPendingMessages; -try { - kMaxPendingMessages = Services.prefs.getIntPref("dom.messages.maxPendingMessages"); -} catch(e) { - // getIntPref throws when the pref is not set. - kMaxPendingMessages = 5; -} - function debug(aMsg) { //dump("-- SystemMessageManager " + Date.now() + " : " + aMsg + "\n"); } @@ -102,61 +93,23 @@ SystemMessageManager.prototype = { // Last registered handler wins. handlers[aType] = aHandler; - // If we have pending messages, send them asynchronously. - if (this._getPendingMessages(aType, true)) { - let thread = Services.tm.mainThread; - let pending = this._pendings[aType]; - this._pendings[aType] = []; - let self = this; - pending.forEach(function dispatch_pending(aPending) { - thread.dispatch({ - run: function run() { - self._dispatchMessage(aType, aHandler, aPending); - } - }, Ci.nsIEventTarget.DISPATCH_NORMAL); - }); - } - }, - - _getPendingMessages: function sysMessMgr_getPendingMessages(aType, aForceUpdate) { - debug("hasPendingMessage " + aType); - let pendings = this._pendings; - - // If we have a handler for this type, we can't have any pending message. - // If called from setMessageHandler, we still want to update the pending - // queue to deliver existing messages. - if (aType in this._handlers && !aForceUpdate) { - return false; - } - - // Send a sync message to the parent to check if we have a pending message - // for this type. - let messages = cpmm.sendSyncMessage("SystemMessageManager:GetPendingMessages", - { type: aType, - uri: this._uri, - manifest: this._manifest })[0]; - if (!messages) { - // No new pending messages, but the queue may not be empty yet. - return pendings[aType] && pendings[aType].length != 0; - } - - if (!pendings[aType]) { - pendings[aType] = []; - } - - // Doing that instead of pending.concat() to avoid array copy. - messages.forEach(function hpm_addPendings(aMessage) { - pendings[aType].push(aMessage); - if (pendings[aType].length > kMaxPendingMessages) { - pendings[aType].splice(0, 1); - } - }); - - return pendings[aType].length != 0; + // Ask for the list of currently pending messages. + cpmm.sendAsyncMessage("SystemMessageManager:GetPendingMessages", + { type: aType, + uri: this._uri, + manifest: this._manifest }); }, mozHasPendingMessage: function sysMessMgr_hasPendingMessage(aType) { - return this._getPendingMessages(aType, false); + // If we have a handler for this type, we can't have any pending message. + if (aType in this._handlers) { + return false; + } + + return cpmm.sendSyncMessage("SystemMessageManager:HasPendingMessages", + { type: aType, + uri: this._uri, + manifest: this._manifest })[0]; }, uninit: function sysMessMgr_uninit() { @@ -170,22 +123,24 @@ SystemMessageManager.prototype = { receiveMessage: function sysMessMgr_receiveMessage(aMessage) { debug("receiveMessage " + aMessage.name + " - " + - aMessage.json.type + " for " + aMessage.json.manifest + + aMessage.data.type + " for " + aMessage.data.manifest + " (" + this._manifest + ")"); - let msg = aMessage.json; + let msg = aMessage.data; if (msg.manifest != this._manifest || msg.uri != this._uri) { return; } - // Send an acknowledgement to parent to clean up the pending message, - // so a re-launched app won't handle it again, which is redundant. - cpmm.sendAsyncMessage( - "SystemMessageManager:Message:Return:OK", - { type: msg.type, - manifest: msg.manifest, - uri: msg.uri, - msgID: msg.msgID }); + if (aMessage.name == "SystemMessageManager:Message") { + // Send an acknowledgement to parent to clean up the pending message, + // so a re-launched app won't handle it again, which is redundant. + cpmm.sendAsyncMessage( + "SystemMessageManager:Message:Return:OK", + { type: msg.type, + manifest: msg.manifest, + uri: msg.uri, + msgID: msg.msgID }); + } // Bail out if we have no handlers registered for this type. if (!(msg.type in this._handlers)) { @@ -193,13 +148,20 @@ SystemMessageManager.prototype = { return; } - this._dispatchMessage(msg.type, this._handlers[msg.type], msg.msg); + let messages = (aMessage.name == "SystemMessageManager:Message") + ? [msg.msg] + : msg.msgQueue; + + messages.forEach(function(aMsg) { + this._dispatchMessage(msg.type, this._handlers[msg.type], aMsg); + }, this); }, // nsIDOMGlobalPropertyInitializer implementation. init: function sysMessMgr_init(aWindow) { debug("init"); - this.initHelper(aWindow, ["SystemMessageManager:Message"]); + this.initHelper(aWindow, ["SystemMessageManager:Message", + "SystemMessageManager:GetPendingMessages:Return"]); let principal = aWindow.document.nodePrincipal; this._uri = principal.URI.spec;