Bumping manifests a=b2g-bump
[gecko.git] / ipc / glue / BackgroundImpl.cpp
blob11ee7f540e17173d4e7d1eb52dc04fe100563d4d
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "BackgroundChild.h"
6 #include "BackgroundParent.h"
8 #include "BackgroundChildImpl.h"
9 #include "BackgroundParentImpl.h"
10 #include "base/process_util.h"
11 #include "FileDescriptor.h"
12 #include "GeckoProfiler.h"
13 #include "InputStreamUtils.h"
14 #include "mozilla/Assertions.h"
15 #include "mozilla/Atomics.h"
16 #include "mozilla/ClearOnShutdown.h"
17 #include "mozilla/DebugOnly.h"
18 #include "mozilla/Services.h"
19 #include "mozilla/StaticPtr.h"
20 #include "mozilla/unused.h"
21 #include "mozilla/dom/ContentChild.h"
22 #include "mozilla/dom/ContentParent.h"
23 #include "mozilla/dom/File.h"
24 #include "mozilla/dom/ipc/BlobChild.h"
25 #include "mozilla/dom/ipc/BlobParent.h"
26 #include "mozilla/dom/ipc/nsIRemoteBlob.h"
27 #include "mozilla/ipc/ProtocolTypes.h"
28 #include "nsAutoPtr.h"
29 #include "nsCOMPtr.h"
30 #include "nsIEventTarget.h"
31 #include "nsIIPCBackgroundChildCreateCallback.h"
32 #include "nsIMutable.h"
33 #include "nsIObserver.h"
34 #include "nsIObserverService.h"
35 #include "nsIRunnable.h"
36 #include "nsISupportsImpl.h"
37 #include "nsIThread.h"
38 #include "nsITimer.h"
39 #include "nsTArray.h"
40 #include "nsThreadUtils.h"
41 #include "nsTraceRefcnt.h"
42 #include "nsXULAppAPI.h"
43 #include "nsXPCOMPrivate.h"
44 #include "prthread.h"
46 #ifdef RELEASE_BUILD
47 #define THREADSAFETY_ASSERT MOZ_ASSERT
48 #else
49 #define THREADSAFETY_ASSERT MOZ_RELEASE_ASSERT
50 #endif
52 #define CRASH_IN_CHILD_PROCESS(_msg) \
53 do { \
54 if (IsMainProcess()) { \
55 MOZ_ASSERT(false, _msg); \
56 } else { \
57 MOZ_CRASH(_msg); \
58 } \
59 } \
60 while (0)
62 using namespace mozilla;
63 using namespace mozilla::dom;
64 using namespace mozilla::ipc;
66 namespace {
68 // -----------------------------------------------------------------------------
69 // Utility Functions
70 // -----------------------------------------------------------------------------
72 bool
73 IsMainProcess()
75 static const bool isMainProcess =
76 XRE_GetProcessType() == GeckoProcessType_Default;
77 return isMainProcess;
80 #ifdef DEBUG
81 bool
82 IsChildProcess()
84 return !IsMainProcess();
86 #endif
88 void
89 AssertIsInMainProcess()
91 MOZ_ASSERT(IsMainProcess());
94 void
95 AssertIsInChildProcess()
97 MOZ_ASSERT(IsChildProcess());
100 void
101 AssertIsOnMainThread()
103 THREADSAFETY_ASSERT(NS_IsMainThread());
106 // -----------------------------------------------------------------------------
107 // ParentImpl Declaration
108 // -----------------------------------------------------------------------------
110 class ParentImpl MOZ_FINAL : public BackgroundParentImpl
112 friend class mozilla::ipc::BackgroundParent;
114 public:
115 class CreateCallback;
117 private:
118 class ShutdownObserver;
119 class RequestMessageLoopRunnable;
120 class ShutdownBackgroundThreadRunnable;
121 class ForceCloseBackgroundActorsRunnable;
122 class CreateCallbackRunnable;
123 class ConnectActorRunnable;
125 struct MOZ_STACK_CLASS TimerCallbackClosure
127 nsIThread* mThread;
128 nsTArray<ParentImpl*>* mLiveActors;
130 TimerCallbackClosure(nsIThread* aThread, nsTArray<ParentImpl*>* aLiveActors)
131 : mThread(aThread), mLiveActors(aLiveActors)
133 AssertIsInMainProcess();
134 AssertIsOnMainThread();
135 MOZ_ASSERT(aThread);
136 MOZ_ASSERT(aLiveActors);
140 // A handle that is invalid on any platform.
141 static const ProcessHandle kInvalidProcessHandle;
143 // The length of time we will wait at shutdown for all actors to clean
144 // themselves up before forcing them to be destroyed.
145 static const uint32_t kShutdownTimerDelayMS = 10000;
147 // This is only modified on the main thread. It is null if the thread does not
148 // exist or is shutting down.
149 static StaticRefPtr<nsIThread> sBackgroundThread;
151 // This is created and destroyed on the main thread but only modified on the
152 // background thread. It is specific to each instance of sBackgroundThread.
153 static nsTArray<ParentImpl*>* sLiveActorsForBackgroundThread;
155 // This is only modified on the main thread.
156 static StaticRefPtr<nsITimer> sShutdownTimer;
158 // This exists so that that [Assert]IsOnBackgroundThread() can continue to
159 // work during shutdown.
160 static Atomic<PRThread*> sBackgroundPRThread;
162 // This is only modified on the main thread. It is null if the thread does not
163 // exist or is shutting down.
164 static MessageLoop* sBackgroundThreadMessageLoop;
166 // This is only modified on the main thread. It maintains a count of live
167 // actors so that the background thread can be shut down when it is no longer
168 // needed.
169 static uint64_t sLiveActorCount;
171 // This is only modified on the main thread. It is true after the shutdown
172 // observer is registered and is never unset thereafter.
173 static bool sShutdownObserverRegistered;
175 // This is only modified on the main thread. It prevents us from trying to
176 // create the background thread after application shutdown has started.
177 static bool sShutdownHasStarted;
179 // This is only modified on the main thread. It is a FIFO queue for callbacks
180 // waiting for the background thread to be created.
181 static StaticAutoPtr<nsTArray<nsRefPtr<CreateCallback>>> sPendingCallbacks;
183 // Only touched on the main thread, null if this is a same-process actor.
184 nsRefPtr<ContentParent> mContent;
186 // mTransport is "owned" by this object but it must only be released on the
187 // IPC thread. It's left as a raw pointer here to prevent accidentally
188 // deleting it on the wrong thread. Only non-null for other-process actors.
189 Transport* mTransport;
191 // Set when the actor is opened successfully and used to handle shutdown
192 // hangs. Only touched on the background thread.
193 nsTArray<ParentImpl*>* mLiveActorArray;
195 // Set at construction to indicate whether this parent actor corresponds to a
196 // child actor in another process or to a child actor from a different thread
197 // in the same process.
198 const bool mIsOtherProcessActor;
200 // Set after ActorDestroy has been called. Only touched on the background
201 // thread.
202 bool mActorDestroyed;
204 public:
205 static bool
206 CreateActorForSameProcess(CreateCallback* aCallback);
208 static bool
209 IsOnBackgroundThread()
211 return PR_GetCurrentThread() == sBackgroundPRThread;
214 static void
215 AssertIsOnBackgroundThread()
217 THREADSAFETY_ASSERT(IsOnBackgroundThread());
220 NS_INLINE_DECL_REFCOUNTING(ParentImpl)
222 void
223 Destroy();
225 private:
226 // Forwarded from BackgroundParent.
227 static bool
228 IsOtherProcessActor(PBackgroundParent* aBackgroundActor);
230 // Forwarded from BackgroundParent.
231 static already_AddRefed<ContentParent>
232 GetContentParent(PBackgroundParent* aBackgroundActor);
234 // Forwarded from BackgroundParent.
235 static intptr_t
236 GetRawContentParentForComparison(PBackgroundParent* aBackgroundActor);
238 // Forwarded from BackgroundParent.
239 static PBackgroundParent*
240 Alloc(ContentParent* aContent,
241 Transport* aTransport,
242 ProcessId aOtherProcess);
244 static bool
245 CreateBackgroundThread();
247 static void
248 ShutdownBackgroundThread();
250 static void
251 ShutdownTimerCallback(nsITimer* aTimer, void* aClosure);
253 // For same-process actors.
254 ParentImpl()
255 : mTransport(nullptr), mLiveActorArray(nullptr), mIsOtherProcessActor(false),
256 mActorDestroyed(false)
258 AssertIsInMainProcess();
259 AssertIsOnMainThread();
261 SetOtherProcess(kInvalidProcessHandle);
264 // For other-process actors.
265 ParentImpl(ContentParent* aContent, Transport* aTransport)
266 : mContent(aContent), mTransport(aTransport), mLiveActorArray(nullptr),
267 mIsOtherProcessActor(true), mActorDestroyed(false)
269 AssertIsInMainProcess();
270 AssertIsOnMainThread();
271 MOZ_ASSERT(aContent);
272 MOZ_ASSERT(aTransport);
275 ~ParentImpl()
277 AssertIsInMainProcess();
278 AssertIsOnMainThread();
279 MOZ_ASSERT(!mContent);
280 MOZ_ASSERT(!mTransport);
283 void
284 MainThreadActorDestroy();
286 void
287 SetLiveActorArray(nsTArray<ParentImpl*>* aLiveActorArray)
289 AssertIsInMainProcess();
290 AssertIsOnBackgroundThread();
291 MOZ_ASSERT(aLiveActorArray);
292 MOZ_ASSERT(!aLiveActorArray->Contains(this));
293 MOZ_ASSERT(!mLiveActorArray);
294 MOZ_ASSERT(mIsOtherProcessActor);
296 mLiveActorArray = aLiveActorArray;
297 mLiveActorArray->AppendElement(this);
300 // These methods are only called by IPDL.
301 virtual IToplevelProtocol*
302 CloneToplevel(const InfallibleTArray<ProtocolFdMapping>& aFds,
303 ProcessHandle aPeerProcess,
304 ProtocolCloneContext* aCtx) MOZ_OVERRIDE;
306 virtual void
307 ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
310 // -----------------------------------------------------------------------------
311 // ChildImpl Declaration
312 // -----------------------------------------------------------------------------
314 class ChildImpl MOZ_FINAL : public BackgroundChildImpl
316 friend class mozilla::ipc::BackgroundChild;
317 friend class mozilla::ipc::BackgroundChildImpl;
319 typedef base::ProcessId ProcessId;
320 typedef mozilla::ipc::Transport Transport;
322 class ShutdownObserver;
323 class CreateActorRunnable;
324 class ParentCreateCallback;
325 class AlreadyCreatedCallbackRunnable;
326 class FailedCreateCallbackRunnable;
327 class OpenChildProcessActorRunnable;
328 class OpenMainProcessActorRunnable;
330 // A thread-local index that is not valid.
331 static const unsigned int kBadThreadLocalIndex =
332 static_cast<unsigned int>(-1);
334 // This is only modified on the main thread. It is the thread-local index that
335 // we use to store the BackgroundChild for each thread.
336 static unsigned int sThreadLocalIndex;
338 struct ThreadLocalInfo
340 explicit ThreadLocalInfo(nsIIPCBackgroundChildCreateCallback* aCallback)
341 : mClosed(false)
343 mCallbacks.AppendElement(aCallback);
346 nsRefPtr<ChildImpl> mActor;
347 nsTArray<nsCOMPtr<nsIIPCBackgroundChildCreateCallback>> mCallbacks;
348 nsAutoPtr<BackgroundChildImpl::ThreadLocal> mConsumerThreadLocal;
349 DebugOnly<bool> mClosed;
352 // This is only modified on the main thread. It is a FIFO queue for actors
353 // that are in the process of construction.
354 static StaticAutoPtr<nsTArray<nsCOMPtr<nsIEventTarget>>> sPendingTargets;
356 // This is only modified on the main thread. It prevents us from trying to
357 // create the background thread after application shutdown has started.
358 static bool sShutdownHasStarted;
360 #ifdef RELEASE_BUILD
361 DebugOnly<nsIThread*> mBoundThread;
362 #else
363 nsIThread* mBoundThread;
364 #endif
366 DebugOnly<bool> mActorDestroyed;
368 public:
369 static bool
370 OpenProtocolOnMainThread(nsIEventTarget* aEventTarget);
372 static void
373 Shutdown();
375 void
376 AssertIsOnBoundThread()
378 THREADSAFETY_ASSERT(mBoundThread);
380 #ifdef RELEASE_BUILD
381 DebugOnly<bool> current;
382 #else
383 bool current;
384 #endif
385 THREADSAFETY_ASSERT(
386 NS_SUCCEEDED(mBoundThread->IsOnCurrentThread(&current)));
387 THREADSAFETY_ASSERT(current);
390 void
391 AssertActorDestroyed()
393 MOZ_ASSERT(mActorDestroyed, "ChildImpl::ActorDestroy not called in time");
396 ChildImpl()
397 : mBoundThread(nullptr)
398 , mActorDestroyed(false)
400 AssertIsOnMainThread();
403 NS_INLINE_DECL_REFCOUNTING(ChildImpl)
405 private:
406 // Forwarded from BackgroundChild.
407 static void
408 Startup();
410 // Forwarded from BackgroundChild.
411 static PBackgroundChild*
412 Alloc(Transport* aTransport, ProcessId aOtherProcess);
414 // Forwarded from BackgroundChild.
415 static PBackgroundChild*
416 GetForCurrentThread();
418 // Forwarded from BackgroundChild.
419 static bool
420 GetOrCreateForCurrentThread(nsIIPCBackgroundChildCreateCallback* aCallback);
422 // Forwarded from BackgroundChild.
423 static void
424 CloseForCurrentThread();
426 // Forwarded from BackgroundChildImpl.
427 static BackgroundChildImpl::ThreadLocal*
428 GetThreadLocalForCurrentThread();
430 static void
431 ThreadLocalDestructor(void* aThreadLocal)
433 auto threadLocalInfo = static_cast<ThreadLocalInfo*>(aThreadLocal);
435 if (threadLocalInfo) {
436 MOZ_ASSERT(threadLocalInfo->mClosed);
438 if (threadLocalInfo->mActor) {
439 threadLocalInfo->mActor->Close();
440 threadLocalInfo->mActor->AssertActorDestroyed();
442 // Since the actor is created on the main thread it must only
443 // be released on the main thread as well.
444 if (!NS_IsMainThread()) {
445 ChildImpl* actor;
446 threadLocalInfo->mActor.forget(&actor);
448 nsCOMPtr<nsIRunnable> releaser =
449 NS_NewNonOwningRunnableMethod(actor, &ChildImpl::Release);
450 MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(releaser)));
453 delete threadLocalInfo;
457 static void
458 DispatchFailureCallback(nsIEventTarget* aEventTarget);
460 // This class is reference counted.
461 ~ChildImpl()
463 AssertActorDestroyed();
466 void
467 SetBoundThread()
469 THREADSAFETY_ASSERT(!mBoundThread);
471 #if defined(DEBUG) || !defined(RELEASE_BUILD)
472 mBoundThread = NS_GetCurrentThread();
473 #endif
475 THREADSAFETY_ASSERT(mBoundThread);
478 // Only called by IPDL.
479 virtual void
480 ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
482 static already_AddRefed<nsIIPCBackgroundChildCreateCallback>
483 GetNextCallback();
486 // -----------------------------------------------------------------------------
487 // ParentImpl Helper Declarations
488 // -----------------------------------------------------------------------------
490 class ParentImpl::ShutdownObserver MOZ_FINAL : public nsIObserver
492 public:
493 ShutdownObserver()
495 AssertIsOnMainThread();
498 NS_DECL_ISUPPORTS
499 NS_DECL_NSIOBSERVER
501 private:
502 ~ShutdownObserver()
504 AssertIsOnMainThread();
508 class ParentImpl::RequestMessageLoopRunnable MOZ_FINAL :
509 public nsRunnable
511 nsCOMPtr<nsIThread> mTargetThread;
512 MessageLoop* mMessageLoop;
514 public:
515 explicit RequestMessageLoopRunnable(nsIThread* aTargetThread)
516 : mTargetThread(aTargetThread), mMessageLoop(nullptr)
518 AssertIsInMainProcess();
519 AssertIsOnMainThread();
520 MOZ_ASSERT(aTargetThread);
523 NS_DECL_ISUPPORTS_INHERITED
525 private:
526 ~RequestMessageLoopRunnable()
529 NS_DECL_NSIRUNNABLE
532 class ParentImpl::ShutdownBackgroundThreadRunnable MOZ_FINAL : public nsRunnable
534 public:
535 ShutdownBackgroundThreadRunnable()
537 AssertIsInMainProcess();
538 AssertIsOnMainThread();
541 NS_DECL_ISUPPORTS_INHERITED
543 private:
544 ~ShutdownBackgroundThreadRunnable()
547 NS_DECL_NSIRUNNABLE
550 class ParentImpl::ForceCloseBackgroundActorsRunnable MOZ_FINAL : public nsRunnable
552 nsTArray<ParentImpl*>* mActorArray;
554 public:
555 explicit ForceCloseBackgroundActorsRunnable(nsTArray<ParentImpl*>* aActorArray)
556 : mActorArray(aActorArray)
558 AssertIsInMainProcess();
559 AssertIsOnMainThread();
560 MOZ_ASSERT(aActorArray);
563 NS_DECL_ISUPPORTS_INHERITED
565 private:
566 ~ForceCloseBackgroundActorsRunnable()
569 NS_DECL_NSIRUNNABLE
572 class ParentImpl::CreateCallbackRunnable MOZ_FINAL : public nsRunnable
574 nsRefPtr<CreateCallback> mCallback;
576 public:
577 explicit CreateCallbackRunnable(CreateCallback* aCallback)
578 : mCallback(aCallback)
580 AssertIsInMainProcess();
581 AssertIsOnMainThread();
582 MOZ_ASSERT(aCallback);
585 NS_DECL_ISUPPORTS_INHERITED
587 private:
588 ~CreateCallbackRunnable()
591 NS_DECL_NSIRUNNABLE
594 class ParentImpl::ConnectActorRunnable MOZ_FINAL : public nsRunnable
596 nsRefPtr<ParentImpl> mActor;
597 Transport* mTransport;
598 ProcessHandle mProcessHandle;
599 nsTArray<ParentImpl*>* mLiveActorArray;
601 public:
602 ConnectActorRunnable(ParentImpl* aActor,
603 Transport* aTransport,
604 ProcessHandle aProcessHandle,
605 nsTArray<ParentImpl*>* aLiveActorArray)
606 : mActor(aActor), mTransport(aTransport), mProcessHandle(aProcessHandle),
607 mLiveActorArray(aLiveActorArray)
609 AssertIsInMainProcess();
610 AssertIsOnMainThread();
611 MOZ_ASSERT(aActor);
612 MOZ_ASSERT(aTransport);
613 MOZ_ASSERT(aLiveActorArray);
616 NS_DECL_ISUPPORTS_INHERITED
618 private:
619 ~ConnectActorRunnable()
621 AssertIsInMainProcess();
624 NS_DECL_NSIRUNNABLE
627 class NS_NO_VTABLE ParentImpl::CreateCallback
629 public:
630 NS_INLINE_DECL_REFCOUNTING(CreateCallback)
632 virtual void
633 Success(already_AddRefed<ParentImpl> aActor, MessageLoop* aMessageLoop) = 0;
635 virtual void
636 Failure() = 0;
638 protected:
639 virtual ~CreateCallback()
643 // -----------------------------------------------------------------------------
644 // ChildImpl Helper Declarations
645 // -----------------------------------------------------------------------------
647 class ChildImpl::ShutdownObserver MOZ_FINAL : public nsIObserver
649 public:
650 ShutdownObserver()
652 AssertIsOnMainThread();
655 NS_DECL_ISUPPORTS
656 NS_DECL_NSIOBSERVER
658 private:
659 ~ShutdownObserver()
661 AssertIsOnMainThread();
665 class ChildImpl::CreateActorRunnable MOZ_FINAL : public nsRunnable
667 nsCOMPtr<nsIEventTarget> mEventTarget;
669 public:
670 CreateActorRunnable()
671 : mEventTarget(NS_GetCurrentThread())
673 MOZ_ASSERT(mEventTarget);
676 NS_DECL_ISUPPORTS_INHERITED
678 private:
679 ~CreateActorRunnable()
682 NS_DECL_NSIRUNNABLE
685 class ChildImpl::ParentCreateCallback MOZ_FINAL :
686 public ParentImpl::CreateCallback
688 nsCOMPtr<nsIEventTarget> mEventTarget;
690 public:
691 explicit ParentCreateCallback(nsIEventTarget* aEventTarget)
692 : mEventTarget(aEventTarget)
694 AssertIsInMainProcess();
695 AssertIsOnMainThread();
696 MOZ_ASSERT(aEventTarget);
699 private:
700 ~ParentCreateCallback()
703 virtual void
704 Success(already_AddRefed<ParentImpl> aActor, MessageLoop* aMessageLoop)
705 MOZ_OVERRIDE;
707 virtual void
708 Failure() MOZ_OVERRIDE;
711 // Must be cancelable in order to dispatch on active worker threads
712 class ChildImpl::AlreadyCreatedCallbackRunnable MOZ_FINAL :
713 public nsCancelableRunnable
715 public:
716 AlreadyCreatedCallbackRunnable()
718 // May be created on any thread!
721 NS_DECL_ISUPPORTS_INHERITED
723 protected:
724 virtual ~AlreadyCreatedCallbackRunnable()
727 NS_DECL_NSIRUNNABLE
728 NS_DECL_NSICANCELABLERUNNABLE
731 class ChildImpl::FailedCreateCallbackRunnable MOZ_FINAL : public nsRunnable
733 public:
734 FailedCreateCallbackRunnable()
736 // May be created on any thread!
739 NS_DECL_ISUPPORTS_INHERITED
741 protected:
742 virtual ~FailedCreateCallbackRunnable()
745 NS_DECL_NSIRUNNABLE
748 class ChildImpl::OpenChildProcessActorRunnable MOZ_FINAL : public nsRunnable
750 nsRefPtr<ChildImpl> mActor;
751 nsAutoPtr<Transport> mTransport;
752 ProcessHandle mProcessHandle;
754 public:
755 OpenChildProcessActorRunnable(already_AddRefed<ChildImpl>&& aActor,
756 Transport* aTransport,
757 ProcessHandle aProcessHandle)
758 : mActor(aActor), mTransport(aTransport),
759 mProcessHandle(aProcessHandle)
761 AssertIsOnMainThread();
762 MOZ_ASSERT(mActor);
763 MOZ_ASSERT(aTransport);
766 NS_DECL_ISUPPORTS_INHERITED
768 private:
769 ~OpenChildProcessActorRunnable()
771 if (mTransport) {
772 CRASH_IN_CHILD_PROCESS("Leaking transport!");
773 unused << mTransport.forget();
777 NS_DECL_NSIRUNNABLE
780 class ChildImpl::OpenMainProcessActorRunnable MOZ_FINAL : public nsRunnable
782 nsRefPtr<ChildImpl> mActor;
783 nsRefPtr<ParentImpl> mParentActor;
784 MessageLoop* mParentMessageLoop;
786 public:
787 OpenMainProcessActorRunnable(already_AddRefed<ChildImpl>&& aChildActor,
788 already_AddRefed<ParentImpl> aParentActor,
789 MessageLoop* aParentMessageLoop)
790 : mActor(aChildActor), mParentActor(aParentActor),
791 mParentMessageLoop(aParentMessageLoop)
793 AssertIsOnMainThread();
794 MOZ_ASSERT(mParentActor);
795 MOZ_ASSERT(aParentMessageLoop);
798 NS_DECL_ISUPPORTS_INHERITED
800 private:
801 ~OpenMainProcessActorRunnable()
804 NS_DECL_NSIRUNNABLE
807 } // anonymous namespace
809 namespace mozilla {
810 namespace ipc {
812 bool
813 IsOnBackgroundThread()
815 return ParentImpl::IsOnBackgroundThread();
818 #ifdef DEBUG
820 void
821 AssertIsOnBackgroundThread()
823 ParentImpl::AssertIsOnBackgroundThread();
826 #endif // DEBUG
828 } // namespace ipc
829 } // namespace mozilla
831 // -----------------------------------------------------------------------------
832 // BackgroundParent Public Methods
833 // -----------------------------------------------------------------------------
835 // static
836 bool
837 BackgroundParent::IsOtherProcessActor(PBackgroundParent* aBackgroundActor)
839 return ParentImpl::IsOtherProcessActor(aBackgroundActor);
842 // static
843 already_AddRefed<ContentParent>
844 BackgroundParent::GetContentParent(PBackgroundParent* aBackgroundActor)
846 return ParentImpl::GetContentParent(aBackgroundActor);
849 // static
850 PBlobParent*
851 BackgroundParent::GetOrCreateActorForBlobImpl(
852 PBackgroundParent* aBackgroundActor,
853 FileImpl* aBlobImpl)
855 AssertIsOnBackgroundThread();
856 MOZ_ASSERT(aBackgroundActor);
857 MOZ_ASSERT(aBlobImpl);
859 BlobParent* actor = BlobParent::GetOrCreate(aBackgroundActor, aBlobImpl);
860 if (NS_WARN_IF(!actor)) {
861 return nullptr;
864 return actor;
867 // static
868 intptr_t
869 BackgroundParent::GetRawContentParentForComparison(
870 PBackgroundParent* aBackgroundActor)
872 return ParentImpl::GetRawContentParentForComparison(aBackgroundActor);
875 // static
876 PBackgroundParent*
877 BackgroundParent::Alloc(ContentParent* aContent,
878 Transport* aTransport,
879 ProcessId aOtherProcess)
881 return ParentImpl::Alloc(aContent, aTransport, aOtherProcess);
884 // -----------------------------------------------------------------------------
885 // BackgroundChild Public Methods
886 // -----------------------------------------------------------------------------
888 // static
889 void
890 BackgroundChild::Startup()
892 ChildImpl::Startup();
895 // static
896 PBackgroundChild*
897 BackgroundChild::Alloc(Transport* aTransport, ProcessId aOtherProcess)
899 return ChildImpl::Alloc(aTransport, aOtherProcess);
902 // static
903 PBackgroundChild*
904 BackgroundChild::GetForCurrentThread()
906 return ChildImpl::GetForCurrentThread();
909 // static
910 bool
911 BackgroundChild::GetOrCreateForCurrentThread(
912 nsIIPCBackgroundChildCreateCallback* aCallback)
914 return ChildImpl::GetOrCreateForCurrentThread(aCallback);
917 // static
918 PBlobChild*
919 BackgroundChild::GetOrCreateActorForBlob(PBackgroundChild* aBackgroundActor,
920 nsIDOMBlob* aBlob)
922 MOZ_ASSERT(aBackgroundActor);
923 MOZ_ASSERT(aBlob);
924 MOZ_ASSERT(GetForCurrentThread(),
925 "BackgroundChild not created on this thread yet!");
926 MOZ_ASSERT(aBackgroundActor == GetForCurrentThread(),
927 "BackgroundChild is bound to a different thread!");
929 nsRefPtr<FileImpl> blobImpl = static_cast<File*>(aBlob)->Impl();
930 MOZ_ASSERT(blobImpl);
932 BlobChild* actor = BlobChild::GetOrCreate(aBackgroundActor, blobImpl);
933 if (NS_WARN_IF(!actor)) {
934 return nullptr;
937 return actor;
940 // static
941 void
942 BackgroundChild::CloseForCurrentThread()
944 ChildImpl::CloseForCurrentThread();
947 // -----------------------------------------------------------------------------
948 // BackgroundChildImpl Public Methods
949 // -----------------------------------------------------------------------------
951 // static
952 BackgroundChildImpl::ThreadLocal*
953 BackgroundChildImpl::GetThreadLocalForCurrentThread()
955 return ChildImpl::GetThreadLocalForCurrentThread();
958 // -----------------------------------------------------------------------------
959 // ParentImpl Static Members
960 // -----------------------------------------------------------------------------
962 const ParentImpl::ProcessHandle ParentImpl::kInvalidProcessHandle =
963 #ifdef XP_WIN
964 ProcessHandle(INVALID_HANDLE_VALUE);
965 #else
966 ProcessHandle(-1);
967 #endif
969 StaticRefPtr<nsIThread> ParentImpl::sBackgroundThread;
971 nsTArray<ParentImpl*>* ParentImpl::sLiveActorsForBackgroundThread;
973 StaticRefPtr<nsITimer> ParentImpl::sShutdownTimer;
975 Atomic<PRThread*> ParentImpl::sBackgroundPRThread;
977 MessageLoop* ParentImpl::sBackgroundThreadMessageLoop = nullptr;
979 uint64_t ParentImpl::sLiveActorCount = 0;
981 bool ParentImpl::sShutdownObserverRegistered = false;
983 bool ParentImpl::sShutdownHasStarted = false;
985 StaticAutoPtr<nsTArray<nsRefPtr<ParentImpl::CreateCallback>>>
986 ParentImpl::sPendingCallbacks;
988 // -----------------------------------------------------------------------------
989 // ChildImpl Static Members
990 // -----------------------------------------------------------------------------
992 unsigned int ChildImpl::sThreadLocalIndex = kBadThreadLocalIndex;
994 StaticAutoPtr<nsTArray<nsCOMPtr<nsIEventTarget>>> ChildImpl::sPendingTargets;
996 bool ChildImpl::sShutdownHasStarted = false;
998 // -----------------------------------------------------------------------------
999 // ParentImpl Implementation
1000 // -----------------------------------------------------------------------------
1002 // static
1003 bool
1004 ParentImpl::IsOtherProcessActor(PBackgroundParent* aBackgroundActor)
1006 AssertIsOnBackgroundThread();
1007 MOZ_ASSERT(aBackgroundActor);
1009 return static_cast<ParentImpl*>(aBackgroundActor)->mIsOtherProcessActor;
1012 // static
1013 already_AddRefed<ContentParent>
1014 ParentImpl::GetContentParent(PBackgroundParent* aBackgroundActor)
1016 AssertIsOnBackgroundThread();
1017 MOZ_ASSERT(aBackgroundActor);
1019 auto actor = static_cast<ParentImpl*>(aBackgroundActor);
1020 if (actor->mActorDestroyed) {
1021 MOZ_ASSERT(false, "GetContentParent called after ActorDestroy was called!");
1022 return nullptr;
1025 if (actor->mContent) {
1026 // We need to hand out a reference to our ContentParent but we also need to
1027 // keep the one we have. We can't call AddRef here because ContentParent is
1028 // not threadsafe so instead we dispatch a runnable to the main thread to do
1029 // it for us. This is safe since we are guaranteed that our AddRef runnable
1030 // will run before the reference we hand out can be released, and the
1031 // ContentParent can't die as long as the existing reference is maintained.
1032 nsCOMPtr<nsIRunnable> runnable =
1033 NS_NewNonOwningRunnableMethod(actor->mContent, &ContentParent::AddRef);
1034 MOZ_ASSERT(runnable);
1036 MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(runnable)));
1039 return already_AddRefed<ContentParent>(actor->mContent.get());
1042 // static
1043 intptr_t
1044 ParentImpl::GetRawContentParentForComparison(
1045 PBackgroundParent* aBackgroundActor)
1047 AssertIsOnBackgroundThread();
1048 MOZ_ASSERT(aBackgroundActor);
1050 auto actor = static_cast<ParentImpl*>(aBackgroundActor);
1051 if (actor->mActorDestroyed) {
1052 MOZ_ASSERT(false,
1053 "GetRawContentParentForComparison called after ActorDestroy was "
1054 "called!");
1055 return intptr_t(-1);
1058 return intptr_t(static_cast<nsIContentParent*>(actor->mContent.get()));
1061 // static
1062 PBackgroundParent*
1063 ParentImpl::Alloc(ContentParent* aContent,
1064 Transport* aTransport,
1065 ProcessId aOtherProcess)
1067 AssertIsInMainProcess();
1068 AssertIsOnMainThread();
1069 MOZ_ASSERT(aTransport);
1071 ProcessHandle processHandle;
1072 if (!base::OpenProcessHandle(aOtherProcess, &processHandle)) {
1073 // Process has already died?
1074 return nullptr;
1077 if (!sBackgroundThread && !CreateBackgroundThread()) {
1078 NS_WARNING("Failed to create background thread!");
1079 return nullptr;
1082 MOZ_ASSERT(sLiveActorsForBackgroundThread);
1084 sLiveActorCount++;
1086 nsRefPtr<ParentImpl> actor = new ParentImpl(aContent, aTransport);
1088 nsCOMPtr<nsIRunnable> connectRunnable =
1089 new ConnectActorRunnable(actor, aTransport, processHandle,
1090 sLiveActorsForBackgroundThread);
1092 if (NS_FAILED(sBackgroundThread->Dispatch(connectRunnable,
1093 NS_DISPATCH_NORMAL))) {
1094 NS_WARNING("Failed to dispatch connect runnable!");
1096 MOZ_ASSERT(sLiveActorCount);
1097 sLiveActorCount--;
1099 return nullptr;
1102 return actor;
1105 // static
1106 bool
1107 ParentImpl::CreateActorForSameProcess(CreateCallback* aCallback)
1109 AssertIsInMainProcess();
1110 AssertIsOnMainThread();
1111 MOZ_ASSERT(aCallback);
1113 if (!sBackgroundThread && !CreateBackgroundThread()) {
1114 NS_WARNING("Failed to create background thread!");
1115 return false;
1118 MOZ_ASSERT(!sShutdownHasStarted);
1120 sLiveActorCount++;
1122 if (sBackgroundThreadMessageLoop) {
1123 nsCOMPtr<nsIRunnable> callbackRunnable =
1124 new CreateCallbackRunnable(aCallback);
1125 MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToCurrentThread(callbackRunnable)));
1126 return true;
1129 if (!sPendingCallbacks) {
1130 sPendingCallbacks = new nsTArray<nsRefPtr<CreateCallback>>();
1133 sPendingCallbacks->AppendElement(aCallback);
1134 return true;
1137 // static
1138 bool
1139 ParentImpl::CreateBackgroundThread()
1141 AssertIsInMainProcess();
1142 AssertIsOnMainThread();
1143 MOZ_ASSERT(!sBackgroundThread);
1144 MOZ_ASSERT(!sLiveActorsForBackgroundThread);
1146 if (sShutdownHasStarted) {
1147 NS_WARNING("Trying to create background thread after shutdown has "
1148 "already begun!");
1149 return false;
1152 nsCOMPtr<nsITimer> newShutdownTimer;
1154 if (!sShutdownTimer) {
1155 nsresult rv;
1156 newShutdownTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
1157 if (NS_WARN_IF(NS_FAILED(rv))) {
1158 return false;
1162 if (!sShutdownObserverRegistered) {
1163 nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
1164 if (NS_WARN_IF(!obs)) {
1165 return false;
1168 nsCOMPtr<nsIObserver> observer = new ShutdownObserver();
1170 nsresult rv =
1171 obs->AddObserver(observer, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, false);
1172 if (NS_WARN_IF(NS_FAILED(rv))) {
1173 return false;
1176 sShutdownObserverRegistered = true;
1179 nsCOMPtr<nsIThread> thread;
1180 if (NS_FAILED(NS_NewNamedThread("IPDL Background", getter_AddRefs(thread)))) {
1181 NS_WARNING("NS_NewNamedThread failed!");
1182 return false;
1185 nsCOMPtr<nsIRunnable> messageLoopRunnable =
1186 new RequestMessageLoopRunnable(thread);
1187 if (NS_FAILED(thread->Dispatch(messageLoopRunnable, NS_DISPATCH_NORMAL))) {
1188 NS_WARNING("Failed to dispatch RequestMessageLoopRunnable!");
1189 return false;
1192 sBackgroundThread = thread;
1193 sLiveActorsForBackgroundThread = new nsTArray<ParentImpl*>(1);
1195 if (!sShutdownTimer) {
1196 MOZ_ASSERT(newShutdownTimer);
1197 sShutdownTimer = newShutdownTimer;
1200 return true;
1203 // static
1204 void
1205 ParentImpl::ShutdownBackgroundThread()
1207 AssertIsInMainProcess();
1208 AssertIsOnMainThread();
1209 MOZ_ASSERT_IF(!sBackgroundThread, !sBackgroundThreadMessageLoop);
1210 MOZ_ASSERT(sShutdownHasStarted);
1211 MOZ_ASSERT_IF(!sBackgroundThread, !sLiveActorCount);
1212 MOZ_ASSERT_IF(sBackgroundThread, sShutdownTimer);
1214 if (sPendingCallbacks) {
1215 if (!sPendingCallbacks->IsEmpty()) {
1216 nsTArray<nsRefPtr<CreateCallback>> callbacks;
1217 sPendingCallbacks->SwapElements(callbacks);
1219 for (uint32_t index = 0; index < callbacks.Length(); index++) {
1220 nsRefPtr<CreateCallback> callback;
1221 callbacks[index].swap(callback);
1222 MOZ_ASSERT(callback);
1224 callback->Failure();
1228 sPendingCallbacks = nullptr;
1231 nsCOMPtr<nsITimer> shutdownTimer = sShutdownTimer.get();
1232 sShutdownTimer = nullptr;
1234 if (sBackgroundThread) {
1235 nsCOMPtr<nsIThread> thread = sBackgroundThread.get();
1236 sBackgroundThread = nullptr;
1238 nsAutoPtr<nsTArray<ParentImpl*>> liveActors(sLiveActorsForBackgroundThread);
1239 sLiveActorsForBackgroundThread = nullptr;
1241 sBackgroundThreadMessageLoop = nullptr;
1243 MOZ_ASSERT_IF(!sShutdownHasStarted, !sLiveActorCount);
1245 if (sLiveActorCount) {
1246 // We need to spin the event loop while we wait for all the actors to be
1247 // cleaned up. We also set a timeout to force-kill any hanging actors.
1248 TimerCallbackClosure closure(thread, liveActors);
1250 MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
1251 shutdownTimer->InitWithFuncCallback(&ShutdownTimerCallback,
1252 &closure,
1253 kShutdownTimerDelayMS,
1254 nsITimer::TYPE_ONE_SHOT)));
1256 nsIThread* currentThread = NS_GetCurrentThread();
1257 MOZ_ASSERT(currentThread);
1259 while (sLiveActorCount) {
1260 NS_ProcessNextEvent(currentThread);
1263 MOZ_ASSERT(liveActors->IsEmpty());
1265 MOZ_ALWAYS_TRUE(NS_SUCCEEDED(shutdownTimer->Cancel()));
1268 // Dispatch this runnable to unregister the thread from the profiler.
1269 nsCOMPtr<nsIRunnable> shutdownRunnable =
1270 new ShutdownBackgroundThreadRunnable();
1271 MOZ_ALWAYS_TRUE(NS_SUCCEEDED(thread->Dispatch(shutdownRunnable,
1272 NS_DISPATCH_NORMAL)));
1274 MOZ_ALWAYS_TRUE(NS_SUCCEEDED(thread->Shutdown()));
1278 // static
1279 void
1280 ParentImpl::ShutdownTimerCallback(nsITimer* aTimer, void* aClosure)
1282 AssertIsInMainProcess();
1283 AssertIsOnMainThread();
1284 MOZ_ASSERT(sShutdownHasStarted);
1285 MOZ_ASSERT(sLiveActorCount);
1287 auto closure = static_cast<TimerCallbackClosure*>(aClosure);
1288 MOZ_ASSERT(closure);
1290 // Don't let the stack unwind until the ForceCloseBackgroundActorsRunnable has
1291 // finished.
1292 sLiveActorCount++;
1294 nsCOMPtr<nsIRunnable> forceCloseRunnable =
1295 new ForceCloseBackgroundActorsRunnable(closure->mLiveActors);
1296 MOZ_ALWAYS_TRUE(NS_SUCCEEDED(closure->mThread->Dispatch(forceCloseRunnable,
1297 NS_DISPATCH_NORMAL)));
1300 void
1301 ParentImpl::Destroy()
1303 // May be called on any thread!
1305 AssertIsInMainProcess();
1307 nsCOMPtr<nsIRunnable> destroyRunnable =
1308 NS_NewNonOwningRunnableMethod(this, &ParentImpl::MainThreadActorDestroy);
1309 MOZ_ASSERT(destroyRunnable);
1311 MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(destroyRunnable)));
1314 void
1315 ParentImpl::MainThreadActorDestroy()
1317 AssertIsInMainProcess();
1318 AssertIsOnMainThread();
1319 MOZ_ASSERT_IF(mIsOtherProcessActor, mContent);
1320 MOZ_ASSERT_IF(!mIsOtherProcessActor, !mContent);
1321 MOZ_ASSERT_IF(mIsOtherProcessActor, mTransport);
1322 MOZ_ASSERT_IF(!mIsOtherProcessActor, !mTransport);
1324 if (mTransport) {
1325 XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
1326 new DeleteTask<Transport>(mTransport));
1327 mTransport = nullptr;
1330 ProcessHandle otherProcess = OtherProcess();
1331 if (otherProcess != kInvalidProcessHandle) {
1332 base::CloseProcessHandle(otherProcess);
1333 #ifdef DEBUG
1334 SetOtherProcess(kInvalidProcessHandle);
1335 #endif
1338 mContent = nullptr;
1340 MOZ_ASSERT(sLiveActorCount);
1341 sLiveActorCount--;
1343 // This may be the last reference!
1344 Release();
1347 IToplevelProtocol*
1348 ParentImpl::CloneToplevel(const InfallibleTArray<ProtocolFdMapping>& aFds,
1349 ProcessHandle aPeerProcess,
1350 ProtocolCloneContext* aCtx)
1352 AssertIsInMainProcess();
1353 AssertIsOnMainThread();
1354 MOZ_ASSERT(aCtx->GetContentParent());
1356 const ProtocolId protocolId = GetProtocolId();
1358 for (unsigned int i = 0; i < aFds.Length(); i++) {
1359 if (static_cast<ProtocolId>(aFds[i].protocolId()) != protocolId) {
1360 continue;
1363 Transport* transport = OpenDescriptor(aFds[i].fd(),
1364 Transport::MODE_SERVER);
1365 if (!transport) {
1366 NS_WARNING("Failed to open transport!");
1367 break;
1370 PBackgroundParent* clonedActor =
1371 Alloc(aCtx->GetContentParent(), transport, base::GetProcId(aPeerProcess));
1372 MOZ_ASSERT(clonedActor);
1374 clonedActor->CloneManagees(this, aCtx);
1375 clonedActor->SetTransport(transport);
1377 return clonedActor;
1380 return nullptr;
1383 void
1384 ParentImpl::ActorDestroy(ActorDestroyReason aWhy)
1386 AssertIsInMainProcess();
1387 AssertIsOnBackgroundThread();
1388 MOZ_ASSERT(!mActorDestroyed);
1389 MOZ_ASSERT_IF(mIsOtherProcessActor, mLiveActorArray);
1391 BackgroundParentImpl::ActorDestroy(aWhy);
1393 mActorDestroyed = true;
1395 if (mLiveActorArray) {
1396 MOZ_ALWAYS_TRUE(mLiveActorArray->RemoveElement(this));
1397 mLiveActorArray = nullptr;
1400 // This is tricky. We should be able to call Destroy() here directly because
1401 // we're not going to touch 'this' or our MessageChannel any longer on this
1402 // thread. Destroy() dispatches the MainThreadActorDestroy runnable and when
1403 // it runs it will destroy 'this' and our associated MessageChannel. However,
1404 // IPDL is about to call MessageChannel::Clear() on this thread! To avoid
1405 // racing with the main thread we must ensure that the MessageChannel lives
1406 // long enough to be cleared in this call stack.
1407 nsCOMPtr<nsIRunnable> destroyRunnable =
1408 NS_NewNonOwningRunnableMethod(this, &ParentImpl::Destroy);
1409 MOZ_ASSERT(destroyRunnable);
1411 MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToCurrentThread(destroyRunnable)));
1414 NS_IMPL_ISUPPORTS(ParentImpl::ShutdownObserver, nsIObserver)
1416 NS_IMETHODIMP
1417 ParentImpl::ShutdownObserver::Observe(nsISupports* aSubject,
1418 const char* aTopic,
1419 const char16_t* aData)
1421 AssertIsInMainProcess();
1422 AssertIsOnMainThread();
1423 MOZ_ASSERT(!sShutdownHasStarted);
1424 MOZ_ASSERT(!strcmp(aTopic, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID));
1426 sShutdownHasStarted = true;
1428 // Do this first before calling (and spinning the event loop in)
1429 // ShutdownBackgroundThread().
1430 ChildImpl::Shutdown();
1432 ShutdownBackgroundThread();
1434 return NS_OK;
1437 NS_IMPL_ISUPPORTS_INHERITED0(ParentImpl::RequestMessageLoopRunnable,
1438 nsRunnable)
1440 NS_IMETHODIMP
1441 ParentImpl::RequestMessageLoopRunnable::Run()
1443 AssertIsInMainProcess();
1444 MOZ_ASSERT(mTargetThread);
1446 char stackBaseGuess;
1448 if (NS_IsMainThread()) {
1449 MOZ_ASSERT(mMessageLoop);
1451 if (!sBackgroundThread ||
1452 !SameCOMIdentity(mTargetThread.get(), sBackgroundThread.get())) {
1453 return NS_OK;
1456 MOZ_ASSERT(!sBackgroundThreadMessageLoop);
1457 sBackgroundThreadMessageLoop = mMessageLoop;
1459 if (sPendingCallbacks && !sPendingCallbacks->IsEmpty()) {
1460 nsTArray<nsRefPtr<CreateCallback>> callbacks;
1461 sPendingCallbacks->SwapElements(callbacks);
1463 for (uint32_t index = 0; index < callbacks.Length(); index++) {
1464 MOZ_ASSERT(callbacks[index]);
1466 nsCOMPtr<nsIRunnable> callbackRunnable =
1467 new CreateCallbackRunnable(callbacks[index]);
1468 if (NS_FAILED(NS_DispatchToCurrentThread(callbackRunnable))) {
1469 NS_WARNING("Failed to dispatch callback runnable!");
1474 return NS_OK;
1477 profiler_register_thread("IPDL Background", &stackBaseGuess);
1479 #ifdef DEBUG
1481 bool correctThread;
1482 MOZ_ASSERT(NS_SUCCEEDED(mTargetThread->IsOnCurrentThread(&correctThread)));
1483 MOZ_ASSERT(correctThread);
1485 #endif
1487 DebugOnly<PRThread*> oldBackgroundThread =
1488 sBackgroundPRThread.exchange(PR_GetCurrentThread());
1490 MOZ_ASSERT_IF(oldBackgroundThread,
1491 PR_GetCurrentThread() != oldBackgroundThread);
1493 MOZ_ASSERT(!mMessageLoop);
1495 mMessageLoop = MessageLoop::current();
1496 MOZ_ASSERT(mMessageLoop);
1498 if (NS_FAILED(NS_DispatchToMainThread(this))) {
1499 NS_WARNING("Failed to dispatch RequestMessageLoopRunnable to main thread!");
1500 return NS_ERROR_FAILURE;
1503 return NS_OK;
1506 NS_IMPL_ISUPPORTS_INHERITED0(ParentImpl::ShutdownBackgroundThreadRunnable,
1507 nsRunnable)
1509 NS_IMETHODIMP
1510 ParentImpl::ShutdownBackgroundThreadRunnable::Run()
1512 AssertIsInMainProcess();
1514 // It is possible that another background thread was created while this thread
1515 // was shutting down. In that case we can't assert anything about
1516 // sBackgroundPRThread and we should not modify it here.
1517 sBackgroundPRThread.compareExchange(PR_GetCurrentThread(), nullptr);
1519 profiler_unregister_thread();
1521 return NS_OK;
1524 NS_IMPL_ISUPPORTS_INHERITED0(ParentImpl::ForceCloseBackgroundActorsRunnable,
1525 nsRunnable)
1527 NS_IMETHODIMP
1528 ParentImpl::ForceCloseBackgroundActorsRunnable::Run()
1530 AssertIsInMainProcess();
1531 MOZ_ASSERT(mActorArray);
1533 if (NS_IsMainThread()) {
1534 MOZ_ASSERT(sLiveActorCount);
1535 sLiveActorCount--;
1536 return NS_OK;
1539 AssertIsOnBackgroundThread();
1541 if (!mActorArray->IsEmpty()) {
1542 // Copy the array since calling Close() could mutate the actual array.
1543 nsTArray<ParentImpl*> actorsToClose(*mActorArray);
1545 for (uint32_t index = 0; index < actorsToClose.Length(); index++) {
1546 actorsToClose[index]->Close();
1550 MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(this)));
1552 return NS_OK;
1555 NS_IMPL_ISUPPORTS_INHERITED0(ParentImpl::CreateCallbackRunnable, nsRunnable)
1557 NS_IMETHODIMP
1558 ParentImpl::CreateCallbackRunnable::Run()
1560 AssertIsInMainProcess();
1561 AssertIsOnMainThread();
1562 MOZ_ASSERT(sBackgroundThreadMessageLoop);
1563 MOZ_ASSERT(mCallback);
1565 nsRefPtr<CreateCallback> callback;
1566 mCallback.swap(callback);
1568 nsRefPtr<ParentImpl> actor = new ParentImpl();
1570 callback->Success(actor.forget(), sBackgroundThreadMessageLoop);
1572 return NS_OK;
1575 NS_IMPL_ISUPPORTS_INHERITED0(ParentImpl::ConnectActorRunnable, nsRunnable)
1577 NS_IMETHODIMP
1578 ParentImpl::ConnectActorRunnable::Run()
1580 AssertIsInMainProcess();
1581 AssertIsOnBackgroundThread();
1583 // Transfer ownership to this thread. If Open() fails then we will release
1584 // this reference in Destroy.
1585 ParentImpl* actor;
1586 mActor.forget(&actor);
1588 if (!actor->Open(mTransport, mProcessHandle, XRE_GetIOMessageLoop(),
1589 ParentSide)) {
1590 actor->Destroy();
1591 return NS_ERROR_FAILURE;
1594 actor->SetLiveActorArray(mLiveActorArray);
1596 return NS_OK;
1599 // -----------------------------------------------------------------------------
1600 // ChildImpl Implementation
1601 // -----------------------------------------------------------------------------
1603 // static
1604 void
1605 ChildImpl::Startup()
1607 // This happens on the main thread but before XPCOM has started so we can't
1608 // assert that we're being called on the main thread here.
1610 MOZ_ASSERT(sThreadLocalIndex == kBadThreadLocalIndex,
1611 "BackgroundChild::Startup() called more than once!");
1613 PRStatus status =
1614 PR_NewThreadPrivateIndex(&sThreadLocalIndex, ThreadLocalDestructor);
1615 MOZ_RELEASE_ASSERT(status == PR_SUCCESS, "PR_NewThreadPrivateIndex failed!");
1617 MOZ_ASSERT(sThreadLocalIndex != kBadThreadLocalIndex);
1619 nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
1620 MOZ_RELEASE_ASSERT(observerService);
1622 nsCOMPtr<nsIObserver> observer = new ShutdownObserver();
1624 nsresult rv =
1625 observerService->AddObserver(observer,
1626 NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID,
1627 false);
1628 MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
1631 // static
1632 void
1633 ChildImpl::Shutdown()
1635 AssertIsOnMainThread();
1637 if (sShutdownHasStarted) {
1638 MOZ_ASSERT_IF(sThreadLocalIndex != kBadThreadLocalIndex,
1639 !PR_GetThreadPrivate(sThreadLocalIndex));
1640 return;
1643 sShutdownHasStarted = true;
1645 MOZ_ASSERT(sThreadLocalIndex != kBadThreadLocalIndex);
1647 auto threadLocalInfo =
1648 static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(sThreadLocalIndex));
1650 if (threadLocalInfo) {
1651 MOZ_ASSERT(!threadLocalInfo->mClosed);
1652 threadLocalInfo->mClosed = true;
1655 DebugOnly<PRStatus> status = PR_SetThreadPrivate(sThreadLocalIndex, nullptr);
1656 MOZ_ASSERT(status == PR_SUCCESS);
1659 // static
1660 PBackgroundChild*
1661 ChildImpl::Alloc(Transport* aTransport, ProcessId aOtherProcess)
1663 AssertIsInChildProcess();
1664 AssertIsOnMainThread();
1665 MOZ_ASSERT(aTransport);
1666 MOZ_ASSERT(sPendingTargets);
1667 MOZ_ASSERT(!sPendingTargets->IsEmpty());
1669 nsCOMPtr<nsIEventTarget> eventTarget;
1670 sPendingTargets->ElementAt(0).swap(eventTarget);
1672 sPendingTargets->RemoveElementAt(0);
1674 ProcessHandle processHandle;
1675 if (!base::OpenProcessHandle(aOtherProcess, &processHandle)) {
1676 MOZ_CRASH("Failed to open process handle!");
1679 nsRefPtr<ChildImpl> actor = new ChildImpl();
1681 ChildImpl* weakActor = actor;
1683 nsCOMPtr<nsIRunnable> openRunnable =
1684 new OpenChildProcessActorRunnable(actor.forget(), aTransport,
1685 processHandle);
1686 if (NS_FAILED(eventTarget->Dispatch(openRunnable, NS_DISPATCH_NORMAL))) {
1687 MOZ_CRASH("Failed to dispatch OpenActorRunnable!");
1690 // This value is only checked against null to determine success/failure, so
1691 // there is no need to worry about the reference count here.
1692 return weakActor;
1695 // static
1696 PBackgroundChild*
1697 ChildImpl::GetForCurrentThread()
1699 MOZ_ASSERT(sThreadLocalIndex != kBadThreadLocalIndex);
1701 auto threadLocalInfo =
1702 static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(sThreadLocalIndex));
1704 if (!threadLocalInfo) {
1705 return nullptr;
1708 return threadLocalInfo->mActor;
1711 // static
1712 bool
1713 ChildImpl::GetOrCreateForCurrentThread(
1714 nsIIPCBackgroundChildCreateCallback* aCallback)
1716 MOZ_ASSERT(aCallback);
1717 MOZ_ASSERT(sThreadLocalIndex != kBadThreadLocalIndex,
1718 "BackgroundChild::Startup() was never called!");
1720 bool created = false;
1722 auto threadLocalInfo =
1723 static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(sThreadLocalIndex));
1725 if (threadLocalInfo) {
1726 threadLocalInfo->mCallbacks.AppendElement(aCallback);
1727 } else {
1728 nsAutoPtr<ThreadLocalInfo> newInfo(new ThreadLocalInfo(aCallback));
1730 if (PR_SetThreadPrivate(sThreadLocalIndex, newInfo) != PR_SUCCESS) {
1731 CRASH_IN_CHILD_PROCESS("PR_SetThreadPrivate failed!");
1732 return false;
1735 created = true;
1736 threadLocalInfo = newInfo.forget();
1739 if (threadLocalInfo->mActor) {
1740 // Runnable will use GetForCurrentThread() to retrieve actor again. This
1741 // allows us to avoid addref'ing on the wrong thread.
1742 nsCOMPtr<nsIRunnable> runnable = new AlreadyCreatedCallbackRunnable();
1743 MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToCurrentThread(runnable)));
1745 return true;
1748 if (!created) {
1749 // We have already started the sequence for opening the actor so there's
1750 // nothing else we need to do here. This callback will be called after the
1751 // first callback in the schedule runnable.
1752 return true;
1755 if (NS_IsMainThread()) {
1756 if (NS_WARN_IF(!OpenProtocolOnMainThread(NS_GetCurrentThread()))) {
1757 return false;
1760 return true;
1763 nsRefPtr<CreateActorRunnable> runnable = new CreateActorRunnable();
1764 if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
1765 CRASH_IN_CHILD_PROCESS("Failed to dispatch to main thread!");
1766 return false;
1769 return true;
1772 // static
1773 void
1774 ChildImpl::CloseForCurrentThread()
1776 MOZ_ASSERT(sThreadLocalIndex != kBadThreadLocalIndex,
1777 "BackgroundChild::Startup() was never called!");
1778 auto threadLocalInfo =
1779 static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(sThreadLocalIndex));
1781 if (!threadLocalInfo) {
1782 return;
1785 MOZ_ASSERT(!threadLocalInfo->mClosed);
1786 threadLocalInfo->mClosed = true;
1788 if (threadLocalInfo->mActor) {
1789 threadLocalInfo->mActor->FlushPendingInterruptQueue();
1792 // Clearing the thread local will synchronously close the actor.
1793 DebugOnly<PRStatus> status = PR_SetThreadPrivate(sThreadLocalIndex, nullptr);
1794 MOZ_ASSERT(status == PR_SUCCESS);
1797 // static
1798 BackgroundChildImpl::ThreadLocal*
1799 ChildImpl::GetThreadLocalForCurrentThread()
1801 MOZ_ASSERT(sThreadLocalIndex != kBadThreadLocalIndex,
1802 "BackgroundChild::Startup() was never called!");
1804 auto threadLocalInfo =
1805 static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(sThreadLocalIndex));
1807 if (!threadLocalInfo) {
1808 return nullptr;
1811 if (!threadLocalInfo->mConsumerThreadLocal) {
1812 threadLocalInfo->mConsumerThreadLocal =
1813 new BackgroundChildImpl::ThreadLocal();
1816 return threadLocalInfo->mConsumerThreadLocal;
1819 // static
1820 already_AddRefed<nsIIPCBackgroundChildCreateCallback>
1821 ChildImpl::GetNextCallback()
1823 // May run on any thread!
1825 auto threadLocalInfo =
1826 static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(sThreadLocalIndex));
1827 MOZ_ASSERT(threadLocalInfo);
1829 if (threadLocalInfo->mCallbacks.IsEmpty()) {
1830 return nullptr;
1833 nsCOMPtr<nsIIPCBackgroundChildCreateCallback> callback;
1834 threadLocalInfo->mCallbacks[0].swap(callback);
1836 threadLocalInfo->mCallbacks.RemoveElementAt(0);
1838 return callback.forget();
1841 NS_IMPL_ISUPPORTS_INHERITED0(ChildImpl::AlreadyCreatedCallbackRunnable,
1842 nsCancelableRunnable)
1844 NS_IMETHODIMP
1845 ChildImpl::AlreadyCreatedCallbackRunnable::Run()
1847 // May run on any thread!
1849 // Report the current actor back in the callback.
1850 PBackgroundChild* actor = ChildImpl::GetForCurrentThread();
1852 // If the current actor is null, do not create a new actor here. This likely
1853 // means we are in the process of cleaning up a worker thread and do not want
1854 // a new actor created. Unfortunately we cannot report back to the callback
1855 // because the thread local is gone at this point. Instead simply do nothing
1856 // and return.
1857 if (NS_WARN_IF(!actor)) {
1858 return NS_OK;
1861 nsCOMPtr<nsIIPCBackgroundChildCreateCallback> callback =
1862 ChildImpl::GetNextCallback();
1863 while (callback) {
1864 callback->ActorCreated(actor);
1865 callback = ChildImpl::GetNextCallback();
1868 return NS_OK;
1871 NS_IMETHODIMP
1872 ChildImpl::AlreadyCreatedCallbackRunnable::Cancel()
1874 // These are IPC infrastructure objects and need to run unconditionally.
1875 Run();
1876 return NS_OK;
1879 NS_IMPL_ISUPPORTS_INHERITED0(ChildImpl::FailedCreateCallbackRunnable,
1880 nsRunnable);
1882 NS_IMETHODIMP
1883 ChildImpl::FailedCreateCallbackRunnable::Run()
1885 // May run on any thread!
1887 nsCOMPtr<nsIIPCBackgroundChildCreateCallback> callback =
1888 ChildImpl::GetNextCallback();
1889 while (callback) {
1890 callback->ActorFailed();
1891 callback = ChildImpl::GetNextCallback();
1894 return NS_OK;
1897 NS_IMPL_ISUPPORTS_INHERITED0(ChildImpl::OpenChildProcessActorRunnable,
1898 nsRunnable);
1900 NS_IMETHODIMP
1901 ChildImpl::OpenChildProcessActorRunnable::Run()
1903 // May be run on any thread!
1905 AssertIsInChildProcess();
1906 MOZ_ASSERT(mActor);
1907 MOZ_ASSERT(mTransport);
1909 nsCOMPtr<nsIIPCBackgroundChildCreateCallback> callback =
1910 ChildImpl::GetNextCallback();
1911 MOZ_ASSERT(callback,
1912 "There should be at least one callback when first creating the "
1913 "actor!");
1915 nsRefPtr<ChildImpl> strongActor;
1916 mActor.swap(strongActor);
1918 if (!strongActor->Open(mTransport.forget(), mProcessHandle,
1919 XRE_GetIOMessageLoop(), ChildSide)) {
1920 CRASH_IN_CHILD_PROCESS("Failed to open ChildImpl!");
1922 while (callback) {
1923 callback->ActorFailed();
1924 callback = ChildImpl::GetNextCallback();
1927 return NS_OK;
1930 // Now that Open() has succeeded transfer the ownership of the actor to IPDL.
1931 auto threadLocalInfo =
1932 static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(sThreadLocalIndex));
1934 MOZ_ASSERT(threadLocalInfo);
1935 MOZ_ASSERT(!threadLocalInfo->mActor);
1937 nsRefPtr<ChildImpl>& actor = threadLocalInfo->mActor;
1938 strongActor.swap(actor);
1940 actor->SetBoundThread();
1942 while (callback) {
1943 callback->ActorCreated(actor);
1944 callback = ChildImpl::GetNextCallback();
1947 return NS_OK;
1950 NS_IMPL_ISUPPORTS_INHERITED0(ChildImpl::OpenMainProcessActorRunnable,
1951 nsRunnable);
1953 NS_IMETHODIMP
1954 ChildImpl::OpenMainProcessActorRunnable::Run()
1956 // May run on any thread!
1958 AssertIsInMainProcess();
1959 MOZ_ASSERT(mActor);
1960 MOZ_ASSERT(mParentActor);
1961 MOZ_ASSERT(mParentMessageLoop);
1963 nsCOMPtr<nsIIPCBackgroundChildCreateCallback> callback =
1964 ChildImpl::GetNextCallback();
1965 MOZ_ASSERT(callback,
1966 "There should be at least one callback when first creating the "
1967 "actor!");
1969 nsRefPtr<ChildImpl> strongChildActor;
1970 mActor.swap(strongChildActor);
1972 nsRefPtr<ParentImpl> parentActor;
1973 mParentActor.swap(parentActor);
1975 MessageChannel* parentChannel = parentActor->GetIPCChannel();
1976 MOZ_ASSERT(parentChannel);
1978 if (!strongChildActor->Open(parentChannel, mParentMessageLoop, ChildSide)) {
1979 NS_WARNING("Failed to open ChildImpl!");
1981 parentActor->Destroy();
1983 while (callback) {
1984 callback->ActorFailed();
1985 callback = ChildImpl::GetNextCallback();
1988 return NS_OK;
1991 // Now that Open() has succeeded transfer the ownership of the actors to IPDL.
1992 unused << parentActor.forget();
1994 auto threadLocalInfo =
1995 static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(sThreadLocalIndex));
1997 MOZ_ASSERT(threadLocalInfo);
1998 MOZ_ASSERT(!threadLocalInfo->mActor);
2000 nsRefPtr<ChildImpl>& childActor = threadLocalInfo->mActor;
2001 strongChildActor.swap(childActor);
2003 childActor->SetBoundThread();
2005 while (callback) {
2006 callback->ActorCreated(childActor);
2007 callback = ChildImpl::GetNextCallback();
2010 return NS_OK;
2013 NS_IMPL_ISUPPORTS_INHERITED0(ChildImpl::CreateActorRunnable, nsRunnable)
2015 NS_IMETHODIMP
2016 ChildImpl::CreateActorRunnable::Run()
2018 AssertIsOnMainThread();
2020 if (!OpenProtocolOnMainThread(mEventTarget)) {
2021 NS_WARNING("OpenProtocolOnMainThread failed!");
2022 return NS_ERROR_FAILURE;
2025 return NS_OK;
2028 void
2029 ChildImpl::ParentCreateCallback::Success(
2030 already_AddRefed<ParentImpl> aParentActor,
2031 MessageLoop* aParentMessageLoop)
2033 AssertIsInMainProcess();
2034 AssertIsOnMainThread();
2036 nsRefPtr<ParentImpl> parentActor = aParentActor;
2037 MOZ_ASSERT(parentActor);
2038 MOZ_ASSERT(aParentMessageLoop);
2039 MOZ_ASSERT(mEventTarget);
2041 nsRefPtr<ChildImpl> childActor = new ChildImpl();
2043 nsCOMPtr<nsIEventTarget> target;
2044 mEventTarget.swap(target);
2046 nsCOMPtr<nsIRunnable> openRunnable =
2047 new OpenMainProcessActorRunnable(childActor.forget(), parentActor.forget(),
2048 aParentMessageLoop);
2049 if (NS_FAILED(target->Dispatch(openRunnable, NS_DISPATCH_NORMAL))) {
2050 NS_WARNING("Failed to dispatch open runnable!");
2054 void
2055 ChildImpl::ParentCreateCallback::Failure()
2057 AssertIsInMainProcess();
2058 AssertIsOnMainThread();
2059 MOZ_ASSERT(mEventTarget);
2061 nsCOMPtr<nsIEventTarget> target;
2062 mEventTarget.swap(target);
2064 DispatchFailureCallback(target);
2067 // static
2068 bool
2069 ChildImpl::OpenProtocolOnMainThread(nsIEventTarget* aEventTarget)
2071 AssertIsOnMainThread();
2072 MOZ_ASSERT(aEventTarget);
2074 if (sShutdownHasStarted) {
2075 MOZ_CRASH("Called BackgroundChild::GetOrCreateForCurrentThread after "
2076 "shutdown has started!");
2079 if (IsMainProcess()) {
2080 nsRefPtr<ParentImpl::CreateCallback> parentCallback =
2081 new ParentCreateCallback(aEventTarget);
2083 if (!ParentImpl::CreateActorForSameProcess(parentCallback)) {
2084 NS_WARNING("BackgroundParent::CreateActor() failed!");
2085 DispatchFailureCallback(aEventTarget);
2086 return false;
2089 return true;
2092 ContentChild* content = ContentChild::GetSingleton();
2093 MOZ_ASSERT(content);
2095 if (!PBackground::Open(content)) {
2096 MOZ_CRASH("Failed to create top level actor!");
2097 return false;
2100 if (!sPendingTargets) {
2101 sPendingTargets = new nsTArray<nsCOMPtr<nsIEventTarget>>(1);
2102 ClearOnShutdown(&sPendingTargets);
2105 sPendingTargets->AppendElement(aEventTarget);
2107 return true;
2110 // static
2111 void
2112 ChildImpl::DispatchFailureCallback(nsIEventTarget* aEventTarget)
2114 MOZ_ASSERT(aEventTarget);
2116 nsCOMPtr<nsIRunnable> callbackRunnable = new FailedCreateCallbackRunnable();
2117 if (NS_FAILED(aEventTarget->Dispatch(callbackRunnable, NS_DISPATCH_NORMAL))) {
2118 NS_WARNING("Failed to dispatch CreateCallbackRunnable!");
2122 void
2123 ChildImpl::ActorDestroy(ActorDestroyReason aWhy)
2125 AssertIsOnBoundThread();
2127 MOZ_ASSERT(!mActorDestroyed);
2128 mActorDestroyed = true;
2130 BackgroundChildImpl::ActorDestroy(aWhy);
2133 NS_IMPL_ISUPPORTS(ChildImpl::ShutdownObserver, nsIObserver)
2135 NS_IMETHODIMP
2136 ChildImpl::ShutdownObserver::Observe(nsISupports* aSubject,
2137 const char* aTopic,
2138 const char16_t* aData)
2140 AssertIsOnMainThread();
2141 MOZ_ASSERT(!strcmp(aTopic, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID));
2143 ChildImpl::Shutdown();
2145 return NS_OK;