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_