Bug 1513057 - P5: Create IPC between content process and socket process r=dragana,mayhemer

Differential Revision: https://phabricator.services.mozilla.com/D14257

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Kershaw Chang 2019-01-11 20:55:07 +00:00
Родитель 30b52ec47d
Коммит f13da4ca28
14 изменённых файлов: 395 добавлений и 2 удалений

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

@ -28,6 +28,8 @@
#include "mozilla/net/IPCTransportProvider.h"
#include "mozilla/net/RequestContextService.h"
#include "mozilla/net/TrackingDummyChannelParent.h"
#include "mozilla/net/SocketProcessParent.h"
#include "mozilla/net/PSocketProcessBridgeParent.h"
#ifdef MOZ_WEBRTC
#include "mozilla/net/StunAddrsRequestParent.h"
#include "mozilla/net/WebrtcProxyChannelParent.h"
@ -74,7 +76,7 @@ namespace mozilla {
namespace net {
// C++ file contents
NeckoParent::NeckoParent() {
NeckoParent::NeckoParent() : mSocketProcessBridgeInited(false) {
// Init HTTP protocol handler now since we need atomTable up and running very
// early (IPDL argument handling for PHttpChannel constructor needs it) so
// normal init (during 1st Http channel request) isn't early enough.
@ -954,5 +956,41 @@ bool NeckoParent::DeallocPTrackingDummyChannelParent(
return true;
}
mozilla::ipc::IPCResult NeckoParent::RecvInitSocketProcessBridge(
InitSocketProcessBridgeResolver&& aResolver) {
MOZ_ASSERT(NS_IsMainThread());
Endpoint<PSocketProcessBridgeChild> invalidEndpoint;
if (NS_WARN_IF(mSocketProcessBridgeInited)) {
aResolver(std::move(invalidEndpoint));
return IPC_OK();
}
SocketProcessParent* parent = SocketProcessParent::GetSingleton();
if (NS_WARN_IF(!parent)) {
aResolver(std::move(invalidEndpoint));
return IPC_OK();
}
Endpoint<PSocketProcessBridgeParent> parentEndpoint;
Endpoint<PSocketProcessBridgeChild> childEndpoint;
if (NS_WARN_IF(NS_FAILED(PSocketProcessBridge::CreateEndpoints(
parent->OtherPid(), Manager()->OtherPid(), &parentEndpoint,
&childEndpoint)))) {
aResolver(std::move(invalidEndpoint));
return IPC_OK();
}
if (NS_WARN_IF(!parent->SendInitSocketProcessBridgeParent(
Manager()->OtherPid(), std::move(parentEndpoint)))) {
aResolver(std::move(invalidEndpoint));
return IPC_OK();
}
aResolver(std::move(childEndpoint));
mSocketProcessBridgeInited = true;
return IPC_OK();
}
} // namespace net
} // namespace mozilla

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

@ -87,6 +87,8 @@ class NeckoParent : public PNeckoParent {
};
protected:
bool mSocketProcessBridgeInited;
virtual PHttpChannelParent* AllocPHttpChannelParent(
const PBrowserOrId&, const SerializedLoadContext&,
const HttpChannelCreationArgs& aOpenArgs) override;
@ -246,6 +248,9 @@ class NeckoParent : public PNeckoParent {
PTrackingDummyChannelParent* aActor, nsIURI* aURI, nsIURI* aTopWindowURI,
const nsresult& aTopWindowURIResult,
const OptionalLoadInfoArgs& aLoadInfo) override;
virtual mozilla::ipc::IPCResult RecvInitSocketProcessBridge(
InitSocketProcessBridgeResolver&& aResolver) override;
};
} // namespace net

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

@ -28,6 +28,7 @@ include protocol PStunAddrsRequest;
include protocol PFileChannel;
include protocol PTrackingDummyChannel;
include protocol PWebrtcProxyChannel;
include protocol PSocketProcessBridge;
include IPCStream;
include URIParams;
@ -143,6 +144,9 @@ parent:
async GetExtensionStream(URIParams uri) returns (nsIInputStream stream);
async GetExtensionFD(URIParams uri) returns (FileDescriptor fd);
async InitSocketProcessBridge()
returns (Endpoint<PSocketProcessBridgeChild> endpoint);
child:
/*
* Bring up the http auth prompt for a nested remote mozbrowser.

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

@ -4,9 +4,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include MemoryReportTypes;
include protocol PSocketProcessBridge;
include PrefsTypes;
using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
using base::ProcessId from "base/process.h";
namespace mozilla {
namespace net {
@ -25,6 +27,7 @@ child:
bool minimizeMemoryUsage,
MaybeFileDesc DMDFile);
async SetOffline(bool offline);
async InitSocketProcessBridgeParent(ProcessId processId, Endpoint<PSocketProcessBridgeParent> endpoint);
};
} // namespace net

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

@ -0,0 +1,25 @@
/* -*- 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/. */
namespace mozilla {
namespace net {
/**
* PSocketProcessBridge is the IPC protocol between content process and
* socket process. This protocol allows socket process to send data to
* content process bypassing parent process.
* Once created, PSocketProcessBridgeChild is the actor that lives in
* content process and PSocketProcessBridgeParent lives in
* socket process.
*/
nested(upto inside_cpow) sync protocol PSocketProcessBridge
{
both:
async Test();
};
}
}

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

@ -0,0 +1,133 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "SocketProcessBridgeChild.h"
#include "SocketProcessLogging.h"
#include "mozilla/net/NeckoChild.h"
#include "nsIObserverService.h"
#include "nsThreadUtils.h"
namespace mozilla {
namespace net {
StaticRefPtr<SocketProcessBridgeChild>
SocketProcessBridgeChild::sSocketProcessBridgeChild;
NS_IMPL_ISUPPORTS(SocketProcessBridgeChild, nsIObserver)
// static
bool SocketProcessBridgeChild::Create(
Endpoint<PSocketProcessBridgeChild>&& aEndpoint) {
MOZ_ASSERT(NS_IsMainThread());
sSocketProcessBridgeChild =
new SocketProcessBridgeChild(std::move(aEndpoint));
if (sSocketProcessBridgeChild->Inited()) {
return true;
}
sSocketProcessBridgeChild = nullptr;
return false;
}
// static
already_AddRefed<SocketProcessBridgeChild>
SocketProcessBridgeChild::GetSinglton() {
MOZ_ASSERT(NS_IsMainThread());
if (!sSocketProcessBridgeChild) {
return nullptr;
}
RefPtr<SocketProcessBridgeChild> child = sSocketProcessBridgeChild.get();
return child.forget();
}
// static
void SocketProcessBridgeChild::EnsureSocketProcessBridge(
std::function<void()>&& aOnSuccess, std::function<void()>&& aOnFailure) {
MOZ_ASSERT(IsNeckoChild() && gNeckoChild);
MOZ_ASSERT(NS_IsMainThread());
if (!gNeckoChild) {
aOnFailure();
return;
}
if (sSocketProcessBridgeChild) {
aOnSuccess();
return;
}
gNeckoChild->SendInitSocketProcessBridge()->Then(
GetMainThreadSerialEventTarget(), __func__,
[onSuccess = std::move(aOnSuccess), onFailure = std::move(aOnFailure)](
Endpoint<PSocketProcessBridgeChild>&& aEndpoint) {
if (aEndpoint.IsValid()) {
if (SocketProcessBridgeChild::Create(std::move(aEndpoint))) {
onSuccess();
return;
}
}
onFailure();
},
[onFailure = std::move(aOnFailure)](
const mozilla::ipc::ResponseRejectReason) { onFailure(); });
}
SocketProcessBridgeChild::SocketProcessBridgeChild(
Endpoint<PSocketProcessBridgeChild>&& aEndpoint) {
LOG(("CONSTRUCT SocketProcessBridgeChild::SocketProcessBridgeChild\n"));
mInited = aEndpoint.Bind(this);
if (!mInited) {
MOZ_ASSERT(false, "Bind failed!");
return;
}
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
if (os) {
os->AddObserver(this, "content-child-shutdown", false);
}
}
SocketProcessBridgeChild::~SocketProcessBridgeChild() {
LOG(("DESTRUCT SocketProcessBridgeChild::SocketProcessBridgeChild\n"));
}
mozilla::ipc::IPCResult SocketProcessBridgeChild::RecvTest() {
LOG(("SocketProcessBridgeChild::RecvTest\n"));
return IPC_OK();
}
void SocketProcessBridgeChild::ActorDestroy(ActorDestroyReason aWhy) {
LOG(("SocketProcessBridgeChild::ActorDestroy\n"));
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
if (os) {
os->RemoveObserver(this, "content-child-shutdown");
}
MessageLoop::current()->PostTask(
NewRunnableMethod("net::SocketProcessBridgeChild::DeferredDestroy", this,
&SocketProcessBridgeChild::DeferredDestroy));
}
NS_IMETHODIMP
SocketProcessBridgeChild::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData) {
if (!strcmp(aTopic, "content-child-shutdown")) {
PSocketProcessBridgeChild::Close();
}
return NS_OK;
}
void SocketProcessBridgeChild::DeferredDestroy() {
MOZ_ASSERT(NS_IsMainThread());
sSocketProcessBridgeChild = nullptr;
}
} // namespace net
} // namespace mozilla

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

@ -0,0 +1,48 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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_net_SocketProcessBridgeChild_h
#define mozilla_net_SocketProcessBridgeChild_h
#include <functional>
#include "mozilla/net/PSocketProcessBridgeChild.h"
#include "nsIObserver.h"
namespace mozilla {
namespace net {
// The IPC actor implements PSocketProcessBridgeChild in content process.
// This is allocated and kept alive by NeckoChild. When "content-child-shutdown"
// topic is observed, this actor will be destroyed.
class SocketProcessBridgeChild final : public PSocketProcessBridgeChild,
public nsIObserver {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
static bool Create(Endpoint<PSocketProcessBridgeChild>&& aEndpoint);
static already_AddRefed<SocketProcessBridgeChild> GetSinglton();
static void EnsureSocketProcessBridge(std::function<void()>&& aOnSuccess,
std::function<void()>&& aOnFailure);
mozilla::ipc::IPCResult RecvTest() override;
void ActorDestroy(ActorDestroyReason aWhy) override;
void DeferredDestroy();
bool Inited() const { return mInited; };
private:
DISALLOW_COPY_AND_ASSIGN(SocketProcessBridgeChild);
explicit SocketProcessBridgeChild(
Endpoint<PSocketProcessBridgeChild>&& aEndpoint);
virtual ~SocketProcessBridgeChild();
static StaticRefPtr<SocketProcessBridgeChild> sSocketProcessBridgeChild;
bool mInited = false;
};
} // namespace net
} // namespace mozilla
#endif // mozilla_net_SocketProcessBridgeChild_h

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

@ -0,0 +1,49 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "SocketProcessBridgeParent.h"
#include "SocketProcessLogging.h"
#include "SocketProcessChild.h"
namespace mozilla {
namespace net {
SocketProcessBridgeParent::SocketProcessBridgeParent(
ProcessId aId, Endpoint<PSocketProcessBridgeParent>&& aEndpoint)
: mId(aId) {
LOG((
"CONSTRUCT SocketProcessBridgeParent::SocketProcessBridgeParent mId=%d\n",
mId));
MOZ_COUNT_CTOR(SocketProcessBridgeParent);
DebugOnly<bool> ok = aEndpoint.Bind(this);
MOZ_ASSERT(ok);
}
SocketProcessBridgeParent::~SocketProcessBridgeParent() {
LOG(("DESTRUCT SocketProcessBridgeParent::SocketProcessBridgeParent\n"));
MOZ_COUNT_DTOR(SocketProcessBridgeParent);
}
mozilla::ipc::IPCResult SocketProcessBridgeParent::RecvTest() {
LOG(("SocketProcessBridgeParent::RecvTest\n"));
Unused << SendTest();
return IPC_OK();
}
void SocketProcessBridgeParent::ActorDestroy(ActorDestroyReason aWhy) {
LOG(("SocketProcessBridgeParent::ActorDestroy mId=%d\n", mId));
MessageLoop::current()->PostTask(
NewRunnableMethod("net::SocketProcessBridgeParent::DeferredDestroy", this,
&SocketProcessBridgeParent::DeferredDestroy));
}
void SocketProcessBridgeParent::DeferredDestroy() {
SocketProcessChild::GetSingleton()->DestroySocketProcessBridgeParent(mId);
}
} // namespace net
} // namespace mozilla

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

@ -0,0 +1,38 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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_net_SocketProcessBridgeParent_h
#define mozilla_net_SocketProcessBridgeParent_h
#include "mozilla/net/PSocketProcessBridgeParent.h"
namespace mozilla {
namespace net {
// The IPC actor implements PSocketProcessBridgeParent in socket process.
// This is allocated and kept alive by SocketProcessChild. When |ActorDestroy|
// is called, |SocketProcessChild::DestroySocketProcessBridgeParent| will be
// called to destroy this actor.
class SocketProcessBridgeParent final : public PSocketProcessBridgeParent {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SocketProcessBridgeParent)
explicit SocketProcessBridgeParent(
ProcessId aId, Endpoint<PSocketProcessBridgeParent>&& aEndpoint);
mozilla::ipc::IPCResult RecvTest() override;
void ActorDestroy(ActorDestroyReason aWhy) override;
void DeferredDestroy();
private:
~SocketProcessBridgeParent();
ProcessId mId;
};
} // namespace net
} // namespace mozilla
#endif // mozilla_net_SocketProcessBridgeParent_h

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

@ -15,6 +15,7 @@
#include "nsDebugImpl.h"
#include "nsThreadManager.h"
#include "ProcessUtils.h"
#include "SocketProcessBridgeParent.h"
namespace mozilla {
namespace net {
@ -118,5 +119,23 @@ mozilla::ipc::IPCResult SocketProcessChild::RecvSetOffline(
return IPC_OK();
}
mozilla::ipc::IPCResult SocketProcessChild::RecvInitSocketProcessBridgeParent(
const ProcessId& aContentProcessId,
Endpoint<mozilla::net::PSocketProcessBridgeParent>&& aEndpoint) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mSocketProcessBridgeParentMap.Get(aContentProcessId, nullptr));
mSocketProcessBridgeParentMap.Put(
aContentProcessId,
new SocketProcessBridgeParent(aContentProcessId, std::move(aEndpoint)));
return IPC_OK();
}
void SocketProcessChild::DestroySocketProcessBridgeParent(ProcessId aId) {
MOZ_ASSERT(NS_IsMainThread());
mSocketProcessBridgeParentMap.Remove(aId);
}
} // namespace net
} // namespace mozilla

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

@ -7,10 +7,13 @@
#define mozilla_net_SocketProcessChild_h
#include "mozilla/net/PSocketProcessChild.h"
#include "nsRefPtrHashtable.h"
namespace mozilla {
namespace net {
class SocketProcessBridgeParent;
// The IPC actor implements PSocketProcessChild in child process.
// This is allocated and kept alive by SocketProcessImpl.
class SocketProcessChild final : public PSocketProcessChild {
@ -30,10 +33,18 @@ class SocketProcessChild final : public PSocketProcessChild {
const uint32_t& generation, const bool& anonymize,
const bool& minimizeMemoryUsage, const MaybeFileDesc& DMDFile) override;
mozilla::ipc::IPCResult RecvSetOffline(const bool& aOffline) override;
mozilla::ipc::IPCResult RecvInitSocketProcessBridgeParent(
const ProcessId& aContentProcessId,
Endpoint<mozilla::net::PSocketProcessBridgeParent>&& aEndpoint) override;
void CleanUp();
void DestroySocketProcessBridgeParent(ProcessId aId);
private:
// Mapping of content process id and the SocketProcessBridgeParent.
// This table keeps SocketProcessBridgeParent alive in socket process.
nsRefPtrHashtable<nsUint32HashKey, SocketProcessBridgeParent>
mSocketProcessBridgeParentMap;
};
} // namespace net

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

@ -11,15 +11,28 @@
namespace mozilla {
namespace net {
static SocketProcessParent* sSocketProcessParent;
SocketProcessParent::SocketProcessParent(SocketProcessHost* aHost)
: mHost(aHost) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mHost);
MOZ_COUNT_CTOR(SocketProcessParent);
sSocketProcessParent = this;
}
SocketProcessParent::~SocketProcessParent() {
MOZ_ASSERT(NS_IsMainThread());
MOZ_COUNT_DTOR(SocketProcessParent);
sSocketProcessParent = nullptr;
}
/* static */ SocketProcessParent* SocketProcessParent::GetSingleton() {
MOZ_ASSERT(NS_IsMainThread());
return sSocketProcessParent;
}
mozilla::ipc::IPCResult SocketProcessParent::RecvInitCrashReporter(

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

@ -33,6 +33,8 @@ class SocketProcessParent final : public PSocketProcessParent {
explicit SocketProcessParent(SocketProcessHost* aHost);
~SocketProcessParent();
static SocketProcessParent* GetSingleton();
mozilla::ipc::IPCResult RecvInitCrashReporter(
Shmem&& aShmem, const NativeThreadId& aThreadId) override;
mozilla::ipc::IPCResult RecvAddMemoryReport(

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

@ -11,6 +11,8 @@ EXPORTS.mozilla.net += [
'NeckoMessageUtils.h',
'NeckoParent.h',
'NeckoTargetHolder.h',
'SocketProcessBridgeChild.h',
'SocketProcessBridgeParent.h',
'SocketProcessChild.h',
'SocketProcessHost.h',
'SocketProcessImpl.h',
@ -23,6 +25,8 @@ UNIFIED_SOURCES += [
'NeckoCommon.cpp',
'NeckoParent.cpp',
'NeckoTargetHolder.cpp',
'SocketProcessBridgeChild.cpp',
'SocketProcessBridgeParent.cpp',
'SocketProcessChild.cpp',
'SocketProcessHost.cpp',
'SocketProcessImpl.cpp',
@ -36,7 +40,8 @@ IPDL_SOURCES = [
'PFileChannel.ipdl',
'PNecko.ipdl',
'PSimpleChannel.ipdl',
'PSocketProcess.ipdl'
'PSocketProcess.ipdl',
'PSocketProcessBridge.ipdl'
]
# needed so --disable-webrtc builds work (yes, a bit messy)