Bug 680413 - Allow using child process message manager in chrome process, r=benjamin

This commit is contained in:
Olli Pettay 2011-10-11 13:28:46 +03:00
parent 36dd68c066
commit d0c37fecac
4 changed files with 158 additions and 26 deletions

View File

@ -815,6 +815,8 @@ NS_IMPL_ISUPPORTS1(nsScriptCacheCleaner, nsIObserver)
nsFrameMessageManager* nsFrameMessageManager::sChildProcessManager = nsnull;
nsFrameMessageManager* nsFrameMessageManager::sParentProcessManager = nsnull;
nsFrameMessageManager* nsFrameMessageManager::sSameProcessParentManager = nsnull;
nsTArray<nsCOMPtr<nsIRunnable> >* nsFrameMessageManager::sPendingSameProcessAsyncMessages = nsnull;
bool SendAsyncMessageToChildProcess(void* aCallbackData,
const nsAString& aMessage,
@ -829,6 +831,35 @@ bool SendAsyncMessageToChildProcess(void* aCallbackData,
return true;
}
class nsAsyncMessageToSameProcessChild : public nsRunnable
{
public:
nsAsyncMessageToSameProcessChild(const nsAString& aMessage, const nsAString& aJSON)
: mMessage(aMessage), mJSON(aJSON) {}
NS_IMETHOD Run()
{
if (nsFrameMessageManager::sChildProcessManager) {
nsRefPtr<nsFrameMessageManager> ppm = nsFrameMessageManager::sChildProcessManager;
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), mMessage,
PR_FALSE, mJSON, nsnull, nsnull);
}
return NS_OK;
}
nsString mMessage;
nsString mJSON;
};
bool SendAsyncMessageToSameProcessChild(void* aCallbackData,
const nsAString& aMessage,
const nsAString& aJSON)
{
nsRefPtr<nsIRunnable> ev =
new nsAsyncMessageToSameProcessChild(aMessage, aJSON);
NS_DispatchToCurrentThread(ev);
return true;
}
bool SendSyncMessageToParentProcess(void* aCallbackData,
const nsAString& aMessage,
const nsAString& aJSON,
@ -843,6 +874,28 @@ bool SendSyncMessageToParentProcess(void* aCallbackData,
return true;
}
bool SendSyncMessageToSameProcessParent(void* aCallbackData,
const nsAString& aMessage,
const nsAString& aJSON,
InfallibleTArray<nsString>* aJSONRetVal)
{
nsTArray<nsCOMPtr<nsIRunnable> > asyncMessages;
if (nsFrameMessageManager::sPendingSameProcessAsyncMessages) {
asyncMessages.SwapElements(*nsFrameMessageManager::sPendingSameProcessAsyncMessages);
PRUint32 len = asyncMessages.Length();
for (PRUint32 i = 0; i < len; ++i) {
nsCOMPtr<nsIRunnable> async = asyncMessages[i];
async->Run();
}
}
if (nsFrameMessageManager::sSameProcessParentManager) {
nsRefPtr<nsFrameMessageManager> ppm = nsFrameMessageManager::sSameProcessParentManager;
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), aMessage,
PR_TRUE, aJSON, nsnull, aJSONRetVal);
}
return true;
}
bool SendAsyncMessageToParentProcess(void* aCallbackData,
const nsAString& aMessage,
const nsAString& aJSON)
@ -855,6 +908,42 @@ bool SendAsyncMessageToParentProcess(void* aCallbackData,
return true;
}
class nsAsyncMessageToSameProcessParent : public nsRunnable
{
public:
nsAsyncMessageToSameProcessParent(const nsAString& aMessage, const nsAString& aJSON)
: mMessage(aMessage), mJSON(aJSON) {}
NS_IMETHOD Run()
{
if (nsFrameMessageManager::sPendingSameProcessAsyncMessages) {
nsFrameMessageManager::sPendingSameProcessAsyncMessages->RemoveElement(this);
}
if (nsFrameMessageManager::sSameProcessParentManager) {
nsRefPtr<nsFrameMessageManager> ppm = nsFrameMessageManager::sSameProcessParentManager;
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), mMessage, PR_FALSE,
mJSON, nsnull, nsnull);
}
return NS_OK;
}
nsString mMessage;
nsString mJSON;
};
bool SendAsyncMessageToSameProcessParent(void* aCallbackData,
const nsAString& aMessage,
const nsAString& aJSON)
{
if (!nsFrameMessageManager::sPendingSameProcessAsyncMessages) {
nsFrameMessageManager::sPendingSameProcessAsyncMessages = new nsTArray<nsCOMPtr<nsIRunnable> >;
}
nsCOMPtr<nsIRunnable> ev =
new nsAsyncMessageToSameProcessParent(aMessage, aJSON);
nsFrameMessageManager::sPendingSameProcessAsyncMessages->AppendElement(ev);
NS_DispatchToCurrentThread(ev);
return true;
}
// This creates the global parent process message manager.
nsresult
NS_NewParentProcessMessageManager(nsIFrameMessageManager** aResult)
@ -862,17 +951,18 @@ NS_NewParentProcessMessageManager(nsIFrameMessageManager** aResult)
NS_ASSERTION(!nsFrameMessageManager::sParentProcessManager,
"Re-creating sParentProcessManager");
NS_ENSURE_TRUE(IsChromeProcess(), NS_ERROR_NOT_AVAILABLE);
nsFrameMessageManager* mm = new nsFrameMessageManager(PR_TRUE,
nsnull,
nsnull,
nsnull,
nsnull,
nsnull,
nsnull,
PR_FALSE,
PR_TRUE);
nsRefPtr<nsFrameMessageManager> mm = new nsFrameMessageManager(PR_TRUE,
nsnull,
nsnull,
nsnull,
nsnull,
nsnull,
nsnull,
PR_FALSE,
PR_TRUE);
NS_ENSURE_TRUE(mm, NS_ERROR_OUT_OF_MEMORY);
nsFrameMessageManager::sParentProcessManager = mm;
nsFrameMessageManager::NewProcessMessageManager(nsnull); // Create same process message manager.
return CallQueryInterface(mm, aResult);
}
@ -886,13 +976,18 @@ nsFrameMessageManager::NewProcessMessageManager(mozilla::dom::ContentParent* aPr
nsFrameMessageManager* mm = new nsFrameMessageManager(PR_TRUE,
nsnull,
SendAsyncMessageToChildProcess,
aProcess ? SendAsyncMessageToChildProcess
: SendAsyncMessageToSameProcessChild,
nsnull,
aProcess,
aProcess ? static_cast<void*>(aProcess)
: static_cast<void*>(&nsFrameMessageManager::sChildProcessManager),
nsFrameMessageManager::sParentProcessManager,
nsnull,
PR_FALSE,
PR_TRUE);
if (!aProcess) {
sSameProcessParentManager = mm;
}
return mm;
}
@ -901,10 +996,12 @@ NS_NewChildProcessMessageManager(nsISyncMessageSender** aResult)
{
NS_ASSERTION(!nsFrameMessageManager::sChildProcessManager,
"Re-creating sChildProcessManager");
NS_ENSURE_TRUE(!IsChromeProcess(), NS_ERROR_NOT_AVAILABLE);
PRBool isChrome = IsChromeProcess();
nsFrameMessageManager* mm = new nsFrameMessageManager(PR_FALSE,
SendSyncMessageToParentProcess,
SendAsyncMessageToParentProcess,
isChrome ? SendSyncMessageToSameProcessParent
: SendSyncMessageToParentProcess,
isChrome ? SendAsyncMessageToSameProcessParent
: SendAsyncMessageToParentProcess,
nsnull,
&nsFrameMessageManager::sChildProcessManager,
nsnull,

View File

@ -51,6 +51,7 @@
#include "nsDataHashtable.h"
#include "mozilla/Services.h"
#include "nsIObserverService.h"
#include "nsThreadUtils.h"
namespace mozilla {
namespace dom {
@ -120,6 +121,11 @@ public:
}
if (this == sChildProcessManager) {
sChildProcessManager = nsnull;
delete sPendingSameProcessAsyncMessages;
sPendingSameProcessAsyncMessages = nsnull;
}
if (this == sSameProcessParentManager) {
sSameProcessParentManager = nsnull;
}
}
}
@ -190,6 +196,8 @@ protected:
public:
static nsFrameMessageManager* sParentProcessManager;
static nsFrameMessageManager* sChildProcessManager;
static nsFrameMessageManager* sSameProcessParentManager;
static nsTArray<nsCOMPtr<nsIRunnable> >* sPendingSameProcessAsyncMessages;
};
void

View File

@ -14,6 +14,39 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=549682
var didRunAsync = false;
var didRunLocal = false;
var global = Components.classes["@mozilla.org/globalmessagemanager;1"].getService(Components.interfaces.nsIChromeFrameMessageManager);
var ppm = Components.classes["@mozilla.org/parentprocessmessagemanager;1"].getService(Components.interfaces.nsIFrameMessageManager);
var cpm = Components.classes["@mozilla.org/childprocessmessagemanager;1"].getService(Components.interfaces.nsISyncMessageSender);
var asyncPPML = false;
function ppmASL(m) {
asyncPPML = true;
}
var syncPPML = false;
function ppmSL(m) {
syncPPML = true;
}
ppm.addMessageListener("processmessageAsync", ppmASL);
ppm.addMessageListener("processmessageSync", ppmSL);
cpm.sendAsyncMessage("processmessageAsync", "");
cpm.sendSyncMessage("processmessageSync", "");
var asyncCPML = false;
function cpmASL(m) {
asyncCPML = true;
}
cpm.addMessageListener("childprocessmessage", cpmASL);
ppm.sendAsyncMessage("childprocessmessage", "");
function checkPMMMessages() {
opener.wrappedJSObject.ok(asyncPPML, "should have handled async message");
opener.wrappedJSObject.ok(syncPPML, "should have handled sync message");
opener.wrappedJSObject.ok(asyncCPML, "should have handled async message");
ppm.removeMessageListener("processmessageAsync", ppmASL);
ppm.removeMessageListener("processmessageSync", ppmSL);
cpm.removeMessageListener("childprocessmessage", cpmASL);
}
var globalListenerCallCount = 0;
function globalListener(m) {
++globalListenerCallCount;
@ -85,6 +118,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=549682
opener.wrappedJSObject.is(globalListenerCallCount, oldValue + 1,
"Wrong message count");
setTimeout(checkPMMMessages, 0);
setTimeout(loadScript, 0);
}

View File

@ -96,21 +96,14 @@
.getService(Components.interfaces.nsIFrameMessageManager);
var gm = Components.classes["@mozilla.org/globalmessagemanager;1"]
.getService(Components.interfaces.nsIChromeFrameMessageManager);
var didThrow = false;
try {
var cpm = Components.classes["@mozilla.org/childprocessmessagemanager;1"]
var cpm = Components.classes["@mozilla.org/childprocessmessagemanager;1"]
.getService(Components.interfaces.nsISyncMessageSender);
} catch (ex) {
didThrow = true;
}
if (!didThrow) {
alert("One shouldn't be able to create content process message manager in chrome process!");
}
var tppm = ppm.QueryInterface(Components.interfaces.nsITreeItemFrameMessageManager);
if (tppm.childCount != 1) {
alert("Should have one child process!");
if (tppm.childCount != 2) {
alert("Should have two child processes!");
}
var childprocessmm = tppm.getChildAt(0);
var childprocessmm = tppm.getChildAt(1); // 0 is the in-process child process mm
childprocessmm.addMessageListener("ppm-sync",
function(m) {