/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef GMPServiceParent_h_ #define GMPServiceParent_h_ #include "GMPService.h" #include "mozilla/gmp/PGMPServiceParent.h" #include "mozIGeckoMediaPluginChromeService.h" #include "nsClassHashtable.h" #include "nsDataHashtable.h" #include "mozilla/Atomics.h" #include "nsThreadUtils.h" #include "mozilla/MozPromise.h" #include "GMPStorage.h" template struct already_AddRefed; namespace mozilla { namespace gmp { class GMPParent; class GeckoMediaPluginServiceParent final : public GeckoMediaPluginService , public mozIGeckoMediaPluginChromeService { public: static already_AddRefed GetSingleton(); GeckoMediaPluginServiceParent(); nsresult Init() override; NS_DECL_ISUPPORTS_INHERITED // mozIGeckoMediaPluginService NS_IMETHOD GetPluginVersionForAPI(const nsACString& aAPI, nsTArray* aTags, bool* aHasPlugin, nsACString& aOutVersion) override; NS_IMETHOD GetNodeId(const nsAString& aOrigin, const nsAString& aTopLevelOrigin, const nsAString& aGMPName, bool aInPrivateBrowsingMode, UniquePtr&& aCallback) override; NS_DECL_MOZIGECKOMEDIAPLUGINCHROMESERVICE NS_DECL_NSIOBSERVER void AsyncShutdownNeeded(GMPParent* aParent); void AsyncShutdownComplete(GMPParent* aParent); int32_t AsyncShutdownTimeoutMs(); #ifdef MOZ_CRASHREPORTER void SetAsyncShutdownPluginState(GMPParent* aGMPParent, char aId, const nsCString& aState); #endif // MOZ_CRASHREPORTER RefPtr EnsureInitialized(); RefPtr AsyncAddPluginDirectory(const nsAString& aDirectory); // GMP thread access only bool IsShuttingDown(); already_AddRefed GetMemoryStorageFor(const nsACString& aNodeId); private: friend class GMPServiceParent; virtual ~GeckoMediaPluginServiceParent(); void ClearStorage(); already_AddRefed SelectPluginForAPI(const nsACString& aNodeId, const nsCString& aAPI, const nsTArray& aTags); already_AddRefed FindPluginForAPIFrom(size_t aSearchStartIndex, const nsCString& aAPI, const nsTArray& aTags, size_t* aOutPluginIndex); nsresult GetNodeId(const nsAString& aOrigin, const nsAString& aTopLevelOrigin, const nsAString& aGMPName, bool aInPrivateBrowsing, nsACString& aOutId); void UnloadPlugins(); void CrashPlugins(); void NotifySyncShutdownComplete(); void NotifyAsyncShutdownComplete(); void ProcessPossiblePlugin(nsIFile* aDir); void RemoveOnGMPThread(const nsAString& aDirectory, const bool aDeleteFromDisk, const bool aCanDefer); nsresult SetAsyncShutdownTimeout(); struct DirectoryFilter { virtual bool operator()(nsIFile* aPath) = 0; ~DirectoryFilter() {} }; void ClearNodeIdAndPlugin(DirectoryFilter& aFilter); void ClearNodeIdAndPlugin(nsIFile* aPluginStorageDir, DirectoryFilter& aFilter); void ForgetThisSiteOnGMPThread(const nsACString& aOrigin); void ClearRecentHistoryOnGMPThread(PRTime aSince); protected: friend class GMPParent; void ReAddOnGMPThread(const RefPtr& aOld); void PluginTerminated(const RefPtr& aOld); void InitializePlugins(AbstractThread* aAbstractGMPThread) override; RefPtr LoadFromEnvironment(); RefPtr AddOnGMPThread(nsString aDirectory); bool GetContentParentFrom(const nsACString& aNodeId, const nsCString& aAPI, const nsTArray& aTags, UniquePtr&& aCallback) override; private: // Creates a copy of aOriginal. Note that the caller is responsible for // adding this to GeckoMediaPluginServiceParent::mPlugins. already_AddRefed ClonePlugin(const GMPParent* aOriginal); nsresult EnsurePluginsOnDiskScanned(); nsresult InitStorage(); class PathRunnable : public Runnable { public: enum EOperation { REMOVE, REMOVE_AND_DELETE_FROM_DISK, }; PathRunnable(GeckoMediaPluginServiceParent* aService, const nsAString& aPath, EOperation aOperation, bool aDefer = false) : mService(aService) , mPath(aPath) , mOperation(aOperation) , mDefer(aDefer) { } NS_DECL_NSIRUNNABLE private: RefPtr mService; nsString mPath; EOperation mOperation; bool mDefer; }; // Protected by mMutex from the base class. nsTArray> mPlugins; bool mShuttingDown; nsTArray> mAsyncShutdownPlugins; #ifdef MOZ_CRASHREPORTER Mutex mAsyncShutdownPluginStatesMutex; // Protects mAsyncShutdownPluginStates. class AsyncShutdownPluginStates { public: void Update(const nsCString& aPlugin, const nsCString& aInstance, char aId, const nsCString& aState); private: struct State { nsCString mStateSequence; nsCString mLastStateDescription; }; typedef nsClassHashtable StatesByInstance; typedef nsClassHashtable StateInstancesByPlugin; StateInstancesByPlugin mStates; } mAsyncShutdownPluginStates; #endif // MOZ_CRASHREPORTER // True if we've inspected MOZ_GMP_PATH on the GMP thread and loaded any // plugins found there into mPlugins. Atomic mScannedPluginOnDisk; template class MainThreadOnly { public: MOZ_IMPLICIT MainThreadOnly(T aValue) : mValue(aValue) {} operator T&() { MOZ_ASSERT(NS_IsMainThread()); return mValue; } private: T mValue; }; MainThreadOnly mWaitingForPluginsSyncShutdown; nsTArray mPluginsWaitingForDeletion; nsCOMPtr mStorageBaseDir; // Hashes of (origin,topLevelOrigin) to the node id for // non-persistent sessions. nsClassHashtable mTempNodeIds; // Hashes node id to whether that node id is allowed to store data // persistently on disk. nsDataHashtable mPersistentStorageAllowed; // Synchronization for barrier that ensures we've loaded GMPs from // MOZ_GMP_PATH before allowing GetContentParentFrom() to proceed. Monitor mInitPromiseMonitor; MozPromiseHolder mInitPromise; bool mLoadPluginsFromDiskComplete; // Hashes nodeId to the hashtable of storage for that nodeId. nsRefPtrHashtable mTempGMPStorage; }; nsresult ReadSalt(nsIFile* aPath, nsACString& aOutData); bool MatchOrigin(nsIFile* aPath, const nsACString& aSite); class GMPServiceParent final : public PGMPServiceParent { public: explicit GMPServiceParent(GeckoMediaPluginServiceParent* aService) : mService(aService) { } virtual ~GMPServiceParent(); bool RecvLoadGMP(const nsCString& aNodeId, const nsCString& aApi, nsTArray&& aTags, nsTArray&& aAlreadyBridgedTo, base::ProcessId* aID, nsCString* aDisplayName, uint32_t* aPluginId, nsresult* aRv) override; bool RecvGetGMPNodeId(const nsString& aOrigin, const nsString& aTopLevelOrigin, const nsString& aGMPName, const bool& aInPrivateBrowsing, nsCString* aID) override; static bool RecvGetGMPPluginVersionForAPI(const nsCString& aAPI, nsTArray&& aTags, bool* aHasPlugin, nsCString* aVersion); void ActorDestroy(ActorDestroyReason aWhy) override; static PGMPServiceParent* Create(Transport* aTransport, ProcessId aOtherPid); private: RefPtr mService; }; } // namespace gmp } // namespace mozilla #endif // GMPServiceParent_h_