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/dom/ContentChild.h"
11 #include "mozilla/ipc/BackgroundChild.h"
12 #include "mozilla/ipc/Endpoint.h"
13 #include "mozilla/net/NeckoChild.h"
14 #include "nsIObserverService.h"
15 #include "nsThreadUtils.h"
16 #include "mozilla/Preferences.h"
17 #include "mozilla/StaticPrefs_network.h"
21 using dom::ContentChild
;
25 StaticRefPtr
<SocketProcessBridgeChild
>
26 SocketProcessBridgeChild::sSocketProcessBridgeChild
;
28 NS_IMPL_ISUPPORTS(SocketProcessBridgeChild
, nsIObserver
)
31 bool SocketProcessBridgeChild::Create(
32 Endpoint
<PSocketProcessBridgeChild
>&& aEndpoint
) {
33 MOZ_ASSERT(NS_IsMainThread());
35 sSocketProcessBridgeChild
= new SocketProcessBridgeChild();
37 if (!aEndpoint
.Bind(sSocketProcessBridgeChild
)) {
38 MOZ_ASSERT(false, "Bind failed!");
39 sSocketProcessBridgeChild
= nullptr;
43 nsCOMPtr
<nsIObserverService
> os
= mozilla::services::GetObserverService();
45 os
->AddObserver(sSocketProcessBridgeChild
, "content-child-shutdown", false);
48 sSocketProcessBridgeChild
->mSocketProcessPid
= aEndpoint
.OtherPid();
53 already_AddRefed
<SocketProcessBridgeChild
>
54 SocketProcessBridgeChild::GetSingleton() {
55 RefPtr
<SocketProcessBridgeChild
> child
= sSocketProcessBridgeChild
;
56 return child
.forget();
60 RefPtr
<SocketProcessBridgeChild::GetPromise
>
61 SocketProcessBridgeChild::GetSocketProcessBridge() {
62 MOZ_ASSERT(NS_IsMainThread());
64 if (!StaticPrefs::network_process_enabled()) {
65 return GetPromise::CreateAndReject(nsCString("Socket process disabled!"),
70 return GetPromise::CreateAndReject(nsCString("No NeckoChild!"), __func__
);
73 // ContentChild is shutting down, we should not try to create
74 // SocketProcessBridgeChild.
75 ContentChild
* content
= ContentChild::GetSingleton();
76 if (!content
|| content
->IsShuttingDown()) {
77 return GetPromise::CreateAndReject(
78 nsCString("ContentChild is shutting down."), __func__
);
81 if (sSocketProcessBridgeChild
) {
82 return GetPromise::CreateAndResolve(sSocketProcessBridgeChild
, __func__
);
85 return gNeckoChild
->SendInitSocketProcessBridge()->Then(
86 GetMainThreadSerialEventTarget(), __func__
,
87 [](NeckoChild::InitSocketProcessBridgePromise::ResolveOrRejectValue
&&
89 ContentChild
* content
= ContentChild::GetSingleton();
90 if (!content
|| content
->IsShuttingDown()) {
91 return GetPromise::CreateAndReject(
92 nsCString("ContentChild is shutting down."), __func__
);
94 if (!sSocketProcessBridgeChild
) {
95 if (aResult
.IsReject()) {
96 return GetPromise::CreateAndReject(
97 nsCString("SendInitSocketProcessBridge failed"), __func__
);
100 if (!aResult
.ResolveValue().IsValid()) {
101 return GetPromise::CreateAndReject(
103 "SendInitSocketProcessBridge resolved with an invalid "
108 if (!SocketProcessBridgeChild::Create(
109 std::move(aResult
.ResolveValue()))) {
110 return GetPromise::CreateAndReject(
111 nsCString("SendInitSocketProcessBridge resolved with a valid "
113 "but SocketProcessBridgeChild::Create failed!"),
118 return GetPromise::CreateAndResolve(sSocketProcessBridgeChild
,
123 SocketProcessBridgeChild::SocketProcessBridgeChild() : mShuttingDown(false) {
124 LOG(("CONSTRUCT SocketProcessBridgeChild::SocketProcessBridgeChild\n"));
127 SocketProcessBridgeChild::~SocketProcessBridgeChild() {
128 LOG(("DESTRUCT SocketProcessBridgeChild::SocketProcessBridgeChild\n"));
131 mozilla::ipc::IPCResult
SocketProcessBridgeChild::RecvTest() {
132 LOG(("SocketProcessBridgeChild::RecvTest\n"));
136 void SocketProcessBridgeChild::ActorDestroy(ActorDestroyReason aWhy
) {
137 LOG(("SocketProcessBridgeChild::ActorDestroy\n"));
138 if (AbnormalShutdown
== aWhy
) {
140 !AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed
)) {
141 // Let NeckoParent know that the socket process connections must be
143 gNeckoChild
->SendResetSocketProcessBridge();
147 nsCOMPtr
<nsISerialEventTarget
> mSTSThread
=
148 do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID
, &res
);
149 if (NS_SUCCEEDED(res
) && mSTSThread
) {
150 // This must be called off the main thread. If we don't make this call
151 // ipc::BackgroundChild::GetOrCreateSocketActorForCurrentThread() will
152 // return the previous actor that is no longer able to send. This causes
153 // rebuilding the socket process connections to fail.
154 MOZ_ALWAYS_SUCCEEDS(mSTSThread
->Dispatch(NS_NewRunnableFunction(
155 "net::SocketProcessBridgeChild::ActorDestroy",
156 []() { ipc::BackgroundChild::CloseForCurrentThread(); })));
160 nsCOMPtr
<nsIObserverService
> os
= mozilla::services::GetObserverService();
162 os
->RemoveObserver(this, "content-child-shutdown");
164 GetCurrentSerialEventTarget()->Dispatch(
165 NewRunnableMethod("net::SocketProcessBridgeChild::DeferredDestroy", this,
166 &SocketProcessBridgeChild::DeferredDestroy
));
167 mShuttingDown
= true;
171 SocketProcessBridgeChild::Observe(nsISupports
* aSubject
, const char* aTopic
,
172 const char16_t
* aData
) {
173 if (!strcmp(aTopic
, "content-child-shutdown")) {
174 PSocketProcessBridgeChild::Close();
179 void SocketProcessBridgeChild::DeferredDestroy() {
180 MOZ_ASSERT(NS_IsMainThread());
182 sSocketProcessBridgeChild
= nullptr;
186 } // namespace mozilla