tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

RemoteWorkerService.h (6039B)


      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
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef mozilla_dom_RemoteWorkerService_h
      8 #define mozilla_dom_RemoteWorkerService_h
      9 
     10 #include "mozilla/AlreadyAddRefed.h"
     11 #include "mozilla/DataMutex.h"
     12 #include "mozilla/dom/RemoteWorkerTypes.h"
     13 #include "mozilla/ipc/Endpoint.h"
     14 #include "nsCOMPtr.h"
     15 #include "nsIObserver.h"
     16 #include "nsISupportsImpl.h"
     17 
     18 class nsIThread;
     19 
     20 namespace mozilla::dom {
     21 
     22 class RemoteWorkerDebuggerManagerChild;
     23 class RemoteWorkerDebuggerManagerParent;
     24 class RemoteWorkerService;
     25 class RemoteWorkerServiceChild;
     26 class RemoteWorkerServiceShutdownBlocker;
     27 class PRemoteWorkerDebuggerManagerChild;
     28 class PRemoteWorkerDebuggerParent;
     29 class PRemoteWorkerServiceChild;
     30 
     31 /**
     32 * Refcounted lifecycle helper; when its refcount goes to zero its destructor
     33 * will call RemoteWorkerService::Shutdown() which will remove the shutdown
     34 * blocker and shutdown the "Worker Launcher" thread.
     35 *
     36 * The RemoteWorkerService itself will hold a reference to this singleton which
     37 * it will use to hand out additional refcounts to RemoteWorkerChild instances.
     38 * When the shutdown blocker is notified that it's time to shutdown, the
     39 * RemoteWorkerService's reference will be dropped.
     40 */
     41 class RemoteWorkerServiceKeepAlive {
     42 public:
     43  explicit RemoteWorkerServiceKeepAlive(
     44      RemoteWorkerServiceShutdownBlocker* aBlocker);
     45 
     46 private:
     47  ~RemoteWorkerServiceKeepAlive();
     48 
     49  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteWorkerServiceKeepAlive);
     50 
     51  RefPtr<RemoteWorkerServiceShutdownBlocker> mBlocker;
     52 };
     53 
     54 /**
     55 * Every process has a RemoteWorkerService which does the actual spawning of
     56 * RemoteWorkerChild instances. The RemoteWorkerService creates a "Worker
     57 * Launcher" thread at initialization on which it creates a
     58 * RemoteWorkerServiceChild to service spawn requests. The thread is exposed as
     59 * RemoteWorkerService::Thread(). A new/distinct thread is used because we
     60 * (eventually) don't want to deal with main-thread contention, content
     61 * processes have no equivalent of a PBackground thread, and actors are bound to
     62 * specific threads.
     63 *
     64 * (Disclaimer: currently most RemoteWorkerOps need to happen on the main thread
     65 * because the main-thread ends up as the owner of the worker and all
     66 * manipulation of the worker must happen from the owning thread.)
     67 */
     68 class RemoteWorkerService final : public nsIObserver {
     69  friend class RemoteWorkerServiceShutdownBlocker;
     70  friend class RemoteWorkerServiceKeepAlive;
     71 
     72 public:
     73  NS_DECL_THREADSAFE_ISUPPORTS
     74  NS_DECL_NSIOBSERVER
     75 
     76  // To be called when a process is initialized on main-thread.
     77  static void InitializeParent();
     78  static void InitializeChild(
     79      mozilla::ipc::Endpoint<PRemoteWorkerServiceChild> aEndpoint,
     80      mozilla::ipc::Endpoint<PRemoteWorkerDebuggerManagerChild>
     81          aDebuggerChildEp);
     82 
     83  static nsIThread* Thread();
     84  static void RegisterRemoteDebugger(
     85      RemoteWorkerDebuggerInfo aDebuggerInfo,
     86      mozilla::ipc::Endpoint<PRemoteWorkerDebuggerParent> aDebuggerParentEp);
     87 
     88  // Called by RemoteWorkerChild instances on the "Worker Launcher" thread at
     89  // their creation to assist in tracking when it's safe to shutdown the
     90  // RemoteWorkerService and "Worker Launcher" thread.  This method will return
     91  // a null pointer if the RemoteWorkerService has already begun shutdown.
     92  //
     93  // This is somewhat awkwardly a static method because the RemoteWorkerChild
     94  // instances are not managed by RemoteWorkerServiceChild, but instead are
     95  // managed by PBackground(Child).  So we either need to find the
     96  // RemoteWorkerService via the hidden singleton or by having the
     97  // RemoteWorkerChild use PBackgroundChild::ManagedPRemoteWorkerServiceChild()
     98  // to locate the instance.  We are choosing to use the singleton because we
     99  // already need to acquire a mutex in the call regardless and the upcoming
    100  // refactorings may want to start using new toplevel protocols and this will
    101  // avoid requiring a change when that happens.
    102  static already_AddRefed<RemoteWorkerServiceKeepAlive> MaybeGetKeepAlive();
    103 
    104 private:
    105  RemoteWorkerService();
    106  ~RemoteWorkerService();
    107 
    108  nsresult InitializeOnMainThread(
    109      mozilla::ipc::Endpoint<PRemoteWorkerServiceChild> aEndpoint,
    110      mozilla::ipc::Endpoint<PRemoteWorkerDebuggerManagerChild>
    111          aDebuggerChildEp);
    112 
    113  void InitializeOnTargetThread(
    114      mozilla::ipc::Endpoint<PRemoteWorkerServiceChild> aEndpoint,
    115      mozilla::ipc::Endpoint<PRemoteWorkerDebuggerManagerChild>
    116          aDebuggerMgrEndpoint);
    117 
    118  void CloseActorOnTargetThread();
    119 
    120  // Called by RemoteWorkerServiceShutdownBlocker when it's time to drop the
    121  // RemoteWorkerServiceKeepAlive reference.
    122  void BeginShutdown();
    123 
    124  // Called by RemoteWorkerServiceShutdownBlocker when the blocker has been
    125  // removed and it's safe to shutdown the "Worker Launcher" thread.
    126  void FinishShutdown();
    127 
    128  nsCOMPtr<nsIThread> mThread;
    129  RefPtr<RemoteWorkerServiceChild> mActor;
    130  RefPtr<RemoteWorkerDebuggerManagerChild> mDebuggerManagerChild;
    131  RefPtr<RemoteWorkerDebuggerManagerParent> mDebuggerManagerParent;
    132  // The keep-alive is set and cleared on the main thread but we will hand out
    133  // additional references to it from the "Worker Launcher" thread, so it's
    134  // appropriate to use a mutex.  (Alternately we could have used a ThreadBound
    135  // and set and cleared on the "Worker Launcher" thread, but that would
    136  // involve more moving parts and could have complicated edge cases.)
    137  DataMutex<RefPtr<RemoteWorkerServiceKeepAlive>> mKeepAlive;
    138  // In order to poll the blocker to know when we can stop spinning the event
    139  // loop at shutdown, we retain a reference to the blocker.
    140  RefPtr<RemoteWorkerServiceShutdownBlocker> mShutdownBlocker;
    141 };
    142 
    143 }  // namespace mozilla::dom
    144 
    145 #endif  // mozilla_dom_RemoteWorkerService_h