1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "SocketProcessBridgeChild.h"
7 #include "SocketProcessLogging.h"
9 #include "mozilla/AppShutdown.h"
10 #include "mozilla/Components.h"
11 #include "mozilla/dom/ContentChild.h"
12 #include "mozilla/ipc/BackgroundChild.h"
13 #include "mozilla/ipc/Endpoint.h"
14 #include "mozilla/net/NeckoChild.h"
15 #include "nsIObserverService.h"
16 #include "nsThreadUtils.h"
17 #include "mozilla/Preferences.h"
18 #include "mozilla/StaticPrefs_network.h"
22 using dom::ContentChild
;
26 StaticRefPtr
<SocketProcessBridgeChild
>
27 SocketProcessBridgeChild::sSocketProcessBridgeChild
;
29 NS_IMPL_ISUPPORTS(SocketProcessBridgeChild
, nsIObserver
)
32 bool SocketProcessBridgeChild::Create(
33 Endpoint
<PSocketProcessBridgeChild
>&& aEndpoint
) {
34 MOZ_ASSERT(NS_IsMainThread());
36 sSocketProcessBridgeChild
= new SocketProcessBridgeChild();
38 if (!aEndpoint
.Bind(sSocketProcessBridgeChild
)) {
39 MOZ_ASSERT(false, "Bind failed!");
40 sSocketProcessBridgeChild
= nullptr;
44 nsCOMPtr
<nsIObserverService
> os
= mozilla::services::GetObserverService();
46 os
->AddObserver(sSocketProcessBridgeChild
, "content-child-shutdown", false);
49 sSocketProcessBridgeChild
->mSocketProcessPid
= aEndpoint
.OtherPid();
54 already_AddRefed
<SocketProcessBridgeChild
>
55 SocketProcessBridgeChild::GetSingleton() {
56 RefPtr
<SocketProcessBridgeChild
> child
= sSocketProcessBridgeChild
;
57 return child
.forget();
61 RefPtr
<SocketProcessBridgeChild::GetPromise
>
62 SocketProcessBridgeChild::GetSocketProcessBridge() {
63 MOZ_ASSERT(NS_IsMainThread());
65 if (!StaticPrefs::network_process_enabled()) {
66 return GetPromise::CreateAndReject(nsCString("Socket process disabled!"),
71 return GetPromise::CreateAndReject(nsCString("No NeckoChild!"), __func__
);
74 // ContentChild is shutting down, we should not try to create
75 // SocketProcessBridgeChild.
76 ContentChild
* content
= ContentChild::GetSingleton();
77 if (!content
|| content
->IsShuttingDown()) {
78 return GetPromise::CreateAndReject(
79 nsCString("ContentChild is shutting down."), __func__
);
82 if (sSocketProcessBridgeChild
) {
83 return GetPromise::CreateAndResolve(sSocketProcessBridgeChild
, __func__
);
86 return gNeckoChild
->SendInitSocketProcessBridge()->Then(
87 GetMainThreadSerialEventTarget(), __func__
,
88 [](NeckoChild::InitSocketProcessBridgePromise::ResolveOrRejectValue
&&
90 ContentChild
* content
= ContentChild::GetSingleton();
91 if (!content
|| content
->IsShuttingDown()) {
92 return GetPromise::CreateAndReject(
93 nsCString("ContentChild is shutting down."), __func__
);
95 if (!sSocketProcessBridgeChild
) {
96 if (aResult
.IsReject()) {
97 return GetPromise::CreateAndReject(
98 nsCString("SendInitSocketProcessBridge failed"), __func__
);
101 if (!aResult
.ResolveValue().IsValid()) {
102 return GetPromise::CreateAndReject(
104 "SendInitSocketProcessBridge resolved with an invalid "
109 if (!SocketProcessBridgeChild::Create(
110 std::move(aResult
.ResolveValue()))) {
111 return GetPromise::CreateAndReject(
112 nsCString("SendInitSocketProcessBridge resolved with a valid "
114 "but SocketProcessBridgeChild::Create failed!"),
119 return GetPromise::CreateAndResolve(sSocketProcessBridgeChild
,
124 SocketProcessBridgeChild::SocketProcessBridgeChild() : mShuttingDown(false) {
125 LOG(("CONSTRUCT SocketProcessBridgeChild::SocketProcessBridgeChild\n"));
128 SocketProcessBridgeChild::~SocketProcessBridgeChild() {
129 LOG(("DESTRUCT SocketProcessBridgeChild::SocketProcessBridgeChild\n"));
132 mozilla::ipc::IPCResult
SocketProcessBridgeChild::RecvTest() {
133 LOG(("SocketProcessBridgeChild::RecvTest\n"));
137 void SocketProcessBridgeChild::ActorDestroy(ActorDestroyReason aWhy
) {
138 LOG(("SocketProcessBridgeChild::ActorDestroy\n"));
139 if (AbnormalShutdown
== aWhy
) {
141 !AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed
)) {
142 // Let NeckoParent know that the socket process connections must be
144 gNeckoChild
->SendResetSocketProcessBridge();
148 nsCOMPtr
<nsISerialEventTarget
> mSTSThread
;
149 mSTSThread
= mozilla::components::SocketTransport::Service(&res
);
150 if (NS_SUCCEEDED(res
) && mSTSThread
) {
151 // This must be called off the main thread. If we don't make this call
152 // ipc::BackgroundChild::GetOrCreateSocketActorForCurrentThread() will
153 // return the previous actor that is no longer able to send. This causes
154 // rebuilding the socket process connections to fail.
155 MOZ_ALWAYS_SUCCEEDS(mSTSThread
->Dispatch(NS_NewRunnableFunction(
156 "net::SocketProcessBridgeChild::ActorDestroy",
157 []() { ipc::BackgroundChild::CloseForCurrentThread(); })));
161 nsCOMPtr
<nsIObserverService
> os
= mozilla::services::GetObserverService();
163 os
->RemoveObserver(this, "content-child-shutdown");
165 GetCurrentSerialEventTarget()->Dispatch(
166 NewRunnableMethod("net::SocketProcessBridgeChild::DeferredDestroy", this,
167 &SocketProcessBridgeChild::DeferredDestroy
));
168 mShuttingDown
= true;
172 SocketProcessBridgeChild::Observe(nsISupports
* aSubject
, const char* aTopic
,
173 const char16_t
* aData
) {
174 if (!strcmp(aTopic
, "content-child-shutdown")) {
175 PSocketProcessBridgeChild::Close();
180 void SocketProcessBridgeChild::DeferredDestroy() {
181 MOZ_ASSERT(NS_IsMainThread());
183 sSocketProcessBridgeChild
= nullptr;
187 } // namespace mozilla