mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Bug 554941 - [E10s] CPOW for synchronous TabChildGlobal messages, r=bnewman
This commit is contained in:
parent
3905ca35a7
commit
1795ed6f2e
@ -284,6 +284,7 @@ nsresult
|
||||
nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
|
||||
const nsAString& aMessage,
|
||||
PRBool aSync, const nsAString& aJSON,
|
||||
JSObject* aObjectsArray,
|
||||
nsTArray<nsString>* aJSONRetVal)
|
||||
{
|
||||
if (mListeners.Length()) {
|
||||
@ -347,6 +348,8 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
|
||||
JS_DefineProperty(mContext, param, "sync",
|
||||
BOOLEAN_TO_JSVAL(aSync), NULL, NULL, JSPROP_ENUMERATE);
|
||||
JS_DefineProperty(mContext, param, "json", json, NULL, NULL, JSPROP_ENUMERATE);
|
||||
JS_DefineProperty(mContext, param, "objects", OBJECT_TO_JSVAL(aObjectsArray),
|
||||
NULL, NULL, JSPROP_ENUMERATE);
|
||||
|
||||
jsval thisValue = JSVAL_VOID;
|
||||
nsAutoGCRoot resultGCRoot3(&thisValue, &rv);
|
||||
@ -397,7 +400,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
|
||||
}
|
||||
}
|
||||
return mParentManager ? mParentManager->ReceiveMessage(aTarget, aMessage,
|
||||
aSync, aJSON,
|
||||
aSync, aJSON, aObjectsArray,
|
||||
aJSONRetVal) : NS_OK;
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,7 @@
|
||||
|
||||
class nsAXPCNativeCallContext;
|
||||
struct JSContext;
|
||||
struct JSObject;
|
||||
|
||||
struct nsMessageListenerInfo
|
||||
{
|
||||
@ -103,6 +104,7 @@ public:
|
||||
|
||||
nsresult ReceiveMessage(nsISupports* aTarget, const nsAString& aMessage,
|
||||
PRBool aSync, const nsAString& aJSON,
|
||||
JSObject* aObjectsArray,
|
||||
nsTArray<nsString>* aJSONRetVal);
|
||||
void AddChildManager(nsFrameMessageManager* aManager);
|
||||
void RemoveChildManager(nsFrameMessageManager* aManager)
|
||||
@ -115,6 +117,7 @@ public:
|
||||
nsresult GetParamsForMessage(nsAString& aMessageName, nsAString& aJSON);
|
||||
nsresult SendAsyncMessageInternal(const nsAString& aMessage,
|
||||
const nsAString& aJSON);
|
||||
JSContext* GetJSContext() { return mContext; }
|
||||
protected:
|
||||
nsTArray<nsMessageListenerInfo> mListeners;
|
||||
nsCOMArray<nsIContentFrameMessageManager> mChildManagers;
|
||||
|
@ -126,6 +126,7 @@ ContentProcessParent::DestroyTestShell(TestShellParent* aTestShell)
|
||||
ContentProcessParent::ContentProcessParent()
|
||||
: mMonitor("ContentProcessParent::mMonitor")
|
||||
, mRunToCompletionDepth(0)
|
||||
, mShouldCallUnblockChild(false)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
mSubprocess = new GeckoChildProcessHost(GeckoProcessType_Content);
|
||||
@ -217,6 +218,18 @@ ContentProcessParent::DeallocPNecko(PNeckoParent* necko)
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ContentProcessParent::ReportChildAlreadyBlocked()
|
||||
{
|
||||
if (!mRunToCompletionDepth) {
|
||||
#ifdef DEBUG
|
||||
printf("Running to completion...\n");
|
||||
#endif
|
||||
mRunToCompletionDepth = 1;
|
||||
mShouldCallUnblockChild = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ContentProcessParent::RequestRunToCompletion()
|
||||
{
|
||||
@ -226,8 +239,8 @@ ContentProcessParent::RequestRunToCompletion()
|
||||
printf("Running to completion...\n");
|
||||
#endif
|
||||
mRunToCompletionDepth = 1;
|
||||
mShouldCallUnblockChild = true;
|
||||
}
|
||||
|
||||
return !!mRunToCompletionDepth;
|
||||
}
|
||||
|
||||
@ -266,7 +279,10 @@ ContentProcessParent::AfterProcessNextEvent(nsIThreadInternal *thread,
|
||||
#ifdef DEBUG
|
||||
printf("... ran to completion.\n");
|
||||
#endif
|
||||
UnblockChild();
|
||||
if (mShouldCallUnblockChild) {
|
||||
mShouldCallUnblockChild = false;
|
||||
UnblockChild();
|
||||
}
|
||||
}
|
||||
|
||||
if (mOldObserver)
|
||||
|
@ -83,6 +83,7 @@ public:
|
||||
TestShellParent* CreateTestShell();
|
||||
bool DestroyTestShell(TestShellParent* aTestShell);
|
||||
|
||||
void ReportChildAlreadyBlocked();
|
||||
bool RequestRunToCompletion();
|
||||
|
||||
protected:
|
||||
@ -113,6 +114,7 @@ private:
|
||||
GeckoChildProcessHost* mSubprocess;
|
||||
|
||||
int mRunToCompletionDepth;
|
||||
bool mShouldCallUnblockChild;
|
||||
nsCOMPtr<nsIThreadObserver> mOldObserver;
|
||||
|
||||
};
|
||||
|
@ -41,6 +41,7 @@ include protocol "PContentProcess.ipdl";
|
||||
include protocol "PDocumentRenderer.ipdl";
|
||||
include protocol "PDocumentRendererShmem.ipdl";
|
||||
include protocol "PContextWrapper.ipdl";
|
||||
include protocol "PObjectWrapper.ipdl";
|
||||
|
||||
include "mozilla/TabTypes.h";
|
||||
include "TabMessageUtils.h";
|
||||
@ -94,7 +95,9 @@ parent:
|
||||
|
||||
PContextWrapper();
|
||||
|
||||
sync sendSyncMessageToParent(nsString aMessage, nsString aJSON) returns (nsString[] retval);
|
||||
rpc sendSyncMessageToParent(nsString aMessage, nsString aJSON, PObjectWrapper[] aObjects)
|
||||
returns (nsString[] retval);
|
||||
|
||||
sendAsyncMessageToParent(nsString aMessage, nsString aJSON);
|
||||
child:
|
||||
createWidget(MagicWindowHandle parentWidget);
|
||||
|
@ -102,6 +102,7 @@ ContentListener::HandleEvent(nsIDOMEvent* aEvent)
|
||||
}
|
||||
|
||||
TabChild::TabChild()
|
||||
: mCx(nsnull), mContextWrapper(nsnull), mTabChildGlobal(nsnull)
|
||||
{
|
||||
printf("creating %d!\n", NS_IsMainThread());
|
||||
}
|
||||
@ -757,10 +758,9 @@ TabChild::RecvsendAsyncMessageToChild(const nsString& aMessage,
|
||||
const nsString& aJSON)
|
||||
{
|
||||
if (mTabChildGlobal) {
|
||||
nsTArray<nsString> dummy;
|
||||
static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get())->
|
||||
ReceiveMessage(static_cast<nsPIDOMEventTarget*>(mTabChildGlobal),
|
||||
aMessage, PR_FALSE, aJSON, nsnull);
|
||||
aMessage, PR_FALSE, aJSON, nsnull, nsnull);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -846,16 +846,57 @@ TabChild::InitTabChildGlobal()
|
||||
|
||||
JS_SetGlobalObject(cx, global);
|
||||
|
||||
mContextWrapper = new ContextWrapperChild(mCx);
|
||||
SendPContextWrapperConstructor(mContextWrapper);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TabChild::GetObjectsForMessage(nsTArray<mozilla::jsipc::PObjectWrapperChild*>& aObjects)
|
||||
{
|
||||
nsAXPCNativeCallContext* ncc = nsnull;
|
||||
nsresult rv = nsContentUtils::XPConnect()->GetCurrentNativeCallContext(&ncc);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_STATE(ncc);
|
||||
|
||||
JSContext* ctx = nsnull;
|
||||
rv = ncc->GetJSContext(&ctx);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint32 argc;
|
||||
jsval* argv = nsnull;
|
||||
ncc->GetArgc(&argc);
|
||||
ncc->GetArgvPtr(&argv);
|
||||
|
||||
JSAutoRequest ar(ctx);
|
||||
|
||||
JSObject* obj = nsnull;
|
||||
nsAutoGCRoot resultGCRoot(&obj, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// First parameter is the message name, second is the JSON.
|
||||
for (PRUint32 i = 2; i < argc; ++i) {
|
||||
if (JSVAL_IS_OBJECT(argv[i])) {
|
||||
obj = JSVAL_TO_OBJECT(argv[i]);
|
||||
} else if (!JS_ValueToObject(ctx, argv[i], &obj)) {
|
||||
obj = nsnull;
|
||||
}
|
||||
// GetOrCreateWrapper is null safe!
|
||||
aObjects.AppendElement(mContextWrapper->GetOrCreateWrapper(obj));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool SendSyncMessageToParent(void* aCallbackData,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aJSON,
|
||||
nsTArray<nsString>* aJSONRetVal)
|
||||
{
|
||||
nsTArray<mozilla::jsipc::PObjectWrapperChild*> objects;
|
||||
static_cast<TabChild*>(aCallbackData)->GetObjectsForMessage(objects);
|
||||
return static_cast<TabChild*>(aCallbackData)->
|
||||
SendsendSyncMessageToParent(nsString(aMessage), nsString(aJSON), aJSONRetVal);
|
||||
CallsendSyncMessageToParent(nsString(aMessage), nsString(aJSON), objects,
|
||||
aJSONRetVal);
|
||||
}
|
||||
|
||||
bool SendAsyncMessageToParent(void* aCallbackData,
|
||||
|
@ -75,6 +75,7 @@ namespace mozilla {
|
||||
|
||||
namespace jsipc {
|
||||
class PContextWrapperChild;
|
||||
class ContextWrapperChild;
|
||||
}
|
||||
|
||||
namespace dom {
|
||||
@ -244,6 +245,7 @@ public:
|
||||
virtual PContextWrapperChild* AllocPContextWrapper();
|
||||
virtual bool DeallocPContextWrapper(PContextWrapperChild* actor);
|
||||
|
||||
nsresult GetObjectsForMessage(nsTArray<PObjectWrapperChild*>& aObjects);
|
||||
private:
|
||||
bool InitTabChildGlobal();
|
||||
|
||||
@ -253,6 +255,8 @@ private:
|
||||
|
||||
JSContext* mCx;
|
||||
|
||||
mozilla::jsipc::ContextWrapperChild* mContextWrapper;
|
||||
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
|
||||
TabChildGlobal* mTabChildGlobal;
|
||||
|
@ -55,6 +55,8 @@
|
||||
#include "nsIWebProgressListener2.h"
|
||||
#include "nsFrameLoader.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "jsarray.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
using mozilla::ipc::DocumentRendererParent;
|
||||
using mozilla::ipc::DocumentRendererShmemParent;
|
||||
@ -443,9 +445,20 @@ TabParent::GetGlobalJSObject(JSContext* cx, JSObject** globalp)
|
||||
ManagedPContextWrapperParent(cwps);
|
||||
if (cwps.Length() < 1)
|
||||
return false;
|
||||
NS_ASSERTION(cwps.Length() == 1, "More than one PContextWrapper?");
|
||||
|
||||
// This is temporary until we decide whether to return
|
||||
// TabChildGlobal or top level page's global object.
|
||||
// Currently this returns the page global object.
|
||||
// Note, TabChildGlobal's context doesn't report its global object here!
|
||||
NS_ASSERTION(cwps.Length() <= 2, "More than two PContextWrappers?");
|
||||
ContextWrapperParent* cwp = static_cast<ContextWrapperParent*>(cwps[0]);
|
||||
return (cwp->GetGlobalJSObject(cx, globalp));
|
||||
if (cwp->GetGlobalObjectWrapper()) {
|
||||
return cwp->GetGlobalJSObject(cx, globalp);
|
||||
} else if (cwps.Length() == 2) {
|
||||
cwp = static_cast<ContextWrapperParent*>(cwps[1]);
|
||||
return cwp->GetGlobalJSObject(cx, globalp);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
@ -469,40 +482,62 @@ TabParent::SendKeyEvent(const nsAString& aType,
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::RecvsendSyncMessageToParent(const nsString& aMessage,
|
||||
const nsString& aJSON,
|
||||
nsTArray<nsString>* aJSONRetVal)
|
||||
TabParent::AnswersendSyncMessageToParent(const nsString& aMessage,
|
||||
const nsString& aJSON,
|
||||
const nsTArray<PObjectWrapperParent*>& aObjects,
|
||||
nsTArray<nsString>* aJSONRetVal)
|
||||
{
|
||||
nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner =
|
||||
do_QueryInterface(mFrameElement);
|
||||
if (frameLoaderOwner) {
|
||||
nsRefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader();
|
||||
if (frameLoader && frameLoader->GetFrameMessageManager()) {
|
||||
frameLoader->GetFrameMessageManager()->ReceiveMessage(mFrameElement,
|
||||
aMessage,
|
||||
PR_TRUE,
|
||||
aJSON,
|
||||
aJSONRetVal);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
static_cast<ContentProcessParent*>(Manager())->ReportChildAlreadyBlocked();
|
||||
return ReceiveMessage(aMessage, PR_TRUE, aJSON, &aObjects, aJSONRetVal);
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::RecvsendAsyncMessageToParent(const nsString& aMessage,
|
||||
const nsString& aJSON)
|
||||
{
|
||||
return ReceiveMessage(aMessage, PR_FALSE, aJSON, nsnull);
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::ReceiveMessage(const nsString& aMessage,
|
||||
PRBool aSync,
|
||||
const nsString& aJSON,
|
||||
const nsTArray<PObjectWrapperParent*>* aObjects,
|
||||
nsTArray<nsString>* aJSONRetVal)
|
||||
{
|
||||
nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner =
|
||||
do_QueryInterface(mFrameElement);
|
||||
if (frameLoaderOwner) {
|
||||
nsRefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader();
|
||||
if (frameLoader && frameLoader->GetFrameMessageManager()) {
|
||||
nsTArray<nsString> dummy;
|
||||
frameLoader->GetFrameMessageManager()->ReceiveMessage(mFrameElement,
|
||||
aMessage,
|
||||
PR_FALSE,
|
||||
aJSON,
|
||||
nsnull);
|
||||
nsFrameMessageManager* manager = frameLoader->GetFrameMessageManager();
|
||||
JSContext* ctx = manager->GetJSContext();
|
||||
JSAutoRequest ar(ctx);
|
||||
jsval* dest;
|
||||
PRUint32 len = aObjects ? aObjects->Length() : 0;
|
||||
// Because we want JS messages to have always the same properties,
|
||||
// create array even if len == 0.
|
||||
JSObject* objectsArray =
|
||||
js_NewArrayObjectWithCapacity(ctx, len, &dest);
|
||||
if (!objectsArray) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsAutoGCRoot arrayGCRoot(&objectsArray, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
for (PRUint32 i = 0; i < len; ++i) {
|
||||
mozilla::jsipc::ObjectWrapperParent* wrapper =
|
||||
static_cast<mozilla::jsipc::ObjectWrapperParent*>(aObjects->ElementAt(i));
|
||||
dest[i] = OBJECT_TO_JSVAL(wrapper ? wrapper->GetJSObject(ctx) : nsnull);
|
||||
}
|
||||
|
||||
manager->ReceiveMessage(mFrameElement,
|
||||
aMessage,
|
||||
aSync,
|
||||
aJSON,
|
||||
objectsArray,
|
||||
aJSONRetVal);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -60,6 +60,7 @@ namespace mozilla {
|
||||
|
||||
namespace jsipc {
|
||||
class PContextWrapperParent;
|
||||
class PObjectWrapperParent;
|
||||
}
|
||||
|
||||
namespace dom {
|
||||
@ -114,9 +115,10 @@ public:
|
||||
bool* aAllowRefresh);
|
||||
|
||||
virtual bool AnswercreateWindow(PIFrameEmbeddingParent** retval);
|
||||
virtual bool RecvsendSyncMessageToParent(const nsString& aMessage,
|
||||
const nsString& aJSON,
|
||||
nsTArray<nsString>* aJSONRetVal);
|
||||
virtual bool AnswersendSyncMessageToParent(const nsString& aMessage,
|
||||
const nsString& aJSON,
|
||||
const nsTArray<PObjectWrapperParent*>&,
|
||||
nsTArray<nsString>* aJSONRetVal);
|
||||
virtual bool RecvsendAsyncMessageToParent(const nsString& aMessage,
|
||||
const nsString& aJSON);
|
||||
|
||||
@ -163,6 +165,12 @@ public:
|
||||
NS_DECL_NSIWEBPROGRESS
|
||||
|
||||
protected:
|
||||
bool ReceiveMessage(const nsString& aMessage,
|
||||
PRBool aSync,
|
||||
const nsString& aJSON,
|
||||
const nsTArray<PObjectWrapperParent*>* aObjects,
|
||||
nsTArray<nsString>* aJSONRetVal = nsnull);
|
||||
|
||||
TabParentListenerInfo* GetListenerInfo(nsIWebProgressListener *aListener);
|
||||
|
||||
nsIDOMElement* mFrameElement;
|
||||
|
@ -15,7 +15,7 @@ addEventListener("click",
|
||||
dump(e.target + "\n");
|
||||
if (e.target instanceof Components.interfaces.nsIDOMHTMLAnchorElement &&
|
||||
dshell == docShell) {
|
||||
var retval = sendSyncMessage("linkclick", { href : e.target.href });
|
||||
var retval = sendSyncMessage("linkclick", { href : e.target.href }, e, 123, "a string");
|
||||
dump(uneval(retval[0]) + "\n");
|
||||
// Test here also that both retvals are the same
|
||||
sendAsyncMessage("linkclick-reply-object", uneval(retval[0]) == uneval(retval[1]) ? retval[0] : "");
|
||||
|
@ -98,8 +98,19 @@
|
||||
// 2. Test that adding message listener works, and that receiving a sync message works.
|
||||
messageManager.addMessageListener("linkclick",
|
||||
function(m) {
|
||||
document.getElementById("messageLog").value = m.name + ": " + m.json.href;
|
||||
return { message: "linkclick-received" };
|
||||
// This checks that json and CPOW sending works in sync messages.
|
||||
if (m.objects.length == 3 &&
|
||||
m.objects[0].target.href == m.json.href &&
|
||||
m.objects[1] == 123 &&
|
||||
m.objects[2] == "a string") {
|
||||
// Test that crossProcessObjectWrapper can be used in sync messages.
|
||||
if ((document.getElementById('page')
|
||||
.QueryInterface(Components.interfaces.nsIFrameLoaderOwner)
|
||||
.crossProcessObjectWrapper + "").indexOf("Window") >= 0) {
|
||||
document.getElementById("messageLog").value = m.name + ": " + m.json.href;
|
||||
return { message: "linkclick-received" };
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 3. Test that returning multiple json results works.
|
||||
@ -124,9 +135,14 @@
|
||||
// 5. Final test to check that everything went ok.
|
||||
messageManager.addMessageListener("chrome-message-reply",
|
||||
function(m) {
|
||||
// Check that 'this' and .target values are handled correctly.
|
||||
// Check that 'this' and .target values are handled correctly
|
||||
// Check also that crossProcessObjectWrapper can be used in
|
||||
// asynchronous message handlers.
|
||||
if (m.target == document.getElementById("page") &&
|
||||
this == messageManager) {
|
||||
this == messageManager &&
|
||||
(document.getElementById('page')
|
||||
.QueryInterface(Components.interfaces.nsIFrameLoaderOwner)
|
||||
.crossProcessObjectWrapper + "").indexOf("Window") >= 0) {
|
||||
// Check that the message properties are enumerable.
|
||||
var hasName = false;
|
||||
var hasSync = false;
|
||||
|
@ -73,7 +73,7 @@ namespace {
|
||||
JSOPTION_DONT_REPORT_UNCAUGHT)))
|
||||
{
|
||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
mStack.Push(cx);
|
||||
mStack.Push(cx, PR_FALSE);
|
||||
}
|
||||
|
||||
~AutoContextPusher() {
|
||||
|
Loading…
Reference in New Issue
Block a user