Backed out 10 changesets (bug 1803810) for xpcshell failures on test_import_global...
[gecko.git] / netwerk / ipc / SocketProcessBridgeChild.cpp
blob798ce37bf1490f6df26fbdd3eb7de0500b239e0f
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"
19 namespace mozilla {
21 using dom::ContentChild;
23 namespace net {
25 StaticRefPtr<SocketProcessBridgeChild>
26 SocketProcessBridgeChild::sSocketProcessBridgeChild;
28 NS_IMPL_ISUPPORTS(SocketProcessBridgeChild, nsIObserver)
30 // static
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;
40 return false;
43 nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
44 if (os) {
45 os->AddObserver(sSocketProcessBridgeChild, "content-child-shutdown", false);
48 sSocketProcessBridgeChild->mSocketProcessPid = aEndpoint.OtherPid();
49 return true;
52 // static
53 already_AddRefed<SocketProcessBridgeChild>
54 SocketProcessBridgeChild::GetSingleton() {
55 RefPtr<SocketProcessBridgeChild> child = sSocketProcessBridgeChild;
56 return child.forget();
59 // static
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!"),
66 __func__);
69 if (!gNeckoChild) {
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&&
88 aResult) {
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(
102 nsCString(
103 "SendInitSocketProcessBridge resolved with an invalid "
104 "endpoint!"),
105 __func__);
108 if (!SocketProcessBridgeChild::Create(
109 std::move(aResult.ResolveValue()))) {
110 return GetPromise::CreateAndReject(
111 nsCString("SendInitSocketProcessBridge resolved with a valid "
112 "endpoint, "
113 "but SocketProcessBridgeChild::Create failed!"),
114 __func__);
118 return GetPromise::CreateAndResolve(sSocketProcessBridgeChild,
119 __func__);
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"));
133 return IPC_OK();
136 void SocketProcessBridgeChild::ActorDestroy(ActorDestroyReason aWhy) {
137 LOG(("SocketProcessBridgeChild::ActorDestroy\n"));
138 if (AbnormalShutdown == aWhy) {
139 if (gNeckoChild &&
140 !AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
141 // Let NeckoParent know that the socket process connections must be
142 // rebuilt.
143 gNeckoChild->SendResetSocketProcessBridge();
146 nsresult res;
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();
161 if (os) {
162 os->RemoveObserver(this, "content-child-shutdown");
164 GetCurrentSerialEventTarget()->Dispatch(
165 NewRunnableMethod("net::SocketProcessBridgeChild::DeferredDestroy", this,
166 &SocketProcessBridgeChild::DeferredDestroy));
167 mShuttingDown = true;
170 NS_IMETHODIMP
171 SocketProcessBridgeChild::Observe(nsISupports* aSubject, const char* aTopic,
172 const char16_t* aData) {
173 if (!strcmp(aTopic, "content-child-shutdown")) {
174 PSocketProcessBridgeChild::Close();
176 return NS_OK;
179 void SocketProcessBridgeChild::DeferredDestroy() {
180 MOZ_ASSERT(NS_IsMainThread());
182 sSocketProcessBridgeChild = nullptr;
185 } // namespace net
186 } // namespace mozilla