Bug 516522 - CPOW: Cross-Process (JavaScript) Object Wrapper. r=mrbkap r=bent sr=jst

This commit is contained in:
Ben Newman 2009-11-06 12:43:39 -08:00
parent 523160aa40
commit b3cb7ea79d
38 changed files with 2372 additions and 18 deletions

View File

@ -43,6 +43,7 @@ interface nsIDocShell;
interface nsIURI;
interface nsIFrame;
interface nsIChromeFrameMessageManager;
interface nsIVariant;
[scriptable, uuid(e511f61f-97db-448a-8b29-a10c470df3fa)]
interface nsIFrameLoader : nsISupports
@ -121,7 +122,7 @@ interface nsIFrameLoader : nsISupports
native alreadyAddRefed_nsFrameLoader(already_AddRefed<nsFrameLoader>);
[scriptable, uuid(8f3b12a0-35ae-4e0d-9152-8e0d7e49d446)]
[scriptable, uuid(5879040e-83e9-40e3-b2bb-5ddf43b76e47)]
interface nsIFrameLoaderOwner : nsISupports
{
/**
@ -130,6 +131,8 @@ interface nsIFrameLoaderOwner : nsISupports
readonly attribute nsIFrameLoader frameLoader;
[noscript, notxpcom] alreadyAddRefed_nsFrameLoader GetFrameLoader();
readonly attribute nsIVariant crossProcessObjectWrapper;
/**
* Swap frame loaders with the given nsIFrameLoaderOwner. This may
* only be posible in a very limited range of circumstances, or

View File

@ -75,6 +75,8 @@
#include "nsIDocShellLoadInfo.h"
#include "nsIBaseWindow.h"
#include "nsContentUtils.h"
#include "nsIXPConnect.h"
#include "nsIJSContextStack.h"
#include "nsUnicharUtils.h"
#include "nsIScriptGlobalObject.h"
#include "nsIScriptSecurityManager.h"
@ -123,6 +125,8 @@ using namespace mozilla;
using namespace mozilla::dom;
#endif
#include "jsapi.h"
class nsAsyncDocShellDestroyer : public nsRunnable
{
public:
@ -1594,6 +1598,24 @@ nsFrameLoader::SendCrossProcessKeyEvent(const nsAString& aType,
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsFrameLoader::GetCrossProcessObjectWrapper(nsIVariant** cpow)
{
nsIXPConnect* xpc;
nsIThreadJSContextStack* stack;
JSContext* cx;
JSObject* global;
if ((xpc = nsContentUtils::XPConnect()) &&
(stack = nsContentUtils::ThreadJSContextStack()) &&
NS_SUCCEEDED(stack->Peek(&cx)) && cx &&
mChildProcess->GetGlobalJSObject(cx, &global)) {
return xpc->JSToVariant(cx, OBJECT_TO_JSVAL(global), cpow);
}
return NS_ERROR_NOT_AVAILABLE;
}
nsresult
nsFrameLoader::CreateStaticClone(nsIFrameLoader* aDest)
{

View File

@ -140,6 +140,7 @@ public:
#ifdef MOZ_IPC
mozilla::dom::PIFrameEmbeddingParent* GetChildProcess();
NS_IMETHOD GetCrossProcessObjectWrapper(nsIVariant** cpow);
#endif
nsFrameMessageManager* GetFrameMessageManager() { return mMessageManager; }

View File

@ -795,6 +795,12 @@ nsObjectLoadingContent::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherLoader)
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsObjectLoadingContent::GetCrossProcessObjectWrapper(nsIVariant**)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
// nsIObjectLoadingContent
NS_IMETHODIMP
nsObjectLoadingContent::GetActualType(nsACString& aType)

View File

@ -2775,6 +2775,13 @@ nsGenericHTMLFrameElement::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner)
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsGenericHTMLFrameElement::GetCrossProcessObjectWrapper(nsIVariant**)
{
// We don't support this yet
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult
nsGenericHTMLFrameElement::LoadSrc()
{

View File

@ -2003,6 +2003,12 @@ nsXULElement::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner)
otherSlots->mFrameLoader);
}
NS_IMETHODIMP
nsXULElement::GetCrossProcessObjectWrapper(nsIVariant** cpow)
{
nsRefPtr<nsFrameLoader> frameLoader(GetFrameLoader());
return frameLoader->GetCrossProcessObjectWrapper(cpow);
}
NS_IMETHODIMP
nsXULElement::GetParentTree(nsIDOMXULMultiSelectControlElement** aTreeElement)

View File

@ -563,6 +563,8 @@ public:
already_AddRefed<nsFrameLoader> GetFrameLoader();
nsresult SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner);
NS_IMETHOD GetCrossProcessObjectWrapper(nsIVariant** cpow);
virtual void RecompileScriptEventListeners();
// This function should ONLY be used by BindToTree implementations.

View File

@ -45,6 +45,8 @@
#include "mozilla/ipc/TestShellChild.h"
#include "mozilla/net/NeckoChild.h"
#include "mozilla/ipc/XPCShellEnvironment.h"
#include "mozilla/jsipc/PContextWrapperChild.h"
#include "nsXULAppAPI.h"
@ -131,6 +133,13 @@ ContentProcessChild::DeallocPTestShell(PTestShellChild* shell)
return true;
}
bool
ContentProcessChild::RecvPTestShellConstructor(PTestShellChild* actor)
{
actor->SendPContextWrapperConstructor()->SendPObjectWrapperConstructor(true);
return true;
}
PNeckoChild*
ContentProcessChild::AllocPNecko()
{

View File

@ -78,6 +78,7 @@ public:
virtual PTestShellChild* AllocPTestShell();
virtual bool DeallocPTestShell(PTestShellChild*);
virtual bool RecvPTestShellConstructor(PTestShellChild*);
virtual PNeckoChild* AllocPNecko();
virtual bool DeallocPNecko(PNeckoChild*);

View File

@ -40,6 +40,7 @@
include protocol "PContentProcess.ipdl";
include protocol "PDocumentRenderer.ipdl";
include protocol "PDocumentRendererShmem.ipdl";
include protocol "PContextWrapper.ipdl";
include "mozilla/TabTypes.h";
include "TabMessageUtils.h";
@ -57,6 +58,7 @@ rpc protocol PIFrameEmbedding
manager PContentProcess;
manages PDocumentRenderer;
manages PDocumentRendererShmem;
manages PContextWrapper;
child:
__delete__();
@ -72,6 +74,8 @@ parent:
rpc createWindow() returns (PIFrameEmbedding window);
PContextWrapper();
sync sendSyncMessageToParent(nsString aMessage, nsString aJSON) returns (nsString[] retval);
sendAsyncMessageToParent(nsString aMessage, nsString aJSON);
child:

View File

@ -37,6 +37,8 @@
* ***** END LICENSE BLOCK ***** */
#include "TabChild.h"
#include "mozilla/dom/PContentProcessChild.h"
#include "mozilla/jsipc/ContextWrapperChild.h"
#include "nsIWebBrowser.h"
#include "nsEmbedCID.h"
@ -68,6 +70,8 @@
#include "nsPIWindowRoot.h"
#include "nsIScriptContext.h"
#include "nsPresContext.h"
#include "nsIDocument.h"
#include "nsIScriptGlobalObject.h"
#ifdef MOZ_WIDGET_QT
#include <QX11EmbedWidget>
@ -81,6 +85,7 @@
#endif
using namespace mozilla::dom;
using namespace mozilla::jsipc;
NS_IMPL_ISUPPORTS1(ContentListener, nsIDOMEventListener)
@ -375,6 +380,9 @@ TabChild::RecvloadURL(const nsCString& uri)
if (NS_FAILED(rv)) {
NS_WARNING("mWebNav->LoadURI failed. Eating exception, what else can I do?");
}
SendPContextWrapperConstructor()->SendPObjectWrapperConstructor(true);
return true;
}
@ -433,6 +441,37 @@ TabChild::RecvsendKeyEvent(const nsString& aType,
return true;
}
static JSContext*
GetJSContextFrom(nsIWebNavigation* webNav)
{
nsCOMPtr<nsIDOMDocument> domDocument;
nsCOMPtr<nsIDocument> document;
nsCOMPtr<nsIScriptGlobalObject> global;
nsCOMPtr<nsIScriptContext> context;
if (NS_SUCCEEDED(webNav->GetDocument(getter_AddRefs(domDocument))) &&
(document = do_QueryInterface(domDocument)) &&
(global = do_QueryInterface(document->GetScriptGlobalObject())) &&
(context = do_QueryInterface(global->GetContext()))) {
return static_cast<JSContext*>(context->GetNativeContext());
}
return NULL;
}
PContextWrapperChild*
TabChild::AllocPContextWrapper()
{
return new ContextWrapperChild(GetJSContextFrom(mWebNav));
}
bool
TabChild::DeallocPContextWrapper(PContextWrapperChild* actor)
{
delete actor;
return true;
}
mozilla::ipc::PDocumentRendererChild*
TabChild::AllocPDocumentRenderer(
const PRInt32& x,

View File

@ -69,6 +69,11 @@
class gfxMatrix;
namespace mozilla {
namespace jsipc {
class PContextWrapperChild;
}
namespace dom {
class TabChild;
@ -228,6 +233,10 @@ public:
JSContext* GetJSContext() { return mCx; }
nsIPrincipal* GetPrincipal() { return mPrincipal; }
virtual PContextWrapperChild* AllocPContextWrapper();
virtual bool DeallocPContextWrapper(PContextWrapperChild* actor);
private:
bool InitTabChildGlobal();

View File

@ -40,6 +40,7 @@
#include "mozilla/ipc/DocumentRendererParent.h"
#include "mozilla/ipc/DocumentRendererShmemParent.h"
#include "mozilla/jsipc/ContextWrapperParent.h"
#include "nsIURI.h"
#include "nsFocusManager.h"
@ -54,6 +55,8 @@
using mozilla::ipc::DocumentRendererParent;
using mozilla::ipc::DocumentRendererShmemParent;
using mozilla::jsipc::PContextWrapperParent;
using mozilla::jsipc::ContextWrapperParent;
namespace mozilla {
namespace dom {
@ -173,6 +176,32 @@ TabParent::DeallocPDocumentRendererShmem(PDocumentRendererShmemParent* actor)
return true;
}
PContextWrapperParent*
TabParent::AllocPContextWrapper()
{
return new ContextWrapperParent();
}
bool
TabParent::DeallocPContextWrapper(PContextWrapperParent* actor)
{
delete actor;
return true;
}
bool
TabParent::GetGlobalJSObject(JSContext* cx, JSObject** globalp)
{
// TODO Unify this code with TestShellParent::GetGlobalJSObject.
nsTArray<PContextWrapperParent*> cwps(1);
ManagedPContextWrapperParent(cwps);
if (cwps.Length() < 1)
return false;
NS_ASSERTION(cwps.Length() == 1, "More than one PContextWrapper?");
ContextWrapperParent* cwp = static_cast<ContextWrapperParent*>(cwps[0]);
return (cwp->GetGlobalJSObject(cx, globalp));
}
void
TabParent::SendMouseEvent(const nsAString& aType, float aX, float aY,
PRInt32 aButton, PRInt32 aClickCount,

View File

@ -50,7 +50,15 @@ class nsIURI;
class nsIDOMElement;
class gfxMatrix;
struct JSContext;
struct JSObject;
namespace mozilla {
namespace jsipc {
class PContextWrapperParent;
}
namespace dom {
class TabParent : public PIFrameEmbeddingParent
@ -106,6 +114,11 @@ public:
Shmem& buf);
virtual bool DeallocPDocumentRendererShmem(PDocumentRendererShmemParent* actor);
virtual PContextWrapperParent* AllocPContextWrapper();
virtual bool DeallocPContextWrapper(PContextWrapperParent* actor);
bool GetGlobalJSObject(JSContext* cx, JSObject** globalp);
protected:
nsIDOMElement* mFrameElement;
nsCOMPtr<nsIBrowserDOMWindow> mBrowserDOMWindow;

View File

@ -60,6 +60,7 @@ IPDLDIRS = \
netwerk/protocol/http/src \
ipc/ipdl/test/cxx \
ipc/testshell \
js/src/ipc \
$(NULL)
##-----------------------------------------------------------------------------

View File

@ -37,15 +37,17 @@
include protocol "PContentProcess.ipdl";
include protocol "PTestShellCommand.ipdl";
include protocol "PContextWrapper.ipdl";
namespace mozilla {
namespace ipc {
protocol PTestShell
rpc protocol PTestShell
{
manager PContentProcess;
manages PTestShellCommand;
manages PContextWrapper;
child:
__delete__();
@ -53,6 +55,10 @@ child:
ExecuteCommand(nsString aCommand);
PTestShellCommand(nsString aCommand);
parent:
PContextWrapper();
};
} // namespace ipc

View File

@ -35,10 +35,13 @@
* ***** END LICENSE BLOCK ***** */
#include "TestShellChild.h"
#include "mozilla/jsipc/ContextWrapperChild.h"
using mozilla::ipc::TestShellChild;
using mozilla::ipc::PTestShellCommandChild;
using mozilla::ipc::XPCShellEnvironment;
using mozilla::jsipc::PContextWrapperChild;
using mozilla::jsipc::ContextWrapperChild;
TestShellChild::TestShellChild()
: mXPCShell(XPCShellEnvironment::CreateEnvironment())
@ -85,3 +88,20 @@ TestShellChild::RecvPTestShellCommandConstructor(PTestShellCommandChild* aActor,
return PTestShellCommandChild::Send__delete__(aActor, response);
}
PContextWrapperChild*
TestShellChild::AllocPContextWrapper()
{
JSContext* cx;
if (mXPCShell && (cx = mXPCShell->GetContext())) {
return new ContextWrapperChild(cx);
}
return NULL;
}
bool
TestShellChild::DeallocPContextWrapper(PContextWrapperChild* actor)
{
delete actor;
return true;
}

View File

@ -44,6 +44,11 @@
#include "nsAutoPtr.h"
namespace mozilla {
namespace jsipc {
class PContextWrapperChild;
}
namespace ipc {
class XPCShellEnvironment;
@ -66,10 +71,9 @@ public:
bool
DeallocPTestShellCommand(PTestShellCommandChild* aCommand);
void SetXPCShell(XPCShellEnvironment* aXPCShell) {
mXPCShell = aXPCShell;
}
PContextWrapperChild* AllocPContextWrapper();
bool DeallocPContextWrapper(PContextWrapperChild* actor);
private:
nsAutoPtr<XPCShellEnvironment> mXPCShell;
};

View File

@ -35,12 +35,15 @@
* ***** END LICENSE BLOCK ***** */
#include "TestShellParent.h"
#include "mozilla/jsipc/ContextWrapperParent.h"
#include "nsAutoPtr.h"
using mozilla::ipc::TestShellParent;
using mozilla::ipc::TestShellCommandParent;
using mozilla::ipc::PTestShellCommandParent;
using mozilla::jsipc::PContextWrapperParent;
using mozilla::jsipc::ContextWrapperParent;
PTestShellCommandParent*
TestShellParent::AllocPTestShellCommand(const nsString& aCommand)
@ -66,6 +69,32 @@ TestShellParent::CommandDone(TestShellCommandParent* command,
return true;
}
PContextWrapperParent*
TestShellParent::AllocPContextWrapper()
{
return new ContextWrapperParent();
}
bool
TestShellParent::DeallocPContextWrapper(PContextWrapperParent* actor)
{
delete actor;
return true;
}
bool
TestShellParent::GetGlobalJSObject(JSContext* cx, JSObject** globalp)
{
// TODO Unify this code with TabParent::GetGlobalJSObject.
nsTArray<PContextWrapperParent*> cwps(1);
ManagedPContextWrapperParent(cwps);
if (cwps.Length() < 1)
return false;
NS_ASSERTION(cwps.Length() == 1, "More than one PContextWrapper?");
ContextWrapperParent* cwp = static_cast<ContextWrapperParent*>(cwps[0]);
return (cwp->GetGlobalJSObject(cx, globalp));
}
JSBool
TestShellCommandParent::SetCallback(JSContext* aCx,
jsval aCallback)

View File

@ -47,12 +47,19 @@
#include "nsAutoJSValHolder.h"
#include "nsStringGlue.h"
struct JSContext;
struct JSObject;
namespace mozilla {
namespace jsipc {
class PContextWrapperParent;
}
namespace ipc {
class TestShellCommandParent;
class TestShellParent : public PTestShellParent
{
public:
@ -64,6 +71,11 @@ public:
bool
CommandDone(TestShellCommandParent* aActor, const nsString& aResponse);
PContextWrapperParent* AllocPContextWrapper();
bool DeallocPContextWrapper(PContextWrapperParent* actor);
bool GetGlobalJSObject(JSContext* cx, JSObject** globalp);
};

View File

@ -73,6 +73,10 @@ public:
return mGlobalHolder.ToJSObject();
}
JSContext* GetContext() {
return mCx;
}
void SetExitCode(int aExitCode) {
mExitCode = aExitCode;
}
@ -129,4 +133,4 @@ private:
} /* namespace ipc */
} /* namespace mozilla */
#endif /* _IPC_TESTSHELL_XPCSHELLENVIRONMENT_H_ */
#endif /* _IPC_TESTSHELL_XPCSHELLENVIRONMENT_H_ */

101
js/src/ipc/CPOWTypes.h Normal file
View File

@ -0,0 +1,101 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=80:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Newman <b{enjam,newma}n@mozilla.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef mozilla_jsipc_ContextWrapperTypes_h__
#define mozilla_jsipc_ContextWrapperTypes_h__
#include "jsapi.h"
#include "jspubtd.h"
namespace mozilla {
namespace jsipc {
using namespace IPC;
struct void_t {};
template <typename P>
struct CPOWSingleton
{
static void Write(Message*, const P&) {}
static bool Read(const Message*, void**, P*) { return true; }
};
template <typename Type, typename As>
struct CPOWConvertible
{
static void Write(Message* m, const Type& t) {
WriteParam(m, As(t));
}
static bool Read(const Message* m, void** iter, Type* tp) {
As a;
return (ReadParam(m, iter, &a) &&
(*tp = Type(a), true));
}
};
} // namespace jsipc
} // namespace mozilla
namespace IPC {
using namespace mozilla::jsipc;
template <> struct ParamTraits<void_t> : public CPOWSingleton<void_t> {};
template <> struct ParamTraits<JSType> : public CPOWConvertible<JSType, int> {};
}
// TODO Use a more standard logging mechanism.
#ifdef LOGGING
#define CPOW_LOG(PRINTF_ARGS) \
JS_BEGIN_MACRO \
printf("CPOW | "); \
printf PRINTF_ARGS ; \
printf("\n"); \
JS_END_MACRO
#define JSVAL_TO_CSTR(CX, V) \
NS_ConvertUTF16toUTF8(nsString(JS_GetStringChars(JS_ValueToString(CX, V)))).get()
#else
#define CPOW_LOG(_) JS_BEGIN_MACRO JS_END_MACRO
#define JSVAL_TO_CSTR(CX, V) ((char*)0)
#endif
#endif

View File

@ -0,0 +1,111 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=80:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Newman <b{enjam,newma}n@mozilla.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef mozilla_jsipc_ContextWrapperChild_h__
#define mozilla_jsipc_ContextWrapperChild_h__
#include "mozilla/jsipc/PContextWrapperChild.h"
#include "mozilla/jsipc/ObjectWrapperChild.h"
#include "jsapi.h"
#include "nsClassHashtable.h"
#include "nsHashKeys.h"
namespace mozilla {
namespace jsipc {
class ContextWrapperChild
: public PContextWrapperChild
{
public:
ContextWrapperChild(JSContext* cx)
: mContext(cx)
{
mResidentObjectTable.Init();
}
JSContext* GetContext() { return mContext; }
PObjectWrapperChild* GetOrCreateWrapper(JSObject* obj,
bool makeGlobal = false)
{
if (!obj) // Don't wrap nothin'!
return NULL;
PObjectWrapperChild* wrapper;
while (!mResidentObjectTable.Get(obj, &wrapper)) {
wrapper = SendPObjectWrapperConstructor(AllocPObjectWrapper(obj),
makeGlobal);
if (wrapper)
mResidentObjectTable.Put(obj, wrapper);
else
return NULL;
}
return wrapper;
}
protected:
PObjectWrapperChild* AllocPObjectWrapper(JSObject* obj) {
return new ObjectWrapperChild(mContext, obj);
}
PObjectWrapperChild* AllocPObjectWrapper(const bool&) {
return AllocPObjectWrapper(JS_GetGlobalObject(mContext));
}
bool DeallocPObjectWrapper(PObjectWrapperChild* actor) {
ObjectWrapperChild* owc = static_cast<ObjectWrapperChild*>(actor);
mResidentObjectTable.Remove(owc->GetJSObject());
return true;
}
private:
JSContext* const mContext;
nsClassHashtable<nsPtrHashKey<JSObject>,
PObjectWrapperChild> mResidentObjectTable;
};
}}
#endif

View File

@ -0,0 +1,106 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=80:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Newman <b{enjam,newma}n@mozilla.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef mozilla_jsipc_ContextWrapperParent_h__
#define mozilla_jsipc_ContextWrapperParent_h__
#include "mozilla/jsipc/PContextWrapperParent.h"
#include "mozilla/jsipc/ObjectWrapperParent.h"
#include "jsapi.h"
#include "nsAutoJSValHolder.h"
namespace mozilla {
namespace jsipc {
class ContextWrapperParent
: public PContextWrapperParent
{
public:
ContextWrapperParent() : mGlobal(NULL) {}
bool GetGlobalJSObject(JSContext* cx, JSObject** globalp) {
if (!mGlobal)
return false;
mGlobalHolder.Hold(cx);
mGlobalHolder = *globalp = mGlobal->GetJSObject(cx);
return true;
}
ObjectWrapperParent* GetGlobalObjectWrapper() const {
return mGlobal;
}
private:
ObjectWrapperParent* mGlobal;
nsAutoJSValHolder mGlobalHolder;
PObjectWrapperParent* AllocPObjectWrapper(const bool&) {
return new ObjectWrapperParent();
}
bool RecvPObjectWrapperConstructor(PObjectWrapperParent* actor,
const bool& makeGlobal)
{
if (makeGlobal) {
mGlobalHolder.Release();
mGlobal = static_cast<ObjectWrapperParent*>(actor);
}
return true;
}
bool DeallocPObjectWrapper(PObjectWrapperParent* actor)
{
if (mGlobal &&
mGlobal == static_cast<ObjectWrapperParent*>(actor)) {
mGlobalHolder.Release();
mGlobal = NULL;
}
delete actor;
return true;
}
};
}}
#endif

70
js/src/ipc/Makefile.in Normal file
View File

@ -0,0 +1,70 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# The Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2010
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Ben Newman <b{enjam,newma}n@mozilla.com> (original author)
#
# Alternatively, the contents of this file may be used under the terms of
# either of the GNU General Public License Version 2 or later (the "GPL"),
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = js
LIBRARY_NAME = jsipc_s
LIBXUL_LIBRARY = 1
FORCE_STATIC_LIB = 1
EXPORT_LIBRARY = 1
EXPORTS_NAMESPACES = mozilla/jsipc
EXPORTS_mozilla/jsipc = \
CPOWTypes.h \
ContextWrapperChild.h \
ContextWrapperParent.h \
ObjectWrapperParent.h \
ObjectWrapperChild.h \
$(NULL)
CPPSRCS = \
ObjectWrapperParent.cpp \
ObjectWrapperChild.cpp \
$(NULL)
include $(topsrcdir)/config/config.mk
include $(topsrcdir)/ipc/chromium/chromium-config.mk
include $(topsrcdir)/config/rules.mk
DEFINES += -DBIN_SUFFIX='"$(BIN_SUFFIX)"'

View File

@ -0,0 +1,558 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=80:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Newman <b{enjam,newma}n@mozilla.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "base/basictypes.h"
#include "jscntxt.h"
#include "mozilla/jsipc/ContextWrapperChild.h"
#include "mozilla/jsipc/ObjectWrapperChild.h"
#include "mozilla/jsipc/CPOWTypes.h"
#include "nsTArray.h"
using namespace mozilla::jsipc;
ObjectWrapperChild::ObjectWrapperChild(JSContext* cx, JSObject* obj)
: mObj(obj)
{
JSAutoRequest request(cx);
#ifdef DEBUG
bool added =
#endif
JS_AddNamedRoot(cx, (void*)&mObj,
"mozilla::jsipc::ObjectWrapperChild-rooted JSObject*");
NS_ASSERTION(added, "ObjectWrapperChild constructor failed to root JSObject*");
}
void
ObjectWrapperChild::ActorDestroy(ActorDestroyReason why)
{
JSContext* cx = Manager()->GetContext();
JSAutoRequest request(cx);
JS_RemoveRoot(cx, (void*)&mObj);
}
bool
ObjectWrapperChild::JSObject_to_JSVariant(JSContext* cx, JSObject* from,
JSVariant* to)
{
*to = Manager()->GetOrCreateWrapper(from);
return true;
}
bool
ObjectWrapperChild::jsval_to_JSVariant(JSContext* cx, jsval from, JSVariant* to)
{
switch (JS_TypeOfValue(cx, from)) {
case JSTYPE_VOID:
*to = void_t();
return true;
case JSTYPE_NULL:
if (from != JSVAL_NULL)
return false;
// fall through
case JSTYPE_FUNCTION:
// fall through
case JSTYPE_OBJECT:
return JSObject_to_JSVariant(cx, JSVAL_TO_OBJECT(from), to);
case JSTYPE_STRING:
*to = nsDependentString((PRUnichar*)JS_GetStringChars(JSVAL_TO_STRING(from)),
JS_GetStringLength(JSVAL_TO_STRING(from)));
return true;
case JSTYPE_NUMBER:
if (JSVAL_IS_INT(from))
*to = JSVAL_TO_INT(from);
else if (JSVAL_IS_DOUBLE(from))
*to = *JSVAL_TO_DOUBLE(from);
else return false;
return true;
case JSTYPE_BOOLEAN:
*to = !!JSVAL_TO_BOOLEAN(from);
return true;
case JSTYPE_XML:
// fall through
default:
return false;
}
}
/*static*/ bool
ObjectWrapperChild::
JSObject_from_PObjectWrapperChild(JSContext*,
const PObjectWrapperChild* from,
JSObject** to)
{
const ObjectWrapperChild* owc =
static_cast<const ObjectWrapperChild*>(from);
*to = owc ? owc->mObj : JSVAL_NULL;
return true;
}
/*static*/ bool
ObjectWrapperChild::JSObject_from_JSVariant(JSContext* cx,
const JSVariant& from,
JSObject** to)
{
if (from.type() != JSVariant::TPObjectWrapperChild)
return false;
return JSObject_from_PObjectWrapperChild(cx,
from.get_PObjectWrapperChild(),
to);
}
/*static*/ bool
ObjectWrapperChild::jsval_from_JSVariant(JSContext* cx, const JSVariant& from,
jsval* to)
{
switch (from.type()) {
case JSVariant::Tvoid_t:
*to = JSVAL_VOID;
return true;
case JSVariant::TPObjectWrapperChild:
{
JSObject* obj;
if (!JSObject_from_JSVariant(cx, from, &obj))
return false;
*to = OBJECT_TO_JSVAL(obj);
return true;
}
case JSVariant::TnsString:
{
const nsString& str = from.get_nsString();
JSString* s = JS_NewUCStringCopyN(cx,
str.BeginReading(),
str.Length());
if (!s)
return false;
*to = STRING_TO_JSVAL(s);
}
return true;
case JSVariant::Tint:
*to = INT_TO_JSVAL(from.get_int());
return true;
case JSVariant::Tdouble:
return !!JS_NewDoubleValue(cx, from.get_double(), to);
case JSVariant::Tbool:
*to = BOOLEAN_TO_JSVAL(from.get_bool());
return true;
default:
return false;
}
}
ContextWrapperChild*
ObjectWrapperChild::Manager()
{
PContextWrapperChild* pcwc = PObjectWrapperChild::Manager();
return static_cast<ContextWrapperChild*>(pcwc);
}
static bool
jsid_to_nsString(JSContext* cx, jsid from, nsString* to)
{
jsval v;
if (JS_IdToValue(cx, from, &v) && JSVAL_IS_STRING(v)) {
*to = nsDependentString((PRUnichar*)JS_GetStringChars(JSVAL_TO_STRING(v)),
JS_GetStringLength(JSVAL_TO_STRING(v)));
return true;
}
return false;
}
static bool
jsid_from_nsString(JSContext* cx, const nsString& from, jsid* to)
{
JSString* str = JS_NewUCStringCopyN(cx, from.BeginReading(), from.Length());
if (!str)
return false;
return JS_ValueToId(cx, STRING_TO_JSVAL(str), to);
}
#if 0
// The general schema for ObjectWrapperChild::Answer* methods:
bool
ObjectWrapperChild::AnswerSomething(/* in-parameters */
/* out-parameters */)
{
// initialize out-parameters for failure
JSAutoRequest request(Manager()->GetContext());
// validate in-parameters, else return false
// successfully perform local JS operations, else return true
// perform out-parameter conversions, else return false
return true;
}
// There's an important subtlety here: though a local JS operation may
// fail, leaving out-parameters uninitialized, we must initialize all
// out-parameters when reporting success (returning true) to the IPC
// messaging system. See AnswerGetProperty for illustration.
#endif
bool
ObjectWrapperChild::AnswerAddProperty(const nsString& id,
JSBool* ok)
{
jsid interned_id;
*ok = JS_FALSE;
JSContext* cx = Manager()->GetContext();
JSAutoRequest request(cx);
if (!jsid_from_nsString(cx, id, &interned_id))
return false;
*ok = JS_DefinePropertyById(cx, mObj, interned_id, JSVAL_VOID,
NULL, NULL, 0);
return true;
}
bool
ObjectWrapperChild::AnswerGetProperty(const nsString& id,
JSBool* ok, JSVariant* vp)
{
jsid interned_id;
jsval val;
*ok = JS_FALSE;
JSContext* cx = Manager()->GetContext();
JSAutoRequest request(cx);
if (!jsid_from_nsString(cx, id, &interned_id))
return false;
*ok = JS_GetPropertyById(cx, mObj, interned_id, &val);
// Since we fully expect this call to jsval_to_JSVariant to return
// true, we can't just leave vp uninitialized when JS_GetPropertyById
// returns JS_FALSE. This pitfall could be avoided in general if IPDL
// ensured that outparams were pre-initialized to some default value
// (XXXfixme cjones?).
return jsval_to_JSVariant(cx, *ok ? val : JSVAL_VOID, vp);
}
bool
ObjectWrapperChild::AnswerSetProperty(const nsString& id, const JSVariant& v,
JSBool* ok, JSVariant* vp)
{
jsid interned_id;
jsval val;
*ok = JS_FALSE;
*vp = v;
JSContext* cx = Manager()->GetContext();
JSAutoRequest request(cx);
if (!jsid_from_nsString(cx, id, &interned_id) ||
!jsval_from_JSVariant(cx, v, &val))
return false;
*ok = JS_SetPropertyById(cx, mObj, interned_id, &val);
return jsval_to_JSVariant(cx, *ok ? val : JSVAL_VOID, vp);
}
bool
ObjectWrapperChild::AnswerDelProperty(const nsString& id,
JSBool* ok, JSVariant* vp)
{
jsid interned_id;
jsval val;
*ok = JS_FALSE;
JSContext* cx = Manager()->GetContext();
JSAutoRequest request(cx);
if (!jsid_from_nsString(cx, id, &interned_id))
return false;
*ok = JS_DeletePropertyById2(cx, mObj, interned_id, &val);
return jsval_to_JSVariant(cx, *ok ? val : JSVAL_VOID, vp);
}
static const PRUint32 sNextIdIndexSlot = 0;
static const PRUint32 sNumNewEnumerateStateSlots = 1;
static void
CPOW_NewEnumerateState_Finalize(JSContext* cx, JSObject* state)
{
nsTArray<nsString>* strIds =
static_cast<nsTArray<nsString>*>(JS_GetPrivate(cx, state));
if (strIds) {
delete strIds;
JS_SetPrivate(cx, state, NULL);
}
}
// Similar to IteratorClass in XPCWrapper.cpp
static const JSClass sCPOW_NewEnumerateState_JSClass = {
"CPOW NewEnumerate State",
JSCLASS_HAS_PRIVATE |
JSCLASS_HAS_RESERVED_SLOTS(sNumNewEnumerateStateSlots),
JS_PropertyStub, JS_PropertyStub,
JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub,
JS_ConvertStub, CPOW_NewEnumerateState_Finalize,
JSCLASS_NO_OPTIONAL_MEMBERS
};
bool
ObjectWrapperChild::AnswerNewEnumerateInit(/* no in-parameters */
JSBool* ok, JSVariant* statep, int* idp)
{
*ok = JS_FALSE;
*idp = 0;
JSContext* cx = Manager()->GetContext();
JSAutoRequest request(cx);
JSClass* clasp = const_cast<JSClass*>(&sCPOW_NewEnumerateState_JSClass);
JSObject* state = JS_NewObjectWithGivenProto(cx, clasp, NULL, NULL);
if (!state)
return false;
JSAutoTempValueRooter tvr(cx, state);
for (JSObject* proto = mObj;
proto;
proto = JS_GetPrototype(cx, proto))
{
JSAutoIdArray ids(cx, JS_Enumerate(cx, proto));
for (uint i = 0; i < ids.length(); ++i)
JS_DefinePropertyById(cx, state, ids[i], JSVAL_VOID,
NULL, NULL, JSPROP_ENUMERATE | JSPROP_SHARED);
}
nsTArray<nsString>* strIds;
{
JSAutoIdArray ids(cx, JS_Enumerate(cx, state));
if (!ids)
return false;
strIds = new nsTArray<nsString>(ids.length());
for (uint i = 0; i < ids.length(); ++i)
if (!jsid_to_nsString(cx, ids[i], strIds->AppendElement())) {
delete strIds;
return false;
}
}
*idp = strIds->Length();
*ok = (JS_SetPrivate(cx, state, strIds) &&
JS_SetReservedSlot(cx, state, sNextIdIndexSlot,
JSVAL_ZERO) &&
JSObject_to_JSVariant(cx, state, statep));
return true;
}
bool
ObjectWrapperChild::AnswerNewEnumerateNext(const JSVariant& in_state,
JSBool* ok, JSVariant* statep, nsString* idp)
{
JSObject* state;
jsval v;
*ok = JS_FALSE;
*statep = in_state;
idp->Truncate();
JSContext* cx = Manager()->GetContext();
JSAutoRequest request(cx);
if (!JSObject_from_JSVariant(cx, in_state, &state))
return false;
nsTArray<nsString>* strIds =
static_cast<nsTArray<nsString>*>(JS_GetPrivate(cx, state));
if (!strIds || !JS_GetReservedSlot(cx, state, sNextIdIndexSlot, &v))
return false;
jsint i = JSVAL_TO_INT(v);
NS_ASSERTION(i >= 0, "Index of next jsid negative?");
NS_ASSERTION(i <= strIds->Length(), "Index of next jsid too large?");
if (i == strIds->Length()) {
*ok = JS_TRUE;
return JSObject_to_JSVariant(cx, NULL, statep);
}
*idp = strIds->ElementAt(i);
*ok = JS_SetReservedSlot(cx, state, sNextIdIndexSlot,
INT_TO_JSVAL(i + 1));
return true;
}
bool
ObjectWrapperChild::RecvNewEnumerateDestroy(const JSVariant& in_state)
{
JSObject* state;
JSContext* cx = Manager()->GetContext();
JSAutoRequest request(cx);
if (!JSObject_from_JSVariant(cx, in_state, &state))
return false;
CPOW_NewEnumerateState_Finalize(cx, state);
return true;
}
bool
ObjectWrapperChild::AnswerNewResolve(const nsString& id, const int& flags,
JSBool* ok, PObjectWrapperChild** obj2)
{
jsid interned_id;
*ok = JS_FALSE;
*obj2 = NULL;
JSContext* cx = Manager()->GetContext();
JSAutoRequest request(cx);
if (!jsid_from_nsString(cx, id, &interned_id))
return false;
CPOW_LOG(("new-resolving \"%s\"...",
NS_ConvertUTF16toUTF8(id).get()));
JSPropertyDescriptor desc;
if (!JS_GetPropertyDescriptorById(cx, mObj, interned_id, flags, &desc))
return true;
*ok = JS_TRUE;
if (desc.obj)
*obj2 = Manager()->GetOrCreateWrapper(desc.obj);
return true;
}
bool
ObjectWrapperChild::AnswerConvert(const JSType& type,
JSBool* ok, JSVariant* vp)
{
jsval v;
JSContext* cx = Manager()->GetContext();
JSAutoRequest request(cx);
*ok = JS_ConvertValue(cx, OBJECT_TO_JSVAL(mObj), type, &v);
return jsval_to_JSVariant(cx, *ok ? v : JSVAL_VOID, vp);
}
namespace {
// Should be an overestimate of typical JS function arity.
typedef nsAutoTArray<jsval, 5> AutoJSArgs;
}
bool
ObjectWrapperChild::AnswerCall(PObjectWrapperChild* receiver, const nsTArray<JSVariant>& argv,
JSBool* ok, JSVariant* rval)
{
*ok = JS_FALSE;
JSContext* cx = Manager()->GetContext();
JSAutoRequest request(cx);
JSObject* obj;
if (!JSObject_from_PObjectWrapperChild(cx, receiver, &obj))
return false;
AutoJSArgs args;
PRUint32 argc = argv.Length();
jsval *jsargs = args.AppendElements(argc);
if (!jsargs)
return false;
JSAutoTempValueRooter tvr(cx, argc, jsargs);
for (PRUint32 i = 0; i < argc; ++i)
if (!jsval_from_JSVariant(cx, argv.ElementAt(i), jsargs + i))
return false;
jsval rv;
*ok = JS_CallFunctionValue(cx, obj, OBJECT_TO_JSVAL(mObj),
argv.Length(), jsargs, &rv);
return jsval_to_JSVariant(cx, *ok ? rv : JSVAL_VOID, rval);
}
bool
ObjectWrapperChild::AnswerConstruct(const nsTArray<JSVariant>& argv,
JSBool* ok, PObjectWrapperChild** rval)
{
*ok = JS_FALSE;
JSContext* cx = Manager()->GetContext();
JSAutoRequest request(cx);
AutoJSArgs args;
PRUint32 argc = argv.Length();
jsval* jsargs = args.AppendElements(argc);
if (!jsargs)
return false;
JSAutoTempValueRooter tvr(cx, argc, jsargs);
for (PRUint32 i = 0; i < argc; ++i)
if (!jsval_from_JSVariant(cx, argv.ElementAt(i), jsargs + i))
return false;
JSObject* obj = JS_New(cx, mObj, argc, jsargs);
*ok = !!obj;
*rval = Manager()->GetOrCreateWrapper(obj);
return true;
}
bool
ObjectWrapperChild::AnswerHasInstance(const JSVariant& v,
JSBool* ok, JSBool* bp)
{
jsval candidate;
JSContext* cx = Manager()->GetContext();
JSAutoRequest request(cx);
if (!jsval_from_JSVariant(cx, v, &candidate))
return false;
*ok = JS_HasInstance(cx, mObj, candidate, bp);
return true;
}

View File

@ -0,0 +1,121 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=80:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Newman <b{enjam,newma}n@mozilla.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef mozilla_jsipc_ObjectWrapperChild_h__
#define mozilla_jsipc_ObjectWrapperChild_h__
#include "mozilla/jsipc/PObjectWrapperChild.h"
using mozilla::jsipc::JSVariant;
namespace mozilla {
namespace jsipc {
class ContextWrapperChild;
class ObjectWrapperChild
: public PObjectWrapperChild
{
public:
ObjectWrapperChild(JSContext* cx, JSObject* obj);
JSObject* GetJSObject() const { return mObj; }
private:
JSObject* const mObj;
bool JSObject_to_JSVariant(JSContext* cx, JSObject* from, JSVariant* to);
bool jsval_to_JSVariant(JSContext* cx, jsval from, JSVariant* to);
static bool JSObject_from_PObjectWrapperChild(JSContext* cx,
const PObjectWrapperChild* from,
JSObject** to);
static bool JSObject_from_JSVariant(JSContext* cx, const JSVariant& from,
JSObject** to);
static bool jsval_from_JSVariant(JSContext* cx, const JSVariant& from,
jsval* to);
ContextWrapperChild* Manager();
protected:
void ActorDestroy(ActorDestroyReason why);
bool AnswerAddProperty(const nsString& id,
JSBool* ok);
bool AnswerGetProperty(const nsString& id,
JSBool* ok, JSVariant* vp);
bool AnswerSetProperty(const nsString& id, const JSVariant& v,
JSBool* ok, JSVariant* vp);
bool AnswerDelProperty(const nsString& id,
JSBool* ok, JSVariant* vp);
bool AnswerNewEnumerateInit(/* no in-parameters */
JSBool* ok, JSVariant* statep, int* idp);
bool AnswerNewEnumerateNext(const JSVariant& in_state,
JSBool* ok, JSVariant* statep, nsString* idp);
bool RecvNewEnumerateDestroy(const JSVariant& in_state);
bool AnswerNewResolve(const nsString& id, const int& flags,
JSBool* ok, PObjectWrapperChild** obj2);
bool AnswerConvert(const JSType& type,
JSBool* ok, JSVariant* vp);
bool AnswerCall(PObjectWrapperChild* receiver, const nsTArray<JSVariant>& argv,
JSBool* ok, JSVariant* rval);
bool AnswerConstruct(const nsTArray<JSVariant>& argv,
JSBool* ok, PObjectWrapperChild** rval);
bool AnswerHasInstance(const JSVariant& v,
JSBool* ok, JSBool* bp);
};
}}
#endif

View File

@ -0,0 +1,659 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=80:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Newman <b{enjam,newma}n@mozilla.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "mozilla/jsipc/ObjectWrapperParent.h"
#include "mozilla/jsipc/ContextWrapperParent.h"
#include "mozilla/jsipc/CPOWTypes.h"
#include "jsobj.h"
#include "jsfun.h"
#include "jsutil.h"
using namespace mozilla::jsipc;
namespace {
// Only need one reserved slot because the ObjectWrapperParent* is
// stored in the private slot.
static const uintN sFlagsSlot = 0;
static const uintN sNumSlots = 1;
static const uintN CPOW_FLAG_RESOLVING = 1 << 0;
class AutoResolveFlag
{
JSContext* mContext;
JSObject* mObj;
uintN mOldFlags;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER;
static uintN GetFlags(JSContext* cx, JSObject* obj) {
jsval v;
#ifdef DEBUG
JSBool ok =
#endif
JS_GetReservedSlot(cx, obj, sFlagsSlot, &v);
NS_ASSERTION(ok, "Failed to get CPOW flags");
return JSVAL_TO_INT(v);
}
static uintN SetFlags(JSContext* cx, JSObject* obj, uintN flags) {
uintN oldFlags = GetFlags(cx, obj);
if (oldFlags != flags)
JS_SetReservedSlot(cx, obj, sFlagsSlot, INT_TO_JSVAL(flags));
return oldFlags;
}
public:
AutoResolveFlag(JSContext* cx,
JSObject* obj
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: mContext(cx)
, mObj(obj)
, mOldFlags(SetFlags(cx, obj,
GetFlags(cx, obj) | CPOW_FLAG_RESOLVING))
{
JS_GUARD_OBJECT_NOTIFIER_INIT;
}
~AutoResolveFlag() {
SetFlags(mContext, mObj, mOldFlags);
}
static JSBool IsSet(JSContext* cx, JSObject* obj) {
return GetFlags(cx, obj) & CPOW_FLAG_RESOLVING;
}
};
}
const JSExtendedClass ObjectWrapperParent::sCPOW_JSClass = {
// JSClass (JSExtendedClass.base) initialization
{ "CrossProcessObjectWrapper",
JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE | JSCLASS_IS_EXTENDED |
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(sNumSlots),
ObjectWrapperParent::CPOW_AddProperty,
ObjectWrapperParent::CPOW_DelProperty,
ObjectWrapperParent::CPOW_GetProperty,
ObjectWrapperParent::CPOW_SetProperty,
(JSEnumerateOp) ObjectWrapperParent::CPOW_NewEnumerate,
(JSResolveOp) ObjectWrapperParent::CPOW_NewResolve,
ObjectWrapperParent::CPOW_Convert,
ObjectWrapperParent::CPOW_Finalize,
nsnull, // getObjectOps
nsnull, // checkAccess
ObjectWrapperParent::CPOW_Call,
ObjectWrapperParent::CPOW_Construct,
nsnull, // xdrObject
ObjectWrapperParent::CPOW_HasInstance,
nsnull, // mark
nsnull, // reserveSlots
},
// JSExtendedClass initialization
ObjectWrapperParent::CPOW_Equality,
nsnull, // outerObject
nsnull, // innerObject
nsnull, // iterator
nsnull, // wrappedObject
JSCLASS_NO_RESERVED_MEMBERS
};
void
ObjectWrapperParent::ActorDestroy(ActorDestroyReason)
{
if (mObj)
mObj->setPrivate(NULL);
}
JSObject*
ObjectWrapperParent::GetJSObject(JSContext* cx) const
{
JSClass* clasp = const_cast<JSClass*>(&ObjectWrapperParent::sCPOW_JSClass.base);
if (!mObj && (mObj = JS_NewObject(cx, clasp, NULL, NULL))) {
JS_SetPrivate(cx, mObj, (void*)this);
JS_SetReservedSlot(cx, mObj, sFlagsSlot, JSVAL_ZERO);
}
return mObj;
}
static ObjectWrapperParent*
Unwrap(JSContext* cx, JSObject* obj)
{
while (STOBJ_GET_CLASS(obj) != &ObjectWrapperParent::sCPOW_JSClass.base)
if (!(obj = STOBJ_GET_PROTO(obj)))
return NULL;
ObjectWrapperParent* self =
static_cast<ObjectWrapperParent*>(JS_GetPrivate(cx, obj));
NS_ASSERTION(!self || self->GetJSObject(cx) == obj,
"Wrapper and wrapped object disagree?");
return self;
}
/*static*/ bool
ObjectWrapperParent::jsval_to_JSVariant(JSContext* cx, jsval from,
JSVariant* to)
{
switch (JS_TypeOfValue(cx, from)) {
case JSTYPE_VOID:
*to = void_t();
return true;
case JSTYPE_NULL:
if (from != JSVAL_NULL)
return false;
// fall through
case JSTYPE_FUNCTION:
// CPOWs can fool JS_TypeOfValue into returning JSTYPE_FUNCTION
// because they have a call hook, but CPOWs are really objects, so
// fall through to the JSTYPE_OBJECT case:
case JSTYPE_OBJECT:
{
PObjectWrapperParent* powp;
if (!JSObject_to_PObjectWrapperParent(cx, JSVAL_TO_OBJECT(from), &powp))
return false;
*to = powp;
}
return true;
case JSTYPE_STRING:
*to = nsDependentString((PRUnichar*)JS_GetStringChars(JSVAL_TO_STRING(from)),
JS_GetStringLength(JSVAL_TO_STRING(from)));
return true;
case JSTYPE_NUMBER:
if (JSVAL_IS_INT(from))
*to = JSVAL_TO_INT(from);
else if (JSVAL_IS_DOUBLE(from))
*to = *JSVAL_TO_DOUBLE(from);
else return false;
return true;
case JSTYPE_BOOLEAN:
*to = !!JSVAL_TO_BOOLEAN(from);
return true;
case JSTYPE_XML:
default:
return false;
}
}
/*static*/ bool
ObjectWrapperParent::jsval_from_JSVariant(JSContext* cx, const JSVariant& from,
jsval* to)
{
switch (from.type()) {
case JSVariant::Tvoid_t:
*to = JSVAL_VOID;
return true;
case JSVariant::TPObjectWrapperParent:
return jsval_from_PObjectWrapperParent(cx, from.get_PObjectWrapperParent(), to);
case JSVariant::TnsString:
{
JSString* str = JS_NewUCStringCopyZ(cx, from.get_nsString().BeginReading());
if (!str)
return false;
*to = STRING_TO_JSVAL(str);
return true;
}
case JSVariant::Tint:
*to = INT_TO_JSVAL(from.get_int());
return true;
case JSVariant::Tdouble:
return !!JS_NewDoubleValue(cx, from.get_double(), to);
case JSVariant::Tbool:
*to = BOOLEAN_TO_JSVAL(from.get_bool());
return true;
default:
return false;
}
}
/*static*/ bool
ObjectWrapperParent::
JSObject_to_PObjectWrapperParent(JSContext* cx, JSObject* from,
PObjectWrapperParent** to)
{
if (!from) {
*to = NULL;
return true;
}
ObjectWrapperParent* owp = Unwrap(cx, from);
if (!owp)
return false;
*to = owp;
return true;
}
/*static*/ bool
ObjectWrapperParent::
JSObject_from_PObjectWrapperParent(JSContext* cx,
const PObjectWrapperParent* from,
JSObject** to)
{
const ObjectWrapperParent* owp =
static_cast<const ObjectWrapperParent*>(from);
*to = owp
? owp->GetJSObject(cx)
: JSVAL_TO_OBJECT(JSVAL_NULL);
return true;
}
/*static*/ bool
ObjectWrapperParent::
jsval_from_PObjectWrapperParent(JSContext* cx,
const PObjectWrapperParent* from,
jsval* to)
{
JSObject* obj;
if (!JSObject_from_PObjectWrapperParent(cx, from, &obj))
return false;
*to = OBJECT_TO_JSVAL(obj);
return true;
}
static bool
jsid_from_int(JSContext* cx, int from, jsid* to)
{
jsval v = INT_TO_JSVAL(from);
return JS_ValueToId(cx, v, to);
}
static bool
jsid_from_nsString(JSContext* cx, const nsString& from, jsid* to)
{
JSString* str = JS_NewUCStringCopyZ(cx, from.BeginReading());
if (!str)
return false;
return JS_ValueToId(cx, STRING_TO_JSVAL(str), to);
}
static bool
jsval_to_nsString(JSContext* cx, jsval from, nsString* to)
{
JSString* str;
if ((str = JS_ValueToString(cx, from))) {
*to = JS_GetStringChars(str);
return true;
}
return false;
}
/*static*/ JSBool
ObjectWrapperParent::CPOW_AddProperty(JSContext *cx, JSObject *obj, jsval id,
jsval *vp)
{
CPOW_LOG(("Calling CPOW_AddProperty (%s)...",
JSVAL_TO_CSTR(cx, id)));
ObjectWrapperParent* self = Unwrap(cx, obj);
if (!self)
return JS_FALSE;
if (AutoResolveFlag::IsSet(cx, obj))
return JS_TRUE;
nsString in_id;
if (!jsval_to_nsString(cx, id, &in_id))
return JS_FALSE;
JSBool out_ok;
return (self->CallAddProperty(in_id,
&out_ok) &&
out_ok);
}
/*static*/ JSBool
ObjectWrapperParent::CPOW_GetProperty(JSContext *cx, JSObject *obj, jsval id,
jsval *vp)
{
CPOW_LOG(("Calling CPOW_GetProperty (%s)...",
JSVAL_TO_CSTR(cx, id)));
ObjectWrapperParent* self = Unwrap(cx, obj);
if (!self)
return JS_FALSE;
nsString in_id;
if (!jsval_to_nsString(cx, id, &in_id))
return JS_FALSE;
JSBool out_ok;
JSVariant out_v;
return (self->CallGetProperty(in_id,
&out_ok, &out_v) &&
out_ok &&
self->jsval_from_JSVariant(cx, out_v, vp));
}
/*static*/ JSBool
ObjectWrapperParent::CPOW_SetProperty(JSContext *cx, JSObject *obj, jsval id,
jsval *vp)
{
CPOW_LOG(("Calling CPOW_SetProperty (%s)...",
JSVAL_TO_CSTR(cx, id)));
ObjectWrapperParent* self = Unwrap(cx, obj);
if (!self)
return JS_FALSE;
nsString in_id;
JSVariant in_v;
if (!jsval_to_nsString(cx, id, &in_id) ||
!self->jsval_to_JSVariant(cx, *vp, &in_v))
return JS_FALSE;
JSBool out_ok;
JSVariant out_v;
return (self->CallSetProperty(in_id, in_v,
&out_ok, &out_v) &&
out_ok &&
self->jsval_from_JSVariant(cx, out_v, vp));
}
/*static*/ JSBool
ObjectWrapperParent::CPOW_DelProperty(JSContext *cx, JSObject *obj, jsval id,
jsval *vp)
{
CPOW_LOG(("Calling CPOW_DelProperty (%s)...",
JSVAL_TO_CSTR(cx, id)));
ObjectWrapperParent* self = Unwrap(cx, obj);
if (!self)
return JS_FALSE;
nsString in_id;
if (!jsval_to_nsString(cx, id, &in_id))
return JS_FALSE;
JSBool out_ok;
JSVariant out_v;
return (self->CallDelProperty(in_id,
&out_ok, &out_v) &&
out_ok &&
jsval_from_JSVariant(cx, out_v, vp));
}
JSBool
ObjectWrapperParent::NewEnumerateInit(JSContext* cx, jsval* statep, jsid* idp)
{
JSBool out_ok;
JSVariant out_state;
int out_id;
return (CallNewEnumerateInit(&out_ok, &out_state, &out_id) &&
out_ok &&
jsval_from_JSVariant(cx, out_state, statep) &&
(!idp || jsid_from_int(cx, out_id, idp)));
}
JSBool
ObjectWrapperParent::NewEnumerateNext(JSContext* cx, jsval* statep, jsid* idp)
{
JSVariant in_state;
if (!jsval_to_JSVariant(cx, *statep, &in_state))
return JS_FALSE;
JSBool out_ok;
JSVariant out_state;
nsString out_id;
if (CallNewEnumerateNext(in_state,
&out_ok, &out_state, &out_id) &&
out_ok &&
jsval_from_JSVariant(cx, out_state, statep) &&
jsid_from_nsString(cx, out_id, idp))
{
JSObject* obj = GetJSObject(cx);
AutoResolveFlag arf(cx, obj);
return JS_DefinePropertyById(cx, obj, *idp, JSVAL_VOID, NULL, NULL,
JSPROP_ENUMERATE);
}
return JS_FALSE;
}
JSBool
ObjectWrapperParent::NewEnumerateDestroy(JSContext* cx, jsval state)
{
JSVariant in_state;
if (!jsval_to_JSVariant(cx, state, &in_state))
return JS_FALSE;
return SendNewEnumerateDestroy(in_state);
}
/*static*/ JSBool
ObjectWrapperParent::CPOW_NewEnumerate(JSContext *cx, JSObject *obj,
JSIterateOp enum_op, jsval *statep,
jsid *idp)
{
CPOW_LOG(("Calling CPOW_NewEnumerate..."));
ObjectWrapperParent* self = Unwrap(cx, obj);
if (!self)
return JS_FALSE;
switch (enum_op) {
case JSENUMERATE_INIT:
return self->NewEnumerateInit(cx, statep, idp);
case JSENUMERATE_NEXT:
return self->NewEnumerateNext(cx, statep, idp);
case JSENUMERATE_DESTROY:
return self->NewEnumerateDestroy(cx, *statep);
}
return JS_FALSE;
}
/*static*/ JSBool
ObjectWrapperParent::CPOW_NewResolve(JSContext *cx, JSObject *obj, jsval id,
uintN flags, JSObject **objp)
{
CPOW_LOG(("Calling CPOW_NewResolve (%s)...",
JSVAL_TO_CSTR(cx, id)));
ObjectWrapperParent* self = Unwrap(cx, obj);
if (!self)
return JS_FALSE;
nsString in_id;
if (!jsval_to_nsString(cx, id, &in_id))
return JS_FALSE;
JSBool out_ok;
PObjectWrapperParent* out_pobj;
if (!self->CallNewResolve(in_id, flags,
&out_ok, &out_pobj) ||
!out_ok ||
!JSObject_from_PObjectWrapperParent(cx, out_pobj, objp))
return JS_FALSE;
jsid interned_id;
if (*objp &&
JS_ValueToId(cx, id, &interned_id)) {
AutoResolveFlag arf(cx, *objp);
JS_DefinePropertyById(cx, *objp, interned_id, JSVAL_VOID, NULL, NULL,
JSPROP_ENUMERATE);
}
return JS_TRUE;
}
/*static*/ JSBool
ObjectWrapperParent::CPOW_Convert(JSContext *cx, JSObject *obj, JSType type,
jsval *vp)
{
CPOW_LOG(("Calling CPOW_Convert (to %s)...",
JS_GetTypeName(cx, type)));
ObjectWrapperParent* self = Unwrap(cx, obj);
if (!self)
return JS_FALSE;
*vp = OBJECT_TO_JSVAL(obj);
return JS_TRUE;
}
/*static*/ void
ObjectWrapperParent::CPOW_Finalize(JSContext* cx, JSObject* obj)
{
CPOW_LOG(("Calling CPOW_Finalize..."));
ObjectWrapperParent* self = Unwrap(cx, obj);
if (self)
ObjectWrapperParent::Send__delete__(self);
}
/*static*/ JSBool
ObjectWrapperParent::CPOW_Call(JSContext* cx, JSObject* obj, uintN argc,
jsval* argv, jsval* rval)
{
CPOW_LOG(("Calling CPOW_Call..."));
ObjectWrapperParent* function =
Unwrap(cx, JSVAL_TO_OBJECT(JS_ARGV_CALLEE(argv)));
if (!function)
return JS_FALSE;
ObjectWrapperParent* receiver = Unwrap(cx, obj);
if (!receiver) {
// Substitute child global for parent global object.
// TODO First make sure we're really replacing the global object?
ContextWrapperParent* manager =
static_cast<ContextWrapperParent*>(function->Manager());
receiver = manager->GetGlobalObjectWrapper();
}
nsTArray<JSVariant> in_argv(argc);
for (uintN i = 0; i < argc; i++)
if (!jsval_to_JSVariant(cx, argv[i], in_argv.AppendElement()))
return JS_FALSE;
JSBool out_ok;
JSVariant out_rval;
return (function->CallCall(receiver, in_argv,
&out_ok, &out_rval) &&
out_ok &&
jsval_from_JSVariant(cx, out_rval, rval));
}
/*static*/ JSBool
ObjectWrapperParent::CPOW_Construct(JSContext *cx, JSObject *obj, uintN argc,
jsval *argv, jsval *rval)
{
CPOW_LOG(("Calling CPOW_Construct..."));
ObjectWrapperParent* constructor =
Unwrap(cx, JSVAL_TO_OBJECT(JS_ARGV_CALLEE(argv)));
if (!constructor)
return JS_FALSE;
nsTArray<JSVariant> in_argv(argc);
for (uintN i = 0; i < argc; i++)
if (!jsval_to_JSVariant(cx, argv[i], in_argv.AppendElement()))
return JS_FALSE;
JSBool out_ok;
PObjectWrapperParent* out_powp;
return (constructor->CallConstruct(in_argv,
&out_ok, &out_powp) &&
out_ok &&
jsval_from_PObjectWrapperParent(cx, out_powp, rval));
}
/*static*/ JSBool
ObjectWrapperParent::CPOW_HasInstance(JSContext *cx, JSObject *obj, jsval v,
JSBool *bp)
{
CPOW_LOG(("Calling CPOW_HasInstance..."));
*bp = JS_FALSE;
ObjectWrapperParent* self = Unwrap(cx, obj);
if (!self)
return JS_FALSE;
JSVariant in_v;
if (!jsval_to_JSVariant(cx, v, &in_v))
return JS_FALSE;
JSBool out_ok;
return (self->CallHasInstance(in_v,
&out_ok, bp) &&
out_ok);
}
/*static*/ JSBool
ObjectWrapperParent::CPOW_Equality(JSContext *cx, JSObject *obj, jsval v,
JSBool *bp)
{
CPOW_LOG(("Calling CPOW_Equality..."));
*bp = JS_FALSE;
ObjectWrapperParent* self = Unwrap(cx, obj);
if (!self)
return JS_FALSE;
if (JSVAL_IS_PRIMITIVE(v))
return JS_TRUE;
ObjectWrapperParent* other = Unwrap(cx, JSVAL_TO_OBJECT(v));
if (!other)
return JS_TRUE;
*bp = (self == other);
return JS_TRUE;
}

View File

@ -0,0 +1,137 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=80:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Newman <b{enjam,newma}n@mozilla.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef mozilla_jsipc_ObjectWrapperParent_h__
#define mozilla_jsipc_ObjectWrapperParent_h__
#include "mozilla/jsipc/PObjectWrapperParent.h"
#include "jsapi.h"
#include "nsAutoJSValHolder.h"
namespace mozilla {
namespace jsipc {
class ObjectWrapperParent
: public PObjectWrapperParent
{
public:
ObjectWrapperParent()
: mObj(NULL)
{}
JSObject* GetJSObject(JSContext* cx) const;
jsval GetJSVal(JSContext* cx) const {
return OBJECT_TO_JSVAL(GetJSObject(cx));
}
static const JSExtendedClass sCPOW_JSClass;
protected:
void ActorDestroy(ActorDestroyReason why);
private:
mutable JSObject* mObj;
static JSBool
CPOW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
static JSBool
CPOW_DelProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
static JSBool
CPOW_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
static JSBool
CPOW_SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
JSBool NewEnumerateInit(JSContext* cx, jsval* statep, jsid* idp);
JSBool NewEnumerateNext(JSContext* cx, jsval* statep, jsid* idp);
JSBool NewEnumerateDestroy(JSContext* cx, jsval state);
static JSBool
CPOW_NewEnumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
jsval *statep, jsid *idp);
static JSBool
CPOW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
JSObject **objp);
static JSBool
CPOW_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
static void
CPOW_Finalize(JSContext* cx, JSObject* obj);
static JSBool
CPOW_Call(JSContext* cx, JSObject* obj, uintN argc, jsval* argv,
jsval* rval);
static JSBool
CPOW_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval);
static JSBool
CPOW_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
static JSBool
CPOW_Equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
static bool jsval_to_JSVariant(JSContext* cx, jsval from, JSVariant* to);
static bool jsval_from_JSVariant(JSContext* cx, const JSVariant& from,
jsval* to);
static bool
JSObject_to_PObjectWrapperParent(JSContext* cx, JSObject* from,
PObjectWrapperParent** to);
static bool
JSObject_from_PObjectWrapperParent(JSContext* cx,
const PObjectWrapperParent* from,
JSObject** to);
static bool
jsval_from_PObjectWrapperParent(JSContext* cx,
const PObjectWrapperParent* from,
jsval* to);
};
}}
#endif

View File

@ -0,0 +1,57 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=80:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Newman <b{enjam,newma}n@mozilla.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
include protocol "PIFrameEmbedding.ipdl";
include protocol "PTestShell.ipdl";
include protocol "PObjectWrapper.ipdl";
namespace mozilla {
namespace jsipc {
rpc protocol PContextWrapper
{
manager PIFrameEmbedding or PTestShell;
manages PObjectWrapper;
parent:
async __delete__();
async PObjectWrapper(bool makeGlobal);
};
}}

View File

@ -0,0 +1,120 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=80:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Newman <b{enjam,newma}n@mozilla.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
include protocol "PContextWrapper.ipdl";
include "mozilla/jsipc/CPOWTypes.h";
using mozilla::jsipc::void_t;
using JSType;
using JSBool;
namespace mozilla {
namespace jsipc {
union JSVariant {
void_t;
nullable PObjectWrapper;
nsString;
int;
double;
bool; // We'd like to use JSBool here, but JSBool is really JSIntn,
// and IPC::ParamTraits mistakes JSIntn for int.
};
rpc protocol PObjectWrapper
{
manager PContextWrapper;
child:
__delete__(); // unroot
rpc AddProperty(nsString id)
returns (JSBool ok);
rpc GetProperty(nsString id)
returns (JSBool ok,
JSVariant vp);
rpc SetProperty(nsString id,
JSVariant v)
returns (JSBool ok,
JSVariant vp);
rpc DelProperty(nsString id)
returns (JSBool ok,
JSVariant vp);
rpc NewEnumerateInit()
returns (JSBool ok,
JSVariant statep,
int idp);
rpc NewEnumerateNext(JSVariant in_state)
returns (JSBool ok,
JSVariant statep,
nsString idp);
async NewEnumerateDestroy(JSVariant in_state);
rpc NewResolve(nsString id,
int flags)
returns (JSBool ok,
nullable PObjectWrapper obj2);
rpc Convert(JSType type)
returns (JSBool ok,
JSVariant vp);
rpc Call(PObjectWrapper receiver,
JSVariant[] argv)
returns (JSBool ok,
JSVariant rval);
rpc Construct(JSVariant[] argv)
returns (JSBool ok,
nullable PObjectWrapper rval);
rpc HasInstance(JSVariant v)
returns (JSBool ok,
JSBool bp);
};
}}

41
js/src/ipc/ipdl.mk Normal file
View File

@ -0,0 +1,41 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# The Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2010
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Ben Newman <b{enjam,newma}n@mozilla.com> (original author)
#
# Alternatively, the contents of this file may be used under the terms of
# either of the GNU General Public License Version 2 or later (the "GPL"),
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
IPDLSRCS = \
PContextWrapper.ipdl \
PObjectWrapper.ipdl \
$(NULL)

View File

@ -681,6 +681,21 @@ SendCommand(JSContext* cx,
return JS_TRUE;
}
static JSBool
GetChildGlobalObject(JSContext* cx,
JSObject*,
uintN,
jsval*,
jsval* rval)
{
JSObject* global;
if (XRE_GetChildGlobalObject(cx, &global)) {
*rval = OBJECT_TO_JSVAL(global);
return JS_TRUE;
}
return JS_FALSE;
}
#endif // MOZ_IPC
/*
@ -798,6 +813,7 @@ static JSFunctionSpec glob_functions[] = {
#endif
#ifdef MOZ_IPC
{"sendCommand", SendCommand, 1,0,0},
{"getChildGlobalObject", GetChildGlobalObject, 0,0,0},
#endif
#ifdef MOZ_SHARK
{"startShark", js_StartShark, 0,0,0},

View File

@ -93,6 +93,7 @@ endif
# dependent libraries
ifdef MOZ_IPC
STATIC_LIBS += \
jsipc_s \
domipc_s \
domplugins_s \
mozipc_s \

View File

@ -207,6 +207,10 @@ MAKEFILES_xpconnect="
js/src/xpconnect/tools/idl/Makefile
"
MAKEFILES_jsipc="
js/src/ipc/Makefile
"
MAKEFILES_jsdebugger="
js/jsd/Makefile
js/jsd/idl/Makefile
@ -842,6 +846,7 @@ add_makefiles "
$MAKEFILES_htmlparser
$MAKEFILES_intl
$MAKEFILES_xpconnect
$MAKEFILES_jsipc
$MAKEFILES_jsdebugger
$MAKEFILES_jsctypes
$MAKEFILES_content

View File

@ -106,7 +106,7 @@ endif
#
ifdef MOZ_IPC
tier_platform_dirs += ipc
tier_platform_dirs += ipc js/src/ipc
endif
tier_platform_dirs += \

View File

@ -91,6 +91,8 @@
#include "mozilla/dom/ContentProcessParent.h"
#include "mozilla/dom/ContentProcessChild.h"
#include "mozilla/jsipc/ContextWrapperParent.h"
#include "mozilla/ipc/TestShellParent.h"
#include "mozilla/ipc/XPCShellEnvironment.h"
#include "mozilla/Monitor.h"
@ -110,6 +112,10 @@ using mozilla::plugins::PluginThreadChild;
using mozilla::dom::ContentProcessThread;
using mozilla::dom::ContentProcessParent;
using mozilla::dom::ContentProcessChild;
using mozilla::jsipc::PContextWrapperParent;
using mozilla::jsipc::ContextWrapperParent;
using mozilla::ipc::TestShellParent;
using mozilla::ipc::TestShellCommandParent;
using mozilla::ipc::XPCShellEnvironment;
@ -514,6 +520,16 @@ XRE_ShutdownChildProcess()
namespace {
TestShellParent* gTestShellParent = nsnull;
TestShellParent* GetOrCreateTestShellParent()
{
if (!gTestShellParent) {
ContentProcessParent* parent = ContentProcessParent::GetSingleton();
NS_ENSURE_TRUE(parent, nsnull);
gTestShellParent = parent->CreateTestShell();
NS_ENSURE_TRUE(gTestShellParent, nsnull);
}
return gTestShellParent;
}
}
bool
@ -521,22 +537,17 @@ XRE_SendTestShellCommand(JSContext* aCx,
JSString* aCommand,
void* aCallback)
{
if (!gTestShellParent) {
ContentProcessParent* parent = ContentProcessParent::GetSingleton();
NS_ENSURE_TRUE(parent, false);
gTestShellParent = parent->CreateTestShell();
NS_ENSURE_TRUE(gTestShellParent, false);
}
TestShellParent* tsp = GetOrCreateTestShellParent();
NS_ENSURE_TRUE(tsp, false);
nsDependentString command((PRUnichar*)JS_GetStringChars(aCommand),
JS_GetStringLength(aCommand));
if (!aCallback) {
return gTestShellParent->SendExecuteCommand(command);
return tsp->SendExecuteCommand(command);
}
TestShellCommandParent* callback = static_cast<TestShellCommandParent*>(
gTestShellParent->SendPTestShellCommandConstructor(command));
tsp->SendPTestShellCommandConstructor(command));
NS_ENSURE_TRUE(callback, false);
jsval callbackVal = *reinterpret_cast<jsval*>(aCallback);
@ -545,6 +556,13 @@ XRE_SendTestShellCommand(JSContext* aCx,
return true;
}
bool
XRE_GetChildGlobalObject(JSContext* aCx, JSObject** aGlobalP)
{
TestShellParent* tsp = GetOrCreateTestShellParent();
return tsp && tsp->GetGlobalJSObject(aCx, aGlobalP);
}
bool
XRE_ShutdownTestShell()
{

View File

@ -503,6 +503,12 @@ XRE_API(bool,
XRE_SendTestShellCommand, (JSContext* aCx,
JSString* aCommand,
void* aCallback))
struct JSObject;
XRE_API(bool,
XRE_GetChildGlobalObject, (JSContext* aCx,
JSObject** globalp))
XRE_API(bool,
XRE_ShutdownTestShell, ())