1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/glue/BackgroundImpl.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1963 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "base/process_util.h" 1.9 +#include "mozilla/Assertions.h" 1.10 +#include "mozilla/Atomics.h" 1.11 +#include "mozilla/ClearOnShutdown.h" 1.12 +#include "mozilla/DebugOnly.h" 1.13 +#include "mozilla/Services.h" 1.14 +#include "mozilla/StaticPtr.h" 1.15 +#include "mozilla/unused.h" 1.16 +#include "mozilla/dom/ContentChild.h" 1.17 +#include "mozilla/dom/ContentParent.h" 1.18 +#include "mozilla/ipc/ProtocolTypes.h" 1.19 +#include "BackgroundChild.h" 1.20 +#include "BackgroundChildImpl.h" 1.21 +#include "BackgroundParent.h" 1.22 +#include "BackgroundParentImpl.h" 1.23 +#include "GeckoProfiler.h" 1.24 +#include "nsAutoPtr.h" 1.25 +#include "nsCOMPtr.h" 1.26 +#include "nsIEventTarget.h" 1.27 +#include "nsIIPCBackgroundChildCreateCallback.h" 1.28 +#include "nsIObserver.h" 1.29 +#include "nsIObserverService.h" 1.30 +#include "nsIRunnable.h" 1.31 +#include "nsISupportsImpl.h" 1.32 +#include "nsIThread.h" 1.33 +#include "nsITimer.h" 1.34 +#include "nsTArray.h" 1.35 +#include "nsThreadUtils.h" 1.36 +#include "nsTraceRefcnt.h" 1.37 +#include "nsXULAppAPI.h" 1.38 +#include "nsXPCOMPrivate.h" 1.39 +#include "prthread.h" 1.40 + 1.41 +#ifdef RELEASE_BUILD 1.42 +#define THREADSAFETY_ASSERT MOZ_ASSERT 1.43 +#else 1.44 +#define THREADSAFETY_ASSERT MOZ_RELEASE_ASSERT 1.45 +#endif 1.46 + 1.47 +#define CRASH_IN_CHILD_PROCESS(_msg) \ 1.48 + do { \ 1.49 + if (IsMainProcess()) { \ 1.50 + MOZ_ASSERT(false, _msg); \ 1.51 + } else { \ 1.52 + MOZ_CRASH(_msg); \ 1.53 + } \ 1.54 + } \ 1.55 + while (0) 1.56 + 1.57 +using namespace mozilla; 1.58 +using namespace mozilla::ipc; 1.59 + 1.60 +using mozilla::dom::ContentChild; 1.61 +using mozilla::dom::ContentParent; 1.62 + 1.63 +namespace { 1.64 + 1.65 +// ----------------------------------------------------------------------------- 1.66 +// Utility Functions 1.67 +// ----------------------------------------------------------------------------- 1.68 + 1.69 +bool 1.70 +IsMainProcess() 1.71 +{ 1.72 + static const bool isMainProcess = 1.73 + XRE_GetProcessType() == GeckoProcessType_Default; 1.74 + return isMainProcess; 1.75 +} 1.76 + 1.77 +bool 1.78 +IsChildProcess() 1.79 +{ 1.80 + return !IsMainProcess(); 1.81 +} 1.82 + 1.83 +void 1.84 +AssertIsInMainProcess() 1.85 +{ 1.86 + MOZ_ASSERT(IsMainProcess()); 1.87 +} 1.88 + 1.89 +void 1.90 +AssertIsInChildProcess() 1.91 +{ 1.92 + MOZ_ASSERT(IsChildProcess()); 1.93 +} 1.94 + 1.95 +void 1.96 +AssertIsOnMainThread() 1.97 +{ 1.98 + THREADSAFETY_ASSERT(NS_IsMainThread()); 1.99 +} 1.100 + 1.101 +// ----------------------------------------------------------------------------- 1.102 +// ParentImpl Declaration 1.103 +// ----------------------------------------------------------------------------- 1.104 + 1.105 +class ParentImpl MOZ_FINAL : public BackgroundParentImpl 1.106 +{ 1.107 + friend class mozilla::ipc::BackgroundParent; 1.108 + 1.109 +public: 1.110 + class CreateCallback; 1.111 + 1.112 +private: 1.113 + class ShutdownObserver; 1.114 + class RequestMessageLoopRunnable; 1.115 + class ShutdownBackgroundThreadRunnable; 1.116 + class ForceCloseBackgroundActorsRunnable; 1.117 + class CreateCallbackRunnable; 1.118 + class ConnectActorRunnable; 1.119 + 1.120 + struct MOZ_STACK_CLASS TimerCallbackClosure 1.121 + { 1.122 + nsIThread* mThread; 1.123 + nsTArray<ParentImpl*>* mLiveActors; 1.124 + 1.125 + TimerCallbackClosure(nsIThread* aThread, nsTArray<ParentImpl*>* aLiveActors) 1.126 + : mThread(aThread), mLiveActors(aLiveActors) 1.127 + { 1.128 + AssertIsInMainProcess(); 1.129 + AssertIsOnMainThread(); 1.130 + MOZ_ASSERT(aThread); 1.131 + MOZ_ASSERT(aLiveActors); 1.132 + } 1.133 + }; 1.134 + 1.135 + // A handle that is invalid on any platform. 1.136 + static const ProcessHandle kInvalidProcessHandle; 1.137 + 1.138 + // The length of time we will wait at shutdown for all actors to clean 1.139 + // themselves up before forcing them to be destroyed. 1.140 + static const uint32_t kShutdownTimerDelayMS = 10000; 1.141 + 1.142 + // This is only modified on the main thread. It is null if the thread does not 1.143 + // exist or is shutting down. 1.144 + static StaticRefPtr<nsIThread> sBackgroundThread; 1.145 + 1.146 + // This is created and destroyed on the main thread but only modified on the 1.147 + // background thread. It is specific to each instance of sBackgroundThread. 1.148 + static nsTArray<ParentImpl*>* sLiveActorsForBackgroundThread; 1.149 + 1.150 + // This is only modified on the main thread. 1.151 + static StaticRefPtr<nsITimer> sShutdownTimer; 1.152 + 1.153 + // This exists so that that [Assert]IsOnBackgroundThread() can continue to 1.154 + // work during shutdown. 1.155 + static Atomic<PRThread*> sBackgroundPRThread; 1.156 + 1.157 + // This is only modified on the main thread. It is null if the thread does not 1.158 + // exist or is shutting down. 1.159 + static MessageLoop* sBackgroundThreadMessageLoop; 1.160 + 1.161 + // This is only modified on the main thread. It maintains a count of live 1.162 + // actors so that the background thread can be shut down when it is no longer 1.163 + // needed. 1.164 + static uint64_t sLiveActorCount; 1.165 + 1.166 + // This is only modified on the main thread. It is true after the shutdown 1.167 + // observer is registered and is never unset thereafter. 1.168 + static bool sShutdownObserverRegistered; 1.169 + 1.170 + // This is only modified on the main thread. It prevents us from trying to 1.171 + // create the background thread after application shutdown has started. 1.172 + static bool sShutdownHasStarted; 1.173 + 1.174 + // This is only modified on the main thread. It is a FIFO queue for callbacks 1.175 + // waiting for the background thread to be created. 1.176 + static StaticAutoPtr<nsTArray<nsRefPtr<CreateCallback>>> sPendingCallbacks; 1.177 + 1.178 + // Only touched on the main thread, null if this is a same-process actor. 1.179 + nsRefPtr<ContentParent> mContent; 1.180 + 1.181 + // mTransport is "owned" by this object but it must only be released on the 1.182 + // IPC thread. It's left as a raw pointer here to prevent accidentally 1.183 + // deleting it on the wrong thread. Only non-null for other-process actors. 1.184 + Transport* mTransport; 1.185 + 1.186 + // Set when the actor is opened successfully and used to handle shutdown 1.187 + // hangs. Only touched on the background thread. 1.188 + nsTArray<ParentImpl*>* mLiveActorArray; 1.189 + 1.190 + // Set at construction to indicate whether this parent actor corresponds to a 1.191 + // child actor in another process or to a child actor from a different thread 1.192 + // in the same process. 1.193 + const bool mIsOtherProcessActor; 1.194 + 1.195 + // Set after ActorDestroy has been called. Only touched on the background 1.196 + // thread. 1.197 + bool mActorDestroyed; 1.198 + 1.199 +public: 1.200 + static bool 1.201 + CreateActorForSameProcess(CreateCallback* aCallback); 1.202 + 1.203 + static bool 1.204 + IsOnBackgroundThread() 1.205 + { 1.206 + return PR_GetCurrentThread() == sBackgroundPRThread; 1.207 + } 1.208 + 1.209 + static void 1.210 + AssertIsOnBackgroundThread() 1.211 + { 1.212 + THREADSAFETY_ASSERT(IsOnBackgroundThread()); 1.213 + } 1.214 + 1.215 + NS_INLINE_DECL_REFCOUNTING(ParentImpl) 1.216 + 1.217 + void 1.218 + Destroy(); 1.219 + 1.220 +private: 1.221 + // Forwarded from BackgroundParent. 1.222 + static bool 1.223 + IsOtherProcessActor(PBackgroundParent* aBackgroundActor); 1.224 + 1.225 + // Forwarded from BackgroundParent. 1.226 + static already_AddRefed<ContentParent> 1.227 + GetContentParent(PBackgroundParent* aBackgroundActor); 1.228 + 1.229 + // Forwarded from BackgroundParent. 1.230 + static PBackgroundParent* 1.231 + Alloc(ContentParent* aContent, 1.232 + Transport* aTransport, 1.233 + ProcessId aOtherProcess); 1.234 + 1.235 + static bool 1.236 + CreateBackgroundThread(); 1.237 + 1.238 + static void 1.239 + ShutdownBackgroundThread(); 1.240 + 1.241 + static void 1.242 + ShutdownTimerCallback(nsITimer* aTimer, void* aClosure); 1.243 + 1.244 + // For same-process actors. 1.245 + ParentImpl() 1.246 + : mTransport(nullptr), mLiveActorArray(nullptr), mIsOtherProcessActor(false), 1.247 + mActorDestroyed(false) 1.248 + { 1.249 + AssertIsInMainProcess(); 1.250 + AssertIsOnMainThread(); 1.251 + 1.252 + SetOtherProcess(kInvalidProcessHandle); 1.253 + } 1.254 + 1.255 + // For other-process actors. 1.256 + ParentImpl(ContentParent* aContent, Transport* aTransport) 1.257 + : mContent(aContent), mTransport(aTransport), mLiveActorArray(nullptr), 1.258 + mIsOtherProcessActor(true), mActorDestroyed(false) 1.259 + { 1.260 + AssertIsInMainProcess(); 1.261 + AssertIsOnMainThread(); 1.262 + MOZ_ASSERT(aContent); 1.263 + MOZ_ASSERT(aTransport); 1.264 + } 1.265 + 1.266 + ~ParentImpl() 1.267 + { 1.268 + AssertIsInMainProcess(); 1.269 + AssertIsOnMainThread(); 1.270 + MOZ_ASSERT(!mContent); 1.271 + MOZ_ASSERT(!mTransport); 1.272 + } 1.273 + 1.274 + void 1.275 + MainThreadActorDestroy(); 1.276 + 1.277 + void 1.278 + SetLiveActorArray(nsTArray<ParentImpl*>* aLiveActorArray) 1.279 + { 1.280 + AssertIsInMainProcess(); 1.281 + AssertIsOnBackgroundThread(); 1.282 + MOZ_ASSERT(aLiveActorArray); 1.283 + MOZ_ASSERT(!aLiveActorArray->Contains(this)); 1.284 + MOZ_ASSERT(!mLiveActorArray); 1.285 + MOZ_ASSERT(mIsOtherProcessActor); 1.286 + 1.287 + mLiveActorArray = aLiveActorArray; 1.288 + mLiveActorArray->AppendElement(this); 1.289 + } 1.290 + 1.291 + // These methods are only called by IPDL. 1.292 + virtual IToplevelProtocol* 1.293 + CloneToplevel(const InfallibleTArray<ProtocolFdMapping>& aFds, 1.294 + ProcessHandle aPeerProcess, 1.295 + ProtocolCloneContext* aCtx) MOZ_OVERRIDE; 1.296 + 1.297 + virtual void 1.298 + ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; 1.299 +}; 1.300 + 1.301 +// ----------------------------------------------------------------------------- 1.302 +// ChildImpl Declaration 1.303 +// ----------------------------------------------------------------------------- 1.304 + 1.305 +class ChildImpl MOZ_FINAL : public BackgroundChildImpl 1.306 +{ 1.307 + friend class mozilla::ipc::BackgroundChild; 1.308 + friend class mozilla::ipc::BackgroundChildImpl; 1.309 + 1.310 + typedef base::ProcessId ProcessId; 1.311 + typedef mozilla::ipc::Transport Transport; 1.312 + 1.313 + class ShutdownObserver; 1.314 + class CreateActorRunnable; 1.315 + class ParentCreateCallback; 1.316 + class CreateCallbackRunnable; 1.317 + class OpenChildProcessActorRunnable; 1.318 + class OpenMainProcessActorRunnable; 1.319 + 1.320 + // A thread-local index that is not valid. 1.321 + static const unsigned int kBadThreadLocalIndex = 1.322 + static_cast<unsigned int>(-1); 1.323 + 1.324 + // This is only modified on the main thread. It is the thread-local index that 1.325 + // we use to store the BackgroundChild for each thread. 1.326 + static unsigned int sThreadLocalIndex; 1.327 + 1.328 + struct ThreadLocalInfo 1.329 + { 1.330 + ThreadLocalInfo(nsIIPCBackgroundChildCreateCallback* aCallback) 1.331 + { 1.332 + mCallbacks.AppendElement(aCallback); 1.333 + } 1.334 + 1.335 + nsRefPtr<ChildImpl> mActor; 1.336 + nsTArray<nsCOMPtr<nsIIPCBackgroundChildCreateCallback>> mCallbacks; 1.337 + nsAutoPtr<BackgroundChildImpl::ThreadLocal> mConsumerThreadLocal; 1.338 + }; 1.339 + 1.340 + // This is only modified on the main thread. It is a FIFO queue for actors 1.341 + // that are in the process of construction. 1.342 + static StaticAutoPtr<nsTArray<nsCOMPtr<nsIEventTarget>>> sPendingTargets; 1.343 + 1.344 + // This is only modified on the main thread. It prevents us from trying to 1.345 + // create the background thread after application shutdown has started. 1.346 + static bool sShutdownHasStarted; 1.347 + 1.348 +#ifdef RELEASE_BUILD 1.349 + DebugOnly<nsIThread*> mBoundThread; 1.350 +#else 1.351 + nsIThread* mBoundThread; 1.352 +#endif 1.353 + 1.354 +public: 1.355 + static bool 1.356 + OpenProtocolOnMainThread(nsIEventTarget* aEventTarget); 1.357 + 1.358 + static void 1.359 + Shutdown(); 1.360 + 1.361 + void 1.362 + AssertIsOnBoundThread() 1.363 + { 1.364 + THREADSAFETY_ASSERT(mBoundThread); 1.365 + 1.366 +#ifdef RELEASE_BUILD 1.367 + DebugOnly<bool> current; 1.368 +#else 1.369 + bool current; 1.370 +#endif 1.371 + THREADSAFETY_ASSERT( 1.372 + NS_SUCCEEDED(mBoundThread->IsOnCurrentThread(¤t))); 1.373 + THREADSAFETY_ASSERT(current); 1.374 + } 1.375 + 1.376 + ChildImpl() 1.377 + : mBoundThread(nullptr) 1.378 + { 1.379 + AssertIsOnMainThread(); 1.380 + } 1.381 + 1.382 + NS_INLINE_DECL_REFCOUNTING(ChildImpl) 1.383 + 1.384 +private: 1.385 + // Forwarded from BackgroundChild. 1.386 + static void 1.387 + Startup(); 1.388 + 1.389 + // Forwarded from BackgroundChild. 1.390 + static PBackgroundChild* 1.391 + Alloc(Transport* aTransport, ProcessId aOtherProcess); 1.392 + 1.393 + // Forwarded from BackgroundChild. 1.394 + static PBackgroundChild* 1.395 + GetForCurrentThread(); 1.396 + 1.397 + // Forwarded from BackgroundChild. 1.398 + static bool 1.399 + GetOrCreateForCurrentThread(nsIIPCBackgroundChildCreateCallback* aCallback); 1.400 + 1.401 + // Forwarded from BackgroundChildImpl. 1.402 + static BackgroundChildImpl::ThreadLocal* 1.403 + GetThreadLocalForCurrentThread(); 1.404 + 1.405 + static void 1.406 + ThreadLocalDestructor(void* aThreadLocal) 1.407 + { 1.408 + auto threadLocalInfo = static_cast<ThreadLocalInfo*>(aThreadLocal); 1.409 + 1.410 + if (threadLocalInfo) { 1.411 + if (threadLocalInfo->mActor) { 1.412 + threadLocalInfo->mActor->Close(); 1.413 + } 1.414 + delete threadLocalInfo; 1.415 + } 1.416 + } 1.417 + 1.418 + static void 1.419 + DispatchFailureCallback(nsIEventTarget* aEventTarget); 1.420 + 1.421 + // This class is reference counted. 1.422 + ~ChildImpl() 1.423 + { } 1.424 + 1.425 + void 1.426 + SetBoundThread() 1.427 + { 1.428 + THREADSAFETY_ASSERT(!mBoundThread); 1.429 + 1.430 +#if defined(DEBUG) || !defined(RELEASE_BUILD) 1.431 + mBoundThread = NS_GetCurrentThread(); 1.432 +#endif 1.433 + 1.434 + THREADSAFETY_ASSERT(mBoundThread); 1.435 + } 1.436 + 1.437 + // Only called by IPDL. 1.438 + virtual void 1.439 + ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; 1.440 +}; 1.441 + 1.442 +// ----------------------------------------------------------------------------- 1.443 +// ParentImpl Helper Declarations 1.444 +// ----------------------------------------------------------------------------- 1.445 + 1.446 +class ParentImpl::ShutdownObserver MOZ_FINAL : public nsIObserver 1.447 +{ 1.448 +public: 1.449 + ShutdownObserver() 1.450 + { 1.451 + AssertIsOnMainThread(); 1.452 + } 1.453 + 1.454 + NS_DECL_ISUPPORTS 1.455 + NS_DECL_NSIOBSERVER 1.456 + 1.457 +private: 1.458 + ~ShutdownObserver() 1.459 + { 1.460 + AssertIsOnMainThread(); 1.461 + } 1.462 +}; 1.463 + 1.464 +class ParentImpl::RequestMessageLoopRunnable MOZ_FINAL : 1.465 + public nsRunnable 1.466 +{ 1.467 + nsCOMPtr<nsIThread> mTargetThread; 1.468 + MessageLoop* mMessageLoop; 1.469 + 1.470 +public: 1.471 + RequestMessageLoopRunnable(nsIThread* aTargetThread) 1.472 + : mTargetThread(aTargetThread), mMessageLoop(nullptr) 1.473 + { 1.474 + AssertIsInMainProcess(); 1.475 + AssertIsOnMainThread(); 1.476 + MOZ_ASSERT(aTargetThread); 1.477 + } 1.478 + 1.479 + NS_DECL_ISUPPORTS_INHERITED 1.480 + 1.481 +private: 1.482 + ~RequestMessageLoopRunnable() 1.483 + { } 1.484 + 1.485 + NS_DECL_NSIRUNNABLE 1.486 +}; 1.487 + 1.488 +class ParentImpl::ShutdownBackgroundThreadRunnable MOZ_FINAL : public nsRunnable 1.489 +{ 1.490 +public: 1.491 + ShutdownBackgroundThreadRunnable() 1.492 + { 1.493 + AssertIsInMainProcess(); 1.494 + AssertIsOnMainThread(); 1.495 + } 1.496 + 1.497 + NS_DECL_ISUPPORTS_INHERITED 1.498 + 1.499 +private: 1.500 + ~ShutdownBackgroundThreadRunnable() 1.501 + { } 1.502 + 1.503 + NS_DECL_NSIRUNNABLE 1.504 +}; 1.505 + 1.506 +class ParentImpl::ForceCloseBackgroundActorsRunnable MOZ_FINAL : public nsRunnable 1.507 +{ 1.508 + nsTArray<ParentImpl*>* mActorArray; 1.509 + 1.510 +public: 1.511 + ForceCloseBackgroundActorsRunnable(nsTArray<ParentImpl*>* aActorArray) 1.512 + : mActorArray(aActorArray) 1.513 + { 1.514 + AssertIsInMainProcess(); 1.515 + AssertIsOnMainThread(); 1.516 + MOZ_ASSERT(aActorArray); 1.517 + } 1.518 + 1.519 + NS_DECL_ISUPPORTS_INHERITED 1.520 + 1.521 +private: 1.522 + ~ForceCloseBackgroundActorsRunnable() 1.523 + { } 1.524 + 1.525 + NS_DECL_NSIRUNNABLE 1.526 +}; 1.527 + 1.528 +class ParentImpl::CreateCallbackRunnable MOZ_FINAL : public nsRunnable 1.529 +{ 1.530 + nsRefPtr<CreateCallback> mCallback; 1.531 + 1.532 +public: 1.533 + CreateCallbackRunnable(CreateCallback* aCallback) 1.534 + : mCallback(aCallback) 1.535 + { 1.536 + AssertIsInMainProcess(); 1.537 + AssertIsOnMainThread(); 1.538 + MOZ_ASSERT(aCallback); 1.539 + } 1.540 + 1.541 + NS_DECL_ISUPPORTS_INHERITED 1.542 + 1.543 +private: 1.544 + ~CreateCallbackRunnable() 1.545 + { } 1.546 + 1.547 + NS_DECL_NSIRUNNABLE 1.548 +}; 1.549 + 1.550 +class ParentImpl::ConnectActorRunnable MOZ_FINAL : public nsRunnable 1.551 +{ 1.552 + nsRefPtr<ParentImpl> mActor; 1.553 + Transport* mTransport; 1.554 + ProcessHandle mProcessHandle; 1.555 + nsTArray<ParentImpl*>* mLiveActorArray; 1.556 + 1.557 +public: 1.558 + ConnectActorRunnable(ParentImpl* aActor, 1.559 + Transport* aTransport, 1.560 + ProcessHandle aProcessHandle, 1.561 + nsTArray<ParentImpl*>* aLiveActorArray) 1.562 + : mActor(aActor), mTransport(aTransport), mProcessHandle(aProcessHandle), 1.563 + mLiveActorArray(aLiveActorArray) 1.564 + { 1.565 + AssertIsInMainProcess(); 1.566 + AssertIsOnMainThread(); 1.567 + MOZ_ASSERT(aActor); 1.568 + MOZ_ASSERT(aTransport); 1.569 + MOZ_ASSERT(aLiveActorArray); 1.570 + } 1.571 + 1.572 + NS_DECL_ISUPPORTS_INHERITED 1.573 + 1.574 +private: 1.575 + ~ConnectActorRunnable() 1.576 + { 1.577 + AssertIsInMainProcess(); 1.578 + } 1.579 + 1.580 + NS_DECL_NSIRUNNABLE 1.581 +}; 1.582 + 1.583 +class NS_NO_VTABLE ParentImpl::CreateCallback 1.584 +{ 1.585 +public: 1.586 + NS_INLINE_DECL_REFCOUNTING(CreateCallback) 1.587 + 1.588 + virtual void 1.589 + Success(already_AddRefed<ParentImpl> aActor, MessageLoop* aMessageLoop) = 0; 1.590 + 1.591 + virtual void 1.592 + Failure() = 0; 1.593 + 1.594 +protected: 1.595 + virtual ~CreateCallback() 1.596 + { } 1.597 +}; 1.598 + 1.599 +// ----------------------------------------------------------------------------- 1.600 +// ChildImpl Helper Declarations 1.601 +// ----------------------------------------------------------------------------- 1.602 + 1.603 +class ChildImpl::ShutdownObserver MOZ_FINAL : public nsIObserver 1.604 +{ 1.605 +public: 1.606 + ShutdownObserver() 1.607 + { 1.608 + AssertIsOnMainThread(); 1.609 + } 1.610 + 1.611 + NS_DECL_ISUPPORTS 1.612 + NS_DECL_NSIOBSERVER 1.613 + 1.614 +private: 1.615 + ~ShutdownObserver() 1.616 + { 1.617 + AssertIsOnMainThread(); 1.618 + } 1.619 +}; 1.620 + 1.621 +class ChildImpl::CreateActorRunnable MOZ_FINAL : public nsRunnable 1.622 +{ 1.623 + nsCOMPtr<nsIEventTarget> mEventTarget; 1.624 + 1.625 +public: 1.626 + CreateActorRunnable() 1.627 + : mEventTarget(NS_GetCurrentThread()) 1.628 + { 1.629 + MOZ_ASSERT(mEventTarget); 1.630 + } 1.631 + 1.632 + NS_DECL_ISUPPORTS_INHERITED 1.633 + 1.634 +private: 1.635 + ~CreateActorRunnable() 1.636 + { } 1.637 + 1.638 + NS_DECL_NSIRUNNABLE 1.639 +}; 1.640 + 1.641 +class ChildImpl::ParentCreateCallback MOZ_FINAL : 1.642 + public ParentImpl::CreateCallback 1.643 +{ 1.644 + nsCOMPtr<nsIEventTarget> mEventTarget; 1.645 + 1.646 +public: 1.647 + ParentCreateCallback(nsIEventTarget* aEventTarget) 1.648 + : mEventTarget(aEventTarget) 1.649 + { 1.650 + AssertIsInMainProcess(); 1.651 + AssertIsOnMainThread(); 1.652 + MOZ_ASSERT(aEventTarget); 1.653 + } 1.654 + 1.655 +private: 1.656 + ~ParentCreateCallback() 1.657 + { } 1.658 + 1.659 + virtual void 1.660 + Success(already_AddRefed<ParentImpl> aActor, MessageLoop* aMessageLoop) 1.661 + MOZ_OVERRIDE; 1.662 + 1.663 + virtual void 1.664 + Failure() MOZ_OVERRIDE; 1.665 +}; 1.666 + 1.667 +class ChildImpl::CreateCallbackRunnable : public nsRunnable 1.668 +{ 1.669 +protected: 1.670 + nsRefPtr<ChildImpl> mActor; 1.671 + 1.672 +public: 1.673 + CreateCallbackRunnable(already_AddRefed<ChildImpl>&& aActor) 1.674 + : mActor(aActor) 1.675 + { 1.676 + // May be created on any thread! 1.677 + 1.678 + MOZ_ASSERT(mActor); 1.679 + } 1.680 + 1.681 + CreateCallbackRunnable() 1.682 + { 1.683 + // May be created on any thread! 1.684 + } 1.685 + 1.686 + NS_DECL_ISUPPORTS_INHERITED 1.687 + 1.688 +protected: 1.689 + virtual ~CreateCallbackRunnable(); 1.690 + 1.691 + static already_AddRefed<nsIIPCBackgroundChildCreateCallback> 1.692 + GetNextCallback(); 1.693 + 1.694 + NS_DECL_NSIRUNNABLE 1.695 +}; 1.696 + 1.697 +class ChildImpl::OpenChildProcessActorRunnable MOZ_FINAL : 1.698 + public ChildImpl::CreateCallbackRunnable 1.699 +{ 1.700 + nsAutoPtr<Transport> mTransport; 1.701 + ProcessHandle mProcessHandle; 1.702 + 1.703 +public: 1.704 + OpenChildProcessActorRunnable(already_AddRefed<ChildImpl>&& aActor, 1.705 + Transport* aTransport, 1.706 + ProcessHandle aProcessHandle) 1.707 + : CreateCallbackRunnable(Move(aActor)), mTransport(aTransport), 1.708 + mProcessHandle(aProcessHandle) 1.709 + { 1.710 + AssertIsOnMainThread(); 1.711 + MOZ_ASSERT(aTransport); 1.712 + } 1.713 + 1.714 + NS_DECL_ISUPPORTS_INHERITED 1.715 + 1.716 +private: 1.717 + ~OpenChildProcessActorRunnable() 1.718 + { 1.719 + if (mTransport) { 1.720 + CRASH_IN_CHILD_PROCESS("Leaking transport!"); 1.721 + unused << mTransport.forget(); 1.722 + } 1.723 + } 1.724 + 1.725 + NS_DECL_NSIRUNNABLE 1.726 +}; 1.727 + 1.728 +class ChildImpl::OpenMainProcessActorRunnable MOZ_FINAL : 1.729 + public ChildImpl::CreateCallbackRunnable 1.730 +{ 1.731 + nsRefPtr<ParentImpl> mParentActor; 1.732 + MessageLoop* mParentMessageLoop; 1.733 + 1.734 +public: 1.735 + OpenMainProcessActorRunnable(already_AddRefed<ChildImpl>&& aChildActor, 1.736 + already_AddRefed<ParentImpl> aParentActor, 1.737 + MessageLoop* aParentMessageLoop) 1.738 + : CreateCallbackRunnable(Move(aChildActor)), mParentActor(aParentActor), 1.739 + mParentMessageLoop(aParentMessageLoop) 1.740 + { 1.741 + AssertIsOnMainThread(); 1.742 + MOZ_ASSERT(mParentActor); 1.743 + MOZ_ASSERT(aParentMessageLoop); 1.744 + } 1.745 + 1.746 + NS_DECL_ISUPPORTS_INHERITED 1.747 + 1.748 +private: 1.749 + ~OpenMainProcessActorRunnable() 1.750 + { } 1.751 + 1.752 + NS_DECL_NSIRUNNABLE 1.753 +}; 1.754 + 1.755 +} // anonymous namespace 1.756 + 1.757 +namespace mozilla { 1.758 +namespace ipc { 1.759 + 1.760 +bool 1.761 +IsOnBackgroundThread() 1.762 +{ 1.763 + return ParentImpl::IsOnBackgroundThread(); 1.764 +} 1.765 + 1.766 +#ifdef DEBUG 1.767 + 1.768 +void 1.769 +AssertIsOnBackgroundThread() 1.770 +{ 1.771 + ParentImpl::AssertIsOnBackgroundThread(); 1.772 +} 1.773 + 1.774 +#endif // DEBUG 1.775 + 1.776 +} // namespace ipc 1.777 +} // namespace mozilla 1.778 + 1.779 +// ----------------------------------------------------------------------------- 1.780 +// BackgroundParent Public Methods 1.781 +// ----------------------------------------------------------------------------- 1.782 + 1.783 +// static 1.784 +bool 1.785 +BackgroundParent::IsOtherProcessActor(PBackgroundParent* aBackgroundActor) 1.786 +{ 1.787 + return ParentImpl::IsOtherProcessActor(aBackgroundActor); 1.788 +} 1.789 + 1.790 +// static 1.791 +already_AddRefed<ContentParent> 1.792 +BackgroundParent::GetContentParent(PBackgroundParent* aBackgroundActor) 1.793 +{ 1.794 + return ParentImpl::GetContentParent(aBackgroundActor); 1.795 +} 1.796 + 1.797 +// static 1.798 +PBackgroundParent* 1.799 +BackgroundParent::Alloc(ContentParent* aContent, 1.800 + Transport* aTransport, 1.801 + ProcessId aOtherProcess) 1.802 +{ 1.803 + return ParentImpl::Alloc(aContent, aTransport, aOtherProcess); 1.804 +} 1.805 + 1.806 +// ----------------------------------------------------------------------------- 1.807 +// BackgroundChild Public Methods 1.808 +// ----------------------------------------------------------------------------- 1.809 + 1.810 +// static 1.811 +void 1.812 +BackgroundChild::Startup() 1.813 +{ 1.814 + ChildImpl::Startup(); 1.815 +} 1.816 + 1.817 +// static 1.818 +PBackgroundChild* 1.819 +BackgroundChild::Alloc(Transport* aTransport, ProcessId aOtherProcess) 1.820 +{ 1.821 + return ChildImpl::Alloc(aTransport, aOtherProcess); 1.822 +} 1.823 + 1.824 +// static 1.825 +PBackgroundChild* 1.826 +BackgroundChild::GetForCurrentThread() 1.827 +{ 1.828 + return ChildImpl::GetForCurrentThread(); 1.829 +} 1.830 + 1.831 +// static 1.832 +bool 1.833 +BackgroundChild::GetOrCreateForCurrentThread( 1.834 + nsIIPCBackgroundChildCreateCallback* aCallback) 1.835 +{ 1.836 + return ChildImpl::GetOrCreateForCurrentThread(aCallback); 1.837 +} 1.838 + 1.839 +// ----------------------------------------------------------------------------- 1.840 +// BackgroundChildImpl Public Methods 1.841 +// ----------------------------------------------------------------------------- 1.842 + 1.843 +// static 1.844 +BackgroundChildImpl::ThreadLocal* 1.845 +BackgroundChildImpl::GetThreadLocalForCurrentThread() 1.846 +{ 1.847 + return ChildImpl::GetThreadLocalForCurrentThread(); 1.848 +} 1.849 + 1.850 +// ----------------------------------------------------------------------------- 1.851 +// ParentImpl Static Members 1.852 +// ----------------------------------------------------------------------------- 1.853 + 1.854 +const ParentImpl::ProcessHandle ParentImpl::kInvalidProcessHandle = 1.855 +#ifdef XP_WIN 1.856 + ProcessHandle(INVALID_HANDLE_VALUE); 1.857 +#else 1.858 + ProcessHandle(-1); 1.859 +#endif 1.860 + 1.861 +StaticRefPtr<nsIThread> ParentImpl::sBackgroundThread; 1.862 + 1.863 +nsTArray<ParentImpl*>* ParentImpl::sLiveActorsForBackgroundThread; 1.864 + 1.865 +StaticRefPtr<nsITimer> ParentImpl::sShutdownTimer; 1.866 + 1.867 +Atomic<PRThread*> ParentImpl::sBackgroundPRThread; 1.868 + 1.869 +MessageLoop* ParentImpl::sBackgroundThreadMessageLoop = nullptr; 1.870 + 1.871 +uint64_t ParentImpl::sLiveActorCount = 0; 1.872 + 1.873 +bool ParentImpl::sShutdownObserverRegistered = false; 1.874 + 1.875 +bool ParentImpl::sShutdownHasStarted = false; 1.876 + 1.877 +StaticAutoPtr<nsTArray<nsRefPtr<ParentImpl::CreateCallback>>> 1.878 + ParentImpl::sPendingCallbacks; 1.879 + 1.880 +// ----------------------------------------------------------------------------- 1.881 +// ChildImpl Static Members 1.882 +// ----------------------------------------------------------------------------- 1.883 + 1.884 +unsigned int ChildImpl::sThreadLocalIndex = kBadThreadLocalIndex; 1.885 + 1.886 +StaticAutoPtr<nsTArray<nsCOMPtr<nsIEventTarget>>> ChildImpl::sPendingTargets; 1.887 + 1.888 +bool ChildImpl::sShutdownHasStarted = false; 1.889 + 1.890 +// ----------------------------------------------------------------------------- 1.891 +// ParentImpl Implementation 1.892 +// ----------------------------------------------------------------------------- 1.893 + 1.894 +// static 1.895 +bool 1.896 +ParentImpl::IsOtherProcessActor(PBackgroundParent* aBackgroundActor) 1.897 +{ 1.898 + AssertIsOnBackgroundThread(); 1.899 + MOZ_ASSERT(aBackgroundActor); 1.900 + 1.901 + return static_cast<ParentImpl*>(aBackgroundActor)->mIsOtherProcessActor; 1.902 +} 1.903 + 1.904 +// static 1.905 +already_AddRefed<ContentParent> 1.906 +ParentImpl::GetContentParent(PBackgroundParent* aBackgroundActor) 1.907 +{ 1.908 + AssertIsOnBackgroundThread(); 1.909 + MOZ_ASSERT(aBackgroundActor); 1.910 + 1.911 + auto actor = static_cast<ParentImpl*>(aBackgroundActor); 1.912 + if (actor->mActorDestroyed) { 1.913 + MOZ_ASSERT(false, "GetContentParent called after ActorDestroy was called!"); 1.914 + return nullptr; 1.915 + } 1.916 + 1.917 + if (actor->mContent) { 1.918 + // We need to hand out a reference to our ContentParent but we also need to 1.919 + // keep the one we have. We can't call AddRef here because ContentParent is 1.920 + // not threadsafe so instead we dispatch a runnable to the main thread to do 1.921 + // it for us. This is safe since we are guaranteed that our AddRef runnable 1.922 + // will run before the reference we hand out can be released, and the 1.923 + // ContentParent can't die as long as the existing reference is maintained. 1.924 + nsCOMPtr<nsIRunnable> runnable = 1.925 + NS_NewNonOwningRunnableMethod(actor->mContent, &ContentParent::AddRef); 1.926 + MOZ_ASSERT(runnable); 1.927 + 1.928 + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(runnable))); 1.929 + } 1.930 + 1.931 + return actor->mContent.get(); 1.932 +} 1.933 + 1.934 +// static 1.935 +PBackgroundParent* 1.936 +ParentImpl::Alloc(ContentParent* aContent, 1.937 + Transport* aTransport, 1.938 + ProcessId aOtherProcess) 1.939 +{ 1.940 + AssertIsInMainProcess(); 1.941 + AssertIsOnMainThread(); 1.942 + MOZ_ASSERT(aTransport); 1.943 + 1.944 + ProcessHandle processHandle; 1.945 + if (!base::OpenProcessHandle(aOtherProcess, &processHandle)) { 1.946 + // Process has already died? 1.947 + return nullptr; 1.948 + } 1.949 + 1.950 + if (!sBackgroundThread && !CreateBackgroundThread()) { 1.951 + NS_WARNING("Failed to create background thread!"); 1.952 + return nullptr; 1.953 + } 1.954 + 1.955 + MOZ_ASSERT(sLiveActorsForBackgroundThread); 1.956 + 1.957 + sLiveActorCount++; 1.958 + 1.959 + nsRefPtr<ParentImpl> actor = new ParentImpl(aContent, aTransport); 1.960 + 1.961 + nsCOMPtr<nsIRunnable> connectRunnable = 1.962 + new ConnectActorRunnable(actor, aTransport, processHandle, 1.963 + sLiveActorsForBackgroundThread); 1.964 + 1.965 + if (NS_FAILED(sBackgroundThread->Dispatch(connectRunnable, 1.966 + NS_DISPATCH_NORMAL))) { 1.967 + NS_WARNING("Failed to dispatch connect runnable!"); 1.968 + 1.969 + MOZ_ASSERT(sLiveActorCount); 1.970 + sLiveActorCount--; 1.971 + 1.972 + if (!sLiveActorCount) { 1.973 + ShutdownBackgroundThread(); 1.974 + } 1.975 + 1.976 + return nullptr; 1.977 + } 1.978 + 1.979 + return actor; 1.980 +} 1.981 + 1.982 +// static 1.983 +bool 1.984 +ParentImpl::CreateActorForSameProcess(CreateCallback* aCallback) 1.985 +{ 1.986 + AssertIsInMainProcess(); 1.987 + AssertIsOnMainThread(); 1.988 + MOZ_ASSERT(aCallback); 1.989 + 1.990 + if (!sBackgroundThread && !CreateBackgroundThread()) { 1.991 + NS_WARNING("Failed to create background thread!"); 1.992 + return false; 1.993 + } 1.994 + 1.995 + MOZ_ASSERT(!sShutdownHasStarted); 1.996 + 1.997 + sLiveActorCount++; 1.998 + 1.999 + if (sBackgroundThreadMessageLoop) { 1.1000 + nsCOMPtr<nsIRunnable> callbackRunnable = 1.1001 + new CreateCallbackRunnable(aCallback); 1.1002 + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToCurrentThread(callbackRunnable))); 1.1003 + return true; 1.1004 + } 1.1005 + 1.1006 + if (!sPendingCallbacks) { 1.1007 + sPendingCallbacks = new nsTArray<nsRefPtr<CreateCallback>>(); 1.1008 + } 1.1009 + 1.1010 + sPendingCallbacks->AppendElement(aCallback); 1.1011 + return true; 1.1012 +} 1.1013 + 1.1014 +// static 1.1015 +bool 1.1016 +ParentImpl::CreateBackgroundThread() 1.1017 +{ 1.1018 + AssertIsInMainProcess(); 1.1019 + AssertIsOnMainThread(); 1.1020 + MOZ_ASSERT(!sBackgroundThread); 1.1021 + MOZ_ASSERT(!sLiveActorsForBackgroundThread); 1.1022 + 1.1023 + if (sShutdownHasStarted) { 1.1024 + NS_WARNING("Trying to create background thread after shutdown has " 1.1025 + "already begun!"); 1.1026 + return false; 1.1027 + } 1.1028 + 1.1029 + nsCOMPtr<nsITimer> newShutdownTimer; 1.1030 + 1.1031 + if (!sShutdownTimer) { 1.1032 + nsresult rv; 1.1033 + newShutdownTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv); 1.1034 + if (NS_WARN_IF(NS_FAILED(rv))) { 1.1035 + return false; 1.1036 + } 1.1037 + } 1.1038 + 1.1039 + if (!sShutdownObserverRegistered) { 1.1040 + nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); 1.1041 + if (NS_WARN_IF(!obs)) { 1.1042 + return false; 1.1043 + } 1.1044 + 1.1045 + nsCOMPtr<nsIObserver> observer = new ShutdownObserver(); 1.1046 + 1.1047 + nsresult rv = 1.1048 + obs->AddObserver(observer, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, false); 1.1049 + if (NS_WARN_IF(NS_FAILED(rv))) { 1.1050 + return false; 1.1051 + } 1.1052 + 1.1053 + sShutdownObserverRegistered = true; 1.1054 + } 1.1055 + 1.1056 + nsCOMPtr<nsIThread> thread; 1.1057 + if (NS_FAILED(NS_NewNamedThread("IPDL Background", getter_AddRefs(thread)))) { 1.1058 + NS_WARNING("NS_NewNamedThread failed!"); 1.1059 + return false; 1.1060 + } 1.1061 + 1.1062 + nsCOMPtr<nsIRunnable> messageLoopRunnable = 1.1063 + new RequestMessageLoopRunnable(thread); 1.1064 + if (NS_FAILED(thread->Dispatch(messageLoopRunnable, NS_DISPATCH_NORMAL))) { 1.1065 + NS_WARNING("Failed to dispatch RequestMessageLoopRunnable!"); 1.1066 + return false; 1.1067 + } 1.1068 + 1.1069 + sBackgroundThread = thread; 1.1070 + sLiveActorsForBackgroundThread = new nsTArray<ParentImpl*>(1); 1.1071 + 1.1072 + if (!sShutdownTimer) { 1.1073 + MOZ_ASSERT(newShutdownTimer); 1.1074 + sShutdownTimer = newShutdownTimer; 1.1075 + } 1.1076 + 1.1077 + return true; 1.1078 +} 1.1079 + 1.1080 +// static 1.1081 +void 1.1082 +ParentImpl::ShutdownBackgroundThread() 1.1083 +{ 1.1084 + AssertIsInMainProcess(); 1.1085 + AssertIsOnMainThread(); 1.1086 + MOZ_ASSERT_IF(!sBackgroundThread, !sBackgroundThreadMessageLoop); 1.1087 + MOZ_ASSERT_IF(!sShutdownHasStarted, !sLiveActorCount); 1.1088 + MOZ_ASSERT_IF(!sBackgroundThread, !sLiveActorCount); 1.1089 + MOZ_ASSERT_IF(sBackgroundThread, sShutdownTimer); 1.1090 + 1.1091 + if (sPendingCallbacks) { 1.1092 + if (!sPendingCallbacks->IsEmpty()) { 1.1093 + nsTArray<nsRefPtr<CreateCallback>> callbacks; 1.1094 + sPendingCallbacks->SwapElements(callbacks); 1.1095 + 1.1096 + for (uint32_t index = 0; index < callbacks.Length(); index++) { 1.1097 + nsRefPtr<CreateCallback> callback; 1.1098 + callbacks[index].swap(callback); 1.1099 + MOZ_ASSERT(callback); 1.1100 + 1.1101 + callback->Failure(); 1.1102 + } 1.1103 + } 1.1104 + 1.1105 + if (sShutdownHasStarted) { 1.1106 + sPendingCallbacks = nullptr; 1.1107 + } 1.1108 + } 1.1109 + 1.1110 + nsCOMPtr<nsITimer> shutdownTimer; 1.1111 + if (sShutdownHasStarted) { 1.1112 + shutdownTimer = sShutdownTimer.get(); 1.1113 + sShutdownTimer = nullptr; 1.1114 + } 1.1115 + 1.1116 + if (sBackgroundThread) { 1.1117 + nsCOMPtr<nsIThread> thread = sBackgroundThread.get(); 1.1118 + nsAutoPtr<nsTArray<ParentImpl*>> liveActors(sLiveActorsForBackgroundThread); 1.1119 + 1.1120 + sBackgroundThread = nullptr; 1.1121 + sLiveActorsForBackgroundThread = nullptr; 1.1122 + sBackgroundThreadMessageLoop = nullptr; 1.1123 + 1.1124 + MOZ_ASSERT_IF(!sShutdownHasStarted, !sLiveActorCount); 1.1125 + 1.1126 + if (sShutdownHasStarted) { 1.1127 + // If this is final shutdown then we need to spin the event loop while we 1.1128 + // wait for all the actors to be cleaned up. We also set a timeout to 1.1129 + // force-kill any hanging actors. 1.1130 + 1.1131 + if (sLiveActorCount) { 1.1132 + TimerCallbackClosure closure(thread, liveActors); 1.1133 + 1.1134 + MOZ_ALWAYS_TRUE(NS_SUCCEEDED( 1.1135 + shutdownTimer->InitWithFuncCallback(&ShutdownTimerCallback, &closure, 1.1136 + kShutdownTimerDelayMS, 1.1137 + nsITimer::TYPE_ONE_SHOT))); 1.1138 + 1.1139 + nsIThread* currentThread = NS_GetCurrentThread(); 1.1140 + MOZ_ASSERT(currentThread); 1.1141 + 1.1142 + while (sLiveActorCount) { 1.1143 + NS_ProcessNextEvent(currentThread); 1.1144 + } 1.1145 + 1.1146 + MOZ_ASSERT(liveActors->IsEmpty()); 1.1147 + 1.1148 + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(shutdownTimer->Cancel())); 1.1149 + } 1.1150 + } 1.1151 + 1.1152 + // Dispatch this runnable to unregister the thread from the profiler. 1.1153 + nsCOMPtr<nsIRunnable> shutdownRunnable = 1.1154 + new ShutdownBackgroundThreadRunnable(); 1.1155 + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(thread->Dispatch(shutdownRunnable, 1.1156 + NS_DISPATCH_NORMAL))); 1.1157 + 1.1158 + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(thread->Shutdown())); 1.1159 + } 1.1160 +} 1.1161 + 1.1162 +// static 1.1163 +void 1.1164 +ParentImpl::ShutdownTimerCallback(nsITimer* aTimer, void* aClosure) 1.1165 +{ 1.1166 + AssertIsInMainProcess(); 1.1167 + AssertIsOnMainThread(); 1.1168 + MOZ_ASSERT(sShutdownHasStarted); 1.1169 + MOZ_ASSERT(sLiveActorCount); 1.1170 + 1.1171 + auto closure = static_cast<TimerCallbackClosure*>(aClosure); 1.1172 + MOZ_ASSERT(closure); 1.1173 + 1.1174 + // Don't let the stack unwind until the ForceCloseBackgroundActorsRunnable has 1.1175 + // finished. 1.1176 + sLiveActorCount++; 1.1177 + 1.1178 + nsCOMPtr<nsIRunnable> forceCloseRunnable = 1.1179 + new ForceCloseBackgroundActorsRunnable(closure->mLiveActors); 1.1180 + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(closure->mThread->Dispatch(forceCloseRunnable, 1.1181 + NS_DISPATCH_NORMAL))); 1.1182 +} 1.1183 + 1.1184 +void 1.1185 +ParentImpl::Destroy() 1.1186 +{ 1.1187 + // May be called on any thread! 1.1188 + 1.1189 + AssertIsInMainProcess(); 1.1190 + 1.1191 + nsCOMPtr<nsIRunnable> destroyRunnable = 1.1192 + NS_NewNonOwningRunnableMethod(this, &ParentImpl::MainThreadActorDestroy); 1.1193 + MOZ_ASSERT(destroyRunnable); 1.1194 + 1.1195 + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(destroyRunnable))); 1.1196 +} 1.1197 + 1.1198 +void 1.1199 +ParentImpl::MainThreadActorDestroy() 1.1200 +{ 1.1201 + AssertIsInMainProcess(); 1.1202 + AssertIsOnMainThread(); 1.1203 + MOZ_ASSERT_IF(mIsOtherProcessActor, mContent); 1.1204 + MOZ_ASSERT_IF(!mIsOtherProcessActor, !mContent); 1.1205 + MOZ_ASSERT_IF(mIsOtherProcessActor, mTransport); 1.1206 + MOZ_ASSERT_IF(!mIsOtherProcessActor, !mTransport); 1.1207 + 1.1208 + if (mTransport) { 1.1209 + XRE_GetIOMessageLoop()->PostTask(FROM_HERE, 1.1210 + new DeleteTask<Transport>(mTransport)); 1.1211 + mTransport = nullptr; 1.1212 + } 1.1213 + 1.1214 + ProcessHandle otherProcess = OtherProcess(); 1.1215 + if (otherProcess != kInvalidProcessHandle) { 1.1216 + base::CloseProcessHandle(otherProcess); 1.1217 +#ifdef DEBUG 1.1218 + SetOtherProcess(kInvalidProcessHandle); 1.1219 +#endif 1.1220 + } 1.1221 + 1.1222 + mContent = nullptr; 1.1223 + 1.1224 + MOZ_ASSERT(sLiveActorCount); 1.1225 + sLiveActorCount--; 1.1226 + 1.1227 + if (!sLiveActorCount) { 1.1228 + ShutdownBackgroundThread(); 1.1229 + } 1.1230 + 1.1231 + // This may be the last reference! 1.1232 + Release(); 1.1233 +} 1.1234 + 1.1235 +IToplevelProtocol* 1.1236 +ParentImpl::CloneToplevel(const InfallibleTArray<ProtocolFdMapping>& aFds, 1.1237 + ProcessHandle aPeerProcess, 1.1238 + ProtocolCloneContext* aCtx) 1.1239 +{ 1.1240 + AssertIsInMainProcess(); 1.1241 + AssertIsOnMainThread(); 1.1242 + 1.1243 + const ProtocolId protocolId = GetProtocolId(); 1.1244 + 1.1245 + for (unsigned int i = 0; i < aFds.Length(); i++) { 1.1246 + if (static_cast<ProtocolId>(aFds[i].protocolId()) != protocolId) { 1.1247 + continue; 1.1248 + } 1.1249 + 1.1250 + Transport* transport = OpenDescriptor(aFds[i].fd(), 1.1251 + Transport::MODE_SERVER); 1.1252 + if (!transport) { 1.1253 + NS_WARNING("Failed to open transport!"); 1.1254 + break; 1.1255 + } 1.1256 + 1.1257 + PBackgroundParent* clonedActor = 1.1258 + Alloc(mContent, transport, base::GetProcId(aPeerProcess)); 1.1259 + MOZ_ASSERT(clonedActor); 1.1260 + 1.1261 + clonedActor->CloneManagees(this, aCtx); 1.1262 + clonedActor->SetTransport(transport); 1.1263 + 1.1264 + return clonedActor; 1.1265 + } 1.1266 + 1.1267 + return nullptr; 1.1268 +} 1.1269 + 1.1270 +void 1.1271 +ParentImpl::ActorDestroy(ActorDestroyReason aWhy) 1.1272 +{ 1.1273 + AssertIsInMainProcess(); 1.1274 + AssertIsOnBackgroundThread(); 1.1275 + MOZ_ASSERT(!mActorDestroyed); 1.1276 + MOZ_ASSERT_IF(mIsOtherProcessActor, mLiveActorArray); 1.1277 + 1.1278 + BackgroundParentImpl::ActorDestroy(aWhy); 1.1279 + 1.1280 + mActorDestroyed = true; 1.1281 + 1.1282 + if (mLiveActorArray) { 1.1283 + MOZ_ALWAYS_TRUE(mLiveActorArray->RemoveElement(this)); 1.1284 + mLiveActorArray = nullptr; 1.1285 + } 1.1286 + 1.1287 + // This is tricky. We should be able to call Destroy() here directly because 1.1288 + // we're not going to touch 'this' or our MessageChannel any longer on this 1.1289 + // thread. Destroy() dispatches the MainThreadActorDestroy runnable and when 1.1290 + // it runs it will destroy 'this' and our associated MessageChannel. However, 1.1291 + // IPDL is about to call MessageChannel::Clear() on this thread! To avoid 1.1292 + // racing with the main thread we must ensure that the MessageChannel lives 1.1293 + // long enough to be cleared in this call stack. 1.1294 + nsCOMPtr<nsIRunnable> destroyRunnable = 1.1295 + NS_NewNonOwningRunnableMethod(this, &ParentImpl::Destroy); 1.1296 + MOZ_ASSERT(destroyRunnable); 1.1297 + 1.1298 + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToCurrentThread(destroyRunnable))); 1.1299 +} 1.1300 + 1.1301 +NS_IMPL_ISUPPORTS(ParentImpl::ShutdownObserver, nsIObserver) 1.1302 + 1.1303 +NS_IMETHODIMP 1.1304 +ParentImpl::ShutdownObserver::Observe(nsISupports* aSubject, 1.1305 + const char* aTopic, 1.1306 + const char16_t* aData) 1.1307 +{ 1.1308 + AssertIsInMainProcess(); 1.1309 + AssertIsOnMainThread(); 1.1310 + MOZ_ASSERT(!sShutdownHasStarted); 1.1311 + MOZ_ASSERT(!strcmp(aTopic, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID)); 1.1312 + 1.1313 + sShutdownHasStarted = true; 1.1314 + 1.1315 + // Do this first before calling (and spinning the event loop in) 1.1316 + // ShutdownBackgroundThread(). 1.1317 + ChildImpl::Shutdown(); 1.1318 + 1.1319 + ShutdownBackgroundThread(); 1.1320 + 1.1321 + return NS_OK; 1.1322 +} 1.1323 + 1.1324 +NS_IMPL_ISUPPORTS_INHERITED0(ParentImpl::RequestMessageLoopRunnable, 1.1325 + nsRunnable) 1.1326 + 1.1327 +NS_IMETHODIMP 1.1328 +ParentImpl::RequestMessageLoopRunnable::Run() 1.1329 +{ 1.1330 + AssertIsInMainProcess(); 1.1331 + MOZ_ASSERT(mTargetThread); 1.1332 + 1.1333 + if (NS_IsMainThread()) { 1.1334 + MOZ_ASSERT(mMessageLoop); 1.1335 + 1.1336 + if (!sBackgroundThread || 1.1337 + !SameCOMIdentity(mTargetThread.get(), sBackgroundThread.get())) { 1.1338 + return NS_OK; 1.1339 + } 1.1340 + 1.1341 + MOZ_ASSERT(!sBackgroundThreadMessageLoop); 1.1342 + sBackgroundThreadMessageLoop = mMessageLoop; 1.1343 + 1.1344 + if (sPendingCallbacks && !sPendingCallbacks->IsEmpty()) { 1.1345 + nsTArray<nsRefPtr<CreateCallback>> callbacks; 1.1346 + sPendingCallbacks->SwapElements(callbacks); 1.1347 + 1.1348 + for (uint32_t index = 0; index < callbacks.Length(); index++) { 1.1349 + MOZ_ASSERT(callbacks[index]); 1.1350 + 1.1351 + nsCOMPtr<nsIRunnable> callbackRunnable = 1.1352 + new CreateCallbackRunnable(callbacks[index]); 1.1353 + if (NS_FAILED(NS_DispatchToCurrentThread(callbackRunnable))) { 1.1354 + NS_WARNING("Failed to dispatch callback runnable!"); 1.1355 + } 1.1356 + } 1.1357 + } 1.1358 + 1.1359 + return NS_OK; 1.1360 + } 1.1361 + 1.1362 + char stackBaseGuess; 1.1363 + profiler_register_thread("IPDL Background", &stackBaseGuess); 1.1364 + 1.1365 +#ifdef DEBUG 1.1366 + { 1.1367 + bool correctThread; 1.1368 + MOZ_ASSERT(NS_SUCCEEDED(mTargetThread->IsOnCurrentThread(&correctThread))); 1.1369 + MOZ_ASSERT(correctThread); 1.1370 + } 1.1371 +#endif 1.1372 + 1.1373 + DebugOnly<PRThread*> oldBackgroundThread = 1.1374 + sBackgroundPRThread.exchange(PR_GetCurrentThread()); 1.1375 + 1.1376 + MOZ_ASSERT_IF(oldBackgroundThread, 1.1377 + PR_GetCurrentThread() != oldBackgroundThread); 1.1378 + 1.1379 + MOZ_ASSERT(!mMessageLoop); 1.1380 + 1.1381 + mMessageLoop = MessageLoop::current(); 1.1382 + MOZ_ASSERT(mMessageLoop); 1.1383 + 1.1384 + if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) { 1.1385 + NS_WARNING("Failed to dispatch RequestMessageLoopRunnable to main thread!"); 1.1386 + return NS_ERROR_FAILURE; 1.1387 + } 1.1388 + 1.1389 + return NS_OK; 1.1390 +} 1.1391 + 1.1392 +NS_IMPL_ISUPPORTS_INHERITED0(ParentImpl::ShutdownBackgroundThreadRunnable, 1.1393 + nsRunnable) 1.1394 + 1.1395 +NS_IMETHODIMP 1.1396 +ParentImpl::ShutdownBackgroundThreadRunnable::Run() 1.1397 +{ 1.1398 + AssertIsInMainProcess(); 1.1399 + 1.1400 + // It is possible that another background thread was created while this thread 1.1401 + // was shutting down. In that case we can't assert anything about 1.1402 + // sBackgroundPRThread and we should not modify it here. 1.1403 + sBackgroundPRThread.compareExchange(PR_GetCurrentThread(), nullptr); 1.1404 + 1.1405 + profiler_unregister_thread(); 1.1406 + 1.1407 + return NS_OK; 1.1408 +} 1.1409 + 1.1410 +NS_IMPL_ISUPPORTS_INHERITED0(ParentImpl::ForceCloseBackgroundActorsRunnable, 1.1411 + nsRunnable) 1.1412 + 1.1413 +NS_IMETHODIMP 1.1414 +ParentImpl::ForceCloseBackgroundActorsRunnable::Run() 1.1415 +{ 1.1416 + AssertIsInMainProcess(); 1.1417 + MOZ_ASSERT(mActorArray); 1.1418 + 1.1419 + if (NS_IsMainThread()) { 1.1420 + MOZ_ASSERT(sLiveActorCount); 1.1421 + sLiveActorCount--; 1.1422 + return NS_OK; 1.1423 + } 1.1424 + 1.1425 + AssertIsOnBackgroundThread(); 1.1426 + 1.1427 + if (!mActorArray->IsEmpty()) { 1.1428 + // Copy the array since calling Close() could mutate the actual array. 1.1429 + nsTArray<ParentImpl*> actorsToClose(*mActorArray); 1.1430 + 1.1431 + for (uint32_t index = 0; index < actorsToClose.Length(); index++) { 1.1432 + actorsToClose[index]->Close(); 1.1433 + } 1.1434 + } 1.1435 + 1.1436 + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(this))); 1.1437 + 1.1438 + return NS_OK; 1.1439 +} 1.1440 + 1.1441 +NS_IMPL_ISUPPORTS_INHERITED0(ParentImpl::CreateCallbackRunnable, nsRunnable) 1.1442 + 1.1443 +NS_IMETHODIMP 1.1444 +ParentImpl::CreateCallbackRunnable::Run() 1.1445 +{ 1.1446 + AssertIsInMainProcess(); 1.1447 + AssertIsOnMainThread(); 1.1448 + MOZ_ASSERT(sBackgroundThreadMessageLoop); 1.1449 + MOZ_ASSERT(mCallback); 1.1450 + 1.1451 + nsRefPtr<CreateCallback> callback; 1.1452 + mCallback.swap(callback); 1.1453 + 1.1454 + nsRefPtr<ParentImpl> actor = new ParentImpl(); 1.1455 + 1.1456 + callback->Success(actor.forget(), sBackgroundThreadMessageLoop); 1.1457 + 1.1458 + return NS_OK; 1.1459 +} 1.1460 + 1.1461 +NS_IMPL_ISUPPORTS_INHERITED0(ParentImpl::ConnectActorRunnable, nsRunnable) 1.1462 + 1.1463 +NS_IMETHODIMP 1.1464 +ParentImpl::ConnectActorRunnable::Run() 1.1465 +{ 1.1466 + AssertIsInMainProcess(); 1.1467 + AssertIsOnBackgroundThread(); 1.1468 + 1.1469 + // Transfer ownership to this thread. If Open() fails then we will release 1.1470 + // this reference in Destroy. 1.1471 + ParentImpl* actor; 1.1472 + mActor.forget(&actor); 1.1473 + 1.1474 + if (!actor->Open(mTransport, mProcessHandle, XRE_GetIOMessageLoop(), 1.1475 + ParentSide)) { 1.1476 + actor->Destroy(); 1.1477 + return NS_ERROR_FAILURE; 1.1478 + } 1.1479 + 1.1480 + actor->SetLiveActorArray(mLiveActorArray); 1.1481 + 1.1482 + return NS_OK; 1.1483 +} 1.1484 + 1.1485 +// ----------------------------------------------------------------------------- 1.1486 +// ChildImpl Implementation 1.1487 +// ----------------------------------------------------------------------------- 1.1488 + 1.1489 +// static 1.1490 +void 1.1491 +ChildImpl::Startup() 1.1492 +{ 1.1493 + // This happens on the main thread but before XPCOM has started so we can't 1.1494 + // assert that we're being called on the main thread here. 1.1495 + 1.1496 + MOZ_ASSERT(sThreadLocalIndex == kBadThreadLocalIndex, 1.1497 + "BackgroundChild::Startup() called more than once!"); 1.1498 + 1.1499 + PRStatus status = 1.1500 + PR_NewThreadPrivateIndex(&sThreadLocalIndex, ThreadLocalDestructor); 1.1501 + MOZ_RELEASE_ASSERT(status == PR_SUCCESS, "PR_NewThreadPrivateIndex failed!"); 1.1502 + 1.1503 + MOZ_ASSERT(sThreadLocalIndex != kBadThreadLocalIndex); 1.1504 + 1.1505 + nsCOMPtr<nsIObserverService> observerService = services::GetObserverService(); 1.1506 + MOZ_RELEASE_ASSERT(observerService); 1.1507 + 1.1508 + nsCOMPtr<nsIObserver> observer = new ShutdownObserver(); 1.1509 + 1.1510 + nsresult rv = 1.1511 + observerService->AddObserver(observer, 1.1512 + NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, 1.1513 + false); 1.1514 + MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv)); 1.1515 +} 1.1516 + 1.1517 +// static 1.1518 +void 1.1519 +ChildImpl::Shutdown() 1.1520 +{ 1.1521 + AssertIsOnMainThread(); 1.1522 + 1.1523 + if (sShutdownHasStarted) { 1.1524 + MOZ_ASSERT_IF(sThreadLocalIndex != kBadThreadLocalIndex, 1.1525 + !PR_GetThreadPrivate(sThreadLocalIndex)); 1.1526 + return; 1.1527 + } 1.1528 + 1.1529 + sShutdownHasStarted = true; 1.1530 + 1.1531 + MOZ_ASSERT(sThreadLocalIndex != kBadThreadLocalIndex); 1.1532 + 1.1533 + DebugOnly<PRStatus> status = PR_SetThreadPrivate(sThreadLocalIndex, nullptr); 1.1534 + MOZ_ASSERT(status == PR_SUCCESS); 1.1535 +} 1.1536 + 1.1537 +// static 1.1538 +PBackgroundChild* 1.1539 +ChildImpl::Alloc(Transport* aTransport, ProcessId aOtherProcess) 1.1540 +{ 1.1541 + AssertIsInChildProcess(); 1.1542 + AssertIsOnMainThread(); 1.1543 + MOZ_ASSERT(aTransport); 1.1544 + MOZ_ASSERT(sPendingTargets); 1.1545 + MOZ_ASSERT(!sPendingTargets->IsEmpty()); 1.1546 + 1.1547 + nsCOMPtr<nsIEventTarget> eventTarget; 1.1548 + sPendingTargets->ElementAt(0).swap(eventTarget); 1.1549 + 1.1550 + sPendingTargets->RemoveElementAt(0); 1.1551 + 1.1552 + ProcessHandle processHandle; 1.1553 + if (!base::OpenProcessHandle(aOtherProcess, &processHandle)) { 1.1554 + MOZ_CRASH("Failed to open process handle!"); 1.1555 + } 1.1556 + 1.1557 + nsRefPtr<ChildImpl> actor = new ChildImpl(); 1.1558 + 1.1559 + ChildImpl* weakActor = actor; 1.1560 + 1.1561 + nsCOMPtr<nsIRunnable> openRunnable = 1.1562 + new OpenChildProcessActorRunnable(actor.forget(), aTransport, 1.1563 + processHandle); 1.1564 + if (NS_FAILED(eventTarget->Dispatch(openRunnable, NS_DISPATCH_NORMAL))) { 1.1565 + MOZ_CRASH("Failed to dispatch OpenActorRunnable!"); 1.1566 + } 1.1567 + 1.1568 + // This value is only checked against null to determine success/failure, so 1.1569 + // there is no need to worry about the reference count here. 1.1570 + return weakActor; 1.1571 +} 1.1572 + 1.1573 +// static 1.1574 +PBackgroundChild* 1.1575 +ChildImpl::GetForCurrentThread() 1.1576 +{ 1.1577 + MOZ_ASSERT(sThreadLocalIndex != kBadThreadLocalIndex); 1.1578 + 1.1579 + auto threadLocalInfo = 1.1580 + static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(sThreadLocalIndex)); 1.1581 + 1.1582 + return threadLocalInfo ? threadLocalInfo->mActor : nullptr; 1.1583 +} 1.1584 + 1.1585 +// static 1.1586 +bool 1.1587 +ChildImpl::GetOrCreateForCurrentThread( 1.1588 + nsIIPCBackgroundChildCreateCallback* aCallback) 1.1589 +{ 1.1590 + MOZ_ASSERT(aCallback); 1.1591 + MOZ_ASSERT(sThreadLocalIndex != kBadThreadLocalIndex, 1.1592 + "BackgroundChild::Startup() was never called!"); 1.1593 + 1.1594 + bool created = false; 1.1595 + 1.1596 + auto threadLocalInfo = 1.1597 + static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(sThreadLocalIndex)); 1.1598 + 1.1599 + if (threadLocalInfo) { 1.1600 + threadLocalInfo->mCallbacks.AppendElement(aCallback); 1.1601 + } else { 1.1602 + nsAutoPtr<ThreadLocalInfo> newInfo(new ThreadLocalInfo(aCallback)); 1.1603 + 1.1604 + if (PR_SetThreadPrivate(sThreadLocalIndex, newInfo) != PR_SUCCESS) { 1.1605 + CRASH_IN_CHILD_PROCESS("PR_SetThreadPrivate failed!"); 1.1606 + return false; 1.1607 + } 1.1608 + 1.1609 + created = true; 1.1610 + threadLocalInfo = newInfo.forget(); 1.1611 + } 1.1612 + 1.1613 + if (threadLocalInfo->mActor) { 1.1614 + nsRefPtr<ChildImpl> actor = threadLocalInfo->mActor; 1.1615 + 1.1616 + nsCOMPtr<nsIRunnable> runnable = new CreateCallbackRunnable(actor.forget()); 1.1617 + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToCurrentThread(runnable))); 1.1618 + 1.1619 + return true; 1.1620 + } 1.1621 + 1.1622 + if (!created) { 1.1623 + // We have already started the sequence for opening the actor so there's 1.1624 + // nothing else we need to do here. This callback will be called after the 1.1625 + // first callback in CreateCallbackRunnable::Run(). 1.1626 + return true; 1.1627 + } 1.1628 + 1.1629 + if (NS_IsMainThread()) { 1.1630 + if (NS_WARN_IF(!OpenProtocolOnMainThread(NS_GetCurrentThread()))) { 1.1631 + return false; 1.1632 + } 1.1633 + 1.1634 + return true; 1.1635 + } 1.1636 + 1.1637 + nsRefPtr<CreateActorRunnable> runnable = new CreateActorRunnable(); 1.1638 + if (NS_FAILED(NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL))) { 1.1639 + CRASH_IN_CHILD_PROCESS("Failed to dispatch to main thread!"); 1.1640 + return false; 1.1641 + } 1.1642 + 1.1643 + return true; 1.1644 +} 1.1645 + 1.1646 +// static 1.1647 +BackgroundChildImpl::ThreadLocal* 1.1648 +ChildImpl::GetThreadLocalForCurrentThread() 1.1649 +{ 1.1650 + MOZ_ASSERT(sThreadLocalIndex != kBadThreadLocalIndex, 1.1651 + "BackgroundChild::Startup() was never called!"); 1.1652 + 1.1653 + auto threadLocalInfo = 1.1654 + static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(sThreadLocalIndex)); 1.1655 + 1.1656 + if (!threadLocalInfo) { 1.1657 + return nullptr; 1.1658 + } 1.1659 + 1.1660 + if (!threadLocalInfo->mConsumerThreadLocal) { 1.1661 + threadLocalInfo->mConsumerThreadLocal = 1.1662 + new BackgroundChildImpl::ThreadLocal(); 1.1663 + } 1.1664 + 1.1665 + return threadLocalInfo->mConsumerThreadLocal; 1.1666 +} 1.1667 + 1.1668 +ChildImpl::CreateCallbackRunnable::~CreateCallbackRunnable() 1.1669 +{ 1.1670 + if (mActor) { 1.1671 + CRASH_IN_CHILD_PROCESS("Leaking actor!"); 1.1672 + unused << mActor.forget(); 1.1673 + } 1.1674 +} 1.1675 + 1.1676 +// static 1.1677 +already_AddRefed<nsIIPCBackgroundChildCreateCallback> 1.1678 +ChildImpl::CreateCallbackRunnable::GetNextCallback() 1.1679 +{ 1.1680 + // May run on any thread! 1.1681 + 1.1682 + auto threadLocalInfo = 1.1683 + static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(sThreadLocalIndex)); 1.1684 + MOZ_ASSERT(threadLocalInfo); 1.1685 + 1.1686 + if (threadLocalInfo->mCallbacks.IsEmpty()) { 1.1687 + return nullptr; 1.1688 + } 1.1689 + 1.1690 + nsCOMPtr<nsIIPCBackgroundChildCreateCallback> callback; 1.1691 + threadLocalInfo->mCallbacks[0].swap(callback); 1.1692 + 1.1693 + threadLocalInfo->mCallbacks.RemoveElementAt(0); 1.1694 + 1.1695 + return callback.forget(); 1.1696 +} 1.1697 + 1.1698 +NS_IMPL_ISUPPORTS_INHERITED0(ChildImpl::CreateCallbackRunnable, nsRunnable) 1.1699 + 1.1700 +NS_IMETHODIMP 1.1701 +ChildImpl::CreateCallbackRunnable::Run() 1.1702 +{ 1.1703 + // May run on any thread! 1.1704 + 1.1705 + nsRefPtr<ChildImpl> actor; 1.1706 + mActor.swap(actor); 1.1707 + 1.1708 + nsCOMPtr<nsIIPCBackgroundChildCreateCallback> callback = GetNextCallback(); 1.1709 + while (callback) { 1.1710 + if (actor) { 1.1711 + callback->ActorCreated(actor); 1.1712 + } else { 1.1713 + callback->ActorFailed(); 1.1714 + } 1.1715 + 1.1716 + callback = GetNextCallback(); 1.1717 + } 1.1718 + 1.1719 + return NS_OK; 1.1720 +} 1.1721 + 1.1722 +NS_IMPL_ISUPPORTS_INHERITED0(ChildImpl::OpenChildProcessActorRunnable, 1.1723 + ChildImpl::CreateCallbackRunnable) 1.1724 + 1.1725 +NS_IMETHODIMP 1.1726 +ChildImpl::OpenChildProcessActorRunnable::Run() 1.1727 +{ 1.1728 + // May be run on any thread! 1.1729 + 1.1730 + AssertIsInChildProcess(); 1.1731 + MOZ_ASSERT(mActor); 1.1732 + MOZ_ASSERT(mTransport); 1.1733 + 1.1734 + nsCOMPtr<nsIIPCBackgroundChildCreateCallback> callback = GetNextCallback(); 1.1735 + MOZ_ASSERT(callback, 1.1736 + "There should be at least one callback when first creating the " 1.1737 + "actor!"); 1.1738 + 1.1739 + nsRefPtr<ChildImpl> strongActor; 1.1740 + mActor.swap(strongActor); 1.1741 + 1.1742 + if (!strongActor->Open(mTransport.forget(), mProcessHandle, 1.1743 + XRE_GetIOMessageLoop(), ChildSide)) { 1.1744 + CRASH_IN_CHILD_PROCESS("Failed to open ChildImpl!"); 1.1745 + 1.1746 + while (callback) { 1.1747 + callback->ActorFailed(); 1.1748 + callback = GetNextCallback(); 1.1749 + } 1.1750 + 1.1751 + return NS_OK; 1.1752 + } 1.1753 + 1.1754 + // Now that Open() has succeeded transfer the ownership of the actor to IPDL. 1.1755 + auto threadLocalInfo = 1.1756 + static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(sThreadLocalIndex)); 1.1757 + 1.1758 + MOZ_ASSERT(threadLocalInfo); 1.1759 + MOZ_ASSERT(!threadLocalInfo->mActor); 1.1760 + 1.1761 + nsRefPtr<ChildImpl>& actor = threadLocalInfo->mActor; 1.1762 + strongActor.swap(actor); 1.1763 + 1.1764 + actor->SetBoundThread(); 1.1765 + 1.1766 + while (callback) { 1.1767 + callback->ActorCreated(actor); 1.1768 + callback = GetNextCallback(); 1.1769 + } 1.1770 + 1.1771 + return NS_OK; 1.1772 +} 1.1773 + 1.1774 +NS_IMPL_ISUPPORTS_INHERITED0(ChildImpl::OpenMainProcessActorRunnable, 1.1775 + ChildImpl::CreateCallbackRunnable) 1.1776 + 1.1777 +NS_IMETHODIMP 1.1778 +ChildImpl::OpenMainProcessActorRunnable::Run() 1.1779 +{ 1.1780 + // May run on any thread! 1.1781 + 1.1782 + AssertIsInMainProcess(); 1.1783 + MOZ_ASSERT(mActor); 1.1784 + MOZ_ASSERT(mParentActor); 1.1785 + MOZ_ASSERT(mParentMessageLoop); 1.1786 + 1.1787 + nsCOMPtr<nsIIPCBackgroundChildCreateCallback> callback = GetNextCallback(); 1.1788 + MOZ_ASSERT(callback, 1.1789 + "There should be at least one callback when first creating the " 1.1790 + "actor!"); 1.1791 + 1.1792 + nsRefPtr<ChildImpl> strongChildActor; 1.1793 + mActor.swap(strongChildActor); 1.1794 + 1.1795 + nsRefPtr<ParentImpl> parentActor; 1.1796 + mParentActor.swap(parentActor); 1.1797 + 1.1798 + MessageChannel* parentChannel = parentActor->GetIPCChannel(); 1.1799 + MOZ_ASSERT(parentChannel); 1.1800 + 1.1801 + if (!strongChildActor->Open(parentChannel, mParentMessageLoop, ChildSide)) { 1.1802 + NS_WARNING("Failed to open ChildImpl!"); 1.1803 + 1.1804 + parentActor->Destroy(); 1.1805 + 1.1806 + while (callback) { 1.1807 + callback->ActorFailed(); 1.1808 + callback = GetNextCallback(); 1.1809 + } 1.1810 + 1.1811 + return NS_OK; 1.1812 + } 1.1813 + 1.1814 + // Now that Open() has succeeded transfer the ownership of the actors to IPDL. 1.1815 + unused << parentActor.forget(); 1.1816 + 1.1817 + auto threadLocalInfo = 1.1818 + static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(sThreadLocalIndex)); 1.1819 + 1.1820 + MOZ_ASSERT(threadLocalInfo); 1.1821 + MOZ_ASSERT(!threadLocalInfo->mActor); 1.1822 + 1.1823 + nsRefPtr<ChildImpl>& childActor = threadLocalInfo->mActor; 1.1824 + strongChildActor.swap(childActor); 1.1825 + 1.1826 + childActor->SetBoundThread(); 1.1827 + 1.1828 + while (callback) { 1.1829 + callback->ActorCreated(childActor); 1.1830 + callback = GetNextCallback(); 1.1831 + } 1.1832 + 1.1833 + return NS_OK; 1.1834 +} 1.1835 + 1.1836 +NS_IMPL_ISUPPORTS_INHERITED0(ChildImpl::CreateActorRunnable, nsRunnable) 1.1837 + 1.1838 +NS_IMETHODIMP 1.1839 +ChildImpl::CreateActorRunnable::Run() 1.1840 +{ 1.1841 + AssertIsOnMainThread(); 1.1842 + 1.1843 + if (!OpenProtocolOnMainThread(mEventTarget)) { 1.1844 + NS_WARNING("OpenProtocolOnMainThread failed!"); 1.1845 + return NS_ERROR_FAILURE; 1.1846 + } 1.1847 + 1.1848 + return NS_OK; 1.1849 +} 1.1850 + 1.1851 +void 1.1852 +ChildImpl::ParentCreateCallback::Success( 1.1853 + already_AddRefed<ParentImpl> aParentActor, 1.1854 + MessageLoop* aParentMessageLoop) 1.1855 +{ 1.1856 + AssertIsInMainProcess(); 1.1857 + AssertIsOnMainThread(); 1.1858 + 1.1859 + nsRefPtr<ParentImpl> parentActor = aParentActor; 1.1860 + MOZ_ASSERT(parentActor); 1.1861 + MOZ_ASSERT(aParentMessageLoop); 1.1862 + MOZ_ASSERT(mEventTarget); 1.1863 + 1.1864 + nsRefPtr<ChildImpl> childActor = new ChildImpl(); 1.1865 + 1.1866 + nsCOMPtr<nsIEventTarget> target; 1.1867 + mEventTarget.swap(target); 1.1868 + 1.1869 + nsCOMPtr<nsIRunnable> openRunnable = 1.1870 + new OpenMainProcessActorRunnable(childActor.forget(), parentActor.forget(), 1.1871 + aParentMessageLoop); 1.1872 + if (NS_FAILED(target->Dispatch(openRunnable, NS_DISPATCH_NORMAL))) { 1.1873 + NS_WARNING("Failed to dispatch open runnable!"); 1.1874 + } 1.1875 +} 1.1876 + 1.1877 +void 1.1878 +ChildImpl::ParentCreateCallback::Failure() 1.1879 +{ 1.1880 + AssertIsInMainProcess(); 1.1881 + AssertIsOnMainThread(); 1.1882 + MOZ_ASSERT(mEventTarget); 1.1883 + 1.1884 + nsCOMPtr<nsIEventTarget> target; 1.1885 + mEventTarget.swap(target); 1.1886 + 1.1887 + DispatchFailureCallback(target); 1.1888 +} 1.1889 + 1.1890 +// static 1.1891 +bool 1.1892 +ChildImpl::OpenProtocolOnMainThread(nsIEventTarget* aEventTarget) 1.1893 +{ 1.1894 + AssertIsOnMainThread(); 1.1895 + MOZ_ASSERT(aEventTarget); 1.1896 + 1.1897 + if (sShutdownHasStarted) { 1.1898 + MOZ_CRASH("Called BackgroundChild::GetOrCreateForCurrentThread after " 1.1899 + "shutdown has started!"); 1.1900 + } 1.1901 + 1.1902 + if (IsMainProcess()) { 1.1903 + nsRefPtr<ParentImpl::CreateCallback> parentCallback = 1.1904 + new ParentCreateCallback(aEventTarget); 1.1905 + 1.1906 + if (!ParentImpl::CreateActorForSameProcess(parentCallback)) { 1.1907 + NS_WARNING("BackgroundParent::CreateActor() failed!"); 1.1908 + DispatchFailureCallback(aEventTarget); 1.1909 + return false; 1.1910 + } 1.1911 + 1.1912 + return true; 1.1913 + } 1.1914 + 1.1915 + ContentChild* content = ContentChild::GetSingleton(); 1.1916 + MOZ_ASSERT(content); 1.1917 + 1.1918 + if (!PBackground::Open(content)) { 1.1919 + MOZ_CRASH("Failed to create top level actor!"); 1.1920 + return false; 1.1921 + } 1.1922 + 1.1923 + if (!sPendingTargets) { 1.1924 + sPendingTargets = new nsTArray<nsCOMPtr<nsIEventTarget>>(1); 1.1925 + ClearOnShutdown(&sPendingTargets); 1.1926 + } 1.1927 + 1.1928 + sPendingTargets->AppendElement(aEventTarget); 1.1929 + 1.1930 + return true; 1.1931 +} 1.1932 + 1.1933 +// static 1.1934 +void 1.1935 +ChildImpl::DispatchFailureCallback(nsIEventTarget* aEventTarget) 1.1936 +{ 1.1937 + MOZ_ASSERT(aEventTarget); 1.1938 + 1.1939 + nsCOMPtr<nsIRunnable> callbackRunnable = new CreateCallbackRunnable(); 1.1940 + if (NS_FAILED(aEventTarget->Dispatch(callbackRunnable, NS_DISPATCH_NORMAL))) { 1.1941 + NS_WARNING("Failed to dispatch CreateCallbackRunnable!"); 1.1942 + } 1.1943 +} 1.1944 + 1.1945 +void 1.1946 +ChildImpl::ActorDestroy(ActorDestroyReason aWhy) 1.1947 +{ 1.1948 + AssertIsOnBoundThread(); 1.1949 + 1.1950 + BackgroundChildImpl::ActorDestroy(aWhy); 1.1951 +} 1.1952 + 1.1953 +NS_IMPL_ISUPPORTS(ChildImpl::ShutdownObserver, nsIObserver) 1.1954 + 1.1955 +NS_IMETHODIMP 1.1956 +ChildImpl::ShutdownObserver::Observe(nsISupports* aSubject, 1.1957 + const char* aTopic, 1.1958 + const char16_t* aData) 1.1959 +{ 1.1960 + AssertIsOnMainThread(); 1.1961 + MOZ_ASSERT(!strcmp(aTopic, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID)); 1.1962 + 1.1963 + ChildImpl::Shutdown(); 1.1964 + 1.1965 + return NS_OK; 1.1966 +}