1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5  * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "BackgroundChild.h"
8 #include "BackgroundParent.h"
9 
10 #include "BackgroundChildImpl.h"
11 #include "BackgroundParentImpl.h"
12 #include "base/process_util.h"
13 #include "base/task.h"
14 #include "FileDescriptor.h"
15 #include "GeckoProfiler.h"
16 #include "InputStreamUtils.h"
17 #include "mozilla/Assertions.h"
18 #include "mozilla/Atomics.h"
19 #include "mozilla/ClearOnShutdown.h"
20 #include "mozilla/DebugOnly.h"
21 #include "mozilla/MozPromise.h"
22 #include "mozilla/Services.h"
23 #include "mozilla/SpinEventLoopUntil.h"
24 #include "mozilla/StaticPtr.h"
25 #include "mozilla/Unused.h"
26 #include "mozilla/dom/ContentChild.h"
27 #include "mozilla/dom/ContentParent.h"
28 #include "mozilla/dom/File.h"
29 #include "mozilla/dom/WorkerPrivate.h"
30 #include "mozilla/dom/WorkerRef.h"
31 #include "mozilla/ipc/Endpoint.h"
32 #include "mozilla/ipc/ProtocolTypes.h"
33 #include "mozilla/net/SocketProcessChild.h"
34 #include "mozilla/net/SocketProcessBridgeChild.h"
35 #include "nsCOMPtr.h"
36 #include "nsIEventTarget.h"
37 #include "nsIObserver.h"
38 #include "nsIObserverService.h"
39 #include "nsIRunnable.h"
40 #include "nsISupportsImpl.h"
41 #include "nsIThread.h"
42 #include "nsITimer.h"
43 #include "nsTArray.h"
44 #include "nsThreadUtils.h"
45 #include "nsTraceRefcnt.h"
46 #include "nsXULAppAPI.h"
47 #include "nsXPCOMPrivate.h"
48 #include "prthread.h"
49 
50 #include <functional>
51 
52 #ifdef RELEASE_OR_BETA
53 #  define THREADSAFETY_ASSERT MOZ_ASSERT
54 #else
55 #  define THREADSAFETY_ASSERT MOZ_RELEASE_ASSERT
56 #endif
57 
58 #define CRASH_IN_CHILD_PROCESS(_msg) \
59   do {                               \
60     if (XRE_IsParentProcess()) {     \
61       MOZ_ASSERT(false, _msg);       \
62     } else {                         \
63       MOZ_CRASH(_msg);               \
64     }                                \
65   } while (0)
66 
67 using namespace mozilla;
68 using namespace mozilla::dom;
69 using namespace mozilla::ipc;
70 using namespace mozilla::net;
71 
72 namespace {
73 
74 class ChildImpl;
75 
76 // -----------------------------------------------------------------------------
77 // Utility Functions
78 // -----------------------------------------------------------------------------
79 
AssertIsInMainProcess()80 void AssertIsInMainProcess() { MOZ_ASSERT(XRE_IsParentProcess()); }
81 
AssertIsInMainOrSocketProcess()82 void AssertIsInMainOrSocketProcess() {
83   MOZ_ASSERT(XRE_IsParentProcess() || XRE_IsSocketProcess());
84 }
85 
AssertIsOnMainThread()86 void AssertIsOnMainThread() { THREADSAFETY_ASSERT(NS_IsMainThread()); }
87 
AssertIsNotOnMainThread()88 void AssertIsNotOnMainThread() { THREADSAFETY_ASSERT(!NS_IsMainThread()); }
89 
90 // -----------------------------------------------------------------------------
91 // ParentImpl Declaration
92 // -----------------------------------------------------------------------------
93 
94 class ParentImpl final : public BackgroundParentImpl {
95   friend class mozilla::ipc::BackgroundParent;
96 
97  private:
98   class ShutdownObserver;
99   class CreateActorHelper;
100 
101   struct MOZ_STACK_CLASS TimerCallbackClosure {
102     nsIThread* mThread;
103     nsTArray<ParentImpl*>* mLiveActors;
104 
TimerCallbackClosure__anondf7260de0111::ParentImpl::TimerCallbackClosure105     TimerCallbackClosure(nsIThread* aThread, nsTArray<ParentImpl*>* aLiveActors)
106         : mThread(aThread), mLiveActors(aLiveActors) {
107       AssertIsInMainOrSocketProcess();
108       AssertIsOnMainThread();
109       MOZ_ASSERT(aThread);
110       MOZ_ASSERT(aLiveActors);
111     }
112   };
113 
114   // The length of time we will wait at shutdown for all actors to clean
115   // themselves up before forcing them to be destroyed.
116   static const uint32_t kShutdownTimerDelayMS = 10000;
117 
118   // This is only modified on the main thread. It is null if the thread does not
119   // exist or is shutting down.
120   static StaticRefPtr<nsIThread> sBackgroundThread;
121 
122   // This is created and destroyed on the main thread but only modified on the
123   // background thread. It is specific to each instance of sBackgroundThread.
124   static nsTArray<ParentImpl*>* sLiveActorsForBackgroundThread;
125 
126   // This is only modified on the main thread.
127   static StaticRefPtr<nsITimer> sShutdownTimer;
128 
129   // This exists so that that [Assert]IsOnBackgroundThread() can continue to
130   // work during shutdown.
131   static Atomic<PRThread*> sBackgroundPRThread;
132 
133   // This is only modified on the main thread. It maintains a count of live
134   // actors so that the background thread can be shut down when it is no longer
135   // needed.
136   static uint64_t sLiveActorCount;
137 
138   // This is only modified on the main thread. It is true after the shutdown
139   // observer is registered and is never unset thereafter.
140   static bool sShutdownObserverRegistered;
141 
142   // This is only modified on the main thread. It prevents us from trying to
143   // create the background thread after application shutdown has started.
144   static bool sShutdownHasStarted;
145 
146   // Only touched on the main thread, null if this is a same-process actor.
147   RefPtr<ContentParent> mContent;
148 
149   // Set when the actor is opened successfully and used to handle shutdown
150   // hangs. Only touched on the background thread.
151   nsTArray<ParentImpl*>* mLiveActorArray;
152 
153   // Set at construction to indicate whether this parent actor corresponds to a
154   // child actor in another process or to a child actor from a different thread
155   // in the same process.
156   const bool mIsOtherProcessActor;
157 
158   // Set after ActorDestroy has been called. Only touched on the background
159   // thread.
160   bool mActorDestroyed;
161 
162  public:
163   static already_AddRefed<ChildImpl> CreateActorForSameProcess(
164       nsIEventTarget* aMainEventTarget);
165 
IsOnBackgroundThread()166   static bool IsOnBackgroundThread() {
167     return PR_GetCurrentThread() == sBackgroundPRThread;
168   }
169 
AssertIsOnBackgroundThread()170   static void AssertIsOnBackgroundThread() {
171     THREADSAFETY_ASSERT(IsOnBackgroundThread());
172   }
173 
174   // `ParentImpl` instances are created and need to be deleted on the main
175   // thread, despite IPC controlling them on a background thread. Use
176   // `_WITH_DELETE_ON_MAIN_THREAD` to force destruction to occur on the desired
177   // thread.
178   NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DELETE_ON_MAIN_THREAD(ParentImpl,
179                                                                    override)
180 
181   void Destroy();
182 
183  private:
184   // Forwarded from BackgroundParent.
185   static bool IsOtherProcessActor(PBackgroundParent* aBackgroundActor);
186 
187   // Forwarded from BackgroundParent.
188   static already_AddRefed<ContentParent> GetContentParent(
189       PBackgroundParent* aBackgroundActor);
190 
191   // Forwarded from BackgroundParent.
192   static intptr_t GetRawContentParentForComparison(
193       PBackgroundParent* aBackgroundActor);
194 
195   // Forwarded from BackgroundParent.
196   static uint64_t GetChildID(PBackgroundParent* aBackgroundActor);
197 
198   // Forwarded from BackgroundParent.
199   static bool GetLiveActorArray(PBackgroundParent* aBackgroundActor,
200                                 nsTArray<PBackgroundParent*>& aLiveActorArray);
201 
202   // Forwarded from BackgroundParent.
203   static bool Alloc(ContentParent* aContent,
204                     Endpoint<PBackgroundParent>&& aEndpoint);
205 
206   static bool CreateBackgroundThread();
207 
208   static void ShutdownBackgroundThread();
209 
210   static void ShutdownTimerCallback(nsITimer* aTimer, void* aClosure);
211 
212   // For same-process actors.
ParentImpl()213   ParentImpl()
214       : mLiveActorArray(nullptr),
215         mIsOtherProcessActor(false),
216         mActorDestroyed(false) {
217     AssertIsInMainProcess();
218     AssertIsOnMainThread();
219   }
220 
221   // For other-process actors.
222   // NOTE: ParentImpl could be used in 3 cases below.
223   // 1. Between parent process and content process.
224   // 2. Between socket process and content process.
225   // 3. Between parent process and socket process.
226   // |mContent| should be not null for case 1. For case 2 and 3, it's null.
ParentImpl(ContentParent * aContent)227   explicit ParentImpl(ContentParent* aContent)
228       : mContent(aContent),
229         mLiveActorArray(nullptr),
230         mIsOtherProcessActor(true),
231         mActorDestroyed(false) {
232     MOZ_ASSERT(XRE_IsParentProcess() || XRE_IsSocketProcess());
233     AssertIsOnMainThread();
234   }
235 
~ParentImpl()236   ~ParentImpl() {
237     AssertIsInMainOrSocketProcess();
238     AssertIsOnMainThread();
239     MOZ_ASSERT(!mContent);
240   }
241 
242   void MainThreadActorDestroy();
243 
SetLiveActorArray(nsTArray<ParentImpl * > * aLiveActorArray)244   void SetLiveActorArray(nsTArray<ParentImpl*>* aLiveActorArray) {
245     AssertIsInMainOrSocketProcess();
246     AssertIsOnBackgroundThread();
247     MOZ_ASSERT(aLiveActorArray);
248     MOZ_ASSERT(!aLiveActorArray->Contains(this));
249     MOZ_ASSERT(!mLiveActorArray);
250     MOZ_ASSERT(mIsOtherProcessActor);
251 
252     mLiveActorArray = aLiveActorArray;
253     mLiveActorArray->AppendElement(this);
254   }
255 
256   // These methods are only called by IPDL.
257   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
258 };
259 
260 // -----------------------------------------------------------------------------
261 // ChildImpl Declaration
262 // -----------------------------------------------------------------------------
263 
264 class ChildImpl final : public BackgroundChildImpl {
265   friend class mozilla::ipc::BackgroundChild;
266   friend class mozilla::ipc::BackgroundChildImpl;
267 
268   typedef base::ProcessId ProcessId;
269   typedef mozilla::ipc::Transport Transport;
270 
271   class ShutdownObserver;
272 
273  public:
274   class SendInitBackgroundRunnable;
275 
276   struct ThreadLocalInfo {
ThreadLocalInfo__anondf7260de0111::ChildImpl::ThreadLocalInfo277     ThreadLocalInfo()
278 #ifdef DEBUG
279         : mClosed(false)
280 #endif
281     {
282     }
283 
284     RefPtr<ChildImpl> mActor;
285     RefPtr<SendInitBackgroundRunnable> mSendInitBackgroundRunnable;
286     UniquePtr<BackgroundChildImpl::ThreadLocal> mConsumerThreadLocal;
287 #ifdef DEBUG
288     bool mClosed;
289 #endif
290   };
291 
292  private:
293   // A thread-local index that is not valid.
294   static constexpr unsigned int kBadThreadLocalIndex =
295       static_cast<unsigned int>(-1);
296 
297   // ThreadInfoWrapper encapsulates ThreadLocalInfo and ThreadLocalIndex and
298   // also provides some common functions for creating PBackground IPC actor.
299   class ThreadInfoWrapper final {
300     friend class ChildImpl;
301 
302    public:
303     using ActorCreateFunc = void (*)(ThreadLocalInfo*, unsigned int,
304                                      nsIEventTarget*, ChildImpl**);
305 
ThreadInfoWrapper(ActorCreateFunc aFunc)306     constexpr explicit ThreadInfoWrapper(ActorCreateFunc aFunc)
307         : mThreadLocalIndex(kBadThreadLocalIndex),
308           mMainThreadInfo(nullptr),
309           mCreateActorFunc(aFunc) {}
310 
Startup()311     void Startup() {
312       MOZ_ASSERT(mThreadLocalIndex == kBadThreadLocalIndex,
313                  "ThreadInfoWrapper::Startup() called more than once!");
314 
315       PRStatus status =
316           PR_NewThreadPrivateIndex(&mThreadLocalIndex, ThreadLocalDestructor);
317       MOZ_RELEASE_ASSERT(status == PR_SUCCESS,
318                          "PR_NewThreadPrivateIndex failed!");
319 
320       MOZ_ASSERT(mThreadLocalIndex != kBadThreadLocalIndex);
321     }
322 
Shutdown()323     void Shutdown() {
324       if (sShutdownHasStarted) {
325         MOZ_ASSERT_IF(mThreadLocalIndex != kBadThreadLocalIndex,
326                       !PR_GetThreadPrivate(mThreadLocalIndex));
327         return;
328       }
329 
330       if (mThreadLocalIndex == kBadThreadLocalIndex) {
331         return;
332       }
333 
334       ThreadLocalInfo* threadLocalInfo;
335 #ifdef DEBUG
336       threadLocalInfo =
337           static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(mThreadLocalIndex));
338       MOZ_ASSERT(!threadLocalInfo);
339 #endif
340 
341       threadLocalInfo = mMainThreadInfo;
342       if (threadLocalInfo) {
343 #ifdef DEBUG
344         MOZ_ASSERT(!threadLocalInfo->mClosed);
345         threadLocalInfo->mClosed = true;
346 #endif
347 
348         ThreadLocalDestructor(threadLocalInfo);
349         mMainThreadInfo = nullptr;
350       }
351     }
352 
CloseForCurrentThread()353     void CloseForCurrentThread() {
354       MOZ_ASSERT(!NS_IsMainThread());
355 
356       if (mThreadLocalIndex == kBadThreadLocalIndex) {
357         return;
358       }
359 
360       auto threadLocalInfo =
361           static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(mThreadLocalIndex));
362 
363       if (!threadLocalInfo) {
364         return;
365       }
366 
367 #ifdef DEBUG
368       MOZ_ASSERT(!threadLocalInfo->mClosed);
369       threadLocalInfo->mClosed = true;
370 #endif
371 
372       // Clearing the thread local will synchronously close the actor.
373       DebugOnly<PRStatus> status =
374           PR_SetThreadPrivate(mThreadLocalIndex, nullptr);
375       MOZ_ASSERT(status == PR_SUCCESS);
376     }
377 
GetOrCreateForCurrentThread(nsIEventTarget * aMainEventTarget)378     PBackgroundChild* GetOrCreateForCurrentThread(
379         nsIEventTarget* aMainEventTarget) {
380       MOZ_ASSERT_IF(NS_IsMainThread(), !aMainEventTarget);
381 
382       MOZ_ASSERT(mThreadLocalIndex != kBadThreadLocalIndex,
383                  "BackgroundChild::Startup() was never called!");
384 
385       if (NS_IsMainThread() && ChildImpl::sShutdownHasStarted) {
386         return nullptr;
387       }
388 
389       auto threadLocalInfo = NS_IsMainThread()
390                                  ? mMainThreadInfo
391                                  : static_cast<ThreadLocalInfo*>(
392                                        PR_GetThreadPrivate(mThreadLocalIndex));
393 
394       if (!threadLocalInfo) {
395         auto newInfo = MakeUnique<ThreadLocalInfo>();
396 
397         if (NS_IsMainThread()) {
398           mMainThreadInfo = newInfo.get();
399         } else {
400           if (PR_SetThreadPrivate(mThreadLocalIndex, newInfo.get()) !=
401               PR_SUCCESS) {
402             CRASH_IN_CHILD_PROCESS("PR_SetThreadPrivate failed!");
403             return nullptr;
404           }
405         }
406 
407         threadLocalInfo = newInfo.release();
408       }
409 
410       PBackgroundChild* bgChild =
411           GetFromThreadInfo(aMainEventTarget, threadLocalInfo);
412       if (bgChild) {
413         return bgChild;
414       }
415 
416       RefPtr<ChildImpl> actor;
417       mCreateActorFunc(threadLocalInfo, mThreadLocalIndex, aMainEventTarget,
418                        getter_AddRefs(actor));
419       return actor;
420     }
421 
422    private:
423     // This is only modified on the main thread. It is the thread-local index
424     // that we use to store the BackgroundChild for each thread.
425     unsigned int mThreadLocalIndex;
426 
427     // On the main thread, we store TLS in this global instead of in
428     // mThreadLocalIndex. That way, cooperative main threads all share the same
429     // thread info.
430     ThreadLocalInfo* mMainThreadInfo;
431     ActorCreateFunc mCreateActorFunc;
432   };
433 
434   // For PBackground between parent and content process.
435   static ThreadInfoWrapper sParentAndContentProcessThreadInfo;
436 
437   // For PBackground between socket and content process.
438   static ThreadInfoWrapper sSocketAndContentProcessThreadInfo;
439 
440   // For PBackground between socket and parent process.
441   static ThreadInfoWrapper sSocketAndParentProcessThreadInfo;
442 
443   // This is only modified on the main thread. It prevents us from trying to
444   // create the background thread after application shutdown has started.
445   static bool sShutdownHasStarted;
446 
447 #if defined(DEBUG) || !defined(RELEASE_OR_BETA)
448   nsISerialEventTarget* mOwningEventTarget;
449 #endif
450 
451 #ifdef DEBUG
452   bool mActorWasAlive;
453   bool mActorDestroyed;
454 #endif
455 
456  public:
457   static void Shutdown();
458 
AssertIsOnOwningThread()459   void AssertIsOnOwningThread() {
460     THREADSAFETY_ASSERT(mOwningEventTarget);
461 
462 #ifdef RELEASE_OR_BETA
463     DebugOnly<bool> current;
464 #else
465     bool current;
466 #endif
467     THREADSAFETY_ASSERT(
468         NS_SUCCEEDED(mOwningEventTarget->IsOnCurrentThread(&current)));
469     THREADSAFETY_ASSERT(current);
470   }
471 
AssertActorDestroyed()472   void AssertActorDestroyed() {
473     MOZ_ASSERT(mActorDestroyed, "ChildImpl::ActorDestroy not called in time");
474   }
475 
ChildImpl()476   explicit ChildImpl()
477 #if defined(DEBUG) || !defined(RELEASE_OR_BETA)
478       : mOwningEventTarget(GetCurrentSerialEventTarget())
479 #endif
480 #ifdef DEBUG
481         ,
482         mActorWasAlive(false),
483         mActorDestroyed(false)
484 #endif
485   {
486     AssertIsOnOwningThread();
487   }
488 
SetActorAlive()489   void SetActorAlive() {
490     AssertIsOnOwningThread();
491     MOZ_ASSERT(!mActorWasAlive);
492     MOZ_ASSERT(!mActorDestroyed);
493 
494 #ifdef DEBUG
495     mActorWasAlive = true;
496 #endif
497   }
498 
499   NS_INLINE_DECL_REFCOUNTING(ChildImpl, override)
500 
501  private:
502   // Forwarded from BackgroundChild.
503   static void Startup();
504 
505   // Forwarded from BackgroundChild.
506   static PBackgroundChild* GetForCurrentThread();
507 
508   // Helper function for getting PBackgroundChild from thread info.
509   static PBackgroundChild* GetFromThreadInfo(nsIEventTarget* aMainEventTarget,
510                                              ThreadLocalInfo* aThreadLocalInfo);
511 
512   // Forwarded from BackgroundChild.
513   static PBackgroundChild* GetOrCreateForCurrentThread(
514       nsIEventTarget* aMainEventTarget);
515 
516   // Forwarded from BackgroundChild.
517   static PBackgroundChild* GetOrCreateSocketActorForCurrentThread(
518       nsIEventTarget* aMainEventTarget);
519 
520   // Forwarded from BackgroundChild.
521   static PBackgroundChild* GetOrCreateForSocketParentBridgeForCurrentThread(
522       nsIEventTarget* aMainEventTarget);
523 
524   static void CloseForCurrentThread();
525 
526   // Forwarded from BackgroundChildImpl.
527   static BackgroundChildImpl::ThreadLocal* GetThreadLocalForCurrentThread();
528 
529   static void ThreadLocalDestructor(void* aThreadLocal);
530 
531   // This class is reference counted.
~ChildImpl()532   ~ChildImpl() { MOZ_ASSERT_IF(mActorWasAlive, mActorDestroyed); }
533 
534   // Only called by IPDL.
535   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
536 };
537 
538 // -----------------------------------------------------------------------------
539 // ParentImpl Helper Declarations
540 // -----------------------------------------------------------------------------
541 
542 class ParentImpl::ShutdownObserver final : public nsIObserver {
543  public:
ShutdownObserver()544   ShutdownObserver() { AssertIsOnMainThread(); }
545 
546   NS_DECL_ISUPPORTS
547   NS_DECL_NSIOBSERVER
548 
549  private:
~ShutdownObserver()550   ~ShutdownObserver() { AssertIsOnMainThread(); }
551 };
552 
553 class ParentImpl::CreateActorHelper final : public Runnable {
554   mozilla::Monitor mMonitor;
555   RefPtr<ParentImpl> mParentActor;
556   nsCOMPtr<nsIThread> mThread;
557   nsresult mMainThreadResultCode;
558   bool mWaiting;
559 
560  public:
CreateActorHelper()561   explicit CreateActorHelper()
562       : Runnable("Background::ParentImpl::CreateActorHelper"),
563         mMonitor("CreateActorHelper::mMonitor"),
564         mMainThreadResultCode(NS_OK),
565         mWaiting(true) {
566     AssertIsInMainOrSocketProcess();
567     AssertIsNotOnMainThread();
568   }
569 
570   nsresult BlockAndGetResults(nsIEventTarget* aMainEventTarget,
571                               RefPtr<ParentImpl>& aParentActor,
572                               nsCOMPtr<nsIThread>& aThread);
573 
574  private:
~CreateActorHelper()575   ~CreateActorHelper() { AssertIsInMainOrSocketProcess(); }
576 
577   nsresult RunOnMainThread();
578 
579   NS_DECL_NSIRUNNABLE
580 };
581 
582 // -----------------------------------------------------------------------------
583 // ChildImpl Helper Declarations
584 // -----------------------------------------------------------------------------
585 
586 class ChildImpl::ShutdownObserver final : public nsIObserver {
587  public:
ShutdownObserver()588   ShutdownObserver() { AssertIsOnMainThread(); }
589 
590   NS_DECL_ISUPPORTS
591   NS_DECL_NSIOBSERVER
592 
593  private:
~ShutdownObserver()594   ~ShutdownObserver() { AssertIsOnMainThread(); }
595 };
596 
597 class ChildImpl::SendInitBackgroundRunnable final : public DiscardableRunnable {
598   nsCOMPtr<nsISerialEventTarget> mOwningEventTarget;
599   RefPtr<StrongWorkerRef> mWorkerRef;
600   Endpoint<PBackgroundParent> mParent;
601   mozilla::Mutex mMutex;
602   bool mSentInitBackground;
603   std::function<void(Endpoint<PBackgroundParent>&& aParent)> mSendInitfunc;
604   unsigned int mThreadLocalIndex;
605 
606  public:
607   static already_AddRefed<SendInitBackgroundRunnable> Create(
608       Endpoint<PBackgroundParent>&& aParent,
609       std::function<void(Endpoint<PBackgroundParent>&& aParent)>&& aFunc,
610       unsigned int aThreadLocalIndex);
611 
ClearEventTarget()612   void ClearEventTarget() {
613     mWorkerRef = nullptr;
614 
615     mozilla::MutexAutoLock lock(mMutex);
616     mOwningEventTarget = nullptr;
617   }
618 
619  private:
SendInitBackgroundRunnable(Endpoint<PBackgroundParent> && aParent,std::function<void (Endpoint<PBackgroundParent> && aParent)> && aFunc,unsigned int aThreadLocalIndex)620   explicit SendInitBackgroundRunnable(
621       Endpoint<PBackgroundParent>&& aParent,
622       std::function<void(Endpoint<PBackgroundParent>&& aParent)>&& aFunc,
623       unsigned int aThreadLocalIndex)
624       : DiscardableRunnable(
625             "Background::ChildImpl::SendInitBackgroundRunnable"),
626         mOwningEventTarget(GetCurrentSerialEventTarget()),
627         mParent(std::move(aParent)),
628         mMutex("SendInitBackgroundRunnable::mMutex"),
629         mSentInitBackground(false),
630         mSendInitfunc(std::move(aFunc)),
631         mThreadLocalIndex(aThreadLocalIndex) {}
632 
633   ~SendInitBackgroundRunnable() = default;
634 
635   NS_DECL_NSIRUNNABLE
636 };
637 
638 }  // namespace
639 
640 namespace mozilla {
641 namespace ipc {
642 
IsOnBackgroundThread()643 bool IsOnBackgroundThread() { return ParentImpl::IsOnBackgroundThread(); }
644 
645 #ifdef DEBUG
646 
AssertIsOnBackgroundThread()647 void AssertIsOnBackgroundThread() { ParentImpl::AssertIsOnBackgroundThread(); }
648 
649 #endif  // DEBUG
650 
651 }  // namespace ipc
652 }  // namespace mozilla
653 
654 // -----------------------------------------------------------------------------
655 // BackgroundParent Public Methods
656 // -----------------------------------------------------------------------------
657 
658 // static
IsOtherProcessActor(PBackgroundParent * aBackgroundActor)659 bool BackgroundParent::IsOtherProcessActor(
660     PBackgroundParent* aBackgroundActor) {
661   return ParentImpl::IsOtherProcessActor(aBackgroundActor);
662 }
663 
664 // static
GetContentParent(PBackgroundParent * aBackgroundActor)665 already_AddRefed<ContentParent> BackgroundParent::GetContentParent(
666     PBackgroundParent* aBackgroundActor) {
667   return ParentImpl::GetContentParent(aBackgroundActor);
668 }
669 
670 // static
GetRawContentParentForComparison(PBackgroundParent * aBackgroundActor)671 intptr_t BackgroundParent::GetRawContentParentForComparison(
672     PBackgroundParent* aBackgroundActor) {
673   return ParentImpl::GetRawContentParentForComparison(aBackgroundActor);
674 }
675 
676 // static
GetChildID(PBackgroundParent * aBackgroundActor)677 uint64_t BackgroundParent::GetChildID(PBackgroundParent* aBackgroundActor) {
678   return ParentImpl::GetChildID(aBackgroundActor);
679 }
680 
681 // static
GetLiveActorArray(PBackgroundParent * aBackgroundActor,nsTArray<PBackgroundParent * > & aLiveActorArray)682 bool BackgroundParent::GetLiveActorArray(
683     PBackgroundParent* aBackgroundActor,
684     nsTArray<PBackgroundParent*>& aLiveActorArray) {
685   return ParentImpl::GetLiveActorArray(aBackgroundActor, aLiveActorArray);
686 }
687 
688 // static
Alloc(ContentParent * aContent,Endpoint<PBackgroundParent> && aEndpoint)689 bool BackgroundParent::Alloc(ContentParent* aContent,
690                              Endpoint<PBackgroundParent>&& aEndpoint) {
691   return ParentImpl::Alloc(aContent, std::move(aEndpoint));
692 }
693 
694 // -----------------------------------------------------------------------------
695 // BackgroundChild Public Methods
696 // -----------------------------------------------------------------------------
697 
698 // static
Startup()699 void BackgroundChild::Startup() { ChildImpl::Startup(); }
700 
701 // static
GetForCurrentThread()702 PBackgroundChild* BackgroundChild::GetForCurrentThread() {
703   return ChildImpl::GetForCurrentThread();
704 }
705 
706 // static
GetOrCreateForCurrentThread(nsIEventTarget * aMainEventTarget)707 PBackgroundChild* BackgroundChild::GetOrCreateForCurrentThread(
708     nsIEventTarget* aMainEventTarget) {
709   return ChildImpl::GetOrCreateForCurrentThread(aMainEventTarget);
710 }
711 
712 // static
GetOrCreateSocketActorForCurrentThread(nsIEventTarget * aMainEventTarget)713 PBackgroundChild* BackgroundChild::GetOrCreateSocketActorForCurrentThread(
714     nsIEventTarget* aMainEventTarget) {
715   return ChildImpl::GetOrCreateSocketActorForCurrentThread(aMainEventTarget);
716 }
717 
718 // static
719 PBackgroundChild*
GetOrCreateForSocketParentBridgeForCurrentThread(nsIEventTarget * aMainEventTarget)720 BackgroundChild::GetOrCreateForSocketParentBridgeForCurrentThread(
721     nsIEventTarget* aMainEventTarget) {
722   return ChildImpl::GetOrCreateForSocketParentBridgeForCurrentThread(
723       aMainEventTarget);
724 }
725 
726 // static
CloseForCurrentThread()727 void BackgroundChild::CloseForCurrentThread() {
728   ChildImpl::CloseForCurrentThread();
729 }
730 
731 // -----------------------------------------------------------------------------
732 // BackgroundChildImpl Public Methods
733 // -----------------------------------------------------------------------------
734 
735 // static
736 BackgroundChildImpl::ThreadLocal*
GetThreadLocalForCurrentThread()737 BackgroundChildImpl::GetThreadLocalForCurrentThread() {
738   return ChildImpl::GetThreadLocalForCurrentThread();
739 }
740 
741 // -----------------------------------------------------------------------------
742 // ParentImpl Static Members
743 // -----------------------------------------------------------------------------
744 
745 StaticRefPtr<nsIThread> ParentImpl::sBackgroundThread;
746 
747 nsTArray<ParentImpl*>* ParentImpl::sLiveActorsForBackgroundThread;
748 
749 StaticRefPtr<nsITimer> ParentImpl::sShutdownTimer;
750 
751 Atomic<PRThread*> ParentImpl::sBackgroundPRThread;
752 
753 uint64_t ParentImpl::sLiveActorCount = 0;
754 
755 bool ParentImpl::sShutdownObserverRegistered = false;
756 
757 bool ParentImpl::sShutdownHasStarted = false;
758 
759 // -----------------------------------------------------------------------------
760 // ChildImpl Static Members
761 // -----------------------------------------------------------------------------
762 
ParentContentActorCreateFunc(ChildImpl::ThreadLocalInfo * aThreadLocalInfo,unsigned int aThreadLocalIndex,nsIEventTarget * aMainEventTarget,ChildImpl ** aOutput)763 static void ParentContentActorCreateFunc(
764     ChildImpl::ThreadLocalInfo* aThreadLocalInfo,
765     unsigned int aThreadLocalIndex, nsIEventTarget* aMainEventTarget,
766     ChildImpl** aOutput) {
767   if (XRE_IsParentProcess()) {
768     RefPtr<ChildImpl> strongActor =
769         ParentImpl::CreateActorForSameProcess(aMainEventTarget);
770     if (NS_WARN_IF(!strongActor)) {
771       return;
772     }
773 
774     aThreadLocalInfo->mActor = strongActor;
775     strongActor.forget(aOutput);
776     return;
777   }
778 
779   RefPtr<ContentChild> content = ContentChild::GetSingleton();
780   MOZ_ASSERT(content);
781 
782   if (content->IsShuttingDown()) {
783     // The transport for ContentChild is shut down and can't be used to open
784     // PBackground.
785     return;
786   }
787 
788   Endpoint<PBackgroundParent> parent;
789   Endpoint<PBackgroundChild> child;
790   nsresult rv;
791   rv = PBackground::CreateEndpoints(content->OtherPid(),
792                                     base::GetCurrentProcId(), &parent, &child);
793   if (NS_FAILED(rv)) {
794     NS_WARNING("Failed to create top level actor!");
795     return;
796   }
797 
798   RefPtr<ChildImpl::SendInitBackgroundRunnable> runnable;
799   if (!NS_IsMainThread()) {
800     runnable = ChildImpl::SendInitBackgroundRunnable::Create(
801         std::move(parent),
802         [](Endpoint<PBackgroundParent>&& aParent) {
803           RefPtr<ContentChild> content = ContentChild::GetSingleton();
804           MOZ_ASSERT(content);
805 
806           if (!content->SendInitBackground(std::move(aParent))) {
807             NS_WARNING("Failed to create top level actor!");
808           }
809         },
810         aThreadLocalIndex);
811     if (!runnable) {
812       return;
813     }
814   }
815 
816   RefPtr<ChildImpl> strongActor = new ChildImpl();
817 
818   if (!child.Bind(strongActor)) {
819     CRASH_IN_CHILD_PROCESS("Failed to bind ChildImpl!");
820 
821     return;
822   }
823 
824   strongActor->SetActorAlive();
825 
826   if (NS_IsMainThread()) {
827     if (!content->SendInitBackground(std::move(parent))) {
828       NS_WARNING("Failed to create top level actor!");
829       return;
830     }
831   } else {
832     if (aMainEventTarget) {
833       MOZ_ALWAYS_SUCCEEDS(
834           aMainEventTarget->Dispatch(runnable, NS_DISPATCH_NORMAL));
835     } else {
836       MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
837     }
838 
839     aThreadLocalInfo->mSendInitBackgroundRunnable = runnable;
840   }
841 
842   aThreadLocalInfo->mActor = strongActor;
843   strongActor.forget(aOutput);
844 }
845 
846 ChildImpl::ThreadInfoWrapper ChildImpl::sParentAndContentProcessThreadInfo(
847     ParentContentActorCreateFunc);
848 
SocketContentActorCreateFunc(ChildImpl::ThreadLocalInfo * aThreadLocalInfo,unsigned int aThreadLocalIndex,nsIEventTarget * aMainEventTarget,ChildImpl ** aOutput)849 static void SocketContentActorCreateFunc(
850     ChildImpl::ThreadLocalInfo* aThreadLocalInfo,
851     unsigned int aThreadLocalIndex, nsIEventTarget* aMainEventTarget,
852     ChildImpl** aOutput) {
853   RefPtr<SocketProcessBridgeChild> bridgeChild =
854       SocketProcessBridgeChild::GetSingleton();
855 
856   if (!bridgeChild || bridgeChild->IsShuttingDown()) {
857     // The transport for SocketProcessBridgeChild is shut down
858     // and can't be used to open PBackground.
859     return;
860   }
861 
862   Endpoint<PBackgroundParent> parent;
863   Endpoint<PBackgroundChild> child;
864   nsresult rv;
865   rv = PBackground::CreateEndpoints(bridgeChild->SocketProcessPid(),
866                                     base::GetCurrentProcId(), &parent, &child);
867   if (NS_FAILED(rv)) {
868     NS_WARNING("Failed to create top level actor!");
869     return;
870   }
871 
872   RefPtr<ChildImpl::SendInitBackgroundRunnable> runnable;
873   if (!NS_IsMainThread()) {
874     runnable = ChildImpl::SendInitBackgroundRunnable::Create(
875         std::move(parent),
876         [](Endpoint<PBackgroundParent>&& aParent) {
877           RefPtr<SocketProcessBridgeChild> bridgeChild =
878               SocketProcessBridgeChild::GetSingleton();
879 
880           if (!bridgeChild->SendInitBackground(std::move(aParent))) {
881             NS_WARNING("Failed to create top level actor!");
882           }
883         },
884         aThreadLocalIndex);
885     if (!runnable) {
886       return;
887     }
888   }
889 
890   RefPtr<ChildImpl> strongActor = new ChildImpl();
891 
892   if (!child.Bind(strongActor)) {
893     CRASH_IN_CHILD_PROCESS("Failed to bind ChildImpl!");
894 
895     return;
896   }
897 
898   strongActor->SetActorAlive();
899 
900   if (NS_IsMainThread()) {
901     if (!bridgeChild->SendInitBackground(std::move(parent))) {
902       NS_WARNING("Failed to create top level actor!");
903       // Need to close the IPC channel before ChildImpl getting deleted.
904       strongActor->Close();
905       strongActor->AssertActorDestroyed();
906       return;
907     }
908   } else {
909     if (aMainEventTarget) {
910       MOZ_ALWAYS_SUCCEEDS(
911           aMainEventTarget->Dispatch(runnable, NS_DISPATCH_NORMAL));
912     } else {
913       MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
914     }
915 
916     aThreadLocalInfo->mSendInitBackgroundRunnable = runnable;
917   }
918 
919   aThreadLocalInfo->mActor = strongActor;
920   strongActor.forget(aOutput);
921 }
922 
923 ChildImpl::ThreadInfoWrapper ChildImpl::sSocketAndContentProcessThreadInfo(
924     SocketContentActorCreateFunc);
925 
SocketParentActorCreateFunc(ChildImpl::ThreadLocalInfo * aThreadLocalInfo,unsigned int aThreadLocalIndex,nsIEventTarget * aMainEventTarget,ChildImpl ** aOutput)926 static void SocketParentActorCreateFunc(
927     ChildImpl::ThreadLocalInfo* aThreadLocalInfo,
928     unsigned int aThreadLocalIndex, nsIEventTarget* aMainEventTarget,
929     ChildImpl** aOutput) {
930   SocketProcessChild* socketChild = SocketProcessChild::GetSingleton();
931 
932   if (!socketChild || socketChild->IsShuttingDown()) {
933     return;
934   }
935 
936   Endpoint<PBackgroundParent> parent;
937   Endpoint<PBackgroundChild> child;
938   nsresult rv;
939   rv = PBackground::CreateEndpoints(socketChild->OtherPid(),
940                                     base::GetCurrentProcId(), &parent, &child);
941   if (NS_FAILED(rv)) {
942     NS_WARNING("Failed to create top level actor!");
943     return;
944   }
945 
946   RefPtr<ChildImpl::SendInitBackgroundRunnable> runnable;
947   if (!NS_IsMainThread()) {
948     runnable = ChildImpl::SendInitBackgroundRunnable::Create(
949         std::move(parent),
950         [](Endpoint<PBackgroundParent>&& aParent) {
951           SocketProcessChild* socketChild = SocketProcessChild::GetSingleton();
952           MOZ_ASSERT(socketChild);
953 
954           if (!socketChild->SendInitBackground(std::move(aParent))) {
955             MOZ_CRASH("Failed to create top level actor!");
956           }
957         },
958         aThreadLocalIndex);
959     if (!runnable) {
960       return;
961     }
962   }
963 
964   RefPtr<ChildImpl> strongActor = new ChildImpl();
965 
966   if (!child.Bind(strongActor)) {
967     CRASH_IN_CHILD_PROCESS("Failed to bind ChildImpl!");
968     return;
969   }
970 
971   strongActor->SetActorAlive();
972 
973   if (NS_IsMainThread()) {
974     if (!socketChild->SendInitBackground(std::move(parent))) {
975       NS_WARNING("Failed to create top level actor!");
976       return;
977     }
978   } else {
979     if (aMainEventTarget) {
980       MOZ_ALWAYS_SUCCEEDS(
981           aMainEventTarget->Dispatch(runnable, NS_DISPATCH_NORMAL));
982     } else {
983       MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
984     }
985 
986     aThreadLocalInfo->mSendInitBackgroundRunnable = runnable;
987   }
988 
989   aThreadLocalInfo->mActor = strongActor;
990   strongActor.forget(aOutput);
991 }
992 
993 ChildImpl::ThreadInfoWrapper ChildImpl::sSocketAndParentProcessThreadInfo(
994     SocketParentActorCreateFunc);
995 
996 bool ChildImpl::sShutdownHasStarted = false;
997 
998 // -----------------------------------------------------------------------------
999 // ParentImpl Implementation
1000 // -----------------------------------------------------------------------------
1001 
1002 // static
IsOtherProcessActor(PBackgroundParent * aBackgroundActor)1003 bool ParentImpl::IsOtherProcessActor(PBackgroundParent* aBackgroundActor) {
1004   AssertIsOnBackgroundThread();
1005   MOZ_ASSERT(aBackgroundActor);
1006 
1007   return static_cast<ParentImpl*>(aBackgroundActor)->mIsOtherProcessActor;
1008 }
1009 
1010 // static
GetContentParent(PBackgroundParent * aBackgroundActor)1011 already_AddRefed<ContentParent> ParentImpl::GetContentParent(
1012     PBackgroundParent* aBackgroundActor) {
1013   AssertIsOnBackgroundThread();
1014   MOZ_ASSERT(aBackgroundActor);
1015 
1016   auto actor = static_cast<ParentImpl*>(aBackgroundActor);
1017   if (actor->mActorDestroyed) {
1018     MOZ_ASSERT(false, "GetContentParent called after ActorDestroy was called!");
1019     return nullptr;
1020   }
1021 
1022   if (actor->mContent) {
1023     // We need to hand out a reference to our ContentParent but we also need to
1024     // keep the one we have. We can't call AddRef here because ContentParent is
1025     // not threadsafe so instead we dispatch a runnable to the main thread to do
1026     // it for us. This is safe since we are guaranteed that our AddRef runnable
1027     // will run before the reference we hand out can be released, and the
1028     // ContentParent can't die as long as the existing reference is maintained.
1029     MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(NewNonOwningRunnableMethod(
1030         "ContentParent::AddRef", actor->mContent, &ContentParent::AddRef)));
1031   }
1032 
1033   return already_AddRefed<ContentParent>(actor->mContent.get());
1034 }
1035 
1036 // static
GetRawContentParentForComparison(PBackgroundParent * aBackgroundActor)1037 intptr_t ParentImpl::GetRawContentParentForComparison(
1038     PBackgroundParent* aBackgroundActor) {
1039   AssertIsOnBackgroundThread();
1040   MOZ_ASSERT(aBackgroundActor);
1041 
1042   auto actor = static_cast<ParentImpl*>(aBackgroundActor);
1043   if (actor->mActorDestroyed) {
1044     MOZ_ASSERT(false,
1045                "GetRawContentParentForComparison called after ActorDestroy was "
1046                "called!");
1047     return intptr_t(-1);
1048   }
1049 
1050   return intptr_t(static_cast<ContentParent*>(actor->mContent.get()));
1051 }
1052 
1053 // static
GetChildID(PBackgroundParent * aBackgroundActor)1054 uint64_t ParentImpl::GetChildID(PBackgroundParent* aBackgroundActor) {
1055   AssertIsOnBackgroundThread();
1056   MOZ_ASSERT(aBackgroundActor);
1057 
1058   auto actor = static_cast<ParentImpl*>(aBackgroundActor);
1059   if (actor->mActorDestroyed) {
1060     MOZ_ASSERT(false, "GetContentParent called after ActorDestroy was called!");
1061     return 0;
1062   }
1063 
1064   if (actor->mContent) {
1065     return actor->mContent->ChildID();
1066   }
1067 
1068   return 0;
1069 }
1070 
1071 // static
GetLiveActorArray(PBackgroundParent * aBackgroundActor,nsTArray<PBackgroundParent * > & aLiveActorArray)1072 bool ParentImpl::GetLiveActorArray(
1073     PBackgroundParent* aBackgroundActor,
1074     nsTArray<PBackgroundParent*>& aLiveActorArray) {
1075   AssertIsOnBackgroundThread();
1076   MOZ_ASSERT(aBackgroundActor);
1077   MOZ_ASSERT(aLiveActorArray.IsEmpty());
1078 
1079   auto actor = static_cast<ParentImpl*>(aBackgroundActor);
1080   if (actor->mActorDestroyed) {
1081     MOZ_ASSERT(false,
1082                "GetLiveActorArray called after ActorDestroy was called!");
1083     return false;
1084   }
1085 
1086   if (!actor->mLiveActorArray) {
1087     return true;
1088   }
1089 
1090   for (ParentImpl* liveActor : *actor->mLiveActorArray) {
1091     aLiveActorArray.AppendElement(liveActor);
1092   }
1093 
1094   return true;
1095 }
1096 
1097 // static
Alloc(ContentParent * aContent,Endpoint<PBackgroundParent> && aEndpoint)1098 bool ParentImpl::Alloc(ContentParent* aContent,
1099                        Endpoint<PBackgroundParent>&& aEndpoint) {
1100   AssertIsInMainOrSocketProcess();
1101   AssertIsOnMainThread();
1102   MOZ_ASSERT(aEndpoint.IsValid());
1103 
1104   if (!sBackgroundThread && !CreateBackgroundThread()) {
1105     NS_WARNING("Failed to create background thread!");
1106     return false;
1107   }
1108 
1109   MOZ_ASSERT(sLiveActorsForBackgroundThread);
1110 
1111   sLiveActorCount++;
1112 
1113   RefPtr<ParentImpl> actor = new ParentImpl(aContent);
1114 
1115   if (NS_FAILED(sBackgroundThread->Dispatch(NS_NewRunnableFunction(
1116           "Background::ParentImpl::ConnectActorRunnable",
1117           [actor = std::move(actor), endpoint = std::move(aEndpoint),
1118            liveActorArray = sLiveActorsForBackgroundThread]() mutable {
1119             MOZ_ASSERT(endpoint.IsValid());
1120             MOZ_ASSERT(liveActorArray);
1121             // Transfer ownership to this thread. If Open() fails then we will
1122             // release this reference in Destroy.
1123             ParentImpl* actorTmp;
1124             actor.forget(&actorTmp);
1125 
1126             if (!endpoint.Bind(actorTmp)) {
1127               actorTmp->Destroy();
1128               return;
1129             }
1130 
1131             actorTmp->SetLiveActorArray(liveActorArray);
1132           })))) {
1133     NS_WARNING("Failed to dispatch connect runnable!");
1134 
1135     MOZ_ASSERT(sLiveActorCount);
1136     sLiveActorCount--;
1137   }
1138 
1139   return true;
1140 }
1141 
1142 // static
CreateActorForSameProcess(nsIEventTarget * aMainEventTarget)1143 already_AddRefed<ChildImpl> ParentImpl::CreateActorForSameProcess(
1144     nsIEventTarget* aMainEventTarget) {
1145   AssertIsInMainProcess();
1146 
1147   RefPtr<ParentImpl> parentActor;
1148   nsCOMPtr<nsIThread> backgroundThread;
1149 
1150   if (NS_IsMainThread()) {
1151     if (!sBackgroundThread && !CreateBackgroundThread()) {
1152       NS_WARNING("Failed to create background thread!");
1153       return nullptr;
1154     }
1155 
1156     MOZ_ASSERT(!sShutdownHasStarted);
1157 
1158     sLiveActorCount++;
1159 
1160     parentActor = new ParentImpl();
1161     backgroundThread = sBackgroundThread.get();
1162   } else {
1163     RefPtr<CreateActorHelper> helper = new CreateActorHelper();
1164 
1165     nsresult rv = helper->BlockAndGetResults(aMainEventTarget, parentActor,
1166                                              backgroundThread);
1167     if (NS_WARN_IF(NS_FAILED(rv))) {
1168       return nullptr;
1169     }
1170   }
1171 
1172   RefPtr<ChildImpl> childActor = new ChildImpl();
1173 
1174   MessageChannel* parentChannel = parentActor->GetIPCChannel();
1175   MOZ_ASSERT(parentChannel);
1176 
1177   if (!childActor->Open(parentChannel, backgroundThread, ChildSide)) {
1178     NS_WARNING("Failed to open ChildImpl!");
1179 
1180     // Can't release it here, we will release this reference in Destroy.
1181     ParentImpl* actor;
1182     parentActor.forget(&actor);
1183 
1184     actor->Destroy();
1185 
1186     return nullptr;
1187   }
1188 
1189   childActor->SetActorAlive();
1190 
1191   // Make sure the parent knows it is same process.
1192   parentActor->SetOtherProcessId(base::GetCurrentProcId());
1193 
1194   // Now that Open() has succeeded transfer the ownership of the actors to IPDL.
1195   Unused << parentActor.forget();
1196 
1197   return childActor.forget();
1198 }
1199 
1200 // static
CreateBackgroundThread()1201 bool ParentImpl::CreateBackgroundThread() {
1202   AssertIsInMainOrSocketProcess();
1203   AssertIsOnMainThread();
1204   MOZ_ASSERT(!sBackgroundThread);
1205   MOZ_ASSERT(!sLiveActorsForBackgroundThread);
1206 
1207   if (sShutdownHasStarted) {
1208     NS_WARNING(
1209         "Trying to create background thread after shutdown has "
1210         "already begun!");
1211     return false;
1212   }
1213 
1214   nsCOMPtr<nsITimer> newShutdownTimer;
1215 
1216   if (!sShutdownTimer) {
1217     newShutdownTimer = NS_NewTimer();
1218     if (!newShutdownTimer) {
1219       return false;
1220     }
1221   }
1222 
1223   if (!sShutdownObserverRegistered) {
1224     nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
1225     if (NS_WARN_IF(!obs)) {
1226       return false;
1227     }
1228 
1229     nsCOMPtr<nsIObserver> observer = new ShutdownObserver();
1230 
1231     nsresult rv = obs->AddObserver(
1232         observer, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, false);
1233     if (NS_WARN_IF(NS_FAILED(rv))) {
1234       return false;
1235     }
1236 
1237     sShutdownObserverRegistered = true;
1238   }
1239 
1240   nsCOMPtr<nsIThread> thread;
1241   if (NS_FAILED(NS_NewNamedThread(
1242           "IPDL Background", getter_AddRefs(thread),
1243           NS_NewRunnableFunction(
1244               "Background::ParentImpl::CreateBackgroundThreadRunnable", []() {
1245                 DebugOnly<PRThread*> oldBackgroundThread =
1246                     sBackgroundPRThread.exchange(PR_GetCurrentThread());
1247 
1248                 MOZ_ASSERT_IF(oldBackgroundThread,
1249                               PR_GetCurrentThread() != oldBackgroundThread);
1250               })))) {
1251     NS_WARNING("NS_NewNamedThread failed!");
1252     return false;
1253   }
1254 
1255   sBackgroundThread = thread.forget();
1256 
1257   sLiveActorsForBackgroundThread = new nsTArray<ParentImpl*>(1);
1258 
1259   if (!sShutdownTimer) {
1260     MOZ_ASSERT(newShutdownTimer);
1261     sShutdownTimer = newShutdownTimer;
1262   }
1263 
1264   return true;
1265 }
1266 
1267 // static
ShutdownBackgroundThread()1268 void ParentImpl::ShutdownBackgroundThread() {
1269   AssertIsInMainOrSocketProcess();
1270   AssertIsOnMainThread();
1271   MOZ_ASSERT(sShutdownHasStarted);
1272   MOZ_ASSERT_IF(!sBackgroundThread, !sLiveActorCount);
1273   MOZ_ASSERT_IF(sBackgroundThread, sShutdownTimer);
1274 
1275   nsCOMPtr<nsITimer> shutdownTimer = sShutdownTimer.get();
1276   sShutdownTimer = nullptr;
1277 
1278   if (sBackgroundThread) {
1279     nsCOMPtr<nsIThread> thread = sBackgroundThread.get();
1280     sBackgroundThread = nullptr;
1281 
1282     UniquePtr<nsTArray<ParentImpl*>> liveActors(sLiveActorsForBackgroundThread);
1283     sLiveActorsForBackgroundThread = nullptr;
1284 
1285     MOZ_ASSERT_IF(!sShutdownHasStarted, !sLiveActorCount);
1286 
1287     if (sLiveActorCount) {
1288       // We need to spin the event loop while we wait for all the actors to be
1289       // cleaned up. We also set a timeout to force-kill any hanging actors.
1290       TimerCallbackClosure closure(thread, liveActors.get());
1291 
1292       MOZ_ALWAYS_SUCCEEDS(shutdownTimer->InitWithNamedFuncCallback(
1293           &ShutdownTimerCallback, &closure, kShutdownTimerDelayMS,
1294           nsITimer::TYPE_ONE_SHOT, "ParentImpl::ShutdownTimerCallback"));
1295 
1296       SpinEventLoopUntil([&]() { return !sLiveActorCount; });
1297 
1298       MOZ_ASSERT(liveActors->IsEmpty());
1299 
1300       MOZ_ALWAYS_SUCCEEDS(shutdownTimer->Cancel());
1301     }
1302 
1303     // Dispatch this runnable to unregister the PR thread from the profiler.
1304     MOZ_ALWAYS_SUCCEEDS(thread->Dispatch(NS_NewRunnableFunction(
1305         "Background::ParentImpl::ShutdownBackgroundThreadRunnable", []() {
1306           // It is possible that another background thread was created while
1307           // this thread was shutting down. In that case we can't assert
1308           // anything about sBackgroundPRThread and we should not modify it
1309           // here.
1310           sBackgroundPRThread.compareExchange(PR_GetCurrentThread(), nullptr);
1311         })));
1312 
1313     MOZ_ALWAYS_SUCCEEDS(thread->Shutdown());
1314   }
1315 }
1316 
1317 // static
ShutdownTimerCallback(nsITimer * aTimer,void * aClosure)1318 void ParentImpl::ShutdownTimerCallback(nsITimer* aTimer, void* aClosure) {
1319   AssertIsInMainOrSocketProcess();
1320   AssertIsOnMainThread();
1321   MOZ_ASSERT(sShutdownHasStarted);
1322   MOZ_ASSERT(sLiveActorCount);
1323 
1324   auto closure = static_cast<TimerCallbackClosure*>(aClosure);
1325   MOZ_ASSERT(closure);
1326 
1327   // Don't let the stack unwind until the ForceCloseBackgroundActorsRunnable has
1328   // finished.
1329   sLiveActorCount++;
1330 
1331   InvokeAsync(closure->mThread, __func__,
1332               [liveActors = closure->mLiveActors]() {
1333                 MOZ_ASSERT(liveActors);
1334 
1335                 if (!liveActors->IsEmpty()) {
1336                   // Copy the array since calling Close() could mutate the
1337                   // actual array.
1338                   nsTArray<ParentImpl*> actorsToClose(liveActors->Clone());
1339                   for (ParentImpl* actor : actorsToClose) {
1340                     actor->Close();
1341                   }
1342                 }
1343                 return GenericPromise::CreateAndResolve(true, __func__);
1344               })
1345       ->Then(GetCurrentSerialEventTarget(), __func__, []() {
1346         MOZ_ASSERT(sLiveActorCount);
1347         sLiveActorCount--;
1348       });
1349 }
1350 
Destroy()1351 void ParentImpl::Destroy() {
1352   // May be called on any thread!
1353 
1354   AssertIsInMainOrSocketProcess();
1355 
1356   MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(
1357       NewNonOwningRunnableMethod("ParentImpl::MainThreadActorDestroy", this,
1358                                  &ParentImpl::MainThreadActorDestroy)));
1359 }
1360 
MainThreadActorDestroy()1361 void ParentImpl::MainThreadActorDestroy() {
1362   AssertIsInMainOrSocketProcess();
1363   AssertIsOnMainThread();
1364   MOZ_ASSERT_IF(!mIsOtherProcessActor, !mContent);
1365 
1366   mContent = nullptr;
1367 
1368   MOZ_ASSERT(sLiveActorCount);
1369   sLiveActorCount--;
1370 
1371   // This may be the last reference!
1372   Release();
1373 }
1374 
ActorDestroy(ActorDestroyReason aWhy)1375 void ParentImpl::ActorDestroy(ActorDestroyReason aWhy) {
1376   AssertIsInMainOrSocketProcess();
1377   AssertIsOnBackgroundThread();
1378   MOZ_ASSERT(!mActorDestroyed);
1379   MOZ_ASSERT_IF(mIsOtherProcessActor, mLiveActorArray);
1380 
1381   BackgroundParentImpl::ActorDestroy(aWhy);
1382 
1383   mActorDestroyed = true;
1384 
1385   if (mLiveActorArray) {
1386     MOZ_ALWAYS_TRUE(mLiveActorArray->RemoveElement(this));
1387     mLiveActorArray = nullptr;
1388   }
1389 
1390   // This is tricky. We should be able to call Destroy() here directly because
1391   // we're not going to touch 'this' or our MessageChannel any longer on this
1392   // thread. Destroy() dispatches the MainThreadActorDestroy runnable and when
1393   // it runs it will destroy 'this' and our associated MessageChannel. However,
1394   // IPDL is about to call MessageChannel::Clear() on this thread! To avoid
1395   // racing with the main thread we must ensure that the MessageChannel lives
1396   // long enough to be cleared in this call stack.
1397 
1398   MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(NewNonOwningRunnableMethod(
1399       "ParentImpl::Destroy", this, &ParentImpl::Destroy)));
1400 }
1401 
NS_IMPL_ISUPPORTS(ParentImpl::ShutdownObserver,nsIObserver)1402 NS_IMPL_ISUPPORTS(ParentImpl::ShutdownObserver, nsIObserver)
1403 
1404 NS_IMETHODIMP
1405 ParentImpl::ShutdownObserver::Observe(nsISupports* aSubject, const char* aTopic,
1406                                       const char16_t* aData) {
1407   AssertIsInMainOrSocketProcess();
1408   AssertIsOnMainThread();
1409   MOZ_ASSERT(!sShutdownHasStarted);
1410   MOZ_ASSERT(!strcmp(aTopic, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID));
1411 
1412   sShutdownHasStarted = true;
1413 
1414   // Do this first before calling (and spinning the event loop in)
1415   // ShutdownBackgroundThread().
1416   ChildImpl::Shutdown();
1417 
1418   ShutdownBackgroundThread();
1419 
1420   return NS_OK;
1421 }
1422 
BlockAndGetResults(nsIEventTarget * aMainEventTarget,RefPtr<ParentImpl> & aParentActor,nsCOMPtr<nsIThread> & aThread)1423 nsresult ParentImpl::CreateActorHelper::BlockAndGetResults(
1424     nsIEventTarget* aMainEventTarget, RefPtr<ParentImpl>& aParentActor,
1425     nsCOMPtr<nsIThread>& aThread) {
1426   AssertIsNotOnMainThread();
1427 
1428   if (aMainEventTarget) {
1429     MOZ_ALWAYS_SUCCEEDS(aMainEventTarget->Dispatch(this, NS_DISPATCH_NORMAL));
1430   } else {
1431     MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(this));
1432   }
1433 
1434   mozilla::MonitorAutoLock lock(mMonitor);
1435   while (mWaiting) {
1436     lock.Wait();
1437   }
1438 
1439   if (NS_WARN_IF(NS_FAILED(mMainThreadResultCode))) {
1440     return mMainThreadResultCode;
1441   }
1442 
1443   aParentActor = std::move(mParentActor);
1444   aThread = std::move(mThread);
1445   return NS_OK;
1446 }
1447 
RunOnMainThread()1448 nsresult ParentImpl::CreateActorHelper::RunOnMainThread() {
1449   AssertIsOnMainThread();
1450 
1451   if (!sBackgroundThread && !CreateBackgroundThread()) {
1452     NS_WARNING("Failed to create background thread!");
1453     return NS_ERROR_FAILURE;
1454   }
1455 
1456   MOZ_ASSERT(!sShutdownHasStarted);
1457 
1458   sLiveActorCount++;
1459 
1460   mParentActor = new ParentImpl();
1461   mThread = sBackgroundThread;
1462 
1463   return NS_OK;
1464 }
1465 
1466 NS_IMETHODIMP
Run()1467 ParentImpl::CreateActorHelper::Run() {
1468   AssertIsOnMainThread();
1469 
1470   nsresult rv = RunOnMainThread();
1471   if (NS_WARN_IF(NS_FAILED(rv))) {
1472     mMainThreadResultCode = rv;
1473   }
1474 
1475   mozilla::MonitorAutoLock lock(mMonitor);
1476   MOZ_ASSERT(mWaiting);
1477 
1478   mWaiting = false;
1479   lock.Notify();
1480 
1481   return NS_OK;
1482 }
1483 
1484 // -----------------------------------------------------------------------------
1485 // ChildImpl Implementation
1486 // -----------------------------------------------------------------------------
1487 
1488 // static
Startup()1489 void ChildImpl::Startup() {
1490   // This happens on the main thread but before XPCOM has started so we can't
1491   // assert that we're being called on the main thread here.
1492 
1493   sParentAndContentProcessThreadInfo.Startup();
1494   sSocketAndContentProcessThreadInfo.Startup();
1495   sSocketAndParentProcessThreadInfo.Startup();
1496 
1497   nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
1498   MOZ_RELEASE_ASSERT(observerService);
1499 
1500   nsCOMPtr<nsIObserver> observer = new ShutdownObserver();
1501 
1502   nsresult rv = observerService->AddObserver(
1503       observer, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, false);
1504   MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
1505 }
1506 
1507 // static
Shutdown()1508 void ChildImpl::Shutdown() {
1509   AssertIsOnMainThread();
1510 
1511   sParentAndContentProcessThreadInfo.Shutdown();
1512   sSocketAndContentProcessThreadInfo.Shutdown();
1513   sSocketAndParentProcessThreadInfo.Shutdown();
1514 
1515   sShutdownHasStarted = true;
1516 }
1517 
1518 // static
GetForCurrentThread()1519 PBackgroundChild* ChildImpl::GetForCurrentThread() {
1520   MOZ_ASSERT(sParentAndContentProcessThreadInfo.mThreadLocalIndex !=
1521              kBadThreadLocalIndex);
1522 
1523   auto threadLocalInfo =
1524       NS_IsMainThread()
1525           ? sParentAndContentProcessThreadInfo.mMainThreadInfo
1526           : static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(
1527                 sParentAndContentProcessThreadInfo.mThreadLocalIndex));
1528 
1529   if (!threadLocalInfo) {
1530     return nullptr;
1531   }
1532 
1533   return threadLocalInfo->mActor;
1534 }
1535 
1536 /* static */
GetFromThreadInfo(nsIEventTarget * aMainEventTarget,ThreadLocalInfo * aThreadLocalInfo)1537 PBackgroundChild* ChildImpl::GetFromThreadInfo(
1538     nsIEventTarget* aMainEventTarget, ThreadLocalInfo* aThreadLocalInfo) {
1539   MOZ_ASSERT(aThreadLocalInfo);
1540 
1541   if (aThreadLocalInfo->mActor) {
1542     RefPtr<SendInitBackgroundRunnable>& runnable =
1543         aThreadLocalInfo->mSendInitBackgroundRunnable;
1544 
1545     if (aMainEventTarget && runnable) {
1546       // The SendInitBackgroundRunnable was already dispatched to the main
1547       // thread to finish initialization of a new background child actor.
1548       // However, the caller passed a custom main event target which indicates
1549       // that synchronous blocking of the main thread is happening (done by
1550       // creating a nested event target and spinning the event loop).
1551       // It can happen that the SendInitBackgroundRunnable didn't have a chance
1552       // to run before the synchronous blocking has occured. Unblocking of the
1553       // main thread can depend on an IPC message received on this thread, so
1554       // we have to dispatch the SendInitBackgroundRunnable to the custom main
1555       // event target too, otherwise IPC will be only queueing messages on this
1556       // thread. The runnable will run twice in the end, but that's a harmless
1557       // race between the main and nested event queue of the main thread.
1558       // There's a guard in the runnable implementation for calling
1559       // SendInitBackground only once.
1560 
1561       MOZ_ALWAYS_SUCCEEDS(
1562           aMainEventTarget->Dispatch(runnable, NS_DISPATCH_NORMAL));
1563     }
1564 
1565     return aThreadLocalInfo->mActor;
1566   }
1567 
1568   return nullptr;
1569 }
1570 
1571 /* static */
GetOrCreateForCurrentThread(nsIEventTarget * aMainEventTarget)1572 PBackgroundChild* ChildImpl::GetOrCreateForCurrentThread(
1573     nsIEventTarget* aMainEventTarget) {
1574   return sParentAndContentProcessThreadInfo.GetOrCreateForCurrentThread(
1575       aMainEventTarget);
1576 }
1577 
1578 /* static */
GetOrCreateSocketActorForCurrentThread(nsIEventTarget * aMainEventTarget)1579 PBackgroundChild* ChildImpl::GetOrCreateSocketActorForCurrentThread(
1580     nsIEventTarget* aMainEventTarget) {
1581   return sSocketAndContentProcessThreadInfo.GetOrCreateForCurrentThread(
1582       aMainEventTarget);
1583 }
1584 
1585 /* static */
GetOrCreateForSocketParentBridgeForCurrentThread(nsIEventTarget * aMainEventTarget)1586 PBackgroundChild* ChildImpl::GetOrCreateForSocketParentBridgeForCurrentThread(
1587     nsIEventTarget* aMainEventTarget) {
1588   return sSocketAndParentProcessThreadInfo.GetOrCreateForCurrentThread(
1589       aMainEventTarget);
1590 }
1591 
1592 // static
CloseForCurrentThread()1593 void ChildImpl::CloseForCurrentThread() {
1594   MOZ_ASSERT(!NS_IsMainThread(),
1595              "PBackground for the main thread should be shut down via "
1596              "ChildImpl::Shutdown().");
1597 
1598   sParentAndContentProcessThreadInfo.CloseForCurrentThread();
1599   sSocketAndContentProcessThreadInfo.CloseForCurrentThread();
1600   sSocketAndParentProcessThreadInfo.CloseForCurrentThread();
1601 }
1602 
1603 // static
GetThreadLocalForCurrentThread()1604 BackgroundChildImpl::ThreadLocal* ChildImpl::GetThreadLocalForCurrentThread() {
1605   MOZ_ASSERT(sParentAndContentProcessThreadInfo.mThreadLocalIndex !=
1606                  kBadThreadLocalIndex,
1607              "BackgroundChild::Startup() was never called!");
1608 
1609   auto threadLocalInfo =
1610       NS_IsMainThread()
1611           ? sParentAndContentProcessThreadInfo.mMainThreadInfo
1612           : static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(
1613                 sParentAndContentProcessThreadInfo.mThreadLocalIndex));
1614 
1615   if (!threadLocalInfo) {
1616     return nullptr;
1617   }
1618 
1619   if (!threadLocalInfo->mConsumerThreadLocal) {
1620     threadLocalInfo->mConsumerThreadLocal =
1621         MakeUnique<BackgroundChildImpl::ThreadLocal>();
1622   }
1623 
1624   return threadLocalInfo->mConsumerThreadLocal.get();
1625 }
1626 
1627 // static
ThreadLocalDestructor(void * aThreadLocal)1628 void ChildImpl::ThreadLocalDestructor(void* aThreadLocal) {
1629   auto threadLocalInfo = static_cast<ThreadLocalInfo*>(aThreadLocal);
1630 
1631   if (threadLocalInfo) {
1632     MOZ_ASSERT(threadLocalInfo->mClosed);
1633 
1634     if (threadLocalInfo->mActor) {
1635       threadLocalInfo->mActor->Close();
1636       threadLocalInfo->mActor->AssertActorDestroyed();
1637     }
1638 
1639     if (threadLocalInfo->mSendInitBackgroundRunnable) {
1640       threadLocalInfo->mSendInitBackgroundRunnable->ClearEventTarget();
1641     }
1642 
1643     delete threadLocalInfo;
1644   }
1645 }
1646 
ActorDestroy(ActorDestroyReason aWhy)1647 void ChildImpl::ActorDestroy(ActorDestroyReason aWhy) {
1648   AssertIsOnOwningThread();
1649 
1650 #ifdef DEBUG
1651   MOZ_ASSERT(!mActorDestroyed);
1652   mActorDestroyed = true;
1653 #endif
1654 
1655   BackgroundChildImpl::ActorDestroy(aWhy);
1656 }
1657 
NS_IMPL_ISUPPORTS(ChildImpl::ShutdownObserver,nsIObserver)1658 NS_IMPL_ISUPPORTS(ChildImpl::ShutdownObserver, nsIObserver)
1659 
1660 NS_IMETHODIMP
1661 ChildImpl::ShutdownObserver::Observe(nsISupports* aSubject, const char* aTopic,
1662                                      const char16_t* aData) {
1663   AssertIsOnMainThread();
1664   MOZ_ASSERT(!strcmp(aTopic, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID));
1665 
1666   ChildImpl::Shutdown();
1667 
1668   return NS_OK;
1669 }
1670 
1671 // static
1672 already_AddRefed<ChildImpl::SendInitBackgroundRunnable>
Create(Endpoint<PBackgroundParent> && aParent,std::function<void (Endpoint<PBackgroundParent> && aParent)> && aFunc,unsigned int aThreadLocalIndex)1673 ChildImpl::SendInitBackgroundRunnable::Create(
1674     Endpoint<PBackgroundParent>&& aParent,
1675     std::function<void(Endpoint<PBackgroundParent>&& aParent)>&& aFunc,
1676     unsigned int aThreadLocalIndex) {
1677   MOZ_ASSERT(!NS_IsMainThread());
1678 
1679   RefPtr<SendInitBackgroundRunnable> runnable = new SendInitBackgroundRunnable(
1680       std::move(aParent), std::move(aFunc), aThreadLocalIndex);
1681 
1682   WorkerPrivate* workerPrivate = mozilla::dom::GetCurrentThreadWorkerPrivate();
1683   if (!workerPrivate) {
1684     return runnable.forget();
1685   }
1686 
1687   workerPrivate->AssertIsOnWorkerThread();
1688 
1689   runnable->mWorkerRef = StrongWorkerRef::Create(
1690       workerPrivate, "ChildImpl::SendInitBackgroundRunnable");
1691   if (NS_WARN_IF(!runnable->mWorkerRef)) {
1692     return nullptr;
1693   }
1694 
1695   return runnable.forget();
1696 }
1697 
1698 NS_IMETHODIMP
Run()1699 ChildImpl::SendInitBackgroundRunnable::Run() {
1700   if (NS_IsMainThread()) {
1701     if (mSentInitBackground) {
1702       return NS_OK;
1703     }
1704 
1705     mSentInitBackground = true;
1706 
1707     mSendInitfunc(std::move(mParent));
1708 
1709     nsCOMPtr<nsISerialEventTarget> owningEventTarget;
1710     {
1711       mozilla::MutexAutoLock lock(mMutex);
1712       owningEventTarget = mOwningEventTarget;
1713     }
1714 
1715     if (!owningEventTarget) {
1716       return NS_OK;
1717     }
1718 
1719     nsresult rv = owningEventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
1720     if (NS_WARN_IF(NS_FAILED(rv))) {
1721       return rv;
1722     }
1723 
1724     return NS_OK;
1725   }
1726 
1727   ClearEventTarget();
1728 
1729   auto threadLocalInfo =
1730       static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(mThreadLocalIndex));
1731 
1732   if (!threadLocalInfo) {
1733     return NS_OK;
1734   }
1735 
1736   threadLocalInfo->mSendInitBackgroundRunnable = nullptr;
1737 
1738   return NS_OK;
1739 }
1740