GMPServiceParent.h (10791B)
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 GMPServiceParent_h_ 7 #define GMPServiceParent_h_ 8 9 #include "GMPService.h" 10 #include "GMPStorage.h" 11 #include "mozIGeckoMediaPluginChromeService.h" 12 #include "mozilla/Atomics.h" 13 #include "mozilla/MozPromise.h" 14 #include "mozilla/dom/ContentParent.h" 15 #include "mozilla/gmp/PGMPParent.h" 16 #include "mozilla/gmp/PGMPServiceParent.h" 17 #include "mozilla/media/MediaUtils.h" 18 #include "nsClassHashtable.h" 19 #include "nsIAsyncShutdown.h" 20 #include "nsNetUtil.h" 21 #include "nsRefPtrHashtable.h" 22 #include "nsTHashMap.h" 23 #include "nsThreadUtils.h" 24 25 template <class> 26 struct already_AddRefed; 27 using FlushFOGDataPromise = mozilla::dom::ContentParent::FlushFOGDataPromise; 28 using ContentParent = mozilla::dom::ContentParent; 29 30 namespace mozilla { 31 class OriginAttributesPattern; 32 33 namespace gmp { 34 35 class GMPParent; 36 class GMPServiceParent; 37 38 class GeckoMediaPluginServiceParent final 39 : public GeckoMediaPluginService, 40 public mozIGeckoMediaPluginChromeService { 41 public: 42 static already_AddRefed<GeckoMediaPluginServiceParent> GetSingleton(); 43 44 GeckoMediaPluginServiceParent(); 45 nsresult Init() override; 46 47 NS_DECL_ISUPPORTS_INHERITED 48 49 // mozIGeckoMediaPluginService 50 NS_IMETHOD HasPluginForAPI(const nsACString& aAPI, 51 const nsTArray<nsCString>& aTags, 52 bool* aRetVal) override; 53 NS_IMETHOD FindPluginDirectoryForAPI(const nsACString& aAPI, 54 const nsTArray<nsCString>& aTags, 55 nsIFile** aDirectory) override; 56 NS_IMETHOD GetNodeId(const nsAString& aOrigin, 57 const nsAString& aTopLevelOrigin, 58 const nsAString& aGMPName, 59 UniquePtr<GetNodeIdCallback>&& aCallback) override; 60 61 NS_DECL_MOZIGECKOMEDIAPLUGINCHROMESERVICE 62 NS_DECL_NSIOBSERVER 63 64 RefPtr<GenericPromise> EnsureInitialized(); 65 RefPtr<GenericPromise> AsyncAddPluginDirectory(const nsAString& aDirectory); 66 67 // GMP thread access only 68 bool IsShuttingDown(); 69 70 already_AddRefed<GMPStorage> GetMemoryStorageFor(const nsACString& aNodeId, 71 const nsAString& aGMPName); 72 nsresult ForgetThisSiteNative( 73 const nsAString& aSite, const mozilla::OriginAttributesPattern& aPattern); 74 75 nsresult ForgetThisBaseDomainNative(const nsAString& aBaseDomain); 76 77 // Notifies that some user of this class is created/destroyed. 78 void ServiceUserCreated(GMPServiceParent* aServiceParent); 79 void ServiceUserDestroyed(GMPServiceParent* aServiceParent); 80 81 // If aContentProcess is specified, this will only update GMP caps in that 82 // content process, otherwise will update all content processes. 83 void UpdateContentProcessGMPCapabilities( 84 ContentParent* aContentProcess = nullptr); 85 86 void SendFlushFOGData(nsTArray<RefPtr<FlushFOGDataPromise>>& promises); 87 88 #if defined(XP_WIN) 89 using GetUntrustedModulesDataPromise = 90 PGMPParent::GetUntrustedModulesDataPromise; 91 92 void SendGetUntrustedModulesData( 93 nsTArray<RefPtr<GetUntrustedModulesDataPromise>>& promises); 94 95 void SendUnblockUntrustedModulesThread(); 96 #endif 97 98 /* 99 * ** Test-only Method ** 100 * 101 * Trigger GMP-process test metric instrumentation. 102 */ 103 RefPtr<PGMPParent::TestTriggerMetricsPromise> TestTriggerMetrics(); 104 105 private: 106 friend class GMPServiceParent; 107 class Observer; 108 109 virtual ~GeckoMediaPluginServiceParent(); 110 111 void ClearStorage(); 112 113 already_AddRefed<GMPParent> SelectPluginForAPI( 114 const nsACString& aNodeId, const nsACString& aAPI, 115 const nsTArray<nsCString>& aTags); 116 117 already_AddRefed<GMPParent> FindPluginForAPIFrom( 118 size_t aSearchStartIndex, const nsACString& aAPI, 119 const nsTArray<nsCString>& aTags, size_t* aOutPluginIndex) 120 MOZ_REQUIRES(mMutex); 121 122 nsresult GetNodeId(const nsAString& aOrigin, const nsAString& aTopLevelOrigin, 123 const nsAString& aGMPName, nsACString& aOutId); 124 125 void UnloadPlugins(); 126 void CrashPlugins(); 127 void NotifySyncShutdownComplete(); 128 129 void RemoveOnGMPThread(const nsAString& aDirectory, 130 const bool aDeleteFromDisk, const bool aCanDefer); 131 132 struct DirectoryFilter { 133 virtual bool operator()(nsIFile* aPath) = 0; 134 ~DirectoryFilter() = default; 135 }; 136 void ClearNodeIdAndPlugin(DirectoryFilter& aFilter); 137 void ClearNodeIdAndPlugin(nsIFile* aPluginStorageDir, 138 DirectoryFilter& aFilter); 139 void ForgetThisSiteOnGMPThread( 140 const nsACString& aSite, 141 const mozilla::OriginAttributesPattern& aPattern); 142 void ForgetThisBaseDomainOnGMPThread(const nsACString& aBaseDomain); 143 void ClearRecentHistoryOnGMPThread(PRTime aSince); 144 void OnPreferenceChanged(mozilla::dom::Pref&& aPref); 145 146 already_AddRefed<GMPParent> GetById(uint32_t aPluginId); 147 148 protected: 149 friend class GMPParent; 150 void ReAddOnGMPThread(const RefPtr<GMPParent>& aOld); 151 void PluginTerminated(const RefPtr<GMPParent>& aOld); 152 void InitializePlugins(nsISerialEventTarget* GMPThread) override; 153 RefPtr<GenericPromise> LoadFromEnvironment(); 154 RefPtr<GenericPromise> AddOnGMPThread(nsString aDirectory); 155 156 RefPtr<GetGMPContentParentPromise> GetContentParent( 157 GMPCrashHelper* aHelper, const NodeIdVariant& aNodeIdVariant, 158 const nsACString& aAPI, const nsTArray<nsCString>& aTags) override; 159 160 private: 161 already_AddRefed<GMPParent> CreateGMPParent(); 162 163 // Creates a copy of aOriginal. Note that the caller is responsible for 164 // adding this to GeckoMediaPluginServiceParent::mPlugins. 165 already_AddRefed<GMPParent> ClonePlugin(const GMPParent* aOriginal); 166 nsresult EnsurePluginsOnDiskScanned(); 167 nsresult InitStorage(); 168 169 // Get a string based node ID from a NodeIdVariant. This will 170 // either fetch the internal string, or convert the internal NodeIdParts to a 171 // string. The conversion process is fallible, so the return value should be 172 // checked. 173 nsresult GetNodeId(const NodeIdVariant& aNodeIdVariant, nsACString& aOutId); 174 175 class PathRunnable : public Runnable { 176 public: 177 enum EOperation { 178 REMOVE, 179 REMOVE_AND_DELETE_FROM_DISK, 180 }; 181 182 PathRunnable(GeckoMediaPluginServiceParent* aService, 183 const nsAString& aPath, EOperation aOperation, 184 bool aDefer = false) 185 : Runnable("gmp::GeckoMediaPluginServiceParent::PathRunnable"), 186 mService(aService), 187 mPath(aPath), 188 mOperation(aOperation), 189 mDefer(aDefer) {} 190 191 NS_DECL_NSIRUNNABLE 192 193 private: 194 RefPtr<GeckoMediaPluginServiceParent> mService; 195 nsString mPath; 196 EOperation mOperation; 197 bool mDefer; 198 }; 199 200 // Protected by mMutex from the base class. 201 nsTArray<RefPtr<GMPParent>> mPlugins MOZ_GUARDED_BY(mMutex); 202 203 // True if we've inspected MOZ_GMP_PATH on the GMP thread and loaded any 204 // plugins found there into mPlugins. 205 Atomic<bool> mScannedPluginOnDisk; 206 207 template <typename T> 208 class MainThreadOnly { 209 public: 210 MOZ_IMPLICIT MainThreadOnly(T aValue) : mValue(aValue) {} 211 operator T&() { 212 MOZ_ASSERT(NS_IsMainThread()); 213 return mValue; 214 } 215 216 private: 217 T mValue; 218 }; 219 220 MainThreadOnly<bool> mShuttingDown; 221 MainThreadOnly<bool> mWaitingForPluginsSyncShutdown; 222 223 nsTArray<nsString> mPluginsWaitingForDeletion; 224 225 nsCOMPtr<nsIFile> mStorageBaseDir; 226 227 // Hashes of (origin,topLevelOrigin) to the node id for 228 // non-persistent sessions. 229 nsClassHashtable<nsUint32HashKey, nsCString> mTempNodeIds; 230 231 // Hashes node id to whether that node id is allowed to store data 232 // persistently on disk. 233 nsTHashMap<nsCStringHashKey, bool> mPersistentStorageAllowed; 234 235 // Synchronization for barrier that ensures we've loaded GMPs from 236 // MOZ_GMP_PATH before allowing GetContentParentFrom() to proceed. 237 Monitor mInitPromiseMonitor; 238 MozMonitoredPromiseHolder<GenericPromise> mInitPromise; 239 bool mLoadPluginsFromDiskComplete; 240 241 // Hashes nodeId to the hashtable of storage for that nodeId. 242 nsRefPtrHashtable<nsCStringHashKey, GMPStorage> mTempGMPStorage; 243 244 // Tracks how many IPC connections to GMPServices running in content 245 // processes we have. When this is empty we can safely shut down. 246 // Synchronized across thread via mMutex in base class. 247 nsTArray<GMPServiceParent*> mServiceParents; 248 249 uint32_t mDirectoriesAdded = 0; 250 uint32_t mDirectoriesInProgress = 0; 251 }; 252 253 nsresult WriteToFile(nsIFile* aPath, const nsACString& aFileName, 254 const nsACString& aData); 255 nsresult ReadSalt(nsIFile* aPath, nsACString& aOutData); 256 bool MatchOrigin(nsIFile* aPath, const nsACString& aSite, 257 const mozilla::OriginAttributesPattern& aPattern); 258 bool MatchBaseDomain(nsIFile* aPath, const nsACString& aBaseDomain); 259 260 /** 261 * This class runs in the parent process, and manages the lifecycle of the GMP 262 * process and brokering the creation of PGMPContent between the parent/content 263 * processes and the GMP process. 264 */ 265 class GMPServiceParent final : public PGMPServiceParent { 266 public: 267 explicit GMPServiceParent(GeckoMediaPluginServiceParent* aService); 268 269 // Our refcounting is thread safe, and when our refcount drops to zero 270 // we dispatch an event to the main thread to delete the GMPServiceParent. 271 // Note that this means it's safe for references to this object to be 272 // released on a non main thread, but the destructor will always run on 273 // the main thread. 274 275 // Mark AddRef and Release as `final`, as they overload pure virtual 276 // implementations in PGMPServiceParent. 277 NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DELETE_ON_MAIN_THREAD( 278 GMPServiceParent, final); 279 280 ipc::IPCResult RecvGetGMPNodeId(const nsAString& aOrigin, 281 const nsAString& aTopLevelOrigin, 282 const nsAString& aGMPName, 283 GetGMPNodeIdResolver&& aResolve) override; 284 285 static bool Create(Endpoint<PGMPServiceParent>&& aGMPService); 286 287 ipc::IPCResult RecvLaunchGMP(const NodeIdVariant& aNodeIdVariant, 288 const nsACString& aAPI, 289 nsTArray<nsCString>&& aTags, 290 nsTArray<ProcessId>&& aAlreadyBridgedTo, 291 LaunchGMPResolver&& aResolve) override; 292 293 private: 294 ~GMPServiceParent(); 295 296 const RefPtr<GeckoMediaPluginServiceParent> mService; 297 298 // Ticket that controls the shutdown blocker. 299 const UniquePtr<media::ShutdownBlockingTicket> mShutdownBlocker; 300 }; 301 302 } // namespace gmp 303 } // namespace mozilla 304 305 #endif // GMPServiceParent_h_