Implement CPOW support in MessageManager (bug 870180, r=smaug,billm).

This commit is contained in:
David Anderson 2013-07-10 15:05:39 -07:00
Родитель 614d2bf88c
Коммит 5f0258f3c3
28 изменённых файлов: 650 добавлений и 145 удалений

Просмотреть файл

@ -162,9 +162,8 @@ interface nsIMessageListener : nsISupports
* sync: %true or false%. * sync: %true or false%.
* data: %structured clone of the sent message data%, * data: %structured clone of the sent message data%,
* json: %same as .data, deprecated%, * json: %same as .data, deprecated%,
* objects: %array of handles or null, always null if sync is false% * objects: %named table of jsvals/objects, or null%
* } * }
* @note objects property isn't implemented yet.
* *
* Each listener is invoked with its own copy of the message * Each listener is invoked with its own copy of the message
* parameter. * parameter.
@ -232,7 +231,8 @@ interface nsIMessageSender : nsIMessageListenerManager
*/ */
[implicit_jscontext, optional_argc] [implicit_jscontext, optional_argc]
void sendAsyncMessage([optional] in AString messageName, void sendAsyncMessage([optional] in AString messageName,
[optional] in jsval obj); [optional] in jsval obj,
[optional] in jsval objects);
}; };
/** /**
@ -255,7 +255,8 @@ interface nsIMessageBroadcaster : nsIMessageListenerManager
*/ */
[implicit_jscontext, optional_argc] [implicit_jscontext, optional_argc]
void broadcastAsyncMessage([optional] in AString messageName, void broadcastAsyncMessage([optional] in AString messageName,
[optional] in jsval obj); [optional] in jsval obj,
[optional] in jsval objects);
/** /**
* Number of subordinate message managers. * Number of subordinate message managers.
@ -278,7 +279,8 @@ interface nsISyncMessageSender : nsIMessageSender
*/ */
[implicit_jscontext, optional_argc] [implicit_jscontext, optional_argc]
jsval sendSyncMessage([optional] in AString messageName, jsval sendSyncMessage([optional] in AString messageName,
[optional] in jsval obj); [optional] in jsval obj,
[optional] in jsval objects);
}; };
[scriptable, builtinclass, uuid(894ff2d4-39a3-4df8-9d76-8ee329975488)] [scriptable, builtinclass, uuid(894ff2d4-39a3-4df8-9d76-8ee329975488)]

Просмотреть файл

@ -50,6 +50,7 @@ LOCAL_INCLUDES += \
-I$(topsrcdir)/content/xul/document/src \ -I$(topsrcdir)/content/xul/document/src \
-I$(topsrcdir)/dom/base \ -I$(topsrcdir)/dom/base \
-I$(topsrcdir)/dom/ipc \ -I$(topsrcdir)/dom/ipc \
-I$(topsrcdir)/js/ipc \
-I$(topsrcdir)/image/src \ -I$(topsrcdir)/image/src \
-I$(topsrcdir)/js/xpconnect/src \ -I$(topsrcdir)/js/xpconnect/src \
-I$(topsrcdir)/layout/base \ -I$(topsrcdir)/layout/base \

Просмотреть файл

@ -87,6 +87,7 @@
#include "jsapi.h" #include "jsapi.h"
#include "mozilla/dom/HTMLIFrameElement.h" #include "mozilla/dom/HTMLIFrameElement.h"
#include "nsSandboxFlags.h" #include "nsSandboxFlags.h"
#include "JavaScriptParent.h"
#include "mozilla/dom/StructuredCloneUtils.h" #include "mozilla/dom/StructuredCloneUtils.h"
@ -2202,17 +2203,29 @@ nsFrameLoader::DoLoadFrameScript(const nsAString& aURL)
class nsAsyncMessageToChild : public nsRunnable class nsAsyncMessageToChild : public nsRunnable
{ {
public: public:
nsAsyncMessageToChild(nsFrameLoader* aFrameLoader, nsAsyncMessageToChild(JSContext* aCx,
nsFrameLoader* aFrameLoader,
const nsAString& aMessage, const nsAString& aMessage,
const StructuredCloneData& aData) const StructuredCloneData& aData,
: mFrameLoader(aFrameLoader), mMessage(aMessage) JS::Handle<JSObject *> aCpows)
: mRuntime(js::GetRuntime(aCx)), mFrameLoader(aFrameLoader), mMessage(aMessage), mCpows(aCpows)
{ {
if (aData.mDataLength && !mData.copy(aData.mData, aData.mDataLength)) { if (aData.mDataLength && !mData.copy(aData.mData, aData.mDataLength)) {
NS_RUNTIMEABORT("OOM"); NS_RUNTIMEABORT("OOM");
} }
if (mCpows && !js_AddObjectRoot(mRuntime, &mCpows)) {
NS_RUNTIMEABORT("OOM");
}
mClosure = aData.mClosure; mClosure = aData.mClosure;
} }
~nsAsyncMessageToChild()
{
if (mCpows) {
JS_RemoveObjectRootRT(mRuntime, &mCpows);
}
}
NS_IMETHOD Run() NS_IMETHOD Run()
{ {
nsInProcessTabChildGlobal* tabChild = nsInProcessTabChildGlobal* tabChild =
@ -2224,21 +2237,27 @@ public:
data.mDataLength = mData.nbytes(); data.mDataLength = mData.nbytes();
data.mClosure = mClosure; data.mClosure = mClosure;
SameProcessCpowHolder cpows(mRuntime, JS::Handle<JSObject *>::fromMarkedLocation(&mCpows));
nsRefPtr<nsFrameMessageManager> mm = tabChild->GetInnerManager(); nsRefPtr<nsFrameMessageManager> mm = tabChild->GetInnerManager();
mm->ReceiveMessage(static_cast<EventTarget*>(tabChild), mMessage, mm->ReceiveMessage(static_cast<EventTarget*>(tabChild), mMessage,
false, &data, JS::NullPtr(), nullptr); false, &data, &cpows, nullptr);
} }
return NS_OK; return NS_OK;
} }
JSRuntime* mRuntime;
nsRefPtr<nsFrameLoader> mFrameLoader; nsRefPtr<nsFrameLoader> mFrameLoader;
nsString mMessage; nsString mMessage;
JSAutoStructuredCloneBuffer mData; JSAutoStructuredCloneBuffer mData;
StructuredCloneClosure mClosure; StructuredCloneClosure mClosure;
JSObject* mCpows;
}; };
bool bool
nsFrameLoader::DoSendAsyncMessage(const nsAString& aMessage, nsFrameLoader::DoSendAsyncMessage(JSContext* aCx,
const StructuredCloneData& aData) const nsAString& aMessage,
const StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows)
{ {
TabParent* tabParent = mRemoteBrowser; TabParent* tabParent = mRemoteBrowser;
if (tabParent) { if (tabParent) {
@ -2247,11 +2266,15 @@ nsFrameLoader::DoSendAsyncMessage(const nsAString& aMessage,
if (!BuildClonedMessageDataForParent(cp, aData, data)) { if (!BuildClonedMessageDataForParent(cp, aData, data)) {
return false; return false;
} }
return tabParent->SendAsyncMessage(nsString(aMessage), data); InfallibleTArray<mozilla::jsipc::CpowEntry> cpows;
if (aCpows && !cp->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
return false;
}
return tabParent->SendAsyncMessage(nsString(aMessage), data, cpows);
} }
if (mChildMessageManager) { if (mChildMessageManager) {
nsRefPtr<nsIRunnable> ev = new nsAsyncMessageToChild(this, aMessage, aData); nsRefPtr<nsIRunnable> ev = new nsAsyncMessageToChild(aCx, this, aMessage, aData, aCpows);
NS_DispatchToCurrentThread(ev); NS_DispatchToCurrentThread(ev);
return true; return true;
} }

Просмотреть файл

@ -186,8 +186,10 @@ public:
* MessageManagerCallback methods that we override. * MessageManagerCallback methods that we override.
*/ */
virtual bool DoLoadFrameScript(const nsAString& aURL) MOZ_OVERRIDE; virtual bool DoLoadFrameScript(const nsAString& aURL) MOZ_OVERRIDE;
virtual bool DoSendAsyncMessage(const nsAString& aMessage, virtual bool DoSendAsyncMessage(JSContext* aCx,
const mozilla::dom::StructuredCloneData& aData) MOZ_OVERRIDE; const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows);
virtual bool CheckPermission(const nsAString& aPermission) MOZ_OVERRIDE; virtual bool CheckPermission(const nsAString& aPermission) MOZ_OVERRIDE;
virtual bool CheckManifestURL(const nsAString& aManifestURL) MOZ_OVERRIDE; virtual bool CheckManifestURL(const nsAString& aManifestURL) MOZ_OVERRIDE;
virtual bool CheckAppHasPermission(const nsAString& aPermission) MOZ_OVERRIDE; virtual bool CheckAppHasPermission(const nsAString& aPermission) MOZ_OVERRIDE;

Просмотреть файл

@ -31,6 +31,8 @@
#include "xpcpublic.h" #include "xpcpublic.h"
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
#include "mozilla/dom/StructuredCloneUtils.h" #include "mozilla/dom/StructuredCloneUtils.h"
#include "JavaScriptChild.h"
#include "JavaScriptParent.h"
#include <algorithm> #include <algorithm>
#ifdef ANDROID #ifdef ANDROID
@ -220,6 +222,18 @@ mozilla::dom::ipc::UnpackClonedMessageDataForChild(const ClonedMessageData& aDat
return UnpackClonedMessageData<Child>(aData); return UnpackClonedMessageData<Child>(aData);
} }
bool
SameProcessCpowHolder::ToObject(JSContext* aCx, JSObject** aObjp)
{
*aObjp = mObj;
if (!mObj) {
return true;
}
return JS_WrapObject(aCx, aObjp);
}
// nsIMessageListenerManager // nsIMessageListenerManager
NS_IMETHODIMP NS_IMETHODIMP
@ -311,11 +325,11 @@ JSONCreator(const jschar* aBuf, uint32_t aLen, void* aData)
static bool static bool
GetParamsForMessage(JSContext* aCx, GetParamsForMessage(JSContext* aCx,
const JS::Value& aObject, const JS::Value& aJSON,
JSAutoStructuredCloneBuffer& aBuffer, JSAutoStructuredCloneBuffer& aBuffer,
StructuredCloneClosure& aClosure) StructuredCloneClosure& aClosure)
{ {
if (WriteStructuredClone(aCx, aObject, aBuffer, aClosure)) { if (WriteStructuredClone(aCx, aJSON, aBuffer, aClosure)) {
return true; return true;
} }
JS_ClearPendingException(aCx); JS_ClearPendingException(aCx);
@ -325,7 +339,7 @@ GetParamsForMessage(JSContext* aCx,
// properly cases when interface is implemented in JS and used // properly cases when interface is implemented in JS and used
// as a dictionary. // as a dictionary.
nsAutoString json; nsAutoString json;
JS::Rooted<JS::Value> v(aCx, aObject); JS::Rooted<JS::Value> v(aCx, aJSON);
NS_ENSURE_TRUE(JS_Stringify(aCx, v.address(), nullptr, JSVAL_NULL, NS_ENSURE_TRUE(JS_Stringify(aCx, v.address(), nullptr, JSVAL_NULL,
JSONCreator, &json), false); JSONCreator, &json), false);
NS_ENSURE_TRUE(!json.IsEmpty(), false); NS_ENSURE_TRUE(!json.IsEmpty(), false);
@ -342,7 +356,8 @@ GetParamsForMessage(JSContext* aCx,
NS_IMETHODIMP NS_IMETHODIMP
nsFrameMessageManager::SendSyncMessage(const nsAString& aMessageName, nsFrameMessageManager::SendSyncMessage(const nsAString& aMessageName,
const JS::Value& aObject, const JS::Value& aJSON,
const JS::Value& aObjects,
JSContext* aCx, JSContext* aCx,
uint8_t aArgc, uint8_t aArgc,
JS::Value* aRetval) JS::Value* aRetval)
@ -357,14 +372,19 @@ nsFrameMessageManager::SendSyncMessage(const nsAString& aMessageName,
StructuredCloneData data; StructuredCloneData data;
JSAutoStructuredCloneBuffer buffer; JSAutoStructuredCloneBuffer buffer;
if (aArgc >= 2 && if (aArgc >= 2 &&
!GetParamsForMessage(aCx, aObject, buffer, data.mClosure)) { !GetParamsForMessage(aCx, aJSON, buffer, data.mClosure)) {
return NS_ERROR_DOM_DATA_CLONE_ERR; return NS_ERROR_DOM_DATA_CLONE_ERR;
} }
data.mData = buffer.data(); data.mData = buffer.data();
data.mDataLength = buffer.nbytes(); data.mDataLength = buffer.nbytes();
JS::RootedObject objects(aCx);
if (aArgc >= 3 && aObjects.isObject()) {
objects = &aObjects.toObject();
}
InfallibleTArray<nsString> retval; InfallibleTArray<nsString> retval;
if (mCallback->DoSendSyncMessage(aMessageName, data, &retval)) { if (mCallback->DoSendSyncMessage(aCx, aMessageName, data, objects, &retval)) {
uint32_t len = retval.Length(); uint32_t len = retval.Length();
JS::Rooted<JSObject*> dataArray(aCx, JS_NewArrayObject(aCx, len, nullptr)); JS::Rooted<JSObject*> dataArray(aCx, JS_NewArrayObject(aCx, len, nullptr));
NS_ENSURE_TRUE(dataArray, NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_TRUE(dataArray, NS_ERROR_OUT_OF_MEMORY);
@ -389,20 +409,22 @@ nsFrameMessageManager::SendSyncMessage(const nsAString& aMessageName,
} }
nsresult nsresult
nsFrameMessageManager::DispatchAsyncMessageInternal(const nsAString& aMessage, nsFrameMessageManager::DispatchAsyncMessageInternal(JSContext* aCx,
const StructuredCloneData& aData) const nsAString& aMessage,
const StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows)
{ {
if (mIsBroadcaster) { if (mIsBroadcaster) {
int32_t len = mChildManagers.Count(); int32_t len = mChildManagers.Count();
for (int32_t i = 0; i < len; ++i) { for (int32_t i = 0; i < len; ++i) {
static_cast<nsFrameMessageManager*>(mChildManagers[i])-> static_cast<nsFrameMessageManager*>(mChildManagers[i])->
DispatchAsyncMessageInternal(aMessage, aData); DispatchAsyncMessageInternal(aCx, aMessage, aData, aCpows);
} }
return NS_OK; return NS_OK;
} }
NS_ENSURE_TRUE(mCallback, NS_ERROR_NOT_INITIALIZED); NS_ENSURE_TRUE(mCallback, NS_ERROR_NOT_INITIALIZED);
if (!mCallback->DoSendAsyncMessage(aMessage, aData)) { if (!mCallback->DoSendAsyncMessage(aCx, aMessage, aData, aCpows)) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
return NS_OK; return NS_OK;
@ -410,7 +432,8 @@ nsFrameMessageManager::DispatchAsyncMessageInternal(const nsAString& aMessage,
nsresult nsresult
nsFrameMessageManager::DispatchAsyncMessage(const nsAString& aMessageName, nsFrameMessageManager::DispatchAsyncMessage(const nsAString& aMessageName,
const JS::Value& aObject, const JS::Value& aJSON,
const JS::Value& aObjects,
JSContext* aCx, JSContext* aCx,
uint8_t aArgc) uint8_t aArgc)
{ {
@ -418,14 +441,19 @@ nsFrameMessageManager::DispatchAsyncMessage(const nsAString& aMessageName,
JSAutoStructuredCloneBuffer buffer; JSAutoStructuredCloneBuffer buffer;
if (aArgc >= 2 && if (aArgc >= 2 &&
!GetParamsForMessage(aCx, aObject, buffer, data.mClosure)) { !GetParamsForMessage(aCx, aJSON, buffer, data.mClosure)) {
return NS_ERROR_DOM_DATA_CLONE_ERR; return NS_ERROR_DOM_DATA_CLONE_ERR;
} }
JS::RootedObject objects(aCx);
if (aArgc >= 3 && aObjects.isObject()) {
objects = &aObjects.toObject();
}
data.mData = buffer.data(); data.mData = buffer.data();
data.mDataLength = buffer.nbytes(); data.mDataLength = buffer.nbytes();
return DispatchAsyncMessageInternal(aMessageName, data); return DispatchAsyncMessageInternal(aCx, aMessageName, data, objects);
} }
@ -433,11 +461,12 @@ nsFrameMessageManager::DispatchAsyncMessage(const nsAString& aMessageName,
NS_IMETHODIMP NS_IMETHODIMP
nsFrameMessageManager::SendAsyncMessage(const nsAString& aMessageName, nsFrameMessageManager::SendAsyncMessage(const nsAString& aMessageName,
const JS::Value& aObject, const JS::Value& aJSON,
const JS::Value& aObjects,
JSContext* aCx, JSContext* aCx,
uint8_t aArgc) uint8_t aArgc)
{ {
return DispatchAsyncMessage(aMessageName, aObject, aCx, aArgc); return DispatchAsyncMessage(aMessageName, aJSON, aObjects, aCx, aArgc);
} }
@ -445,11 +474,12 @@ nsFrameMessageManager::SendAsyncMessage(const nsAString& aMessageName,
NS_IMETHODIMP NS_IMETHODIMP
nsFrameMessageManager::BroadcastAsyncMessage(const nsAString& aMessageName, nsFrameMessageManager::BroadcastAsyncMessage(const nsAString& aMessageName,
const JS::Value& aObject, const JS::Value& aJSON,
const JS::Value& aObjects,
JSContext* aCx, JSContext* aCx,
uint8_t aArgc) uint8_t aArgc)
{ {
return DispatchAsyncMessage(aMessageName, aObject, aCx, aArgc); return DispatchAsyncMessage(aMessageName, aJSON, aObjects, aCx, aArgc);
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -631,11 +661,10 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
const nsAString& aMessage, const nsAString& aMessage,
bool aSync, bool aSync,
const StructuredCloneData* aCloneData, const StructuredCloneData* aCloneData,
JS::Handle<JSObject*> aObjectsArray, CpowHolder* aCpows,
InfallibleTArray<nsString>* aJSONRetVal) InfallibleTArray<nsString>* aJSONRetVal)
{ {
AutoSafeJSContext ctx; AutoSafeJSContext ctx;
JS::Rooted<JSObject*> objectsArray(ctx, aObjectsArray);
if (mListeners.Length()) { if (mListeners.Length()) {
nsCOMPtr<nsIAtom> name = do_GetAtom(aMessage); nsCOMPtr<nsIAtom> name = do_GetAtom(aMessage);
MMListenerRemover lr(this); MMListenerRemover lr(this);
@ -663,20 +692,21 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
nsContentUtils::WrapNative(ctx, global, aTarget, targetv.address(), nsContentUtils::WrapNative(ctx, global, aTarget, targetv.address(),
nullptr, true); nullptr, true);
// To keep compatibility with e10s message manager, JS::RootedObject cpows(ctx);
// define empty objects array. if (aCpows) {
if (!objectsArray) { if (!aCpows->ToObject(ctx, cpows.address())) {
// Because we want JS messages to have always the same properties, return NS_ERROR_UNEXPECTED;
// create array even if len == 0.
objectsArray = JS_NewArrayObject(ctx, 0, nullptr);
if (!objectsArray) {
return NS_ERROR_OUT_OF_MEMORY;
} }
} }
JS::Rooted<JS::Value> objectsv(ctx, JS::ObjectValue(*objectsArray)); if (!cpows) {
if (!JS_WrapValue(ctx, objectsv.address())) cpows = JS_NewObject(ctx, nullptr, nullptr, nullptr);
if (!cpows) {
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
}
}
JS::RootedValue cpowsv(ctx, JS::ObjectValue(*cpows));
JS::Rooted<JS::Value> json(ctx, JS::NullValue()); JS::Rooted<JS::Value> json(ctx, JS::NullValue());
if (aCloneData && aCloneData->mDataLength && if (aCloneData && aCloneData->mDataLength &&
@ -696,7 +726,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
BOOLEAN_TO_JSVAL(aSync), nullptr, nullptr, JSPROP_ENUMERATE); BOOLEAN_TO_JSVAL(aSync), nullptr, nullptr, JSPROP_ENUMERATE);
JS_DefineProperty(ctx, param, "json", json, nullptr, nullptr, JSPROP_ENUMERATE); // deprecated JS_DefineProperty(ctx, param, "json", json, nullptr, nullptr, JSPROP_ENUMERATE); // deprecated
JS_DefineProperty(ctx, param, "data", json, nullptr, nullptr, JSPROP_ENUMERATE); JS_DefineProperty(ctx, param, "data", json, nullptr, nullptr, JSPROP_ENUMERATE);
JS_DefineProperty(ctx, param, "objects", objectsv, nullptr, nullptr, JSPROP_ENUMERATE); JS_DefineProperty(ctx, param, "objects", cpowsv, nullptr, nullptr, JSPROP_ENUMERATE);
JS::Rooted<JS::Value> thisValue(ctx, JS::UndefinedValue()); JS::Rooted<JS::Value> thisValue(ctx, JS::UndefinedValue());
@ -754,7 +784,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
nsRefPtr<nsFrameMessageManager> kungfuDeathGrip = mParentManager; nsRefPtr<nsFrameMessageManager> kungfuDeathGrip = mParentManager;
return mParentManager ? mParentManager->ReceiveMessage(aTarget, aMessage, return mParentManager ? mParentManager->ReceiveMessage(aTarget, aMessage,
aSync, aCloneData, aSync, aCloneData,
objectsArray, aCpows,
aJSONRetVal) : NS_OK; aJSONRetVal) : NS_OK;
} }
@ -1040,20 +1070,33 @@ nsFrameMessageManager* nsFrameMessageManager::sParentProcessManager = nullptr;
nsFrameMessageManager* nsFrameMessageManager::sSameProcessParentManager = nullptr; nsFrameMessageManager* nsFrameMessageManager::sSameProcessParentManager = nullptr;
nsTArray<nsCOMPtr<nsIRunnable> >* nsFrameMessageManager::sPendingSameProcessAsyncMessages = nullptr; nsTArray<nsCOMPtr<nsIRunnable> >* nsFrameMessageManager::sPendingSameProcessAsyncMessages = nullptr;
class nsAsyncMessageToSameProcessChild : public nsRunnable class nsAsyncMessageToSameProcessChild : public nsRunnable
{ {
public: public:
nsAsyncMessageToSameProcessChild(const nsAString& aMessage, nsAsyncMessageToSameProcessChild(JSContext* aCx,
const StructuredCloneData& aData) const nsAString& aMessage,
: mMessage(aMessage) const StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows)
: mRuntime(js::GetRuntime(aCx)),
mMessage(aMessage),
mCpows(aCpows)
{ {
if (aData.mDataLength && !mData.copy(aData.mData, aData.mDataLength)) { if (aData.mDataLength && !mData.copy(aData.mData, aData.mDataLength)) {
NS_RUNTIMEABORT("OOM"); NS_RUNTIMEABORT("OOM");
} }
if (mCpows && !js_AddObjectRoot(mRuntime, &mCpows)) {
NS_RUNTIMEABORT("OOM");
}
mClosure = aData.mClosure; mClosure = aData.mClosure;
} }
~nsAsyncMessageToSameProcessChild()
{
if (mCpows) {
JS_RemoveObjectRootRT(mRuntime, &mCpows);
}
}
NS_IMETHOD Run() NS_IMETHOD Run()
{ {
if (nsFrameMessageManager::sChildProcessManager) { if (nsFrameMessageManager::sChildProcessManager) {
@ -1062,15 +1105,19 @@ public:
data.mDataLength = mData.nbytes(); data.mDataLength = mData.nbytes();
data.mClosure = mClosure; data.mClosure = mClosure;
SameProcessCpowHolder cpows(mRuntime, JS::Handle<JSObject *>::fromMarkedLocation(&mCpows));
nsRefPtr<nsFrameMessageManager> ppm = nsFrameMessageManager::sChildProcessManager; nsRefPtr<nsFrameMessageManager> ppm = nsFrameMessageManager::sChildProcessManager;
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), mMessage, ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), mMessage,
false, &data, JS::NullPtr(), nullptr); false, &data, &cpows, nullptr);
} }
return NS_OK; return NS_OK;
} }
JSRuntime* mRuntime;
nsString mMessage; nsString mMessage;
JSAutoStructuredCloneBuffer mData; JSAutoStructuredCloneBuffer mData;
StructuredCloneClosure mClosure; StructuredCloneClosure mClosure;
JSObject* mCpows;
}; };
@ -1089,11 +1136,13 @@ public:
MOZ_COUNT_DTOR(SameParentProcessMessageManagerCallback); MOZ_COUNT_DTOR(SameParentProcessMessageManagerCallback);
} }
virtual bool DoSendAsyncMessage(const nsAString& aMessage, virtual bool DoSendAsyncMessage(JSContext* aCx,
const StructuredCloneData& aData) const nsAString& aMessage,
const StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows)
{ {
nsRefPtr<nsIRunnable> ev = nsRefPtr<nsIRunnable> ev =
new nsAsyncMessageToSameProcessChild(aMessage, aData); new nsAsyncMessageToSameProcessChild(aCx, aMessage, aData, aCpows);
NS_DispatchToCurrentThread(ev); NS_DispatchToCurrentThread(ev);
return true; return true;
} }
@ -1133,8 +1182,10 @@ public:
MOZ_COUNT_DTOR(ChildProcessMessageManagerCallback); MOZ_COUNT_DTOR(ChildProcessMessageManagerCallback);
} }
virtual bool DoSendSyncMessage(const nsAString& aMessage, virtual bool DoSendSyncMessage(JSContext* aCx,
const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData, const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
InfallibleTArray<nsString>* aJSONRetVal) InfallibleTArray<nsString>* aJSONRetVal)
{ {
mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild* cc =
@ -1146,11 +1197,17 @@ public:
if (!BuildClonedMessageDataForChild(cc, aData, data)) { if (!BuildClonedMessageDataForChild(cc, aData, data)) {
return false; return false;
} }
return cc->SendSyncMessage(nsString(aMessage), data, aJSONRetVal); InfallibleTArray<mozilla::jsipc::CpowEntry> cpows;
if (!cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
return false;
}
return cc->SendSyncMessage(nsString(aMessage), data, cpows, aJSONRetVal);
} }
virtual bool DoSendAsyncMessage(const nsAString& aMessage, virtual bool DoSendAsyncMessage(JSContext* aCx,
const mozilla::dom::StructuredCloneData& aData) const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows)
{ {
mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild* cc =
mozilla::dom::ContentChild::GetSingleton(); mozilla::dom::ContentChild::GetSingleton();
@ -1161,7 +1218,11 @@ public:
if (!BuildClonedMessageDataForChild(cc, aData, data)) { if (!BuildClonedMessageDataForChild(cc, aData, data)) {
return false; return false;
} }
return cc->SendAsyncMessage(nsString(aMessage), data); InfallibleTArray<mozilla::jsipc::CpowEntry> cpows;
if (!cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
return false;
}
return cc->SendAsyncMessage(nsString(aMessage), data, cpows);
} }
}; };
@ -1170,16 +1231,30 @@ public:
class nsAsyncMessageToSameProcessParent : public nsRunnable class nsAsyncMessageToSameProcessParent : public nsRunnable
{ {
public: public:
nsAsyncMessageToSameProcessParent(const nsAString& aMessage, nsAsyncMessageToSameProcessParent(JSContext* aCx,
const StructuredCloneData& aData) const nsAString& aMessage,
: mMessage(aMessage) const StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows)
: mRuntime(js::GetRuntime(aCx)),
mMessage(aMessage),
mCpows(aCpows)
{ {
if (aData.mDataLength && !mData.copy(aData.mData, aData.mDataLength)) { if (aData.mDataLength && !mData.copy(aData.mData, aData.mDataLength)) {
NS_RUNTIMEABORT("OOM"); NS_RUNTIMEABORT("OOM");
} }
if (mCpows && !js_AddObjectRoot(mRuntime, &mCpows)) {
NS_RUNTIMEABORT("OOM");
}
mClosure = aData.mClosure; mClosure = aData.mClosure;
} }
~nsAsyncMessageToSameProcessParent()
{
if (mCpows) {
JS_RemoveObjectRootRT(mRuntime, &mCpows);
}
}
NS_IMETHOD Run() NS_IMETHOD Run()
{ {
if (nsFrameMessageManager::sPendingSameProcessAsyncMessages) { if (nsFrameMessageManager::sPendingSameProcessAsyncMessages) {
@ -1191,16 +1266,20 @@ public:
data.mDataLength = mData.nbytes(); data.mDataLength = mData.nbytes();
data.mClosure = mClosure; data.mClosure = mClosure;
SameProcessCpowHolder cpows(mRuntime, JS::Handle<JSObject *>::fromMarkedLocation(&mCpows));
nsRefPtr<nsFrameMessageManager> ppm = nsRefPtr<nsFrameMessageManager> ppm =
nsFrameMessageManager::sSameProcessParentManager; nsFrameMessageManager::sSameProcessParentManager;
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
mMessage, false, &data, JS::NullPtr(), nullptr); mMessage, false, &data, &cpows, nullptr);
} }
return NS_OK; return NS_OK;
} }
JSRuntime* mRuntime;
nsString mMessage; nsString mMessage;
JSAutoStructuredCloneBuffer mData; JSAutoStructuredCloneBuffer mData;
StructuredCloneClosure mClosure; StructuredCloneClosure mClosure;
JSObject* mCpows;
}; };
/** /**
@ -1218,8 +1297,10 @@ public:
MOZ_COUNT_DTOR(SameChildProcessMessageManagerCallback); MOZ_COUNT_DTOR(SameChildProcessMessageManagerCallback);
} }
virtual bool DoSendSyncMessage(const nsAString& aMessage, virtual bool DoSendSyncMessage(JSContext* aCx,
const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData, const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
InfallibleTArray<nsString>* aJSONRetVal) InfallibleTArray<nsString>* aJSONRetVal)
{ {
nsTArray<nsCOMPtr<nsIRunnable> > asyncMessages; nsTArray<nsCOMPtr<nsIRunnable> > asyncMessages;
@ -1232,21 +1313,24 @@ public:
} }
} }
if (nsFrameMessageManager::sSameProcessParentManager) { if (nsFrameMessageManager::sSameProcessParentManager) {
SameProcessCpowHolder cpows(js::GetRuntime(aCx), aCpows);
nsRefPtr<nsFrameMessageManager> ppm = nsFrameMessageManager::sSameProcessParentManager; nsRefPtr<nsFrameMessageManager> ppm = nsFrameMessageManager::sSameProcessParentManager;
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), aMessage, ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), aMessage,
true, &aData, JS::NullPtr(), aJSONRetVal); true, &aData, &cpows, aJSONRetVal);
} }
return true; return true;
} }
virtual bool DoSendAsyncMessage(const nsAString& aMessage, virtual bool DoSendAsyncMessage(JSContext* aCx,
const mozilla::dom::StructuredCloneData& aData) const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows)
{ {
if (!nsFrameMessageManager::sPendingSameProcessAsyncMessages) { if (!nsFrameMessageManager::sPendingSameProcessAsyncMessages) {
nsFrameMessageManager::sPendingSameProcessAsyncMessages = new nsTArray<nsCOMPtr<nsIRunnable> >; nsFrameMessageManager::sPendingSameProcessAsyncMessages = new nsTArray<nsCOMPtr<nsIRunnable> >;
} }
nsCOMPtr<nsIRunnable> ev = nsCOMPtr<nsIRunnable> ev =
new nsAsyncMessageToSameProcessParent(aMessage, aData); new nsAsyncMessageToSameProcessParent(aCx, aMessage, aData, aCpows);
nsFrameMessageManager::sPendingSameProcessAsyncMessages->AppendElement(ev); nsFrameMessageManager::sPendingSameProcessAsyncMessages->AppendElement(ev);
NS_DispatchToCurrentThread(ev); NS_DispatchToCurrentThread(ev);
return true; return true;

Просмотреть файл

@ -1,4 +1,5 @@
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=4 sw=4 tw=99 et: */
/* This Source Code Form is subject to the terms of the Mozilla Public /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -51,15 +52,19 @@ public:
return true; return true;
} }
virtual bool DoSendSyncMessage(const nsAString& aMessage, virtual bool DoSendSyncMessage(JSContext* aCx,
const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData, const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
InfallibleTArray<nsString>* aJSONRetVal) InfallibleTArray<nsString>* aJSONRetVal)
{ {
return true; return true;
} }
virtual bool DoSendAsyncMessage(const nsAString& aMessage, virtual bool DoSendAsyncMessage(JSContext* aCx,
const mozilla::dom::StructuredCloneData& aData) const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows)
{ {
return true; return true;
} }
@ -86,11 +91,11 @@ public:
protected: protected:
bool BuildClonedMessageDataForParent(ContentParent* aParent, bool BuildClonedMessageDataForParent(ContentParent* aParent,
const StructuredCloneData& aData, const StructuredCloneData& aData,
ClonedMessageData& aClonedData); ClonedMessageData& aClonedData);
bool BuildClonedMessageDataForChild(ContentChild* aChild, bool BuildClonedMessageDataForChild(ContentChild* aChild,
const StructuredCloneData& aData, const StructuredCloneData& aData,
ClonedMessageData& aClonedData); ClonedMessageData& aClonedData);
}; };
StructuredCloneData UnpackClonedMessageDataForParent(const ClonedMessageData& aData); StructuredCloneData UnpackClonedMessageDataForParent(const ClonedMessageData& aData);
@ -110,6 +115,25 @@ struct nsMessageListenerInfo
nsCOMPtr<nsIAtom> mMessage; nsCOMPtr<nsIAtom> mMessage;
}; };
class CpowHolder
{
public:
virtual bool ToObject(JSContext* cx, JSObject** objp) = 0;
};
class MOZ_STACK_CLASS SameProcessCpowHolder : public CpowHolder
{
public:
SameProcessCpowHolder(JSRuntime *aRuntime, JS::Handle<JSObject *> aObj)
: mObj(aRuntime, aObj)
{
}
bool ToObject(JSContext* aCx, JSObject** aObjp);
private:
JS::RootedObject mObj;
};
class nsFrameMessageManager MOZ_FINAL : public nsIContentFrameMessageManager, class nsFrameMessageManager MOZ_FINAL : public nsIContentFrameMessageManager,
public nsIMessageBroadcaster, public nsIMessageBroadcaster,
@ -183,7 +207,7 @@ public:
nsresult ReceiveMessage(nsISupports* aTarget, const nsAString& aMessage, nsresult ReceiveMessage(nsISupports* aTarget, const nsAString& aMessage,
bool aSync, const StructuredCloneData* aCloneData, bool aSync, const StructuredCloneData* aCloneData,
JS::Handle<JSObject*> aObjectsArray, CpowHolder* aCpows,
InfallibleTArray<nsString>* aJSONRetVal); InfallibleTArray<nsString>* aJSONRetVal);
void AddChildManager(nsFrameMessageManager* aManager, void AddChildManager(nsFrameMessageManager* aManager,
@ -202,11 +226,14 @@ public:
} }
nsresult DispatchAsyncMessage(const nsAString& aMessageName, nsresult DispatchAsyncMessage(const nsAString& aMessageName,
const JS::Value& aObject, const JS::Value& aJSON,
const JS::Value& aObjects,
JSContext* aCx, JSContext* aCx,
uint8_t aArgc); uint8_t aArgc);
nsresult DispatchAsyncMessageInternal(const nsAString& aMessage, nsresult DispatchAsyncMessageInternal(JSContext* aCx,
const StructuredCloneData& aData); const nsAString& aMessage,
const StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows);
void RemoveFromParent(); void RemoveFromParent();
nsFrameMessageManager* GetParentManager() { return mParentManager; } nsFrameMessageManager* GetParentManager() { return mParentManager; }
void SetParentManager(nsFrameMessageManager* aParent) void SetParentManager(nsFrameMessageManager* aParent)

Просмотреть файл

@ -25,8 +25,10 @@ using mozilla::dom::StructuredCloneData;
using mozilla::dom::StructuredCloneClosure; using mozilla::dom::StructuredCloneClosure;
bool bool
nsInProcessTabChildGlobal::DoSendSyncMessage(const nsAString& aMessage, nsInProcessTabChildGlobal::DoSendSyncMessage(JSContext* aCx,
const StructuredCloneData& aData, const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
InfallibleTArray<nsString>* aJSONRetVal) InfallibleTArray<nsString>* aJSONRetVal)
{ {
nsTArray<nsCOMPtr<nsIRunnable> > asyncMessages; nsTArray<nsCOMPtr<nsIRunnable> > asyncMessages;
@ -37,9 +39,9 @@ nsInProcessTabChildGlobal::DoSendSyncMessage(const nsAString& aMessage,
async->Run(); async->Run();
} }
if (mChromeMessageManager) { if (mChromeMessageManager) {
SameProcessCpowHolder cpows(js::GetRuntime(aCx), aCpows);
nsRefPtr<nsFrameMessageManager> mm = mChromeMessageManager; nsRefPtr<nsFrameMessageManager> mm = mChromeMessageManager;
mm->ReceiveMessage(mOwner, aMessage, true, &aData, JS::NullPtr(), mm->ReceiveMessage(mOwner, aMessage, true, &aData, &cpows, aJSONRetVal);
aJSONRetVal);
} }
return true; return true;
} }
@ -47,17 +49,33 @@ nsInProcessTabChildGlobal::DoSendSyncMessage(const nsAString& aMessage,
class nsAsyncMessageToParent : public nsRunnable class nsAsyncMessageToParent : public nsRunnable
{ {
public: public:
nsAsyncMessageToParent(nsInProcessTabChildGlobal* aTabChild, nsAsyncMessageToParent(JSContext* aCx,
nsInProcessTabChildGlobal* aTabChild,
const nsAString& aMessage, const nsAString& aMessage,
const StructuredCloneData& aData) const StructuredCloneData& aData,
: mTabChild(aTabChild), mMessage(aMessage), mRun(false) JS::Handle<JSObject *> aCpows)
: mRuntime(js::GetRuntime(aCx)),
mTabChild(aTabChild),
mMessage(aMessage),
mCpows(aCpows),
mRun(false)
{ {
if (aData.mDataLength && !mData.copy(aData.mData, aData.mDataLength)) { if (aData.mDataLength && !mData.copy(aData.mData, aData.mDataLength)) {
NS_RUNTIMEABORT("OOM"); NS_RUNTIMEABORT("OOM");
} }
if (mCpows && !js_AddObjectRoot(mRuntime, &mCpows)) {
NS_RUNTIMEABORT("OOM");
}
mClosure = aData.mClosure; mClosure = aData.mClosure;
} }
~nsAsyncMessageToParent()
{
if (mCpows) {
JS_RemoveObjectRootRT(mRuntime, &mCpows);
}
}
NS_IMETHOD Run() NS_IMETHOD Run()
{ {
if (mRun) { if (mRun) {
@ -72,27 +90,32 @@ public:
data.mDataLength = mData.nbytes(); data.mDataLength = mData.nbytes();
data.mClosure = mClosure; data.mClosure = mClosure;
SameProcessCpowHolder cpows(mRuntime, JS::Handle<JSObject *>::fromMarkedLocation(&mCpows));
nsRefPtr<nsFrameMessageManager> mm = mTabChild->mChromeMessageManager; nsRefPtr<nsFrameMessageManager> mm = mTabChild->mChromeMessageManager;
mm->ReceiveMessage(mTabChild->mOwner, mMessage, false, &data, mm->ReceiveMessage(mTabChild->mOwner, mMessage, false, &data, &cpows, nullptr);
JS::NullPtr(), nullptr);
} }
return NS_OK; return NS_OK;
} }
JSRuntime* mRuntime;
nsRefPtr<nsInProcessTabChildGlobal> mTabChild; nsRefPtr<nsInProcessTabChildGlobal> mTabChild;
nsString mMessage; nsString mMessage;
JSAutoStructuredCloneBuffer mData; JSAutoStructuredCloneBuffer mData;
StructuredCloneClosure mClosure; StructuredCloneClosure mClosure;
JSObject* mCpows;
// True if this runnable has already been called. This can happen if DoSendSyncMessage // True if this runnable has already been called. This can happen if DoSendSyncMessage
// is called while waiting for an asynchronous message send. // is called while waiting for an asynchronous message send.
bool mRun; bool mRun;
}; };
bool bool
nsInProcessTabChildGlobal::DoSendAsyncMessage(const nsAString& aMessage, nsInProcessTabChildGlobal::DoSendAsyncMessage(JSContext* aCx,
const StructuredCloneData& aData) const nsAString& aMessage,
const StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows)
{ {
nsCOMPtr<nsIRunnable> ev = nsCOMPtr<nsIRunnable> ev =
new nsAsyncMessageToParent(this, aMessage, aData); new nsAsyncMessageToParent(aCx, this, aMessage, aData, aCpows);
mASyncMessages.AppendElement(ev); mASyncMessages.AppendElement(ev);
NS_DispatchToCurrentThread(ev); NS_DispatchToCurrentThread(ev);
return true; return true;

Просмотреть файл

@ -41,12 +41,13 @@ public:
NS_FORWARD_SAFE_NSIMESSAGESENDER(mMessageManager) NS_FORWARD_SAFE_NSIMESSAGESENDER(mMessageManager)
NS_IMETHOD SendSyncMessage(const nsAString& aMessageName, NS_IMETHOD SendSyncMessage(const nsAString& aMessageName,
const JS::Value& aObject, const JS::Value& aObject,
const JS::Value& aRemote,
JSContext* aCx, JSContext* aCx,
uint8_t aArgc, uint8_t aArgc,
JS::Value* aRetval) JS::Value* aRetval)
{ {
return mMessageManager return mMessageManager
? mMessageManager->SendSyncMessage(aMessageName, aObject, aCx, aArgc, aRetval) ? mMessageManager->SendSyncMessage(aMessageName, aObject, aRemote, aCx, aArgc, aRetval)
: NS_ERROR_NULL_POINTER; : NS_ERROR_NULL_POINTER;
} }
NS_IMETHOD GetContent(nsIDOMWindow** aContent) MOZ_OVERRIDE; NS_IMETHOD GetContent(nsIDOMWindow** aContent) MOZ_OVERRIDE;
@ -66,11 +67,15 @@ public:
/** /**
* MessageManagerCallback methods that we override. * MessageManagerCallback methods that we override.
*/ */
virtual bool DoSendSyncMessage(const nsAString& aMessage, virtual bool DoSendSyncMessage(JSContext* aCx,
const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData, const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
InfallibleTArray<nsString>* aJSONRetVal) MOZ_OVERRIDE; InfallibleTArray<nsString>* aJSONRetVal) MOZ_OVERRIDE;
virtual bool DoSendAsyncMessage(const nsAString& aMessage, virtual bool DoSendAsyncMessage(JSContext* aCx,
const mozilla::dom::StructuredCloneData& aData) MOZ_OVERRIDE; const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows);
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor) MOZ_OVERRIDE; virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor) MOZ_OVERRIDE;
NS_IMETHOD AddEventListener(const nsAString& aType, NS_IMETHOD AddEventListener(const nsAString& aType,

Просмотреть файл

@ -61,6 +61,9 @@ MOCHITEST_CHROME_FILES = \
host_bug814638.xul \ host_bug814638.xul \
test_document_register.xul \ test_document_register.xul \
frame_bug814638.xul \ frame_bug814638.xul \
test_cpows.xul \
cpows_parent.xul \
cpows_child.js \
$(NULL) $(NULL)
include $(topsrcdir)/config/rules.mk include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -0,0 +1,58 @@
dump('loaded child cpow test\n');
content.document.title = "Hello, Kitty";
(function start() {
sync_test();
async_test();
sendAsyncMessage("cpows:done", {});
}
)();
function ok(condition, message) {
dump('condition: ' + condition + ', ' + message + '\n');
if (!condition) {
sendAsyncMessage("cpows:fail", { message: message });
throw 'failed check: ' + message;
}
}
var sync_obj;
var async_obj;
function make_object()
{
let o = { };
o.i = 5;
o.b = true;
o.s = "hello";
o.x = { i: 10 };
o.f = function () { return 99; }
return { "data": o,
"document": content.document
};
}
function make_json()
{
return { check: "ok" };
}
function sync_test()
{
dump('beginning cpow sync test\n');
sync_obj = make_object();
sendSyncMessage("cpows:sync",
make_json(),
make_object());
}
function async_test()
{
dump('beginning cpow async test\n');
async_obj = make_object();
sendAsyncMessage("cpows:async",
make_json(),
async_obj);
}

Просмотреть файл

@ -0,0 +1,90 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window title="MessageManager CPOW tests"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="start()">
<!-- test results are displayed in the html:body -->
<label value="CPOWs"/>
<script type="application/javascript"><![CDATA[
var test_state = "remote";
var test_node = null;
function ok(condition, message) {
return opener.wrappedJSObject.ok(condition, message);
}
function testCpowMessage(message) {
ok(message.json.check == "ok", "correct json");
let data = message.objects.data;
let document = message.objects.document;
ok(data.i === 5, "integer property");
ok(data.b === true, "boolean property");
ok(data.s === "hello", "string property");
ok(data.x.i === 10, "nested property");
ok(data.f() === 99, "function call");
ok(document.title === "Hello, Kitty", "document node");
data.i = 6;
data.b = false;
data.s = "bye";
data.x = null;
ok(data.i === 6, "integer property");
ok(data.b === false, "boolean property");
ok(data.s === "bye", "string property");
ok(data.x === null, "nested property");
}
function recvAsyncMessage(message) {
testCpowMessage(message);
}
function recvSyncMessage(message) {
testCpowMessage(message);
}
function recvFailMessage(message) {
ok(false, message.json.message);
}
function recvDoneMessage(message) {
if (test_state == "remote") {
test_node.parentNode.removeChild(test_node);
run_tests("inprocess");
return;
}
finish();
}
function run_tests(type) {
var node = document.getElementById('cpowbrowser_' + type);
test_state = type;
test_node = node;
var mm = node.messageManager;
mm.addMessageListener("cpows:async", recvAsyncMessage);
mm.addMessageListener("cpows:sync", recvSyncMessage);
mm.addMessageListener("cpows:done", recvDoneMessage);
mm.addMessageListener("cpows:fail", recvFailMessage);
mm.loadFrameScript("chrome://mochitests/content/chrome/content/base/test/chrome/cpows_child.js", true);
}
function start() {
run_tests('remote');
}
function finish() {
opener.setTimeout("done()", 0);
window.close();
}
]]></script>
<browser type="content" src="about:blank" id="cpowbrowser_remote" remote="true"/>
<browser type="content" src="about:blank" id="cpowbrowser_inprocess"/>
</window>

Просмотреть файл

@ -0,0 +1,27 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window title="Test CPOWs"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml">
</body>
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
SimpleTest.waitForExplicitFinish();
function done() {
SimpleTest.finish();
}
addLoadEvent(function() {
window.open("cpows_parent.xul", "", "chrome");
});
]]></script>
</window>

Просмотреть файл

@ -321,6 +321,8 @@ ContentChild::Init(MessageLoop* aIOLoop,
SendGetProcessAttributes(&mID, &mIsForApp, &mIsForBrowser); SendGetProcessAttributes(&mID, &mIsForApp, &mIsForBrowser);
GetCPOWManager();
if (mIsForApp && !mIsForBrowser) { if (mIsForApp && !mIsForBrowser) {
SetProcessName(NS_LITERAL_STRING("(Preallocated app)")); SetProcessName(NS_LITERAL_STRING("(Preallocated app)"));
} else { } else {
@ -1059,13 +1061,15 @@ ContentChild::RecvNotifyVisited(const URIParams& aURI)
bool bool
ContentChild::RecvAsyncMessage(const nsString& aMsg, ContentChild::RecvAsyncMessage(const nsString& aMsg,
const ClonedMessageData& aData) const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows)
{ {
nsRefPtr<nsFrameMessageManager> cpm = nsFrameMessageManager::sChildProcessManager; nsRefPtr<nsFrameMessageManager> cpm = nsFrameMessageManager::sChildProcessManager;
if (cpm) { if (cpm) {
StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForChild(aData); StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForChild(aData);
CpowIdHolder cpows(GetCPOWManager(), aCpows);
cpm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(cpm.get()), cpm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(cpm.get()),
aMsg, false, &cloneData, JS::NullPtr(), nullptr); aMsg, false, &cloneData, &cpows, nullptr);
} }
return true; return true;
} }

Просмотреть файл

@ -178,7 +178,8 @@ public:
virtual bool RecvNotifyAlertsObserver(const nsCString& aType, const nsString& aData); virtual bool RecvNotifyAlertsObserver(const nsCString& aType, const nsString& aData);
virtual bool RecvAsyncMessage(const nsString& aMsg, virtual bool RecvAsyncMessage(const nsString& aMsg,
const ClonedMessageData& aData); const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows);
virtual bool RecvGeolocationUpdate(const GeoPosition& somewhere); virtual bool RecvGeolocationUpdate(const GeoPosition& somewhere);

Просмотреть файл

@ -868,7 +868,7 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
if (ppm) { if (ppm) {
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
CHILD_PROCESS_SHUTDOWN_MESSAGE, false, CHILD_PROCESS_SHUTDOWN_MESSAGE, false,
nullptr, JS::NullPtr(), nullptr); nullptr, nullptr, nullptr);
} }
nsCOMPtr<nsIThreadObserver> nsCOMPtr<nsIThreadObserver>
kungFuDeathGrip(static_cast<nsIThreadObserver*>(this)); kungFuDeathGrip(static_cast<nsIThreadObserver*>(this));
@ -2308,26 +2308,30 @@ ContentParent::RecvTestPermissionFromPrincipal(const IPC::Principal& aPrincipal,
bool bool
ContentParent::RecvSyncMessage(const nsString& aMsg, ContentParent::RecvSyncMessage(const nsString& aMsg,
const ClonedMessageData& aData, const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows,
InfallibleTArray<nsString>* aRetvals) InfallibleTArray<nsString>* aRetvals)
{ {
nsRefPtr<nsFrameMessageManager> ppm = mMessageManager; nsRefPtr<nsFrameMessageManager> ppm = mMessageManager;
if (ppm) { if (ppm) {
StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
CpowIdHolder cpows(GetCPOWManager(), aCpows);
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
aMsg, true, &cloneData, JS::NullPtr(), aRetvals); aMsg, true, &cloneData, &cpows, aRetvals);
} }
return true; return true;
} }
bool bool
ContentParent::RecvAsyncMessage(const nsString& aMsg, ContentParent::RecvAsyncMessage(const nsString& aMsg,
const ClonedMessageData& aData) const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows)
{ {
nsRefPtr<nsFrameMessageManager> ppm = mMessageManager; nsRefPtr<nsFrameMessageManager> ppm = mMessageManager;
if (ppm) { if (ppm) {
StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
CpowIdHolder cpows(GetCPOWManager(), aCpows);
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
aMsg, false, &cloneData, JS::NullPtr(), nullptr); aMsg, false, &cloneData, &cpows, nullptr);
} }
return true; return true;
} }
@ -2531,14 +2535,20 @@ ContentParent::RecvPrivateDocShellsExist(const bool& aExist)
} }
bool bool
ContentParent::DoSendAsyncMessage(const nsAString& aMessage, ContentParent::DoSendAsyncMessage(JSContext* aCx,
const mozilla::dom::StructuredCloneData& aData) const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows)
{ {
ClonedMessageData data; ClonedMessageData data;
if (!BuildClonedMessageDataForParent(this, aData, data)) { if (!BuildClonedMessageDataForParent(this, aData, data)) {
return false; return false;
} }
return SendAsyncMessage(nsString(aMessage), data); InfallibleTArray<CpowEntry> cpows;
if (!GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
return false;
}
return SendAsyncMessage(nsString(aMessage), data, cpows);
} }
bool bool

Просмотреть файл

@ -114,8 +114,10 @@ public:
/** /**
* MessageManagerCallback methods that we override. * MessageManagerCallback methods that we override.
*/ */
virtual bool DoSendAsyncMessage(const nsAString& aMessage, virtual bool DoSendAsyncMessage(JSContext* aCx,
const mozilla::dom::StructuredCloneData& aData) MOZ_OVERRIDE; const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows) MOZ_OVERRIDE;
virtual bool CheckPermission(const nsAString& aPermission) MOZ_OVERRIDE; virtual bool CheckPermission(const nsAString& aPermission) MOZ_OVERRIDE;
virtual bool CheckManifestURL(const nsAString& aManifestURL) MOZ_OVERRIDE; virtual bool CheckManifestURL(const nsAString& aManifestURL) MOZ_OVERRIDE;
virtual bool CheckAppHasPermission(const nsAString& aPermission) MOZ_OVERRIDE; virtual bool CheckAppHasPermission(const nsAString& aPermission) MOZ_OVERRIDE;
@ -199,7 +201,6 @@ private:
// using them. // using them.
using PContentParent::SendPBrowserConstructor; using PContentParent::SendPBrowserConstructor;
using PContentParent::SendPTestShellConstructor; using PContentParent::SendPTestShellConstructor;
using PContentParent::SendPJavaScriptConstructor;
// No more than one of !!aApp, aIsForBrowser, and aIsForPreallocated may be // No more than one of !!aApp, aIsForBrowser, and aIsForPreallocated may be
// true. // true.
@ -372,9 +373,11 @@ private:
virtual bool RecvSyncMessage(const nsString& aMsg, virtual bool RecvSyncMessage(const nsString& aMsg,
const ClonedMessageData& aData, const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows,
InfallibleTArray<nsString>* aRetvals); InfallibleTArray<nsString>* aRetvals);
virtual bool RecvAsyncMessage(const nsString& aMsg, virtual bool RecvAsyncMessage(const nsString& aMsg,
const ClonedMessageData& aData); const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows);
virtual bool RecvFilePathUpdateNotify(const nsString& aType, virtual bool RecvFilePathUpdateNotify(const nsString& aType,
const nsString& aStorageName, const nsString& aStorageName,

Просмотреть файл

@ -14,6 +14,7 @@ include protocol PRenderFrame;
include protocol POfflineCacheUpdate; include protocol POfflineCacheUpdate;
include protocol PIndexedDB; include protocol PIndexedDB;
include DOMTypes; include DOMTypes;
include JavaScriptTypes;
include URIParams; include URIParams;
include "gfxMatrix.h"; include "gfxMatrix.h";
@ -67,7 +68,7 @@ rpc protocol PBrowser
manages PIndexedDB; manages PIndexedDB;
both: both:
AsyncMessage(nsString aMessage, ClonedMessageData aData); AsyncMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows);
parent: parent:
/** /**
@ -80,7 +81,7 @@ parent:
rpc CreateWindow() returns (PBrowser window); rpc CreateWindow() returns (PBrowser window);
sync SyncMessage(nsString aMessage, ClonedMessageData aData) sync SyncMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows)
returns (nsString[] retval); returns (nsString[] retval);
/** /**

Просмотреть файл

@ -22,6 +22,7 @@ include protocol PStorage;
include protocol PTestShell; include protocol PTestShell;
include protocol PJavaScript; include protocol PJavaScript;
include DOMTypes; include DOMTypes;
include JavaScriptTypes;
include InputStreamParams; include InputStreamParams;
include PTabContext; include PTabContext;
include URIParams; include URIParams;
@ -190,7 +191,7 @@ both:
async PBlob(BlobConstructorParams params); async PBlob(BlobConstructorParams params);
PJavaScript(); async PJavaScript();
child: child:
/** /**
@ -329,7 +330,7 @@ parent:
sync ReadFontList() returns (FontListEntry[] retValue); sync ReadFontList() returns (FontListEntry[] retValue);
sync SyncMessage(nsString aMessage, ClonedMessageData aData) sync SyncMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows)
returns (nsString[] retval); returns (nsString[] retval);
ShowAlertNotification(nsString imageUrl, ShowAlertNotification(nsString imageUrl,
@ -427,7 +428,7 @@ parent:
async SetFakeVolumeState(nsString fsName, int32_t fsState); async SetFakeVolumeState(nsString fsName, int32_t fsState);
both: both:
AsyncMessage(nsString aMessage, ClonedMessageData aData); AsyncMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows);
}; };
} }

Просмотреть файл

@ -84,6 +84,7 @@
#include "StructuredCloneUtils.h" #include "StructuredCloneUtils.h"
#include "xpcpublic.h" #include "xpcpublic.h"
#include "nsViewportInfo.h" #include "nsViewportInfo.h"
#include "JavaScriptChild.h"
#define BROWSER_ELEMENT_CHILD_SCRIPT \ #define BROWSER_ELEMENT_CHILD_SCRIPT \
NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js") NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js")
@ -97,6 +98,7 @@ using namespace mozilla::layout;
using namespace mozilla::docshell; using namespace mozilla::docshell;
using namespace mozilla::dom::indexedDB; using namespace mozilla::dom::indexedDB;
using namespace mozilla::widget; using namespace mozilla::widget;
using namespace mozilla::jsipc;
NS_IMPL_ISUPPORTS1(ContentListener, nsIDOMEventListener) NS_IMPL_ISUPPORTS1(ContentListener, nsIDOMEventListener)
@ -1454,7 +1456,7 @@ TabChild::DispatchMessageManagerMessage(const nsAString& aMessageName,
nsRefPtr<nsFrameMessageManager> mm = nsRefPtr<nsFrameMessageManager> mm =
static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get()); static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get());
mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildGlobal), mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildGlobal),
aMessageName, false, &cloneData, JS::NullPtr(), nullptr); aMessageName, false, &cloneData, nullptr, nullptr);
} }
static void static void
@ -2030,15 +2032,17 @@ TabChild::RecvLoadRemoteScript(const nsString& aURL)
bool bool
TabChild::RecvAsyncMessage(const nsString& aMessage, TabChild::RecvAsyncMessage(const nsString& aMessage,
const ClonedMessageData& aData) const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows)
{ {
if (mTabChildGlobal) { if (mTabChildGlobal) {
nsCOMPtr<nsIXPConnectJSObjectHolder> kungFuDeathGrip(GetGlobal()); nsCOMPtr<nsIXPConnectJSObjectHolder> kungFuDeathGrip(GetGlobal());
StructuredCloneData cloneData = UnpackClonedMessageDataForChild(aData); StructuredCloneData cloneData = UnpackClonedMessageDataForChild(aData);
nsRefPtr<nsFrameMessageManager> mm = nsRefPtr<nsFrameMessageManager> mm =
static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get()); static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get());
CpowIdHolder cpows(static_cast<ContentChild*>(Manager())->GetCPOWManager(), aCpows);
mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildGlobal), mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildGlobal),
aMessage, false, &cloneData, JS::NullPtr(), nullptr); aMessage, false, &cloneData, &cpows, nullptr);
} }
return true; return true;
} }
@ -2332,8 +2336,10 @@ TabChild::DeallocPIndexedDBChild(PIndexedDBChild* aActor)
} }
bool bool
TabChild::DoSendSyncMessage(const nsAString& aMessage, TabChild::DoSendSyncMessage(JSContext* aCx,
const nsAString& aMessage,
const StructuredCloneData& aData, const StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
InfallibleTArray<nsString>* aJSONRetVal) InfallibleTArray<nsString>* aJSONRetVal)
{ {
ContentChild* cc = Manager(); ContentChild* cc = Manager();
@ -2341,19 +2347,29 @@ TabChild::DoSendSyncMessage(const nsAString& aMessage,
if (!BuildClonedMessageDataForChild(cc, aData, data)) { if (!BuildClonedMessageDataForChild(cc, aData, data)) {
return false; return false;
} }
return SendSyncMessage(nsString(aMessage), data, aJSONRetVal); InfallibleTArray<CpowEntry> cpows;
if (!cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
return false;
}
return SendSyncMessage(nsString(aMessage), data, cpows, aJSONRetVal);
} }
bool bool
TabChild::DoSendAsyncMessage(const nsAString& aMessage, TabChild::DoSendAsyncMessage(JSContext* aCx,
const StructuredCloneData& aData) const nsAString& aMessage,
const StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows)
{ {
ContentChild* cc = Manager(); ContentChild* cc = Manager();
ClonedMessageData data; ClonedMessageData data;
if (!BuildClonedMessageDataForChild(cc, aData, data)) { if (!BuildClonedMessageDataForChild(cc, aData, data)) {
return false; return false;
} }
return SendAsyncMessage(nsString(aMessage), data); InfallibleTArray<CpowEntry> cpows;
if (!cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
return false;
}
return SendAsyncMessage(nsString(aMessage), data, cpows);
} }

Просмотреть файл

@ -78,12 +78,13 @@ public:
NS_FORWARD_SAFE_NSIMESSAGESENDER(mMessageManager) NS_FORWARD_SAFE_NSIMESSAGESENDER(mMessageManager)
NS_IMETHOD SendSyncMessage(const nsAString& aMessageName, NS_IMETHOD SendSyncMessage(const nsAString& aMessageName,
const JS::Value& aObject, const JS::Value& aObject,
const JS::Value& aRemote,
JSContext* aCx, JSContext* aCx,
uint8_t aArgc, uint8_t aArgc,
JS::Value* aRetval) JS::Value* aRetval)
{ {
return mMessageManager return mMessageManager
? mMessageManager->SendSyncMessage(aMessageName, aObject, aCx, aArgc, aRetval) ? mMessageManager->SendSyncMessage(aMessageName, aObject, aRemote, aCx, aArgc, aRetval)
: NS_ERROR_NULL_POINTER; : NS_ERROR_NULL_POINTER;
} }
NS_IMETHOD GetContent(nsIDOMWindow** aContent) MOZ_OVERRIDE; NS_IMETHOD GetContent(nsIDOMWindow** aContent) MOZ_OVERRIDE;
@ -187,11 +188,15 @@ public:
/** /**
* MessageManagerCallback methods that we override. * MessageManagerCallback methods that we override.
*/ */
virtual bool DoSendSyncMessage(const nsAString& aMessage, virtual bool DoSendSyncMessage(JSContext* aCx,
const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData, const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
InfallibleTArray<nsString>* aJSONRetVal); InfallibleTArray<nsString>* aJSONRetVal);
virtual bool DoSendAsyncMessage(const nsAString& aMessage, virtual bool DoSendAsyncMessage(JSContext* aCx,
const mozilla::dom::StructuredCloneData& aData); const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows);
virtual bool RecvLoadURL(const nsCString& uri); virtual bool RecvLoadURL(const nsCString& uri);
virtual bool RecvCacheFileDescriptor(const nsString& aPath, virtual bool RecvCacheFileDescriptor(const nsString& aPath,
@ -228,7 +233,8 @@ public:
virtual bool RecvActivateFrameEvent(const nsString& aType, const bool& capture); virtual bool RecvActivateFrameEvent(const nsString& aType, const bool& capture);
virtual bool RecvLoadRemoteScript(const nsString& aURL); virtual bool RecvLoadRemoteScript(const nsString& aURL);
virtual bool RecvAsyncMessage(const nsString& aMessage, virtual bool RecvAsyncMessage(const nsString& aMessage,
const ClonedMessageData& aData); const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows);
virtual PDocumentRendererChild* virtual PDocumentRendererChild*
AllocPDocumentRendererChild(const nsRect& documentRect, const gfxMatrix& transform, AllocPDocumentRendererChild(const nsRect& documentRect, const gfxMatrix& transform,

Просмотреть файл

@ -52,6 +52,7 @@
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "private/pprio.h" #include "private/pprio.h"
#include "StructuredCloneUtils.h" #include "StructuredCloneUtils.h"
#include "JavaScriptParent.h"
#include "TabChild.h" #include "TabChild.h"
#include <algorithm> #include <algorithm>
@ -62,6 +63,7 @@ using namespace mozilla::layout;
using namespace mozilla::services; using namespace mozilla::services;
using namespace mozilla::widget; using namespace mozilla::widget;
using namespace mozilla::dom::indexedDB; using namespace mozilla::dom::indexedDB;
using namespace mozilla::jsipc;
// The flags passed by the webProgress notifications are 16 bits shifted // The flags passed by the webProgress notifications are 16 bits shifted
// from the ones registered by webProgressListeners. // from the ones registered by webProgressListeners.
@ -708,18 +710,22 @@ TabParent::TryCapture(const nsGUIEvent& aEvent)
bool bool
TabParent::RecvSyncMessage(const nsString& aMessage, TabParent::RecvSyncMessage(const nsString& aMessage,
const ClonedMessageData& aData, const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows,
InfallibleTArray<nsString>* aJSONRetVal) InfallibleTArray<nsString>* aJSONRetVal)
{ {
StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
return ReceiveMessage(aMessage, true, &cloneData, aJSONRetVal); CpowIdHolder cpows(static_cast<ContentParent*>(Manager())->GetCPOWManager(), aCpows);
return ReceiveMessage(aMessage, true, &cloneData, &cpows, aJSONRetVal);
} }
bool bool
TabParent::RecvAsyncMessage(const nsString& aMessage, TabParent::RecvAsyncMessage(const nsString& aMessage,
const ClonedMessageData& aData) const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows)
{ {
StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData); StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
return ReceiveMessage(aMessage, false, &cloneData, nullptr); CpowIdHolder cpows(static_cast<ContentParent*>(Manager())->GetCPOWManager(), aCpows);
return ReceiveMessage(aMessage, false, &cloneData, &cpows, nullptr);
} }
bool bool
@ -1084,26 +1090,19 @@ bool
TabParent::ReceiveMessage(const nsString& aMessage, TabParent::ReceiveMessage(const nsString& aMessage,
bool aSync, bool aSync,
const StructuredCloneData* aCloneData, const StructuredCloneData* aCloneData,
CpowHolder* aCpows,
InfallibleTArray<nsString>* aJSONRetVal) InfallibleTArray<nsString>* aJSONRetVal)
{ {
nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader(); nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
if (frameLoader && frameLoader->GetFrameMessageManager()) { if (frameLoader && frameLoader->GetFrameMessageManager()) {
nsRefPtr<nsFrameMessageManager> manager = nsRefPtr<nsFrameMessageManager> manager =
frameLoader->GetFrameMessageManager(); frameLoader->GetFrameMessageManager();
AutoSafeJSContext ctx;
uint32_t len = 0; //TODO: obtain a real value in bug 572685
// Because we want JS messages to have always the same properties,
// create array even if len == 0.
JS::Rooted<JSObject*> objectsArray(ctx, JS_NewArrayObject(ctx, len, NULL));
if (!objectsArray) {
return false;
}
manager->ReceiveMessage(mFrameElement, manager->ReceiveMessage(mFrameElement,
aMessage, aMessage,
aSync, aSync,
aCloneData, aCloneData,
objectsArray, aCpows,
aJSONRetVal); aJSONRetVal);
} }
return true; return true;

Просмотреть файл

@ -30,6 +30,7 @@ class mozIApplication;
class nsFrameLoader; class nsFrameLoader;
class nsIDOMElement; class nsIDOMElement;
class nsIURI; class nsIURI;
class CpowHolder;
namespace mozilla { namespace mozilla {
@ -122,9 +123,11 @@ public:
virtual bool AnswerCreateWindow(PBrowserParent** retval); virtual bool AnswerCreateWindow(PBrowserParent** retval);
virtual bool RecvSyncMessage(const nsString& aMessage, virtual bool RecvSyncMessage(const nsString& aMessage,
const ClonedMessageData& aData, const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows,
InfallibleTArray<nsString>* aJSONRetVal); InfallibleTArray<nsString>* aJSONRetVal);
virtual bool RecvAsyncMessage(const nsString& aMessage, virtual bool RecvAsyncMessage(const nsString& aMessage,
const ClonedMessageData& aData); const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows);
virtual bool RecvNotifyIMEFocus(const bool& aFocus, virtual bool RecvNotifyIMEFocus(const bool& aFocus,
nsIMEUpdatePreference* aPreference, nsIMEUpdatePreference* aPreference,
uint32_t* aSeqno); uint32_t* aSeqno);
@ -233,6 +236,7 @@ protected:
bool ReceiveMessage(const nsString& aMessage, bool ReceiveMessage(const nsString& aMessage,
bool aSync, bool aSync,
const StructuredCloneData* aCloneData, const StructuredCloneData* aCloneData,
CpowHolder* aCpows,
InfallibleTArray<nsString>* aJSONRetVal = nullptr); InfallibleTArray<nsString>* aJSONRetVal = nullptr);
virtual bool Recv__delete__() MOZ_OVERRIDE; virtual bool Recv__delete__() MOZ_OVERRIDE;

Просмотреть файл

@ -197,6 +197,10 @@ JavaScriptChild::AnswerGet(const ObjectId &objId, const ObjectId &receiverId,
AutoSafeJSContext cx; AutoSafeJSContext cx;
JSAutoRequest request(cx); JSAutoRequest request(cx);
// The outparam will be written to the buffer, so it must be set even if
// the parent won't read it.
*result = void_t();
RootedObject obj(cx, findObject(objId)); RootedObject obj(cx, findObject(objId));
if (!obj) if (!obj)
return false; return false;

Просмотреть файл

@ -455,14 +455,11 @@ CPOWProxyHandler::finalize(JSFreeOp *fop, JSObject *proxy)
void void
JavaScriptParent::drop(JSObject *obj) JavaScriptParent::drop(JSObject *obj)
{ {
if (inactive_)
return;
ObjectId objId = idOf(obj); ObjectId objId = idOf(obj);
objects_.remove(objId); objects_.remove(objId);
if (!SendDropObject(objId)) if (!inactive_ && !SendDropObject(objId))
MOZ_CRASH(); (void)0;
decref(); decref();
} }

Просмотреть файл

@ -395,3 +395,78 @@ JavaScriptShared::toDescriptor(JSContext *cx, const PPropertyDescriptor &in, JSP
return true; return true;
} }
bool
CpowIdHolder::ToObject(JSContext *cx, JSObject **objp)
{
return js_->Unwrap(cx, cpows_, objp);
}
bool
JavaScriptShared::Unwrap(JSContext *cx, const InfallibleTArray<CpowEntry> &aCpows, JSObject **objp)
{
*objp = NULL;
if (!aCpows.Length())
return true;
RootedObject obj(cx, JS_NewObject(cx, NULL, NULL, NULL));
if (!obj)
return false;
RootedValue v(cx);
RootedString str(cx);
for (size_t i = 0; i < aCpows.Length(); i++) {
const nsString &name = aCpows[i].name();
if (!toValue(cx, aCpows[i].value(), &v))
return false;
if (!JS_DefineUCProperty(cx,
obj,
name.BeginReading(),
name.Length(),
v,
NULL,
NULL,
JSPROP_ENUMERATE))
{
return false;
}
}
*objp = obj;
return true;
}
bool
JavaScriptShared::Wrap(JSContext *cx, HandleObject aObj, InfallibleTArray<CpowEntry> *outCpows)
{
if (!aObj)
return true;
AutoIdArray ids(cx, JS_Enumerate(cx, aObj));
if (!ids)
return false;
RootedId id(cx);
RootedValue v(cx);
for (size_t i = 0; i < ids.length(); i++) {
id = ids[i];
nsString str;
if (!convertIdToGeckoString(cx, id, &str))
return false;
if (!JS_GetPropertyById(cx, aObj, id, v.address()))
return false;
JSVariant var;
if (!toVariant(cx, v, &var))
return false;
outCpows->AppendElement(CpowEntry(str, var));
}
return true;
}

Просмотреть файл

@ -21,6 +21,24 @@ namespace jsipc {
typedef uint64_t ObjectId; typedef uint64_t ObjectId;
class JavaScriptShared;
class CpowIdHolder : public CpowHolder
{
public:
CpowIdHolder(JavaScriptShared *js, const InfallibleTArray<CpowEntry> &cpows)
: js_(js),
cpows_(cpows)
{
}
bool ToObject(JSContext *cx, JSObject **objp);
private:
JavaScriptShared *js_;
const InfallibleTArray<CpowEntry> &cpows_;
};
// Map ids -> JSObjects // Map ids -> JSObjects
class ObjectStore class ObjectStore
{ {
@ -70,6 +88,9 @@ class JavaScriptShared
static const uint32_t OBJECT_EXTRA_BITS = 1; static const uint32_t OBJECT_EXTRA_BITS = 1;
static const uint32_t OBJECT_IS_CALLABLE = (1 << 0); static const uint32_t OBJECT_IS_CALLABLE = (1 << 0);
bool Unwrap(JSContext *cx, const InfallibleTArray<CpowEntry> &aCpows, JSObject **objp);
bool Wrap(JSContext *cx, JS::HandleObject aObj, InfallibleTArray<CpowEntry> *outCpows);
protected: protected:
bool toVariant(JSContext *cx, jsval from, JSVariant *to); bool toVariant(JSContext *cx, jsval from, JSVariant *to);
bool toValue(JSContext *cx, const JSVariant &from, JS::MutableHandleValue to); bool toValue(JSContext *cx, const JSVariant &from, JS::MutableHandleValue to);

Просмотреть файл

@ -139,6 +139,12 @@ js_ObjectClassIs(JSContext *cx, JS::HandleObject obj, js::ESClassValue classValu
JS_FRIEND_API(const char *) JS_FRIEND_API(const char *)
js_ObjectClassName(JSContext *cx, JS::HandleObject obj); js_ObjectClassName(JSContext *cx, JS::HandleObject obj);
JS_FRIEND_API(bool)
js_AddObjectRoot(JSRuntime *rt, JSObject **objp);
JS_FRIEND_API(void)
js_RemoveObjectRoot(JSRuntime *rt, JSObject **objp);
#ifdef DEBUG #ifdef DEBUG
/* /*

Просмотреть файл

@ -1084,6 +1084,18 @@ js::AddScriptRoot(JSContext *cx, JSScript **rp, const char *name)
return AddRoot(cx, rp, name, JS_GC_ROOT_SCRIPT_PTR); return AddRoot(cx, rp, name, JS_GC_ROOT_SCRIPT_PTR);
} }
extern JS_FRIEND_API(bool)
js_AddObjectRoot(JSRuntime *rt, JSObject **objp)
{
return AddRoot(rt, objp, NULL, JS_GC_ROOT_OBJECT_PTR);
}
extern JS_FRIEND_API(void)
js_RemoveObjectRoot(JSRuntime *rt, JSObject **objp)
{
js_RemoveRoot(rt, objp);
}
JS_FRIEND_API(void) JS_FRIEND_API(void)
js_RemoveRoot(JSRuntime *rt, void *rp) js_RemoveRoot(JSRuntime *rt, void *rp)
{ {