Bug 879475 - Part 005. Implement ContentBridge r=jlebar

Based on original patch by David Zbarsky <dzbarsky@gmail.com>
This commit is contained in:
"Kan-Ru Chen (陳侃如)" 2014-06-09 16:49:12 +08:00
parent 8fe78e3629
commit c9a438a458
21 changed files with 903 additions and 82 deletions

View File

@ -88,6 +88,7 @@
#include "mozilla/dom/SVGIFrameElement.h"
#include "nsSandboxFlags.h"
#include "JavaScriptParent.h"
#include "CompositorChild.h"
#include "mozilla/dom/StructuredCloneUtils.h"
@ -1543,9 +1544,16 @@ nsFrameLoader::ShouldUseRemoteProcess()
return false;
}
// If we're inside a content process, don't use a remote process for this
// frame; it won't work properly until bug 761935 is fixed.
if (XRE_GetProcessType() == GeckoProcessType_Content) {
// Don't try to launch nested children if we don't have OMTC.
// They won't render!
if (XRE_GetProcessType() == GeckoProcessType_Content &&
!CompositorChild::ChildProcessHasCompositor()) {
return false;
}
if (XRE_GetProcessType() == GeckoProcessType_Content &&
!(PR_GetEnv("MOZ_NESTED_OOP_TABS") ||
Preferences::GetBool("dom.ipc.tabs.nested.enabled", false))) {
return false;
}
@ -2093,10 +2101,7 @@ nsFrameLoader::TryRemoteBrowser()
return false;
}
nsCOMPtr<nsIXULWindow> window(do_GetInterface(parentOwner));
if (!window) {
return false;
}
if (NS_FAILED(window->GetChromeFlags(&chromeFlags))) {
if (window && NS_FAILED(window->GetChromeFlags(&chromeFlags))) {
return false;
}
@ -2135,11 +2140,12 @@ nsFrameLoader::TryRemoteBrowser()
parentAsItem->GetRootTreeItem(getter_AddRefs(rootItem));
nsCOMPtr<nsIDOMWindow> rootWin = rootItem->GetWindow();
nsCOMPtr<nsIDOMChromeWindow> rootChromeWin = do_QueryInterface(rootWin);
NS_ABORT_IF_FALSE(rootChromeWin, "How did we not get a chrome window here?");
nsCOMPtr<nsIBrowserDOMWindow> browserDOMWin;
rootChromeWin->GetBrowserDOMWindow(getter_AddRefs(browserDOMWin));
mRemoteBrowser->SetBrowserDOMWindow(browserDOMWin);
if (rootChromeWin) {
nsCOMPtr<nsIBrowserDOMWindow> browserDOMWin;
rootChromeWin->GetBrowserDOMWindow(getter_AddRefs(browserDOMWin));
mRemoteBrowser->SetBrowserDOMWindow(browserDOMWin);
}
mContentParent = mRemoteBrowser->Manager();
@ -2424,8 +2430,9 @@ nsFrameLoader::EnsureMessageManager()
return NS_OK;
}
bool useRemoteProcess = ShouldUseRemoteProcess();
if (mMessageManager) {
if (ShouldUseRemoteProcess() && mRemoteBrowserShown) {
if (useRemoteProcess && mRemoteBrowserShown) {
mMessageManager->InitWithCallback(this);
}
return NS_OK;
@ -2449,7 +2456,7 @@ nsFrameLoader::EnsureMessageManager()
}
}
if (ShouldUseRemoteProcess()) {
if (useRemoteProcess) {
mMessageManager = new nsFrameMessageManager(mRemoteBrowserShown ? this : nullptr,
static_cast<nsFrameMessageManager*>(parentManager.get()),
MM_CHROME);

View File

@ -1870,8 +1870,6 @@ NS_NewParentProcessMessageManager(nsIMessageBroadcaster** aResult)
{
NS_ASSERTION(!nsFrameMessageManager::sParentProcessManager,
"Re-creating sParentProcessManager");
NS_ENSURE_TRUE(XRE_GetProcessType() == GeckoProcessType_Default,
NS_ERROR_NOT_AVAILABLE);
nsRefPtr<nsFrameMessageManager> mm = new nsFrameMessageManager(nullptr,
nullptr,
MM_CHROME | MM_PROCESSMANAGER | MM_BROADCASTER);

View File

@ -283,9 +283,7 @@ nsGenericHTMLFrameElement::GetReallyIsBrowserOrApp(bool *aOut)
}
// Fail if this frame doesn't have the mozbrowser attribute.
bool hasMozbrowser = false;
GetMozbrowser(&hasMozbrowser);
if (!hasMozbrowser) {
if (!GetBoolAttr(nsGkAtoms::mozbrowser)) {
return NS_OK;
}

View File

@ -0,0 +1,173 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/ContentBridgeChild.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/StructuredCloneUtils.h"
#include "mozilla/dom/TabChild.h"
#include "mozilla/dom/ipc/Blob.h"
#include "mozilla/dom/ipc/nsIRemoteBlob.h"
#include "mozilla/ipc/InputStreamUtils.h"
#include "nsDOMFile.h"
#include "JavaScriptChild.h"
using namespace base;
using namespace mozilla::ipc;
using namespace mozilla::jsipc;
namespace mozilla {
namespace dom {
NS_IMPL_ISUPPORTS(ContentBridgeChild, nsIContentChild)
ContentBridgeChild::ContentBridgeChild(Transport* aTransport)
: mTransport(aTransport)
{}
ContentBridgeChild::~ContentBridgeChild()
{
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new DeleteTask<Transport>(mTransport));
}
void
ContentBridgeChild::ActorDestroy(ActorDestroyReason aWhy)
{
MessageLoop::current()->PostTask(
FROM_HERE,
NewRunnableMethod(this, &ContentBridgeChild::DeferredDestroy));
}
/*static*/ ContentBridgeChild*
ContentBridgeChild::Create(Transport* aTransport, ProcessId aOtherProcess)
{
nsRefPtr<ContentBridgeChild> bridge =
new ContentBridgeChild(aTransport);
ProcessHandle handle;
if (!base::OpenProcessHandle(aOtherProcess, &handle)) {
// XXX need to kill |aOtherProcess|, it's boned
return nullptr;
}
bridge->mSelfRef = bridge;
DebugOnly<bool> ok = bridge->Open(aTransport, handle, XRE_GetIOMessageLoop());
MOZ_ASSERT(ok);
return bridge;
}
void
ContentBridgeChild::DeferredDestroy()
{
mSelfRef = nullptr;
// |this| was just destroyed, hands off
}
bool
ContentBridgeChild::RecvAsyncMessage(const nsString& aMsg,
const ClonedMessageData& aData,
const InfallibleTArray<jsipc::CpowEntry>& aCpows,
const IPC::Principal& aPrincipal)
{
return nsIContentChild::RecvAsyncMessage(aMsg, aData, aCpows, aPrincipal);
}
PBlobChild*
ContentBridgeChild::SendPBlobConstructor(PBlobChild* actor,
const BlobConstructorParams& params)
{
return PContentBridgeChild::SendPBlobConstructor(actor, params);
}
bool
ContentBridgeChild::SendPBrowserConstructor(PBrowserChild* aActor,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const bool& aIsForApp,
const bool& aIsForBrowser)
{
return PContentBridgeChild::SendPBrowserConstructor(aActor,
aContext,
aChromeFlags,
aID,
aIsForApp,
aIsForBrowser);
}
// This implementation is identical to ContentChild::GetCPOWManager but we can't
// move it to nsIContentChild because it calls ManagedPJavaScriptChild() which
// only exists in PContentChild and PContentBridgeChild.
jsipc::JavaScriptChild *
ContentBridgeChild::GetCPOWManager()
{
if (ManagedPJavaScriptChild().Length()) {
return static_cast<JavaScriptChild*>(ManagedPJavaScriptChild()[0]);
}
JavaScriptChild* actor = static_cast<JavaScriptChild*>(SendPJavaScriptConstructor());
return actor;
}
mozilla::jsipc::PJavaScriptChild *
ContentBridgeChild::AllocPJavaScriptChild()
{
return nsIContentChild::AllocPJavaScriptChild();
}
bool
ContentBridgeChild::DeallocPJavaScriptChild(PJavaScriptChild *child)
{
return nsIContentChild::DeallocPJavaScriptChild(child);
}
PBrowserChild*
ContentBridgeChild::AllocPBrowserChild(const IPCTabContext &aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const bool& aIsForApp,
const bool& aIsForBrowser)
{
return nsIContentChild::AllocPBrowserChild(aContext,
aChromeFlags,
aID,
aIsForApp,
aIsForBrowser);
}
bool
ContentBridgeChild::DeallocPBrowserChild(PBrowserChild* aChild)
{
return nsIContentChild::DeallocPBrowserChild(aChild);
}
bool
ContentBridgeChild::RecvPBrowserConstructor(PBrowserChild* aActor,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const bool& aIsForApp,
const bool& aIsForBrowser)
{
return ContentChild::GetSingleton()->RecvPBrowserConstructor(aActor,
aContext,
aChromeFlags,
aID,
aIsForApp,
aIsForBrowser);
}
PBlobChild*
ContentBridgeChild::AllocPBlobChild(const BlobConstructorParams& aParams)
{
return nsIContentChild::AllocPBlobChild(aParams);
}
bool
ContentBridgeChild::DeallocPBlobChild(PBlobChild* aActor)
{
return nsIContentChild::DeallocPBlobChild(aActor);
}
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,80 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_ContentBridgeChild_h
#define mozilla_dom_ContentBridgeChild_h
#include "mozilla/dom/PContentBridgeChild.h"
#include "mozilla/dom/nsIContentChild.h"
namespace mozilla {
namespace dom {
class ContentBridgeChild MOZ_FINAL : public PContentBridgeChild
, public nsIContentChild
{
public:
ContentBridgeChild(Transport* aTransport);
NS_DECL_ISUPPORTS
virtual ~ContentBridgeChild();
static ContentBridgeChild*
Create(Transport* aTransport, ProcessId aOtherProcess);
virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
void DeferredDestroy();
virtual bool RecvAsyncMessage(const nsString& aMsg,
const ClonedMessageData& aData,
const InfallibleTArray<jsipc::CpowEntry>& aCpows,
const IPC::Principal& aPrincipal) MOZ_OVERRIDE;
virtual PBlobChild*
SendPBlobConstructor(PBlobChild* actor,
const BlobConstructorParams& params);
jsipc::JavaScriptChild* GetCPOWManager();
virtual bool SendPBrowserConstructor(PBrowserChild* aActor,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const bool& aIsForApp,
const bool& aIsForBrowser) MOZ_OVERRIDE;
protected:
virtual PBrowserChild* AllocPBrowserChild(const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const bool& aIsForApp,
const bool& aIsForBrowser) MOZ_OVERRIDE;
virtual bool DeallocPBrowserChild(PBrowserChild*) MOZ_OVERRIDE;
virtual bool RecvPBrowserConstructor(PBrowserChild* aCctor,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const bool& aIsForApp,
const bool& aIsForBrowser) MOZ_OVERRIDE;
virtual mozilla::jsipc::PJavaScriptChild* AllocPJavaScriptChild() MOZ_OVERRIDE;
virtual bool DeallocPJavaScriptChild(mozilla::jsipc::PJavaScriptChild*) MOZ_OVERRIDE;
virtual PBlobChild* AllocPBlobChild(const BlobConstructorParams& aParams) MOZ_OVERRIDE;
virtual bool DeallocPBlobChild(PBlobChild*) MOZ_OVERRIDE;
DISALLOW_EVIL_CONSTRUCTORS(ContentBridgeChild);
protected: // members
nsRefPtr<ContentBridgeChild> mSelfRef;
Transport* mTransport; // owned
};
} // dom
} // mozilla
#endif // mozilla_dom_ContentBridgeChild_h

View File

@ -0,0 +1,162 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/ContentBridgeParent.h"
#include "mozilla/dom/TabParent.h"
#include "JavaScriptParent.h"
#include "nsXULAppAPI.h"
using namespace base;
using namespace mozilla::ipc;
using namespace mozilla::jsipc;
namespace mozilla {
namespace dom {
NS_IMPL_ISUPPORTS(ContentBridgeParent, nsIContentParent)
ContentBridgeParent::ContentBridgeParent(Transport* aTransport)
: mTransport(aTransport)
{}
ContentBridgeParent::~ContentBridgeParent()
{
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new DeleteTask<Transport>(mTransport));
}
void
ContentBridgeParent::ActorDestroy(ActorDestroyReason aWhy)
{
MessageLoop::current()->PostTask(
FROM_HERE,
NewRunnableMethod(this, &ContentBridgeParent::DeferredDestroy));
}
/*static*/ ContentBridgeParent*
ContentBridgeParent::Create(Transport* aTransport, ProcessId aOtherProcess)
{
nsRefPtr<ContentBridgeParent> bridge =
new ContentBridgeParent(aTransport);
ProcessHandle handle;
if (!base::OpenProcessHandle(aOtherProcess, &handle)) {
// XXX need to kill |aOtherProcess|, it's boned
return nullptr;
}
bridge->mSelfRef = bridge;
DebugOnly<bool> ok = bridge->Open(aTransport, handle, XRE_GetIOMessageLoop());
MOZ_ASSERT(ok);
return bridge.get();
}
void
ContentBridgeParent::DeferredDestroy()
{
mSelfRef = nullptr;
// |this| was just destroyed, hands off
}
bool
ContentBridgeParent::RecvSyncMessage(const nsString& aMsg,
const ClonedMessageData& aData,
const InfallibleTArray<jsipc::CpowEntry>& aCpows,
const IPC::Principal& aPrincipal,
InfallibleTArray<nsString>* aRetvals)
{
return nsIContentParent::RecvSyncMessage(aMsg, aData, aCpows, aPrincipal, aRetvals);
}
bool
ContentBridgeParent::RecvAsyncMessage(const nsString& aMsg,
const ClonedMessageData& aData,
const InfallibleTArray<jsipc::CpowEntry>& aCpows,
const IPC::Principal& aPrincipal)
{
return nsIContentParent::RecvAsyncMessage(aMsg, aData, aCpows, aPrincipal);
}
PBlobParent*
ContentBridgeParent::SendPBlobConstructor(PBlobParent* actor,
const BlobConstructorParams& params)
{
return PContentBridgeParent::SendPBlobConstructor(actor, params);
}
PBrowserParent*
ContentBridgeParent::SendPBrowserConstructor(PBrowserParent* aActor,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const bool& aIsForApp,
const bool& aIsForBrowser)
{
return PContentBridgeParent::SendPBrowserConstructor(aActor,
aContext,
aChromeFlags,
aID,
aIsForApp,
aIsForBrowser);
}
PBlobParent*
ContentBridgeParent::AllocPBlobParent(const BlobConstructorParams& aParams)
{
return nsIContentParent::AllocPBlobParent(aParams);
}
bool
ContentBridgeParent::DeallocPBlobParent(PBlobParent* aActor)
{
return nsIContentParent::DeallocPBlobParent(aActor);
}
mozilla::jsipc::PJavaScriptParent *
ContentBridgeParent::AllocPJavaScriptParent()
{
return nsIContentParent::AllocPJavaScriptParent();
}
bool
ContentBridgeParent::DeallocPJavaScriptParent(PJavaScriptParent *parent)
{
return nsIContentParent::DeallocPJavaScriptParent(parent);
}
PBrowserParent*
ContentBridgeParent::AllocPBrowserParent(const IPCTabContext &aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const bool& aIsForApp,
const bool& aIsForBrowser)
{
return nsIContentParent::AllocPBrowserParent(aContext,
aChromeFlags,
aID,
aIsForApp,
aIsForBrowser);
}
bool
ContentBridgeParent::DeallocPBrowserParent(PBrowserParent* aParent)
{
return nsIContentParent::DeallocPBrowserParent(aParent);
}
// This implementation is identical to ContentParent::GetCPOWManager but we can't
// move it to nsIContentParent because it calls ManagedPJavaScriptParent() which
// only exists in PContentParent and PContentBridgeParent.
jsipc::JavaScriptParent*
ContentBridgeParent::GetCPOWManager()
{
if (ManagedPJavaScriptParent().Length()) {
return static_cast<JavaScriptParent*>(ManagedPJavaScriptParent()[0]);
}
JavaScriptParent* actor = static_cast<JavaScriptParent*>(SendPJavaScriptConstructor());
return actor;
}
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,117 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_ContentBridgeParent_h
#define mozilla_dom_ContentBridgeParent_h
#include "mozilla/dom/PContentBridgeParent.h"
#include "mozilla/dom/nsIContentParent.h"
namespace mozilla {
namespace dom {
class ContentBridgeParent : public PContentBridgeParent
, public nsIContentParent
{
public:
ContentBridgeParent(Transport* aTransport);
NS_DECL_ISUPPORTS
virtual ~ContentBridgeParent();
virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
void DeferredDestroy();
static ContentBridgeParent*
Create(Transport* aTransport, ProcessId aOtherProcess);
virtual PBlobParent*
SendPBlobConstructor(PBlobParent* actor,
const BlobConstructorParams& params) MOZ_OVERRIDE;
virtual PBrowserParent*
SendPBrowserConstructor(PBrowserParent* aActor,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const bool& aIsForApp,
const bool& aIsForBrowser) MOZ_OVERRIDE;
jsipc::JavaScriptParent* GetCPOWManager();
virtual uint64_t ChildID() MOZ_OVERRIDE
{
return mChildID;
}
virtual bool IsForApp() MOZ_OVERRIDE
{
return mIsForApp;
}
virtual bool IsForBrowser() MOZ_OVERRIDE
{
return mIsForBrowser;
}
protected:
void SetChildID(uint64_t aId)
{
mChildID = aId;
}
void SetIsForApp(bool aIsForApp)
{
mIsForApp = aIsForApp;
}
void SetIsForBrowser(bool aIsForBrowser)
{
mIsForBrowser = aIsForBrowser;
}
protected:
virtual bool RecvSyncMessage(const nsString& aMsg,
const ClonedMessageData& aData,
const InfallibleTArray<jsipc::CpowEntry>& aCpows,
const IPC::Principal& aPrincipal,
InfallibleTArray<nsString>* aRetvals) MOZ_OVERRIDE;
virtual bool RecvAsyncMessage(const nsString& aMsg,
const ClonedMessageData& aData,
const InfallibleTArray<jsipc::CpowEntry>& aCpows,
const IPC::Principal& aPrincipal) MOZ_OVERRIDE;
virtual jsipc::PJavaScriptParent* AllocPJavaScriptParent() MOZ_OVERRIDE;
virtual bool
DeallocPJavaScriptParent(jsipc::PJavaScriptParent*) MOZ_OVERRIDE;
virtual PBrowserParent*
AllocPBrowserParent(const IPCTabContext &aContext,
const uint32_t& aChromeFlags,
const uint64_t& aID,
const bool& aIsForApp,
const bool& aIsForBrowser) MOZ_OVERRIDE;
virtual bool DeallocPBrowserParent(PBrowserParent*) MOZ_OVERRIDE;
virtual PBlobParent*
AllocPBlobParent(const BlobConstructorParams& aParams) MOZ_OVERRIDE;
virtual bool DeallocPBlobParent(PBlobParent*) MOZ_OVERRIDE;
DISALLOW_EVIL_CONSTRUCTORS(ContentBridgeParent);
protected: // members
nsRefPtr<ContentBridgeParent> mSelfRef;
Transport* mTransport; // owned
uint64_t mChildID;
bool mIsForApp;
bool mIsForBrowser;
private:
friend class ContentParent;
};
} // dom
} // mozilla
#endif // mozilla_dom_ContentBridgeParent_h

View File

@ -19,6 +19,8 @@
#include "mozilla/Attributes.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/ContentBridgeChild.h"
#include "mozilla/dom/ContentBridgeParent.h"
#include "mozilla/dom/DOMStorageIPC.h"
#include "mozilla/dom/ExternalHelperAppChild.h"
#include "mozilla/dom/PCrashReporterChild.h"
@ -835,6 +837,23 @@ ContentChild::DeallocPCycleCollectWithLogsChild(PCycleCollectWithLogsChild* /* a
return true;
}
PContentBridgeChild*
ContentChild::AllocPContentBridgeChild(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess)
{
return ContentBridgeChild::Create(aTransport, aOtherProcess);
}
PContentBridgeParent*
ContentChild::AllocPContentBridgeParent(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess)
{
MOZ_ASSERT(!mLastBridge);
mLastBridge = static_cast<ContentBridgeParent*>(
ContentBridgeParent::Create(aTransport, aOtherProcess));
return mLastBridge;
}
PCompositorChild*
ContentChild::AllocPCompositorChild(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess)

View File

@ -8,9 +8,10 @@
#define mozilla_dom_ContentChild_h
#include "mozilla/Attributes.h"
#include "mozilla/dom/ContentBridgeParent.h"
#include "mozilla/dom/ipc/Blob.h"
#include "mozilla/dom/nsIContentChild.h"
#include "mozilla/dom/PContentChild.h"
#include "mozilla/dom/ipc/Blob.h"
#include "nsHashKeys.h"
#include "nsIObserver.h"
#include "nsTHashtable.h"
@ -89,6 +90,21 @@ public:
void GetProcessName(nsACString& aName);
static void AppendProcessId(nsACString& aName);
ContentBridgeParent* GetLastBridge() {
MOZ_ASSERT(mLastBridge);
ContentBridgeParent* parent = mLastBridge;
mLastBridge = nullptr;
return parent;
}
nsRefPtr<ContentBridgeParent> mLastBridge;
PContentBridgeParent*
AllocPContentBridgeParent(mozilla::ipc::Transport* transport,
base::ProcessId otherProcess) MOZ_OVERRIDE;
PContentBridgeChild*
AllocPContentBridgeChild(mozilla::ipc::Transport* transport,
base::ProcessId otherProcess) MOZ_OVERRIDE;
PCompositorChild*
AllocPCompositorChild(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess) MOZ_OVERRIDE;
@ -318,7 +334,7 @@ public:
const uint64_t& aID,
const bool& aIsForApp,
const bool& aIsForBrowser) MOZ_OVERRIDE;
protected:
virtual bool RecvPBrowserConstructor(PBrowserChild* aCctor,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,

View File

@ -22,6 +22,8 @@
#include "chrome/common/process_watcher.h"
#include <set>
#include "AppProcessChecker.h"
#include "AudioChannelService.h"
#include "CrashReporterParent.h"
@ -35,6 +37,7 @@
#include "mozilla/dom/Element.h"
#include "mozilla/dom/DataStoreService.h"
#include "mozilla/dom/ExternalHelperAppParent.h"
#include "mozilla/dom/PContentBridgeParent.h"
#include "mozilla/dom/PFileDescriptorSetParent.h"
#include "mozilla/dom/PCycleCollectWithLogsParent.h"
#include "mozilla/dom/PMemoryReportRequestParent.h"
@ -550,6 +553,7 @@ ContentParent::RunNuwaProcess()
MOZ_ASSERT(NS_IsMainThread());
nsRefPtr<ContentParent> nuwaProcess =
new ContentParent(/* aApp = */ nullptr,
/* aOpener = */ nullptr,
/* aIsForBrowser = */ false,
/* aIsForPreallocated = */ true,
PROCESS_PRIORITY_BACKGROUND,
@ -566,6 +570,7 @@ ContentParent::PreallocateAppProcess()
{
nsRefPtr<ContentParent> process =
new ContentParent(/* app = */ nullptr,
/* aOpener = */ nullptr,
/* isForBrowserElement = */ false,
/* isForPreallocated = */ true,
PROCESS_PRIORITY_PREALLOC);
@ -596,16 +601,14 @@ ContentParent::MaybeTakePreallocatedAppProcess(const nsAString& aAppManifestURL,
/*static*/ void
ContentParent::StartUp()
{
if (XRE_GetProcessType() != GeckoProcessType_Default) {
return;
}
// Note: This reporter measures all ContentParents.
RegisterStrongMemoryReporter(new ContentParentsMemoryReporter());
mozilla::dom::time::InitializeDateCacheCleaner();
BackgroundChild::Startup();
if (XRE_GetProcessType() == GeckoProcessType_Default) {
BackgroundChild::Startup();
}
sCanLaunchSubprocesses = true;
@ -614,7 +617,9 @@ ContentParent::StartUp()
// Test the PBackground infrastructure on ENABLE_TESTS builds when a special
// testing preference is set.
MaybeTestPBackground();
if (XRE_GetProcessType() == GeckoProcessType_Default) {
MaybeTestPBackground();
}
}
/*static*/ void
@ -674,7 +679,9 @@ ContentParent::JoinAllSubprocesses()
}
/*static*/ already_AddRefed<ContentParent>
ContentParent::GetNewOrUsed(bool aForBrowserElement, ProcessPriority aPriority)
ContentParent::GetNewOrUsed(bool aForBrowserElement,
ProcessPriority aPriority,
ContentParent* aOpener)
{
if (!sNonAppContentParents)
sNonAppContentParents = new nsTArray<ContentParent*>();
@ -684,10 +691,16 @@ ContentParent::GetNewOrUsed(bool aForBrowserElement, ProcessPriority aPriority)
maxContentProcesses = 1;
if (sNonAppContentParents->Length() >= uint32_t(maxContentProcesses)) {
uint32_t idx = rand() % sNonAppContentParents->Length();
nsRefPtr<ContentParent> p = (*sNonAppContentParents)[idx];
NS_ASSERTION(p->IsAlive(), "Non-alive contentparent in sNonAppContentParents?");
return p.forget();
uint32_t startIdx = rand() % sNonAppContentParents->Length();
uint32_t currIdx = startIdx;
do {
nsRefPtr<ContentParent> p = (*sNonAppContentParents)[currIdx];
NS_ASSERTION(p->IsAlive(), "Non-alive contentparent in sNonAppContntParents?");
if (p->mOpener == aOpener) {
return p.forget();
}
currIdx = (currIdx + 1) % sNonAppContentParents->Length();
} while (currIdx != startIdx);
}
// Try to take and transform the preallocated process into browser.
@ -703,6 +716,7 @@ ContentParent::GetNewOrUsed(bool aForBrowserElement, ProcessPriority aPriority)
}
#endif
p = new ContentParent(/* app = */ nullptr,
aOpener,
aForBrowserElement,
/* isForPreallocated = */ false,
aPriority);
@ -760,6 +774,57 @@ ContentParent::RunAfterPreallocatedProcessReady(nsIRunnable* aRequest)
#endif
}
typedef std::map<ContentParent*, std::set<ContentParent*> > GrandchildMap;
static GrandchildMap sGrandchildProcessMap;
std::map<uint64_t, ContentParent*> sContentParentMap;
bool
ContentParent::RecvCreateChildProcess(const IPCTabContext& aContext,
const hal::ProcessPriority& aPriority,
uint64_t* aId,
bool* aIsForApp,
bool* aIsForBrowser)
{
#if 0
if (!CanOpenBrowser(aContext)) {
return false;
}
#endif
nsRefPtr<ContentParent> cp = GetNewOrUsed(/* isBrowserElement = */ true,
aPriority,
this);
*aId = cp->ChildID();
*aIsForApp = cp->IsForApp();
*aIsForBrowser = cp->IsForBrowser();
sContentParentMap[*aId] = cp;
auto iter = sGrandchildProcessMap.find(this);
if (iter == sGrandchildProcessMap.end()) {
std::set<ContentParent*> children;
children.insert(cp);
sGrandchildProcessMap[this] = children;
} else {
iter->second.insert(cp);
}
return true;
}
bool
ContentParent::AnswerBridgeToChildProcess(const uint64_t& id)
{
ContentParent* cp = sContentParentMap[id];
auto iter = sGrandchildProcessMap.find(this);
if (iter != sGrandchildProcessMap.end() &&
iter->second.find(cp) != iter->second.end()) {
return PContentBridge::Bridge(this, cp);
} else {
// You can't bridge to a process you didn't open!
KillHard();
return false;
}
}
/*static*/ TabParent*
ContentParent::CreateBrowserOrApp(const TabContext& aContext,
Element* aFrameElement)
@ -771,19 +836,50 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
ProcessPriority initialPriority = GetInitialProcessPriority(aFrameElement);
if (aContext.IsBrowserElement() || !aContext.HasOwnApp()) {
nsRefPtr<ContentParent> cp = GetNewOrUsed(aContext.IsBrowserElement(),
initialPriority);
if (cp) {
nsRefPtr<TabParent> tp;
nsRefPtr<nsIContentParent> constructorSender;
if (XRE_GetProcessType() != GeckoProcessType_Default) {
MOZ_ASSERT(aContext.IsBrowserElement());
ContentChild* child = ContentChild::GetSingleton();
uint64_t id;
bool isForApp;
bool isForBrowser;
if (!child->SendCreateChildProcess(aContext.AsIPCTabContext(),
initialPriority,
&id,
&isForApp,
&isForBrowser)) {
return nullptr;
}
if (!child->CallBridgeToChildProcess(id)) {
return nullptr;
}
ContentBridgeParent* parent = child->GetLastBridge();
parent->SetChildID(id);
parent->SetIsForApp(isForApp);
parent->SetIsForBrowser(isForBrowser);
constructorSender = parent;
} else if (nsRefPtr<ContentParent> cp =
GetNewOrUsed(aContext.IsBrowserElement(), initialPriority)) {
constructorSender = cp;
}
if (constructorSender) {
uint32_t chromeFlags = 0;
// Propagate the private-browsing status of the element's parent
// docshell to the remote docshell, via the chrome flags.
nsCOMPtr<Element> frameElement = do_QueryInterface(aFrameElement);
MOZ_ASSERT(frameElement);
nsIDocShell* docShell =
frameElement->OwnerDoc()->GetWindow()->GetDocShell();
MOZ_ASSERT(docShell);
nsPIDOMWindow* win = frameElement->OwnerDoc()->GetWindow();
if (!win) {
NS_WARNING("Remote frame has no window");
return nullptr;
}
nsIDocShell* docShell = win->GetDocShell();
if (!docShell) {
NS_WARNING("Remote frame has no docshell");
return nullptr;
}
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
if (loadContext && loadContext->UsePrivateBrowsing()) {
chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW;
@ -794,17 +890,18 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME;
}
nsRefPtr<TabParent> tp(new TabParent(cp, aContext, chromeFlags));
nsRefPtr<TabParent> tp(new TabParent(constructorSender,
aContext, chromeFlags));
tp->SetOwnerElement(aFrameElement);
PBrowserParent* browser = cp->SendPBrowserConstructor(
PBrowserParent* browser = constructorSender->SendPBrowserConstructor(
// DeallocPBrowserParent() releases this ref.
tp.forget().take(),
aContext.AsIPCTabContext(),
chromeFlags,
cp->ChildID(),
cp->IsForApp(),
cp->IsForBrowser());
constructorSender->ChildID(),
constructorSender->IsForApp(),
constructorSender->IsForBrowser());
return static_cast<TabParent*>(browser);
}
return nullptr;
@ -886,6 +983,7 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
#endif
NS_WARNING("Unable to use pre-allocated app process");
p = new ContentParent(ownApp,
/* aOpener = */ nullptr,
/* isForBrowserElement = */ false,
/* isForPreallocated = */ false,
initialPriority);
@ -1230,6 +1328,13 @@ ContentParent::MarkAsDead()
}
mIsAlive = false;
sGrandchildProcessMap.erase(this);
for (auto iter = sGrandchildProcessMap.begin();
iter != sGrandchildProcessMap.end();
iter++) {
iter->second.erase(this);
}
}
void
@ -1423,6 +1528,19 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
// This runnable ensures that a reference to |this| lives on at
// least until after the current task finishes running.
NS_DispatchToCurrentThread(new DelayedDeleteContentParentTask(this));
// Destroy any processes created by this ContentParent
auto iter = sGrandchildProcessMap.find(this);
if (iter != sGrandchildProcessMap.end()) {
for(auto child = iter->second.begin();
child != iter->second.end();
child++) {
MessageLoop::current()->PostTask(
FROM_HERE,
NewRunnableMethod(*child, &ContentParent::ShutDownProcess,
/* closeWithError */ false));
}
}
}
void
@ -1519,11 +1637,13 @@ ContentParent::InitializeMembers()
}
ContentParent::ContentParent(mozIApplication* aApp,
ContentParent* aOpener,
bool aIsForBrowser,
bool aIsForPreallocated,
ProcessPriority aInitialPriority /* = PROCESS_PRIORITY_FOREGROUND */,
bool aIsNuwaProcess /* = false */)
: nsIContentParent()
, mOpener(aOpener)
, mIsForBrowser(aIsForBrowser)
, mIsNuwaProcess(aIsNuwaProcess)
{
@ -3297,6 +3417,22 @@ ContentParent::RecvSystemMessageHandled()
return true;
}
PBrowserParent*
ContentParent::SendPBrowserConstructor(PBrowserParent* aActor,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const uint64_t& aId,
const bool& aIsForApp,
const bool& aIsForBrowser)
{
return PContentParent::SendPBrowserConstructor(aActor,
aContext,
aChromeFlags,
aId,
aIsForApp,
aIsForBrowser);
}
bool
ContentParent::RecvCreateFakeVolume(const nsString& fsName, const nsString& mountPoint)
{

View File

@ -98,7 +98,8 @@ public:
static already_AddRefed<ContentParent>
GetNewOrUsed(bool aForBrowserElement = false,
hal::ProcessPriority aPriority =
hal::ProcessPriority::PROCESS_PRIORITY_FOREGROUND);
hal::ProcessPriority::PROCESS_PRIORITY_FOREGROUND,
ContentParent* aOpener = nullptr);
/**
* Create a subprocess suitable for use as a preallocated app process.
@ -119,6 +120,13 @@ public:
static void GetAll(nsTArray<ContentParent*>& aArray);
static void GetAllEvenIfDead(nsTArray<ContentParent*>& aArray);
virtual bool RecvCreateChildProcess(const IPCTabContext& aContext,
const hal::ProcessPriority& aPriority,
uint64_t* aId,
bool* aIsForApp,
bool* aIsForBrowser) MOZ_OVERRIDE;
virtual bool AnswerBridgeToChildProcess(const uint64_t& id) MOZ_OVERRIDE;
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(ContentParent, nsIObserver)
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@ -153,8 +161,8 @@ public:
bool RequestRunToCompletion();
bool IsAlive();
bool IsForApp();
bool IsForBrowser()
virtual bool IsForApp() MOZ_OVERRIDE;
virtual bool IsForBrowser() MOZ_OVERRIDE
{
return mIsForBrowser;
}
@ -168,6 +176,10 @@ public:
int32_t Pid();
ContentParent* Opener() {
return mOpener;
}
bool NeedsPermissionsUpdate() const {
return mSendPermissionUpdates;
}
@ -273,12 +285,19 @@ private:
// Hide the raw constructor methods since we don't want client code
// using them.
using PContentParent::SendPBrowserConstructor;
virtual PBrowserParent* SendPBrowserConstructor(
PBrowserParent* actor,
const IPCTabContext& context,
const uint32_t& chromeFlags,
const uint64_t& aId,
const bool& aIsForApp,
const bool& aIsForBrowser) MOZ_OVERRIDE;
using PContentParent::SendPTestShellConstructor;
// No more than one of !!aApp, aIsForBrowser, and aIsForPreallocated may be
// true.
ContentParent(mozIApplication* aApp,
ContentParent* aOpener,
bool aIsForBrowser,
bool aIsForPreallocated,
hal::ProcessPriority aInitialPriority = hal::PROCESS_PRIORITY_FOREGROUND,
@ -595,6 +614,7 @@ private:
// details.
GeckoChildProcessHost* mSubprocess;
ContentParent* mOpener;
uint64_t mChildID;
int32_t mGeolocationWatchID;

View File

@ -113,7 +113,7 @@ FilePickerParent::FileSizeAndDateRunnable::Destroy()
void
FilePickerParent::SendFiles(const nsCOMArray<nsIDOMFile>& aDomfiles)
{
ContentParent* parent = static_cast<ContentParent*>(Manager()->Manager());
nsIContentParent* parent = static_cast<TabParent*>(Manager())->Manager();
InfallibleTArray<PBlobParent*> files;
for (unsigned i = 0; i < aDomfiles.Length(); i++) {

View File

@ -4,6 +4,7 @@
include protocol PBlobStream;
include protocol PContent;
include protocol PContentBridge;
include DOMTypes;
@ -18,7 +19,7 @@ union ResolveMysteryParams
protocol PBlob
{
manager PContent;
manager PContent or PContentBridge;
manages PBlobStream;
both:

View File

@ -8,6 +8,7 @@
include protocol PBlob;
include protocol PColorPicker;
include protocol PContent;
include protocol PContentBridge;
include protocol PDocumentRenderer;
include protocol PContentPermissionRequest;
include protocol PFilePicker;
@ -70,7 +71,7 @@ union MaybeNativeKeyBinding
intr protocol PBrowser
{
manager PContent;
manager PContent or PContentBridge;
manages PColorPicker;
manages PDocumentRenderer;

View File

@ -10,6 +10,7 @@ include protocol PBlob;
include protocol PBluetooth;
include protocol PBrowser;
include protocol PCompositor;
include protocol PContentBridge;
include protocol PCycleCollectWithLogs;
include protocol PCrashReporter;
include protocol PExternalHelperApp;
@ -443,6 +444,11 @@ parent:
sync GetXPCOMProcessAttributes()
returns (bool isOffline);
sync CreateChildProcess(IPCTabContext context,
ProcessPriority priority)
returns (uint64_t id, bool isForApp, bool isForBrowser);
intr BridgeToChildProcess(uint64_t id);
async PJavaScript();
PDeviceStorageRequest(DeviceStorageParams params);

View File

@ -0,0 +1,56 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBlob;
include protocol PBrowser;
include protocol PContent;
include protocol PJavaScript;
include DOMTypes;
include JavaScriptTypes;
include PTabContext;
using class IPC::Principal from "mozilla/dom/PermissionMessageUtils.h";
namespace mozilla {
namespace dom {
/*
* PContentBridge allows us to represent a parent/child relationship between two
* child processes. When a child process wants to open its own child, it asks
* the root process to create a new process and then bridge them. The first
* child will allocate the PContentBridgeParent, and the newly opened child will
* allocate the PContentBridgeChild. This protocol allows these processes to
* share PBrowsers and send messages to each other.
*/
intr protocol PContentBridge
{
bridges PContent, PContent;
manages PBlob;
manages PBrowser;
manages PJavaScript;
parent:
sync SyncMessage(nsString aMessage, ClonedMessageData aData,
CpowEntry[] aCpows, Principal aPrincipal)
returns (nsString[] retval);
both:
// Both the parent and the child can construct the PBrowser.
// See the comment in PContent::PBrowser().
async PBrowser(IPCTabContext context, uint32_t chromeFlags,
uint64_t id, bool isForApp, bool isForBrowser);
async PBlob(BlobConstructorParams params);
async PJavaScript();
AsyncMessage(nsString aMessage, ClonedMessageData aData,
CpowEntry[] aCpows, Principal aPrincipal);
};
}
}

View File

@ -17,6 +17,8 @@ EXPORTS.mozilla.dom.ipc += [
]
EXPORTS.mozilla.dom += [
'ContentBridgeChild.h',
'ContentBridgeParent.h',
'ContentChild.h',
'ContentParent.h',
'ContentProcess.h',
@ -44,6 +46,8 @@ EXPORTS.mozilla += [
UNIFIED_SOURCES += [
'AppProcessChecker.cpp',
'ColorPickerParent.cpp',
'ContentBridgeChild.cpp',
'ContentBridgeParent.cpp',
'ContentParent.cpp',
'ContentProcess.cpp',
'CrashReporterParent.cpp',
@ -79,6 +83,7 @@ IPDL_SOURCES += [
'PBrowser.ipdl',
'PColorPicker.ipdl',
'PContent.ipdl',
'PContentBridge.ipdl',
'PContentPermission.ipdlh',
'PContentPermissionRequest.ipdl',
'PCrashReporter.ipdl',

View File

@ -64,6 +64,46 @@ nsIContentParent::DeallocPJavaScriptParent(PJavaScriptParent* aParent)
return true;
}
bool
nsIContentParent::CanOpenBrowser(const IPCTabContext& aContext)
{
const IPCTabAppBrowserContext& appBrowser = aContext.appBrowserContext();
// We don't trust the IPCTabContext we receive from the child, so we'll bail
// if we receive an IPCTabContext that's not a PopupIPCTabContext.
// (PopupIPCTabContext lets the child process prove that it has access to
// the app it's trying to open.)
if (appBrowser.type() != IPCTabAppBrowserContext::TPopupIPCTabContext) {
NS_ERROR("Unexpected IPCTabContext type. Aborting AllocPBrowserParent.");
return false;
}
const PopupIPCTabContext& popupContext = appBrowser.get_PopupIPCTabContext();
TabParent* opener = static_cast<TabParent*>(popupContext.openerParent());
if (!opener) {
NS_ERROR("Got null opener from child; aborting AllocPBrowserParent.");
return false;
}
// Popup windows of isBrowser frames must be isBrowser if the parent
// isBrowser. Allocating a !isBrowser frame with same app ID would allow
// the content to access data it's not supposed to.
if (!popupContext.isBrowserElement() && opener->IsBrowserElement()) {
NS_ERROR("Child trying to escalate privileges! Aborting AllocPBrowserParent.");
return false;
}
MaybeInvalidTabContext tc(aContext);
if (!tc.IsValid()) {
NS_ERROR(nsPrintfCString("Child passed us an invalid TabContext. (%s) "
"Aborting AllocPBrowserParent.",
tc.GetInvalidReason()).get());
return false;
}
return true;
}
PBrowserParent*
nsIContentParent::AllocPBrowserParent(const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
@ -76,40 +116,12 @@ nsIContentParent::AllocPBrowserParent(const IPCTabContext& aContext,
unused << aIsForApp;
unused << aIsForBrowser;
const IPCTabAppBrowserContext& appBrowser = aContext.appBrowserContext();
// We don't trust the IPCTabContext we receive from the child, so we'll bail
// if we receive an IPCTabContext that's not a PopupIPCTabContext.
// (PopupIPCTabContext lets the child process prove that it has access to
// the app it's trying to open.)
if (appBrowser.type() != IPCTabAppBrowserContext::TPopupIPCTabContext) {
NS_ERROR("Unexpected IPCTabContext type. Aborting AllocPBrowserParent.");
return nullptr;
}
const PopupIPCTabContext& popupContext = appBrowser.get_PopupIPCTabContext();
TabParent* opener = static_cast<TabParent*>(popupContext.openerParent());
if (!opener) {
NS_ERROR("Got null opener from child; aborting AllocPBrowserParent.");
return nullptr;
}
// Popup windows of isBrowser frames must be isBrowser if the parent
// isBrowser. Allocating a !isBrowser frame with same app ID would allow
// the content to access data it's not supposed to.
if (!popupContext.isBrowserElement() && opener->IsBrowserElement()) {
NS_ERROR("Child trying to escalate privileges! Aborting AllocPBrowserParent.");
if (!CanOpenBrowser(aContext)) {
return nullptr;
}
MaybeInvalidTabContext tc(aContext);
if (!tc.IsValid()) {
NS_ERROR(nsPrintfCString("Child passed us an invalid TabContext. (%s) "
"Aborting AllocPBrowserParent.",
tc.GetInvalidReason()).get());
return nullptr;
}
MOZ_ASSERT(tc.IsValid());
TabParent* parent = new TabParent(this, tc.GetTabContext(), aChromeFlags);
// We release this ref in DeallocPBrowserParent()

View File

@ -44,16 +44,29 @@ public:
BlobParent* GetOrCreateActorForBlob(nsIDOMBlob* aBlob);
virtual uint64_t ChildID() = 0;
virtual bool IsForApp() = 0;
virtual bool IsForBrowser() = 0;
virtual PBlobParent* SendPBlobConstructor(
PBlobParent* actor,
const BlobConstructorParams& params) NS_WARN_UNUSED_RESULT = 0;
virtual PBrowserParent* SendPBrowserConstructor(
PBrowserParent* actor,
const IPCTabContext& context,
const uint32_t& chromeFlags,
const uint64_t& aId,
const bool& aIsForApp,
const bool& aIsForBrowser) NS_WARN_UNUSED_RESULT = 0;
virtual jsipc::JavaScriptParent *GetCPOWManager() = 0;
virtual bool IsContentParent() { return false; }
ContentParent* AsContentParent();
protected: // methods
bool CanOpenBrowser(const IPCTabContext& aContext);
protected: // IPDL methods
virtual mozilla::jsipc::PJavaScriptParent* AllocPJavaScriptParent();
virtual bool DeallocPJavaScriptParent(mozilla::jsipc::PJavaScriptParent*);

View File

@ -4240,7 +4240,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
case.addstmts([
StmtDecl(Decl(Type('Transport', ptr=1), tvar.name)),
StmtDecl(Decl(Type(_actorName(actor.ptype.name(), self.side),
StmtDecl(Decl(Type(_actorName(actor.ptype.name(), actor.side),
ptr=1), pvar.name)),
iffailopen,
iffailalloc,

View File

@ -6,6 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PContent;
include protocol PContentBridge;
include DOMTypes;
include JavaScriptTypes;
@ -16,7 +17,7 @@ namespace jsipc {
intr protocol PJavaScript
{
manager PContent;
manager PContent or PContentBridge;
both:
// Sent when a CPOW has been finalized and table entries can be freed up.