tor-browser

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

GMPServiceChild.h (6577B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #ifndef GMPServiceChild_h_
      7 #define GMPServiceChild_h_
      8 
      9 #include "GMPService.h"
     10 #include "MediaResult.h"
     11 #include "base/process.h"
     12 #include "mozilla/MozPromise.h"
     13 #include "mozilla/dom/PContent.h"
     14 #include "mozilla/gmp/PGMPServiceChild.h"
     15 #include "mozilla/media/MediaUtils.h"
     16 #include "nsRefPtrHashtable.h"
     17 
     18 namespace mozilla::gmp {
     19 
     20 class GMPContentParent;
     21 class GMPContentParentCloseBlocker;
     22 class GMPServiceChild;
     23 
     24 class GeckoMediaPluginServiceChild : public GeckoMediaPluginService {
     25  friend class GMPServiceChild;
     26 
     27 public:
     28  static already_AddRefed<GeckoMediaPluginServiceChild> GetSingleton();
     29  nsresult Init() override;
     30 
     31  NS_DECL_ISUPPORTS_INHERITED
     32 
     33  NS_IMETHOD HasPluginForAPI(const nsACString& aAPI,
     34                             const nsTArray<nsCString>& aTags,
     35                             bool* aRetVal) override;
     36  NS_IMETHOD FindPluginDirectoryForAPI(const nsACString& aAPI,
     37                                       const nsTArray<nsCString>& aTags,
     38                                       nsIFile** aDirectory) override;
     39  NS_IMETHOD GetNodeId(const nsAString& aOrigin,
     40                       const nsAString& aTopLevelOrigin,
     41                       const nsAString& aGMPName,
     42                       UniquePtr<GetNodeIdCallback>&& aCallback) override;
     43 
     44  NS_DECL_NSIOBSERVER
     45 
     46  void SetServiceChild(RefPtr<GMPServiceChild>&& aServiceChild);
     47 
     48  void RemoveGMPContentParent(GMPContentParent* aGMPContentParent);
     49 
     50  static void UpdateGMPCapabilities(
     51      nsTArray<mozilla::dom::GMPCapabilityData>&& aCapabilities);
     52 
     53  void BeginShutdown();
     54 
     55 protected:
     56  void InitializePlugins(nsISerialEventTarget*) override {
     57    // Nothing to do here.
     58  }
     59 
     60  RefPtr<GetGMPContentParentPromise> GetContentParent(
     61      GMPCrashHelper* aHelper, const NodeIdVariant& aNodeIdVariant,
     62      const nsACString& aAPI, const nsTArray<nsCString>& aTags) override;
     63 
     64 private:
     65  friend class OpenPGMPServiceChild;
     66 
     67  ~GeckoMediaPluginServiceChild() override;
     68 
     69  typedef MozPromise<GMPServiceChild*, MediaResult, /* IsExclusive = */ true>
     70      GetServiceChildPromise;
     71  RefPtr<GetServiceChildPromise> GetServiceChild();
     72 
     73  nsTArray<MozPromiseHolder<GetServiceChildPromise>> mGetServiceChildPromises;
     74  RefPtr<GMPServiceChild> mServiceChild;
     75 
     76  // Shutdown blocker management. A shutdown blocker is used to ensure that
     77  // we do not shutdown until all content parents are removed from
     78  // GMPServiceChild::mContentParents.
     79  //
     80  // The following rules let us shutdown block (and thus we shouldn't
     81  // violate them):
     82  // - We will only call GetContentParent if mShuttingDownOnGMPThread is false.
     83  // - mShuttingDownOnGMPThread will become true once profile teardown is
     84  //   observed in the parent process (and once GMPServiceChild receives a
     85  //   message from GMPServiceParent) or if we block shutdown (which implies
     86  //   we're in shutdown).
     87  // - If we currently have mPendingGetContentParents > 0 or parents in
     88  //   GMPServiceChild::mContentParents we should block shutdown so such
     89  //   parents can be cleanly shutdown.
     90  // therefore
     91  // - We can block shutdown at xpcom-will-shutdown until our content parents
     92  //   are handled.
     93  // - Because once mShuttingDownOnGMPThread is true we cannot add new content
     94  //   parents, we know that when mShuttingDownOnGMPThread && all content
     95  //   parents are handled we'll never add more and it's safe to stop blocking
     96  //   shutdown.
     97  // this relies on
     98  // - Once we're shutting down, we need to ensure all content parents are
     99  //   shutdown and removed. Failure to do so will result in a shutdown stall.
    100 
    101  // Note that at the time of writing there are significant differences in how
    102  // xpcom shutdown is handled in release and non-release builds. For example,
    103  // in release builds content processes are exited early, so xpcom shutdown
    104  // is not observed (and not blocked by blockers). This is important to keep
    105  // in mind when testing the shutdown blocking machinery (you won't see most
    106  // of it be invoked in release).
    107 
    108  // All of these members should only be used on the GMP thread unless
    109  // otherwise noted!
    110 
    111  // Add a shutdown blocker. Main thread only. Should only be called once when
    112  // we init the service.
    113  nsresult AddShutdownBlocker();
    114  // Remove a shutdown blocker. Should be called once at most and only when
    115  // mShuttingDownOnGMPThread. Prefer RemoveShutdownBlockerIfNeeded unless
    116  // absolutely certain you need to call this directly.
    117  void RemoveShutdownBlocker();
    118  // Remove shutdown blocker if the following conditions are met:
    119  // - mShuttingDownOnGMPThread.
    120  // - !mServiceChild->HaveContentParents.
    121  // - mPendingGetContentParents == 0.
    122  // - mShutdownBlockerHasBeenAdded.
    123  void RemoveShutdownBlockerIfNeeded();
    124 
    125  // Ticket that controls the shutdown blocker.
    126  UniquePtr<media::ShutdownBlockingTicket> mShutdownBlocker;
    127  // The number of GetContentParent calls that have not yet been resolved or
    128  // rejected. We use this value to help determine if we need to block
    129  // shutdown. Should only be used on GMP thread to avoid races.
    130  uint32_t mPendingGetContentParents = 0;
    131  // End shutdown blocker management.
    132 };
    133 
    134 /**
    135 * This class runs in the content process, and allows the content process to
    136 * request an IPC connection to the desired GMP process.
    137 */
    138 class GMPServiceChild : public PGMPServiceChild {
    139 public:
    140  // Mark AddRef and Release as `final`, as they overload pure virtual
    141  // implementations in PGMPServiceChild.
    142  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPServiceChild, final)
    143 
    144  explicit GMPServiceChild() = default;
    145 
    146  already_AddRefed<GMPContentParent> GetBridgedGMPContentParent(
    147      ProcessId aOtherPid, ipc::Endpoint<PGMPContentParent>&& endpoint);
    148 
    149  void RemoveGMPContentParent(GMPContentParent* aGMPContentParent);
    150 
    151  bool HasAlreadyBridgedTo(base::ProcessId aPid) const;
    152 
    153  void GetAndBlockAlreadyBridgedTo(
    154      nsTArray<ProcessId>& aAlreadyBridgedTo,
    155      nsTArray<RefPtr<GMPContentParentCloseBlocker>>& aBlockers);
    156 
    157  static bool Create(Endpoint<PGMPServiceChild>&& aGMPService);
    158 
    159  ipc::IPCResult RecvBeginShutdown() override;
    160 
    161  bool HaveContentParents() const;
    162 
    163 private:
    164  ~GMPServiceChild() = default;
    165 
    166  nsRefPtrHashtable<nsUint64HashKey, GMPContentParent> mContentParents;
    167 };
    168 
    169 }  // namespace mozilla::gmp
    170 
    171 #endif  // GMPServiceChild_h_