SocketProcessBridgeChild.cpp (6385B)
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/. */ 5 6 #include "SocketProcessBridgeChild.h" 7 #include "SocketProcessLogging.h" 8 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" 19 20 namespace mozilla { 21 22 using dom::ContentChild; 23 24 namespace net { 25 26 StaticRefPtr<SocketProcessBridgeChild> 27 SocketProcessBridgeChild::sSocketProcessBridgeChild; 28 29 NS_IMPL_ISUPPORTS(SocketProcessBridgeChild, nsIObserver) 30 31 // static 32 bool SocketProcessBridgeChild::Create( 33 Endpoint<PSocketProcessBridgeChild>&& aEndpoint) { 34 MOZ_ASSERT(NS_IsMainThread()); 35 36 sSocketProcessBridgeChild = new SocketProcessBridgeChild(); 37 38 if (!aEndpoint.Bind(sSocketProcessBridgeChild)) { 39 MOZ_ASSERT(false, "Bind failed!"); 40 sSocketProcessBridgeChild = nullptr; 41 return false; 42 } 43 44 nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService(); 45 if (os) { 46 os->AddObserver(sSocketProcessBridgeChild, "content-child-shutdown", false); 47 } 48 49 sSocketProcessBridgeChild->mSocketProcessPid = aEndpoint.OtherPid(); 50 return true; 51 } 52 53 // static 54 already_AddRefed<SocketProcessBridgeChild> 55 SocketProcessBridgeChild::GetSingleton() { 56 RefPtr<SocketProcessBridgeChild> child = sSocketProcessBridgeChild; 57 return child.forget(); 58 } 59 60 // static 61 RefPtr<SocketProcessBridgeChild::GetPromise> 62 SocketProcessBridgeChild::GetSocketProcessBridge() { 63 MOZ_ASSERT(NS_IsMainThread()); 64 65 if (!StaticPrefs::network_process_enabled()) { 66 return GetPromise::CreateAndReject(nsCString("Socket process disabled!"), 67 __func__); 68 } 69 70 if (!gNeckoChild) { 71 return GetPromise::CreateAndReject(nsCString("No NeckoChild!"), __func__); 72 } 73 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__); 80 } 81 82 if (sSocketProcessBridgeChild) { 83 return GetPromise::CreateAndResolve(sSocketProcessBridgeChild, __func__); 84 } 85 86 return gNeckoChild->SendInitSocketProcessBridge()->Then( 87 GetMainThreadSerialEventTarget(), __func__, 88 [](NeckoChild::InitSocketProcessBridgePromise::ResolveOrRejectValue&& 89 aResult) { 90 ContentChild* content = ContentChild::GetSingleton(); 91 if (!content || content->IsShuttingDown()) { 92 return GetPromise::CreateAndReject( 93 nsCString("ContentChild is shutting down."), __func__); 94 } 95 if (!sSocketProcessBridgeChild) { 96 if (aResult.IsReject()) { 97 return GetPromise::CreateAndReject( 98 nsCString("SendInitSocketProcessBridge failed"), __func__); 99 } 100 101 if (!aResult.ResolveValue().IsValid()) { 102 return GetPromise::CreateAndReject( 103 nsCString( 104 "SendInitSocketProcessBridge resolved with an invalid " 105 "endpoint!"), 106 __func__); 107 } 108 109 if (!SocketProcessBridgeChild::Create( 110 std::move(aResult.ResolveValue()))) { 111 return GetPromise::CreateAndReject( 112 nsCString("SendInitSocketProcessBridge resolved with a valid " 113 "endpoint, " 114 "but SocketProcessBridgeChild::Create failed!"), 115 __func__); 116 } 117 } 118 119 return GetPromise::CreateAndResolve(sSocketProcessBridgeChild, 120 __func__); 121 }); 122 } 123 124 SocketProcessBridgeChild::SocketProcessBridgeChild() : mShuttingDown(false) { 125 LOG(("CONSTRUCT SocketProcessBridgeChild::SocketProcessBridgeChild\n")); 126 } 127 128 SocketProcessBridgeChild::~SocketProcessBridgeChild() { 129 LOG(("DESTRUCT SocketProcessBridgeChild::SocketProcessBridgeChild\n")); 130 } 131 132 mozilla::ipc::IPCResult SocketProcessBridgeChild::RecvTest() { 133 LOG(("SocketProcessBridgeChild::RecvTest\n")); 134 return IPC_OK(); 135 } 136 137 void SocketProcessBridgeChild::ActorDestroy(ActorDestroyReason aWhy) { 138 LOG(("SocketProcessBridgeChild::ActorDestroy\n")); 139 if (AbnormalShutdown == aWhy) { 140 if (gNeckoChild && 141 !AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) { 142 // Let NeckoParent know that the socket process connections must be 143 // rebuilt. 144 gNeckoChild->SendResetSocketProcessBridge(); 145 } 146 147 nsresult res; 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(); }))); 158 } 159 } 160 161 nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService(); 162 if (os) { 163 os->RemoveObserver(this, "content-child-shutdown"); 164 } 165 GetCurrentSerialEventTarget()->Dispatch( 166 NewRunnableMethod("net::SocketProcessBridgeChild::DeferredDestroy", this, 167 &SocketProcessBridgeChild::DeferredDestroy)); 168 mShuttingDown = true; 169 } 170 171 NS_IMETHODIMP 172 SocketProcessBridgeChild::Observe(nsISupports* aSubject, const char* aTopic, 173 const char16_t* aData) { 174 if (!strcmp(aTopic, "content-child-shutdown")) { 175 PSocketProcessBridgeChild::Close(); 176 } 177 return NS_OK; 178 } 179 180 void SocketProcessBridgeChild::DeferredDestroy() { 181 MOZ_ASSERT(NS_IsMainThread()); 182 183 sSocketProcessBridgeChild = nullptr; 184 } 185 186 } // namespace net 187 } // namespace mozilla