mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 956218 - '(PBackground) Add a mechanism for communicating with
a non-main I/O thread via thread and process links'. r=mrbkap+khuey+bsmedberg.
This commit is contained in:
parent
0282e9aebb
commit
4891b5f251
@ -23,6 +23,7 @@
|
||||
#include "mozilla/dom/PCrashReporterChild.h"
|
||||
#include "mozilla/dom/DOMStorageIPC.h"
|
||||
#include "mozilla/hal_sandbox/PHalChild.h"
|
||||
#include "mozilla/ipc/BackgroundChild.h"
|
||||
#include "mozilla/ipc/GeckoChildProcessHost.h"
|
||||
#include "mozilla/ipc/TestShellChild.h"
|
||||
#include "mozilla/layers/CompositorChild.h"
|
||||
@ -43,6 +44,7 @@
|
||||
#include "mozilla/unused.h"
|
||||
|
||||
#include "nsIConsoleListener.h"
|
||||
#include "nsIIPCBackgroundChildCreateCallback.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "nsIMemoryInfoDumper.h"
|
||||
@ -310,6 +312,34 @@ SystemMessageHandledObserver::Observe(nsISupports* aSubject,
|
||||
|
||||
NS_IMPL_ISUPPORTS1(SystemMessageHandledObserver, nsIObserver)
|
||||
|
||||
class BackgroundChildPrimer MOZ_FINAL :
|
||||
public nsIIPCBackgroundChildCreateCallback
|
||||
{
|
||||
public:
|
||||
BackgroundChildPrimer()
|
||||
{ }
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
private:
|
||||
~BackgroundChildPrimer()
|
||||
{ }
|
||||
|
||||
virtual void
|
||||
ActorCreated(PBackgroundChild* aActor) MOZ_OVERRIDE
|
||||
{
|
||||
MOZ_ASSERT(aActor, "Failed to create a PBackgroundChild actor!");
|
||||
}
|
||||
|
||||
virtual void
|
||||
ActorFailed() MOZ_OVERRIDE
|
||||
{
|
||||
MOZ_CRASH("Failed to create a PBackgroundChild actor!");
|
||||
}
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(BackgroundChildPrimer, nsIIPCBackgroundChildCreateCallback)
|
||||
|
||||
ContentChild* ContentChild::sSingleton;
|
||||
|
||||
// Performs initialization that is not fork-safe, i.e. that must be done after
|
||||
@ -451,6 +481,16 @@ ContentChild::AppendProcessId(nsACString& aName)
|
||||
void
|
||||
ContentChild::InitXPCOM()
|
||||
{
|
||||
// Do this as early as possible to get the parent process to initialize the
|
||||
// background thread since we'll likely need database information very soon.
|
||||
BackgroundChild::Startup();
|
||||
|
||||
nsCOMPtr<nsIIPCBackgroundChildCreateCallback> callback =
|
||||
new BackgroundChildPrimer();
|
||||
if (!BackgroundChild::GetOrCreateForCurrentThread(callback)) {
|
||||
MOZ_CRASH("Failed to create PBackgroundChild!");
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
|
||||
if (!svc) {
|
||||
NS_WARNING("Couldn't acquire console service");
|
||||
@ -606,6 +646,13 @@ ContentChild::AllocPImageBridgeChild(mozilla::ipc::Transport* aTransport,
|
||||
return ImageBridgeChild::StartUpInChildProcess(aTransport, aOtherProcess);
|
||||
}
|
||||
|
||||
PBackgroundChild*
|
||||
ContentChild::AllocPBackgroundChild(Transport* aTransport,
|
||||
ProcessId aOtherProcess)
|
||||
{
|
||||
return BackgroundChild::Alloc(aTransport, aOtherProcess);
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::RecvSetProcessPrivileges(const ChildPrivileges& aPrivs)
|
||||
{
|
||||
@ -1686,6 +1733,20 @@ ContentChild::RecvNuwaFork()
|
||||
}
|
||||
sNuwaForking = true;
|
||||
|
||||
// We want to ensure that the PBackground actor gets cloned in the Nuwa
|
||||
// process before we freeze. Also, we have to do this to avoid deadlock.
|
||||
// Protocols that are "opened" (e.g. PBackground, PCompositor) block the
|
||||
// main thread to wait for the IPC thread during the open operation.
|
||||
// NuwaSpawnWait() blocks the IPC thread to wait for the main thread when
|
||||
// the Nuwa process is forked. Unless we ensure that the two cannot happen
|
||||
// at the same time then we risk deadlock. Spinning the event loop here
|
||||
// guarantees the ordering is safe for PBackground.
|
||||
while (!BackgroundChild::GetForCurrentThread()) {
|
||||
if (NS_WARN_IF(NS_FAILED(NS_ProcessNextEvent()))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
MessageLoop* ioloop = XRE_GetIOMessageLoop();
|
||||
ioloop->PostTask(FROM_HERE, NewRunnableFunction(RunNuwaFork));
|
||||
return true;
|
||||
|
@ -88,6 +88,10 @@ public:
|
||||
|
||||
virtual bool RecvSetProcessPrivileges(const ChildPrivileges& aPrivs) MOZ_OVERRIDE;
|
||||
|
||||
PBackgroundChild*
|
||||
AllocPBackgroundChild(Transport* aTransport, ProcessId aOtherProcess)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
virtual PBrowserChild* AllocPBrowserChild(const IPCTabContext &aContext,
|
||||
const uint32_t &chromeFlags);
|
||||
virtual bool DeallocPBrowserChild(PBrowserChild*);
|
||||
|
@ -39,6 +39,8 @@
|
||||
#include "mozilla/dom/telephony/TelephonyParent.h"
|
||||
#include "SmsParent.h"
|
||||
#include "mozilla/hal_sandbox/PHalParent.h"
|
||||
#include "mozilla/ipc/BackgroundChild.h"
|
||||
#include "mozilla/ipc/BackgroundParent.h"
|
||||
#include "mozilla/ipc/TestShellParent.h"
|
||||
#include "mozilla/ipc/InputStreamUtils.h"
|
||||
#include "mozilla/layers/CompositorParent.h"
|
||||
@ -138,6 +140,11 @@ using namespace mozilla::system;
|
||||
#include "mozilla/dom/SpeechSynthesisParent.h"
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_TESTS
|
||||
#include "mozilla/ipc/PBackgroundChild.h"
|
||||
#include "nsIIPCBackgroundChildCreateCallback.h"
|
||||
#endif
|
||||
|
||||
static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
|
||||
static const char* sClipboardTextFlavors[] = { kUnicodeMime };
|
||||
|
||||
@ -155,6 +162,127 @@ using namespace mozilla::layers;
|
||||
using namespace mozilla::net;
|
||||
using namespace mozilla::jsipc;
|
||||
|
||||
#ifdef ENABLE_TESTS
|
||||
|
||||
class BackgroundTester MOZ_FINAL : public nsIIPCBackgroundChildCreateCallback,
|
||||
public nsIObserver
|
||||
{
|
||||
static uint32_t sCallbackCount;
|
||||
|
||||
private:
|
||||
~BackgroundTester()
|
||||
{ }
|
||||
|
||||
virtual void
|
||||
ActorCreated(PBackgroundChild* aActor) MOZ_OVERRIDE
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(aActor,
|
||||
"Failed to create a PBackgroundChild actor!");
|
||||
|
||||
NS_NAMED_LITERAL_CSTRING(testStr, "0123456789");
|
||||
|
||||
PBackgroundTestChild* testActor =
|
||||
aActor->SendPBackgroundTestConstructor(testStr);
|
||||
MOZ_RELEASE_ASSERT(testActor);
|
||||
|
||||
if (!sCallbackCount) {
|
||||
PBackgroundChild* existingBackgroundChild =
|
||||
BackgroundChild::GetForCurrentThread();
|
||||
|
||||
MOZ_RELEASE_ASSERT(existingBackgroundChild);
|
||||
MOZ_RELEASE_ASSERT(existingBackgroundChild == aActor);
|
||||
|
||||
bool ok =
|
||||
existingBackgroundChild->
|
||||
SendPBackgroundTestConstructor(testStr);
|
||||
MOZ_RELEASE_ASSERT(ok);
|
||||
|
||||
// Callback 3.
|
||||
ok = BackgroundChild::GetOrCreateForCurrentThread(this);
|
||||
MOZ_RELEASE_ASSERT(ok);
|
||||
}
|
||||
|
||||
sCallbackCount++;
|
||||
}
|
||||
|
||||
virtual void
|
||||
ActorFailed() MOZ_OVERRIDE
|
||||
{
|
||||
MOZ_CRASH("Failed to create a PBackgroundChild actor!");
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
|
||||
MOZ_OVERRIDE
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
mozilla::services::GetObserverService();
|
||||
MOZ_RELEASE_ASSERT(observerService);
|
||||
|
||||
nsresult rv = observerService->RemoveObserver(this, aTopic);
|
||||
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
if (!strcmp(aTopic, "profile-after-change")) {
|
||||
if (mozilla::Preferences::GetBool("pbackground.testing", false)) {
|
||||
rv = observerService->AddObserver(this, "xpcom-shutdown",
|
||||
false);
|
||||
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
// Callback 1.
|
||||
bool ok = BackgroundChild::GetOrCreateForCurrentThread(this);
|
||||
MOZ_RELEASE_ASSERT(ok);
|
||||
|
||||
// Callback 2.
|
||||
ok = BackgroundChild::GetOrCreateForCurrentThread(this);
|
||||
MOZ_RELEASE_ASSERT(ok);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, "xpcom-shutdown")) {
|
||||
MOZ_RELEASE_ASSERT(sCallbackCount == 3);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_CRASH("Unknown observer topic!");
|
||||
}
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
};
|
||||
|
||||
uint32_t BackgroundTester::sCallbackCount = 0;
|
||||
|
||||
NS_IMPL_ISUPPORTS2(BackgroundTester, nsIIPCBackgroundChildCreateCallback,
|
||||
nsIObserver)
|
||||
|
||||
#endif // ENABLE_TESTS
|
||||
|
||||
void
|
||||
MaybeTestPBackground()
|
||||
{
|
||||
#ifdef ENABLE_TESTS
|
||||
// This test relies on running the event loop and XPCShell does not always
|
||||
// do so. Bail out here if we detect that we're running in XPCShell.
|
||||
if (PR_GetEnv("XPCSHELL_TEST_PROFILE_DIR")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// This is called too early at startup to test preferences directly. We have
|
||||
// to install an observer to be notified when preferences are available.
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
mozilla::services::GetObserverService();
|
||||
MOZ_RELEASE_ASSERT(observerService);
|
||||
|
||||
nsCOMPtr<nsIObserver> observer = new BackgroundTester();
|
||||
nsresult rv = observerService->AddObserver(observer, "profile-after-change",
|
||||
false);
|
||||
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
@ -360,10 +488,16 @@ ContentParent::StartUp()
|
||||
// Note: This reporter measures all ContentParents.
|
||||
RegisterStrongMemoryReporter(new ContentParentsMemoryReporter());
|
||||
|
||||
BackgroundChild::Startup();
|
||||
|
||||
sCanLaunchSubprocesses = true;
|
||||
|
||||
// Try to preallocate a process that we can transform into an app later.
|
||||
PreallocatedProcessManager::AllocateAfterDelay();
|
||||
|
||||
// Test the PBackground infrastructure on ENABLE_TESTS builds when a special
|
||||
// testing preference is set.
|
||||
MaybeTestPBackground();
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
@ -1973,6 +2107,13 @@ ContentParent::AllocPImageBridgeParent(mozilla::ipc::Transport* aTransport,
|
||||
return ImageBridgeParent::Create(aTransport, aOtherProcess);
|
||||
}
|
||||
|
||||
PBackgroundParent*
|
||||
ContentParent::AllocPBackgroundParent(Transport* aTransport,
|
||||
ProcessId aOtherProcess)
|
||||
{
|
||||
return BackgroundParent::Alloc(this, aTransport, aOtherProcess);
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvGetProcessAttributes(uint64_t* aId,
|
||||
bool* aIsForApp, bool* aIsForBrowser)
|
||||
|
@ -327,6 +327,10 @@ private:
|
||||
AllocPImageBridgeParent(mozilla::ipc::Transport* aTransport,
|
||||
base::ProcessId aOtherProcess) MOZ_OVERRIDE;
|
||||
|
||||
PBackgroundParent*
|
||||
AllocPBackgroundParent(Transport* aTransport, ProcessId aOtherProcess)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
virtual bool RecvGetProcessAttributes(uint64_t* aId,
|
||||
bool* aIsForApp,
|
||||
bool* aIsForBrowser) MOZ_OVERRIDE;
|
||||
|
@ -5,6 +5,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
include protocol PAsmJSCacheEntry;
|
||||
include protocol PBackground;
|
||||
include protocol PBlob;
|
||||
include protocol PBluetooth;
|
||||
include protocol PBrowser;
|
||||
@ -199,6 +200,7 @@ intr protocol PContent
|
||||
{
|
||||
parent opens PCompositor;
|
||||
parent opens PImageBridge;
|
||||
child opens PBackground;
|
||||
|
||||
manages PAsmJSCacheEntry;
|
||||
manages PBlob;
|
||||
|
@ -124,4 +124,8 @@ for var in ('MOZ_PERMISSIONS', 'MOZ_CHILD_PERMISSIONS'):
|
||||
if CONFIG[var]:
|
||||
DEFINES[var] = True
|
||||
|
||||
if CONFIG['ENABLE_TESTS']:
|
||||
DEFINES['ENABLE_TESTS'] = 1
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
|
||||
|
72
ipc/glue/BackgroundChild.h
Normal file
72
ipc/glue/BackgroundChild.h
Normal file
@ -0,0 +1,72 @@
|
||||
/* 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_ipc_backgroundchild_h__
|
||||
#define mozilla_ipc_backgroundchild_h__
|
||||
|
||||
#include "base/process.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ipc/Transport.h"
|
||||
|
||||
class nsIIPCBackgroundChildCreateCallback;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ContentChild;
|
||||
class ContentParent;
|
||||
|
||||
} // namespace dom
|
||||
|
||||
namespace ipc {
|
||||
|
||||
class PBackgroundChild;
|
||||
|
||||
// This class allows access to the PBackground protocol. PBackground allows
|
||||
// communication between any thread (in the parent or a child process) and a
|
||||
// single background thread in the parent process. Each PBackgroundChild
|
||||
// instance is tied to the thread on which it is created and must not be shared
|
||||
// across threads. Each PBackgroundChild is unique and valid as long as its
|
||||
// designated thread lives.
|
||||
//
|
||||
// Creation of PBackground is asynchronous. GetForCurrentThread() will return
|
||||
// null until the sequence is complete. GetOrCreateForCurrentThread() will start
|
||||
// the creation sequence and will call back via the
|
||||
// nsIIPCBackgroundChildCreateCallback interface when completed. Thereafter
|
||||
// (assuming success) GetForCurrentThread() will return the same actor every
|
||||
// time.
|
||||
//
|
||||
// The PBackgroundChild actor and all its sub-protocol actors will be
|
||||
// automatically destroyed when its designated thread completes.
|
||||
class BackgroundChild MOZ_FINAL
|
||||
{
|
||||
friend class mozilla::dom::ContentChild;
|
||||
friend class mozilla::dom::ContentParent;
|
||||
|
||||
typedef base::ProcessId ProcessId;
|
||||
typedef mozilla::ipc::Transport Transport;
|
||||
|
||||
public:
|
||||
// See above.
|
||||
static PBackgroundChild*
|
||||
GetForCurrentThread();
|
||||
|
||||
// See above.
|
||||
static bool
|
||||
GetOrCreateForCurrentThread(nsIIPCBackgroundChildCreateCallback* aCallback);
|
||||
|
||||
private:
|
||||
// Only called by ContentChild or ContentParent.
|
||||
static void
|
||||
Startup();
|
||||
|
||||
// Only called by ContentChild.
|
||||
static PBackgroundChild*
|
||||
Alloc(Transport* aTransport, ProcessId aOtherProcess);
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_ipc_backgroundchild_h__
|
81
ipc/glue/BackgroundChildImpl.cpp
Normal file
81
ipc/glue/BackgroundChildImpl.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
/* 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 "BackgroundChildImpl.h"
|
||||
|
||||
#include "mozilla/ipc/PBackgroundTestChild.h"
|
||||
#include "nsTraceRefcnt.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class TestChild MOZ_FINAL : public mozilla::ipc::PBackgroundTestChild
|
||||
{
|
||||
friend class mozilla::ipc::BackgroundChildImpl;
|
||||
|
||||
nsCString mTestArg;
|
||||
|
||||
TestChild(const nsCString& aTestArg)
|
||||
: mTestArg(aTestArg)
|
||||
{
|
||||
MOZ_COUNT_CTOR(mozilla::ipc::BackgroundTestChild);
|
||||
}
|
||||
|
||||
~TestChild()
|
||||
{
|
||||
MOZ_COUNT_DTOR(mozilla::ipc::BackgroundTestChild);
|
||||
}
|
||||
|
||||
virtual bool
|
||||
Recv__delete__(const nsCString& aTestArg) MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
BackgroundChildImpl::BackgroundChildImpl()
|
||||
{
|
||||
// May happen on any thread!
|
||||
MOZ_COUNT_CTOR(mozilla::ipc::BackgroundChildImpl);
|
||||
}
|
||||
|
||||
BackgroundChildImpl::~BackgroundChildImpl()
|
||||
{
|
||||
// May happen on any thread!
|
||||
MOZ_COUNT_DTOR(mozilla::ipc::BackgroundChildImpl);
|
||||
}
|
||||
|
||||
void
|
||||
BackgroundChildImpl::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
// May happen on any thread!
|
||||
}
|
||||
|
||||
PBackgroundTestChild*
|
||||
BackgroundChildImpl::AllocPBackgroundTestChild(const nsCString& aTestArg)
|
||||
{
|
||||
return new TestChild(aTestArg);
|
||||
}
|
||||
|
||||
bool
|
||||
BackgroundChildImpl::DeallocPBackgroundTestChild(PBackgroundTestChild* aActor)
|
||||
{
|
||||
MOZ_ASSERT(aActor);
|
||||
|
||||
delete static_cast<TestChild*>(aActor);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
bool
|
||||
TestChild::Recv__delete__(const nsCString& aTestArg)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(aTestArg == mTestArg,
|
||||
"BackgroundTest message was corrupted!");
|
||||
|
||||
return true;
|
||||
}
|
35
ipc/glue/BackgroundChildImpl.h
Normal file
35
ipc/glue/BackgroundChildImpl.h
Normal file
@ -0,0 +1,35 @@
|
||||
/* 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_ipc_backgroundchildimpl_h__
|
||||
#define mozilla_ipc_backgroundchildimpl_h__
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ipc/PBackgroundChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
// Instances of this class should never be created directly. This class is meant
|
||||
// to be inherited in BackgroundImpl.
|
||||
class BackgroundChildImpl : public PBackgroundChild
|
||||
{
|
||||
protected:
|
||||
BackgroundChildImpl();
|
||||
virtual ~BackgroundChildImpl();
|
||||
|
||||
virtual void
|
||||
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
|
||||
|
||||
virtual PBackgroundTestChild*
|
||||
AllocPBackgroundTestChild(const nsCString& aTestArg) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
DeallocPBackgroundTestChild(PBackgroundTestChild* aActor) MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_ipc_backgroundchildimpl_h__
|
1800
ipc/glue/BackgroundImpl.cpp
Normal file
1800
ipc/glue/BackgroundImpl.cpp
Normal file
File diff suppressed because it is too large
Load Diff
62
ipc/glue/BackgroundParent.h
Normal file
62
ipc/glue/BackgroundParent.h
Normal file
@ -0,0 +1,62 @@
|
||||
/* 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_ipc_backgroundparent_h__
|
||||
#define mozilla_ipc_backgroundparent_h__
|
||||
|
||||
#include "base/process.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ipc/Transport.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ContentParent;
|
||||
|
||||
} // namespace dom
|
||||
|
||||
namespace ipc {
|
||||
|
||||
class PBackgroundParent;
|
||||
|
||||
// This class is not designed for public consumption. It must only be used by
|
||||
// ContentParent.
|
||||
class BackgroundParent MOZ_FINAL
|
||||
{
|
||||
friend class mozilla::dom::ContentParent;
|
||||
|
||||
typedef base::ProcessId ProcessId;
|
||||
typedef mozilla::dom::ContentParent ContentParent;
|
||||
typedef mozilla::ipc::Transport Transport;
|
||||
|
||||
private:
|
||||
// Only called by ContentParent for cross-process actors.
|
||||
static PBackgroundParent*
|
||||
Alloc(ContentParent* aContent,
|
||||
Transport* aTransport,
|
||||
ProcessId aOtherProcess);
|
||||
};
|
||||
|
||||
// Implemented in BackgroundImpl.cpp.
|
||||
bool
|
||||
IsOnBackgroundThread();
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
// Implemented in BackgroundImpl.cpp.
|
||||
void
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
#else
|
||||
|
||||
inline void
|
||||
AssertIsOnBackgroundThread()
|
||||
{ }
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_ipc_backgroundparent_h__
|
117
ipc/glue/BackgroundParentImpl.cpp
Normal file
117
ipc/glue/BackgroundParentImpl.cpp
Normal file
@ -0,0 +1,117 @@
|
||||
/* 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 "BackgroundParentImpl.h"
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/ipc/BackgroundParent.h"
|
||||
#include "mozilla/ipc/PBackgroundTestParent.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsTraceRefcnt.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
using mozilla::ipc::AssertIsOnBackgroundThread;
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
AssertIsInMainProcess()
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
}
|
||||
|
||||
void
|
||||
AssertIsOnMainThread()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
class TestParent MOZ_FINAL : public mozilla::ipc::PBackgroundTestParent
|
||||
{
|
||||
friend class mozilla::ipc::BackgroundParentImpl;
|
||||
|
||||
TestParent()
|
||||
{
|
||||
MOZ_COUNT_CTOR(mozilla::ipc::BackgroundTestParent);
|
||||
}
|
||||
|
||||
~TestParent()
|
||||
{
|
||||
MOZ_COUNT_DTOR(mozilla::ipc::BackgroundTestParent);
|
||||
}
|
||||
|
||||
virtual void
|
||||
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
BackgroundParentImpl::BackgroundParentImpl()
|
||||
{
|
||||
AssertIsInMainProcess();
|
||||
AssertIsOnMainThread();
|
||||
|
||||
MOZ_COUNT_CTOR(mozilla::ipc::BackgroundParentImpl);
|
||||
}
|
||||
|
||||
BackgroundParentImpl::~BackgroundParentImpl()
|
||||
{
|
||||
AssertIsInMainProcess();
|
||||
AssertIsOnMainThread();
|
||||
|
||||
MOZ_COUNT_DTOR(mozilla::ipc::BackgroundParentImpl);
|
||||
}
|
||||
|
||||
void
|
||||
BackgroundParentImpl::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
AssertIsInMainProcess();
|
||||
AssertIsOnBackgroundThread();
|
||||
}
|
||||
|
||||
PBackgroundTestParent*
|
||||
BackgroundParentImpl::AllocPBackgroundTestParent(const nsCString& aTestArg)
|
||||
{
|
||||
AssertIsInMainProcess();
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
return new TestParent();
|
||||
}
|
||||
|
||||
bool
|
||||
BackgroundParentImpl::RecvPBackgroundTestConstructor(
|
||||
PBackgroundTestParent* aActor,
|
||||
const nsCString& aTestArg)
|
||||
{
|
||||
AssertIsInMainProcess();
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(aActor);
|
||||
|
||||
return PBackgroundTestParent::Send__delete__(aActor, aTestArg);
|
||||
}
|
||||
|
||||
bool
|
||||
BackgroundParentImpl::DeallocPBackgroundTestParent(
|
||||
PBackgroundTestParent* aActor)
|
||||
{
|
||||
AssertIsInMainProcess();
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(aActor);
|
||||
|
||||
delete static_cast<TestParent*>(aActor);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
void
|
||||
TestParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
AssertIsInMainProcess();
|
||||
AssertIsOnBackgroundThread();
|
||||
}
|
39
ipc/glue/BackgroundParentImpl.h
Normal file
39
ipc/glue/BackgroundParentImpl.h
Normal file
@ -0,0 +1,39 @@
|
||||
/* 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_ipc_backgroundparentimpl_h__
|
||||
#define mozilla_ipc_backgroundparentimpl_h__
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ipc/PBackgroundParent.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
// Instances of this class should never be created directly. This class is meant
|
||||
// to be inherited in BackgroundImpl.
|
||||
class BackgroundParentImpl : public PBackgroundParent
|
||||
{
|
||||
protected:
|
||||
BackgroundParentImpl();
|
||||
virtual ~BackgroundParentImpl();
|
||||
|
||||
virtual void
|
||||
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
|
||||
|
||||
virtual PBackgroundTestParent*
|
||||
AllocPBackgroundTestParent(const nsCString& aTestArg) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvPBackgroundTestConstructor(PBackgroundTestParent* aActor,
|
||||
const nsCString& aTestArg) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
DeallocPBackgroundTestParent(PBackgroundTestParent* aActor) MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_ipc_backgroundparentimpl_h__
|
@ -428,8 +428,10 @@ MessageChannel::MaybeInterceptSpecialIOMessage(const Message& aMsg)
|
||||
// :TODO: Sort out Close() on this side racing with Close() on the
|
||||
// other side
|
||||
mChannelState = ChannelClosing;
|
||||
printf("NOTE: %s process received `Goodbye', closing down\n",
|
||||
(mSide == ChildSide) ? "child" : "parent");
|
||||
if (LoggingEnabled()) {
|
||||
printf("NOTE: %s process received `Goodbye', closing down\n",
|
||||
(mSide == ChildSide) ? "child" : "parent");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -1645,14 +1647,20 @@ MessageChannel::Close()
|
||||
return;
|
||||
}
|
||||
|
||||
if (ChannelOpening == mChannelState) {
|
||||
// Mimic CloseWithError().
|
||||
SynchronouslyClose();
|
||||
mChannelState = ChannelError;
|
||||
PostErrorNotifyTask();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ChannelConnected != mChannelState) {
|
||||
// XXX be strict about this until there's a compelling reason
|
||||
// to relax
|
||||
NS_RUNTIMEABORT("Close() called on closed channel!");
|
||||
}
|
||||
|
||||
AssertWorkerThread();
|
||||
|
||||
// notify the other side that we're about to close our socket
|
||||
mLink->SendMessage(new GoodbyeMessage());
|
||||
SynchronouslyClose();
|
||||
@ -1731,4 +1739,3 @@ MessageChannel::DumpInterruptStack(const char* const pfx) const
|
||||
|
||||
} // ipc
|
||||
} // mozilla
|
||||
|
||||
|
20
ipc/glue/PBackground.ipdl
Normal file
20
ipc/glue/PBackground.ipdl
Normal file
@ -0,0 +1,20 @@
|
||||
/* 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 PBackgroundTest;
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
protocol PBackground
|
||||
{
|
||||
manages PBackgroundTest;
|
||||
|
||||
parent:
|
||||
// Only called at startup during mochitests to check the basic infrastructure.
|
||||
PBackgroundTest(nsCString testArg);
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
20
ipc/glue/PBackgroundTest.ipdl
Normal file
20
ipc/glue/PBackgroundTest.ipdl
Normal file
@ -0,0 +1,20 @@
|
||||
/* 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 PBackground;
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
// This is a very simple testing protocol that is only used during mochitests.
|
||||
protocol PBackgroundTest
|
||||
{
|
||||
manager PBackground;
|
||||
|
||||
child:
|
||||
__delete__(nsCString testArg);
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
@ -48,7 +48,7 @@ CreateTransport(ProcessHandle aProcOne, ProcessHandle /*unused*/,
|
||||
|
||||
aOne->mPipeName = aTwo->mPipeName = id;
|
||||
aOne->mServerPipe = serverDup;
|
||||
aTwo->mServerPipe = 0;
|
||||
aTwo->mServerPipe = INVALID_HANDLE_VALUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -5,11 +5,14 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
EXPORTS += [
|
||||
'nsIIPCBackgroundChildCreateCallback.h',
|
||||
'nsIIPCSerializableInputStream.h',
|
||||
'nsIIPCSerializableURI.h',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla.ipc += [
|
||||
'BackgroundChild.h',
|
||||
'BackgroundParent.h',
|
||||
'BrowserProcessSubThread.h',
|
||||
'CrossProcessMutex.h',
|
||||
'FileDescriptor.h',
|
||||
@ -90,6 +93,7 @@ EXPORTS.ipc += [
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'BackgroundImpl.cpp',
|
||||
'BrowserProcessSubThread.cpp',
|
||||
'FileDescriptor.cpp',
|
||||
'FileDescriptorUtils.cpp',
|
||||
@ -108,12 +112,20 @@ UNIFIED_SOURCES += [
|
||||
# GeckoChildProcessHost.cpp cannot be built in unified mode because it uses plarena.h.
|
||||
# URIUtils.cpp cannot be built in unified mode because of name clashes on strdup.
|
||||
SOURCES += [
|
||||
'BackgroundChildImpl.cpp',
|
||||
'BackgroundParentImpl.cpp',
|
||||
'GeckoChildProcessHost.cpp',
|
||||
'URIUtils.cpp',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/xpcom/build',
|
||||
]
|
||||
|
||||
IPDL_SOURCES = [
|
||||
'InputStreamParams.ipdlh',
|
||||
'PBackground.ipdl',
|
||||
'PBackgroundTest.ipdl',
|
||||
'ProtocolTypes.ipdlh',
|
||||
'URIParams.ipdlh',
|
||||
]
|
||||
|
70
ipc/glue/nsIIPCBackgroundChildCreateCallback.h
Normal file
70
ipc/glue/nsIIPCBackgroundChildCreateCallback.h
Normal file
@ -0,0 +1,70 @@
|
||||
/* 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_ipc_nsiipcbackgroundchildcreatecallback_h
|
||||
#define mozilla_ipc_nsiipcbackgroundchildcreatecallback_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsISupports.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
class PBackgroundChild;
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
#define NS_IIPCBACKGROUNDCHILDCREATECALLBACK_IID \
|
||||
{0x4de01707, 0x70e3, 0x4181, {0xbc, 0x9f, 0xa3, 0xec, 0xfe, 0x74, 0x1a, 0xe3}}
|
||||
|
||||
class NS_NO_VTABLE nsIIPCBackgroundChildCreateCallback : public nsISupports
|
||||
{
|
||||
public:
|
||||
typedef mozilla::ipc::PBackgroundChild PBackgroundChild;
|
||||
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IIPCBACKGROUNDCHILDCREATECALLBACK_IID)
|
||||
|
||||
// This will be called upon successful creation of a PBackgroundChild actor.
|
||||
// The actor is unique per-thread and must not be shared across threads. It
|
||||
// may be saved and reused on the same thread for as long as the thread lives.
|
||||
// After this callback BackgroundChild::GetForCurrentThread() will return the
|
||||
// same actor.
|
||||
virtual void
|
||||
ActorCreated(PBackgroundChild*) = 0;
|
||||
|
||||
// This will be called if for some reason the PBackgroundChild actor cannot be
|
||||
// created. This should never be called in child processes as the failure to
|
||||
// create the actor should result in the termination of the child process
|
||||
// first. This may be called for cross-thread actors in the main process.
|
||||
virtual void
|
||||
ActorFailed() = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIIPCBackgroundChildCreateCallback,
|
||||
NS_IIPCBACKGROUNDCHILDCREATECALLBACK_IID)
|
||||
|
||||
#define NS_DECL_NSIIPCBACKGROUNDCHILDCREATECALLBACK \
|
||||
virtual void \
|
||||
ActorCreated(mozilla::ipc::PBackgroundChild*) MOZ_OVERRIDE; \
|
||||
virtual void \
|
||||
ActorFailed() MOZ_OVERRIDE;
|
||||
|
||||
#define NS_FORWARD_NSIIPCBACKGROUNDCHILDCREATECALLBACK(_to) \
|
||||
virtual void \
|
||||
ActorCreated(mozilla::ipc::PBackgroundChild* aActor) MOZ_OVERRIDE \
|
||||
{ _to ActorCreated(aActor); } \
|
||||
virtual void \
|
||||
ActorFailed() MOZ_OVERRIDE \
|
||||
{ _to ActorFailed(); }
|
||||
|
||||
#define NS_FORWARD_SAFE_NSIIPCBACKGROUNDCHILDCREATECALLBACK(_to) \
|
||||
virtual void \
|
||||
ActorCreated(mozilla::ipc::PBackgroundChild* aActor) MOZ_OVERRIDE \
|
||||
{ if (_to) { _to->ActorCreated(aActor); } } \
|
||||
virtual void \
|
||||
ActorFailed() MOZ_OVERRIDE \
|
||||
{ if (_to) { _to->ActorFailed(); } }
|
||||
|
||||
#endif // mozilla_ipc_nsiipcbackgroundchildcreatecallback_h
|
@ -154,6 +154,9 @@ user_pref("browser.download.panel.shown", true);
|
||||
// Disable first-tun tab
|
||||
user_pref("browser.firstrun.count", 0);
|
||||
|
||||
// Tell the PBackground infrastructure to run a test at startup.
|
||||
user_pref("pbackground.testing", true);
|
||||
|
||||
// Enable webapps testing mode, which bypasses native installation.
|
||||
user_pref("browser.webapps.testing", true);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user