--- a/content/base/public/nsIFrameLoader.idl
+++ b/content/base/public/nsIFrameLoader.idl
@@ -38,16 +38,17 @@
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
interface nsIDocShell;
interface nsIURI;
interface nsIFrame;
interface nsIChromeFrameMessageManager;
+interface nsIVariant;
[scriptable, uuid(e511f61f-97db-448a-8b29-a10c470df3fa)]
interface nsIFrameLoader : nsISupports
{
/**
* Get the docshell from the frame loader.
*/
readonly attribute nsIDocShell docShell;
@@ -116,25 +117,27 @@ interface nsIFrameLoader : nsISupports
in long aCharCode,
in long aModifiers,
[optional] in boolean aPreventDefault);
};
native alreadyAddRefed_nsFrameLoader(already_AddRefed<nsFrameLoader>);
-[scriptable, uuid(8f3b12a0-35ae-4e0d-9152-8e0d7e49d446)]
+[scriptable, uuid(5879040e-83e9-40e3-b2bb-5ddf43b76e47)]
interface nsIFrameLoaderOwner : nsISupports
{
/**
* The frame loader owned by this nsIFrameLoaderOwner
*/
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
* never, depending on the object implementing this interface.
*
* @throws NS_ERROR_NOT_IMPLEMENTED if the swapping logic is not
* implemented for the two given frame loader owners.
* @throws NS_ERROR_DOM_SECURITY_ERR if the swap is not allowed on
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -70,16 +70,18 @@
#include "nsIWebNavigation.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
#include "nsIDocShellTreeNode.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIDocShellLoadInfo.h"
#include "nsIBaseWindow.h"
#include "nsContentUtils.h"
+#include "nsIXPConnect.h"
+#include "nsIJSContextStack.h"
#include "nsUnicharUtils.h"
#include "nsIScriptGlobalObject.h"
#include "nsIScriptSecurityManager.h"
#include "nsIScrollable.h"
#include "nsFrameLoader.h"
#include "nsIDOMEventTarget.h"
#include "nsIFrame.h"
#include "nsIFrameFrame.h"
@@ -118,16 +120,18 @@
#ifdef MOZ_IPC
#include "ContentProcessParent.h"
#include "TabParent.h"
using namespace mozilla;
using namespace mozilla::dom;
#endif
+#include "jsapi.h"
+
class nsAsyncDocShellDestroyer : public nsRunnable
{
public:
nsAsyncDocShellDestroyer(nsIDocShell* aDocShell)
: mDocShell(aDocShell)
{
}
@@ -1589,16 +1593,34 @@ nsFrameLoader::SendCrossProcessKeyEvent(
mChildProcess->SendKeyEvent(aType, aKeyCode, aCharCode, aModifiers,
aPreventDefault);
return NS_OK;
}
#endif
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)
{
nsFrameLoader* dest = static_cast<nsFrameLoader*>(aDest);
dest->MaybeCreateDocShell();
NS_ENSURE_STATE(dest->mDocShell);
nsCOMPtr<nsIDOMDocument> dummy = do_GetInterface(dest->mDocShell);
--- a/content/base/src/nsFrameLoader.h
+++ b/content/base/src/nsFrameLoader.h
@@ -135,16 +135,17 @@ public:
// frame loader owner needs to call this, and pass in the two references to
// nsRefPtrs for frame loaders that need to be swapped.
nsresult SwapWithOtherLoader(nsFrameLoader* aOther,
nsRefPtr<nsFrameLoader>& aFirstToSwap,
nsRefPtr<nsFrameLoader>& aSecondToSwap);
#ifdef MOZ_IPC
mozilla::dom::PIFrameEmbeddingParent* GetChildProcess();
+ NS_IMETHOD GetCrossProcessObjectWrapper(nsIVariant** cpow);
#endif
nsFrameMessageManager* GetFrameMessageManager() { return mMessageManager; }
private:
#ifdef MOZ_IPC
bool ShouldUseRemoteProcess();
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -790,16 +790,22 @@ nsObjectLoadingContent::GetFrameLoader()
}
NS_IMETHODIMP
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)
{
aType = mContentType;
return NS_OK;
}
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -2770,16 +2770,23 @@ nsGenericHTMLFrameElement::GetFrameLoade
NS_IMETHODIMP
nsGenericHTMLFrameElement::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner)
{
// We don't support this yet
return NS_ERROR_NOT_IMPLEMENTED;
}
+NS_IMETHODIMP
+nsGenericHTMLFrameElement::GetCrossProcessObjectWrapper(nsIVariant**)
+{
+ // We don't support this yet
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
nsresult
nsGenericHTMLFrameElement::LoadSrc()
{
nsresult rv = EnsureFrameLoader();
NS_ENSURE_SUCCESS(rv, rv);
if (!mFrameLoader) {
return NS_OK;
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -1998,16 +1998,22 @@ nsXULElement::SwapFrameLoaders(nsIFrameL
}
return
ourSlots->mFrameLoader->SwapWithOtherLoader(otherSlots->mFrameLoader,
ourSlots->mFrameLoader,
otherSlots->mFrameLoader);
}
+NS_IMETHODIMP
+nsXULElement::GetCrossProcessObjectWrapper(nsIVariant** cpow)
+{
+ nsRefPtr<nsFrameLoader> frameLoader(GetFrameLoader());
+ return frameLoader->GetCrossProcessObjectWrapper(cpow);
+}
NS_IMETHODIMP
nsXULElement::GetParentTree(nsIDOMXULMultiSelectControlElement** aTreeElement)
{
for (nsIContent* current = GetParent(); current;
current = current->GetParent()) {
if (current->NodeInfo()->Equals(nsGkAtoms::listbox,
kNameSpaceID_XUL)) {
--- a/content/xul/content/src/nsXULElement.h
+++ b/content/xul/content/src/nsXULElement.h
@@ -558,16 +558,18 @@ public:
virtual PRInt32 IntrinsicState() const;
nsresult GetStyle(nsIDOMCSSStyleDeclaration** aStyle);
nsresult GetFrameLoader(nsIFrameLoader** aFrameLoader);
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.
// The function exists solely because XUL elements store the binding
// parent as a member instead of in the slots, as nsGenericElement does.
void SetXULBindingParent(nsIContent* aBindingParent)
{
mBindingParent = aBindingParent;
--- a/dom/ipc/ContentProcessChild.cpp
+++ b/dom/ipc/ContentProcessChild.cpp
@@ -40,16 +40,18 @@
#include <QApplication>
#endif
#include "ContentProcessChild.h"
#include "TabChild.h"
#include "mozilla/ipc/TestShellChild.h"
#include "mozilla/net/NeckoChild.h"
+#include "mozilla/ipc/XPCShellEnvironment.h"
+#include "mozilla/jsipc/PContextWrapperChild.h"
#include "nsXULAppAPI.h"
#include "base/message_loop.h"
#include "base/task.h"
#include "nsChromeRegistryContent.h"
#include "mozilla/chrome/RegistryMessageUtils.h"
@@ -126,16 +128,23 @@ ContentProcessChild::AllocPTestShell()
bool
ContentProcessChild::DeallocPTestShell(PTestShellChild* shell)
{
mTestShells.RemoveElement(shell);
return true;
}
+bool
+ContentProcessChild::RecvPTestShellConstructor(PTestShellChild* actor)
+{
+ actor->SendPContextWrapperConstructor()->SendPObjectWrapperConstructor(true);
+ return true;
+}
+
PNeckoChild*
ContentProcessChild::AllocPNecko()
{
return new NeckoChild();
}
bool
ContentProcessChild::DeallocPNecko(PNeckoChild* necko)
--- a/dom/ipc/ContentProcessChild.h
+++ b/dom/ipc/ContentProcessChild.h
@@ -73,16 +73,17 @@ public:
/* if you remove this, please talk to cjones or dougt */
virtual bool RecvDummy(Shmem& foo) { return true; }
virtual PIFrameEmbeddingChild* AllocPIFrameEmbedding();
virtual bool DeallocPIFrameEmbedding(PIFrameEmbeddingChild*);
virtual PTestShellChild* AllocPTestShell();
virtual bool DeallocPTestShell(PTestShellChild*);
+ virtual bool RecvPTestShellConstructor(PTestShellChild*);
virtual PNeckoChild* AllocPNecko();
virtual bool DeallocPNecko(PNeckoChild*);
virtual bool RecvRegisterChrome(const nsTArray<ChromePackage>& packages,
const nsTArray<ResourceMapping>& resources,
const nsTArray<OverrideMapping>& overrides);
--- a/dom/ipc/PIFrameEmbedding.ipdl
+++ b/dom/ipc/PIFrameEmbedding.ipdl
@@ -35,16 +35,17 @@
* 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 "PContentProcess.ipdl";
include protocol "PDocumentRenderer.ipdl";
include protocol "PDocumentRendererShmem.ipdl";
+include protocol "PContextWrapper.ipdl";
include "mozilla/TabTypes.h";
include "TabMessageUtils.h";
include "gfxMatrix.h";
using MagicWindowHandle;
using RemoteDOMEvent;
using gfxMatrix;
@@ -52,31 +53,34 @@ using gfxMatrix;
namespace mozilla {
namespace dom {
rpc protocol PIFrameEmbedding
{
manager PContentProcess;
manages PDocumentRenderer;
manages PDocumentRendererShmem;
+ manages PContextWrapper;
child:
__delete__();
parent:
/**
* When child sends this message, parent should move focus to
* the next or previous focusable element.
*/
moveFocus(bool forward);
sendEvent(RemoteDOMEvent aEvent);
rpc createWindow() returns (PIFrameEmbedding window);
+ PContextWrapper();
+
sync sendSyncMessageToParent(nsString aMessage, nsString aJSON) returns (nsString[] retval);
sendAsyncMessageToParent(nsString aMessage, nsString aJSON);
child:
createWidget(MagicWindowHandle parentWidget);
loadURL(nsCString uri);
move(PRUint32 x,
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -32,16 +32,18 @@
* 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 "TabChild.h"
+#include "mozilla/dom/PContentProcessChild.h"
+#include "mozilla/jsipc/ContextWrapperChild.h"
#include "nsIWebBrowser.h"
#include "nsEmbedCID.h"
#include "nsComponentManagerUtils.h"
#include "nsIBaseWindow.h"
#include "nsIDOMWindow.h"
#include "nsIDocShellTreeItem.h"
#include "nsThreadUtils.h"
@@ -63,29 +65,32 @@
#include "nsIXPCSecurityManager.h"
#include "nsIJSContextStack.h"
#include "nsComponentManagerUtils.h"
#include "nsIScriptSecurityManager.h"
#include "nsScriptLoader.h"
#include "nsPIWindowRoot.h"
#include "nsIScriptContext.h"
#include "nsPresContext.h"
+#include "nsIDocument.h"
+#include "nsIScriptGlobalObject.h"
#ifdef MOZ_WIDGET_QT
#include <QX11EmbedWidget>
#include <QGraphicsView>
#include <QGraphicsWidget>
#endif
#ifdef MOZ_WIDGET_GTK2
#include <gdk/gdkx.h>
#include <gtk/gtk.h>
#endif
using namespace mozilla::dom;
+using namespace mozilla::jsipc;
NS_IMPL_ISUPPORTS1(ContentListener, nsIDOMEventListener)
NS_IMETHODIMP
ContentListener::HandleEvent(nsIDOMEvent* aEvent)
{
RemoteDOMEvent remoteEvent;
remoteEvent.mEvent = do_QueryInterface(aEvent);
@@ -370,16 +375,19 @@ TabChild::RecvloadURL(const nsCString& u
printf("loading %s, %d\n", uri.get(), NS_IsMainThread());
nsresult rv = mWebNav->LoadURI(NS_ConvertUTF8toUTF16(uri).get(),
nsIWebNavigation::LOAD_FLAGS_NONE,
NULL, NULL, NULL);
if (NS_FAILED(rv)) {
NS_WARNING("mWebNav->LoadURI failed. Eating exception, what else can I do?");
}
+
+ SendPContextWrapperConstructor()->SendPObjectWrapperConstructor(true);
+
return true;
}
bool
TabChild::Recvmove(const PRUint32& x,
const PRUint32& y,
const PRUint32& width,
const PRUint32& height)
@@ -428,16 +436,47 @@ TabChild::RecvsendKeyEvent(const nsStrin
nsCOMPtr<nsIDOMWindowUtils> utils = do_GetInterface(window);
NS_ENSURE_TRUE(utils, true);
PRBool ignored = PR_FALSE;
utils->SendKeyEvent(aType, aKeyCode, aCharCode,
aModifiers, aPreventDefault, &ignored);
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,
const PRInt32& y,
const PRInt32& w,
const PRInt32& h,
const nsString& bgcolor,
const PRUint32& flags,
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -64,16 +64,21 @@
#include "nsDOMEventTargetHelper.h"
#include "nsIPrincipal.h"
#include "nsIScriptObjectPrincipal.h"
#include "nsIScriptContext.h"
class gfxMatrix;
namespace mozilla {
+
+namespace jsipc {
+class PContextWrapperChild;
+}
+
namespace dom {
class TabChild;
class TabChildGlobal : public nsDOMEventTargetHelper,
public nsIContentFrameMessageManager,
public nsIScriptObjectPrincipal,
public nsIScriptContextPrincipal
@@ -223,16 +228,20 @@ public:
const PRInt32& aBufH,
Shmem& aBuf);
nsIWebNavigation* WebNavigation() { return mWebNav; }
JSContext* GetJSContext() { return mCx; }
nsIPrincipal* GetPrincipal() { return mPrincipal; }
+
+ virtual PContextWrapperChild* AllocPContextWrapper();
+ virtual bool DeallocPContextWrapper(PContextWrapperChild* actor);
+
private:
bool InitTabChildGlobal();
nsCOMPtr<nsIWebNavigation> mWebNav;
nsCOMPtr<nsIXPConnectJSObjectHolder> mRootGlobal;
JSContext* mCx;
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -35,30 +35,33 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "TabParent.h"
#include "mozilla/ipc/DocumentRendererParent.h"
#include "mozilla/ipc/DocumentRendererShmemParent.h"
+#include "mozilla/jsipc/ContextWrapperParent.h"
#include "nsIURI.h"
#include "nsFocusManager.h"
#include "nsCOMPtr.h"
#include "nsServiceManagerUtils.h"
#include "nsIDOMElement.h"
#include "nsEventDispatcher.h"
#include "nsIDOMEventTarget.h"
#include "nsIDOMEvent.h"
#include "nsIPrivateDOMEvent.h"
#include "nsFrameLoader.h"
using mozilla::ipc::DocumentRendererParent;
using mozilla::ipc::DocumentRendererShmemParent;
+using mozilla::jsipc::PContextWrapperParent;
+using mozilla::jsipc::ContextWrapperParent;
namespace mozilla {
namespace dom {
TabParent::TabParent()
{
}
@@ -168,16 +171,42 @@ TabParent::AllocPDocumentRendererShmem(c
bool
TabParent::DeallocPDocumentRendererShmem(PDocumentRendererShmemParent* actor)
{
delete 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,
PRInt32 aModifiers, PRBool aIgnoreRootScrollFrame)
{
SendsendMouseEvent(nsString(aType), aX, aY, aButton, aClickCount,
aModifiers, aIgnoreRootScrollFrame);
}
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -45,17 +45,25 @@
#include "nsCOMPtr.h"
#include "nsIBrowserDOMWindow.h"
class nsIURI;
class nsIDOMElement;
class gfxMatrix;
+struct JSContext;
+struct JSObject;
+
namespace mozilla {
+
+namespace jsipc {
+class PContextWrapperParent;
+}
+
namespace dom {
class TabParent : public PIFrameEmbeddingParent
{
public:
TabParent();
virtual ~TabParent();
void SetOwnerElement(nsIDOMElement* aElement) { mFrameElement = aElement; }
@@ -101,16 +109,21 @@ public:
const PRUint32& flags,
const bool& flush,
const gfxMatrix& aMatrix,
const PRInt32& bufw,
const PRInt32& bufh,
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;
};
} // namespace dom
} // namespace mozilla
--- a/ipc/ipdl/Makefile.in
+++ b/ipc/ipdl/Makefile.in
@@ -55,16 +55,17 @@ EXPORT_LIBRARY = 1
##
IPDLDIRS = \
dom/plugins \
dom/ipc \
netwerk/ipc \
netwerk/protocol/http/src \
ipc/ipdl/test/cxx \
ipc/testshell \
+ js/src/ipc \
$(NULL)
##-----------------------------------------------------------------------------
ifdef MOZ_IPDL_TESTS
DIRS += test
endif
vpath %.ipdl $(topsrcdir)
--- a/ipc/testshell/PTestShell.ipdl
+++ b/ipc/testshell/PTestShell.ipdl
@@ -32,28 +32,34 @@
* 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 "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__();
ExecuteCommand(nsString aCommand);
PTestShellCommand(nsString aCommand);
+
+parent:
+ PContextWrapper();
+
};
} // namespace ipc
} // namespace mozilla
--- a/ipc/testshell/TestShellChild.cpp
+++ b/ipc/testshell/TestShellChild.cpp
@@ -30,20 +30,23 @@
* 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 "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())
{
}
bool
TestShellChild::RecvExecuteCommand(const nsString& aCommand)
@@ -80,8 +83,25 @@ TestShellChild::RecvPTestShellCommandCon
nsString response;
if (!mXPCShell->EvaluateString(aCommand, &response)) {
return false;
}
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;
+}
--- a/ipc/testshell/TestShellChild.h
+++ b/ipc/testshell/TestShellChild.h
@@ -39,16 +39,21 @@
#include "mozilla/ipc/PTestShellChild.h"
#include "mozilla/ipc/PTestShellCommandChild.h"
#include "mozilla/ipc/XPCShellEnvironment.h"
#include "nsAutoPtr.h"
namespace mozilla {
+
+namespace jsipc {
+class PContextWrapperChild;
+}
+
namespace ipc {
class XPCShellEnvironment;
class TestShellChild : public PTestShellChild
{
public:
TestShellChild();
@@ -61,20 +66,19 @@ public:
bool
RecvPTestShellCommandConstructor(PTestShellCommandChild* aActor,
const nsString& aCommand);
bool
DeallocPTestShellCommand(PTestShellCommandChild* aCommand);
- void SetXPCShell(XPCShellEnvironment* aXPCShell) {
- mXPCShell = aXPCShell;
- }
-
+ PContextWrapperChild* AllocPContextWrapper();
+ bool DeallocPContextWrapper(PContextWrapperChild* actor);
+
private:
nsAutoPtr<XPCShellEnvironment> mXPCShell;
};
} /* namespace ipc */
} /* namespace mozilla */
#endif /* ipc_testshell_TestShellChild_h */
--- a/ipc/testshell/TestShellParent.cpp
+++ b/ipc/testshell/TestShellParent.cpp
@@ -30,22 +30,25 @@
* 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 "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)
{
return new TestShellCommandParent();
}
bool
@@ -61,16 +64,42 @@ TestShellParent::CommandDone(TestShellCo
{
// XXX what should happen if the callback fails?
/*JSBool ok = */command->RunCallback(aResponse);
command->ReleaseCallback();
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)
{
if (!mCallback.Hold(aCx)) {
return JS_FALSE;
}
--- a/ipc/testshell/TestShellParent.h
+++ b/ipc/testshell/TestShellParent.h
@@ -42,33 +42,45 @@
#include "mozilla/ipc/PTestShellParent.h"
#include "mozilla/ipc/PTestShellCommandParent.h"
#include "jsapi.h"
#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:
PTestShellCommandParent*
AllocPTestShellCommand(const nsString& aCommand);
bool
DeallocPTestShellCommand(PTestShellCommandParent* aActor);
bool
CommandDone(TestShellCommandParent* aActor, const nsString& aResponse);
+
+ PContextWrapperParent* AllocPContextWrapper();
+ bool DeallocPContextWrapper(PContextWrapperParent* actor);
+
+ bool GetGlobalJSObject(JSContext* cx, JSObject** globalp);
};
class TestShellCommandParent : public PTestShellCommandParent
{
public:
TestShellCommandParent() : mCx(NULL) { }
--- a/ipc/testshell/XPCShellEnvironment.h
+++ b/ipc/testshell/XPCShellEnvironment.h
@@ -68,16 +68,20 @@ public:
JSPrincipals* GetPrincipal() {
return mJSPrincipals;
}
JSObject* GetGlobalObject() {
return mGlobalHolder.ToJSObject();
}
+ JSContext* GetContext() {
+ return mCx;
+ }
+
void SetExitCode(int aExitCode) {
mExitCode = aExitCode;
}
int ExitCode() {
return mExitCode;
}
void SetIsQuitting() {
@@ -124,9 +128,9 @@ private:
JSBool mQuitting;
JSBool mReportWarnings;
JSBool mCompileOnly;
};
} /* namespace ipc */
} /* namespace mozilla */
-#endif /* _IPC_TESTSHELL_XPCSHELLENVIRONMENT_H_ */
\ No newline at end of file
+#endif /* _IPC_TESTSHELL_XPCSHELLENVIRONMENT_H_ */
new file mode 100644
--- /dev/null
+++ b/js/src/ipc/CPOWTypes.h
@@ -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
new file mode 100644
--- /dev/null
+++ b/js/src/ipc/ContextWrapperChild.h
@@ -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
new file mode 100644
--- /dev/null
+++ b/js/src/ipc/ContextWrapperParent.h
@@ -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
new file mode 100644
--- /dev/null
+++ b/js/src/ipc/Makefile.in
@@ -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)"'
new file mode 100644
--- /dev/null
+++ b/js/src/ipc/ObjectWrapperChild.cpp
@@ -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;
+}
new file mode 100644
--- /dev/null
+++ b/js/src/ipc/ObjectWrapperChild.h
@@ -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
new file mode 100644
--- /dev/null
+++ b/js/src/ipc/ObjectWrapperParent.cpp
@@ -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;
+}
new file mode 100644
--- /dev/null
+++ b/js/src/ipc/ObjectWrapperParent.h
@@ -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
new file mode 100644
--- /dev/null
+++ b/js/src/ipc/PContextWrapper.ipdl
@@ -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);
+};
+
+}}
new file mode 100644
--- /dev/null
+++ b/js/src/ipc/PObjectWrapper.ipdl
@@ -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);
+};
+
+}}
new file mode 100644
--- /dev/null
+++ b/js/src/ipc/ipdl.mk
@@ -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)
--- a/js/src/xpconnect/shell/xpcshell.cpp
+++ b/js/src/xpconnect/shell/xpcshell.cpp
@@ -676,16 +676,31 @@ SendCommand(JSContext* cx,
if (!XRE_SendTestShellCommand(cx, str, argc > 1 ? &argv[1] : nsnull)) {
JS_ReportError(cx, "Couldn't send command!");
return JS_FALSE;
}
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
/*
* JSContext option name to flag map. The option names are in alphabetical
* order for better reporting.
*/
static const struct {
const char *name;
@@ -793,16 +808,17 @@ static JSFunctionSpec glob_functions[] =
{"gc", GC, 0,0,0},
{"clear", Clear, 1,0,0},
{"options", Options, 0,0,0},
#ifdef DEBUG
{"dumpHeap", DumpHeap, 5,0,0},
#endif
#ifdef MOZ_IPC
{"sendCommand", SendCommand, 1,0,0},
+ {"getChildGlobalObject", GetChildGlobalObject, 0,0,0},
#endif
#ifdef MOZ_SHARK
{"startShark", js_StartShark, 0,0,0},
{"stopShark", js_StopShark, 0,0,0},
{"connectShark", js_ConnectShark, 0,0,0},
{"disconnectShark", js_DisconnectShark, 0,0,0},
#endif
#ifdef MOZ_CALLGRIND
--- a/toolkit/library/libxul-config.mk
+++ b/toolkit/library/libxul-config.mk
@@ -88,16 +88,17 @@ RCFLAGS += -i $(topsrcdir)/widget/src/os
endif
LOCAL_INCLUDES += -I$(topsrcdir)/widget/src/os2
endif
# dependent libraries
ifdef MOZ_IPC
STATIC_LIBS += \
+ jsipc_s \
domipc_s \
domplugins_s \
mozipc_s \
mozipdlgen_s \
ipcshell_s \
gfxipc_s \
$(NULL)
--- a/toolkit/toolkit-makefiles.sh
+++ b/toolkit/toolkit-makefiles.sh
@@ -202,16 +202,20 @@ MAKEFILES_xpconnect="
js/src/xpconnect/loader/Makefile
js/src/xpconnect/tests/Makefile
js/src/xpconnect/tests/components/Makefile
js/src/xpconnect/tests/idl/Makefile
js/src/xpconnect/tools/Makefile
js/src/xpconnect/tools/idl/Makefile
"
+MAKEFILES_jsipc="
+ js/src/ipc/Makefile
+"
+
MAKEFILES_jsdebugger="
js/jsd/Makefile
js/jsd/idl/Makefile
"
MAKEFILES_jsctypes="
js/ctypes/Makefile
"
@@ -837,16 +841,17 @@ add_makefiles "
$MAKEFILES_db
$MAKEFILES_dom
$MAKEFILES_editor
$MAKEFILES_xmlparser
$MAKEFILES_gfx
$MAKEFILES_htmlparser
$MAKEFILES_intl
$MAKEFILES_xpconnect
+ $MAKEFILES_jsipc
$MAKEFILES_jsdebugger
$MAKEFILES_jsctypes
$MAKEFILES_content
$MAKEFILES_layout
$MAKEFILES_libimg
$MAKEFILES_libjar
$MAKEFILES_libreg
$MAKEFILES_libpref
--- a/toolkit/toolkit-tiers.mk
+++ b/toolkit/toolkit-tiers.mk
@@ -101,17 +101,17 @@ ifeq ($(OS_ARCH),WINCE)
tier_platform_dirs += modules/lib7z
endif
#
# "gecko" - core components
#
ifdef MOZ_IPC
-tier_platform_dirs += ipc
+tier_platform_dirs += ipc js/src/ipc
endif
tier_platform_dirs += \
js/src/xpconnect \
js/ctypes \
intl/chardet \
$(NULL)
--- a/toolkit/xre/nsEmbedFunctions.cpp
+++ b/toolkit/xre/nsEmbedFunctions.cpp
@@ -86,16 +86,18 @@
#include "mozilla/ipc/BrowserProcessSubThread.h"
#include "ScopedXREEmbed.h"
#include "mozilla/plugins/PluginThreadChild.h"
#include "mozilla/dom/ContentProcessThread.h"
#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"
#ifdef MOZ_IPDL_TESTS
#include "mozilla/_ipdltest/IPDLUnitTests.h"
#include "mozilla/_ipdltest/IPDLUnitTestThreadChild.h"
@@ -105,16 +107,20 @@ using mozilla::_ipdltest::IPDLUnitTestTh
using mozilla::ipc::GeckoChildProcessHost;
using mozilla::ipc::BrowserProcessSubThread;
using mozilla::ipc::ScopedXREEmbed;
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;
using mozilla::Monitor;
using mozilla::MonitorAutoEnter;
using mozilla::startup::sChildProcessType;
@@ -509,48 +515,60 @@ XRE_ShutdownChildProcess()
MessageLoop* ioLoop = XRE_GetIOMessageLoop();
NS_ABORT_IF_FALSE(!!ioLoop, "Bad shutdown order");
ioLoop->PostTask(FROM_HERE, new MessageLoop::QuitTask());
}
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
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);
NS_ENSURE_TRUE(callback->SetCallback(aCx, callbackVal), false);
return true;
}
bool
+XRE_GetChildGlobalObject(JSContext* aCx, JSObject** aGlobalP)
+{
+ TestShellParent* tsp = GetOrCreateTestShellParent();
+ return tsp && tsp->GetGlobalJSObject(aCx, aGlobalP);
+}
+
+bool
XRE_ShutdownTestShell()
{
if (!gTestShellParent)
return true;
return ContentProcessParent::GetSingleton()->DestroyTestShell(gTestShellParent);
}
#ifdef MOZ_X11
--- a/xpcom/build/nsXULAppAPI.h
+++ b/xpcom/build/nsXULAppAPI.h
@@ -498,14 +498,20 @@ XRE_API(MessageLoop*,
struct JSContext;
struct JSString;
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, ())
XRE_API(void,
XRE_InstallX11ErrorHandler, ())
#endif // _nsXULAppAPI_h__