From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- dom/media/gmp/GMPServiceParent.h | 281 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 dom/media/gmp/GMPServiceParent.h (limited to 'dom/media/gmp/GMPServiceParent.h') diff --git a/dom/media/gmp/GMPServiceParent.h b/dom/media/gmp/GMPServiceParent.h new file mode 100644 index 0000000000..0a897d6a39 --- /dev/null +++ b/dom/media/gmp/GMPServiceParent.h @@ -0,0 +1,281 @@ +/* -*- 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/dom/ContentParent.h" +#include "mozilla/gmp/PGMPServiceParent.h" +#include "mozIGeckoMediaPluginChromeService.h" +#include "nsClassHashtable.h" +#include "nsTHashMap.h" +#include "mozilla/Atomics.h" +#include "nsNetUtil.h" +#include "nsIAsyncShutdown.h" +#include "nsRefPtrHashtable.h" +#include "nsThreadUtils.h" +#include "mozilla/gmp/PGMPParent.h" +#include "mozilla/MozPromise.h" +#include "GMPStorage.h" + +template +struct already_AddRefed; +using FlushFOGDataPromise = mozilla::dom::ContentParent::FlushFOGDataPromise; +using ContentParent = mozilla::dom::ContentParent; + +namespace mozilla { +class OriginAttributesPattern; + +namespace gmp { + +class GMPParent; +class GMPServiceParent; + +class GeckoMediaPluginServiceParent final + : public GeckoMediaPluginService, + public mozIGeckoMediaPluginChromeService, + public nsIAsyncShutdownBlocker { + public: + static already_AddRefed GetSingleton(); + + GeckoMediaPluginServiceParent(); + nsresult Init() override; + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIASYNCSHUTDOWNBLOCKER + + // mozIGeckoMediaPluginService + NS_IMETHOD HasPluginForAPI(const nsACString& aAPI, + const nsTArray& aTags, + bool* aRetVal) override; + NS_IMETHOD GetNodeId(const nsAString& aOrigin, + const nsAString& aTopLevelOrigin, + const nsAString& aGMPName, + UniquePtr&& aCallback) override; + + NS_DECL_MOZIGECKOMEDIAPLUGINCHROMESERVICE + NS_DECL_NSIOBSERVER + + RefPtr EnsureInitialized(); + RefPtr AsyncAddPluginDirectory(const nsAString& aDirectory); + + // GMP thread access only + bool IsShuttingDown(); + + already_AddRefed GetMemoryStorageFor(const nsACString& aNodeId); + nsresult ForgetThisSiteNative( + const nsAString& aSite, const mozilla::OriginAttributesPattern& aPattern); + + nsresult ForgetThisBaseDomainNative(const nsAString& aBaseDomain); + + // Notifies that some user of this class is created/destroyed. + void ServiceUserCreated(GMPServiceParent* aServiceParent); + void ServiceUserDestroyed(GMPServiceParent* aServiceParent); + + // If aContentProcess is specified, this will only update GMP caps in that + // content process, otherwise will update all content processes. + void UpdateContentProcessGMPCapabilities( + ContentParent* aContentProcess = nullptr); + + void SendFlushFOGData(nsTArray>& promises); + + /* + * ** Test-only Method ** + * + * Trigger GMP-process test metric instrumentation. + */ + RefPtr TestTriggerMetrics(); + + private: + friend class GMPServiceParent; + + virtual ~GeckoMediaPluginServiceParent(); + + void ClearStorage(); + + already_AddRefed SelectPluginForAPI( + const nsACString& aNodeId, const nsACString& aAPI, + const nsTArray& aTags); + + already_AddRefed FindPluginForAPIFrom( + size_t aSearchStartIndex, const nsACString& aAPI, + const nsTArray& aTags, size_t* aOutPluginIndex); + + nsresult GetNodeId(const nsAString& aOrigin, const nsAString& aTopLevelOrigin, + const nsAString& aGMPName, nsACString& aOutId); + + void UnloadPlugins(); + void CrashPlugins(); + void NotifySyncShutdownComplete(); + + void RemoveOnGMPThread(const nsAString& aDirectory, + const bool aDeleteFromDisk, const bool aCanDefer); + + struct DirectoryFilter { + virtual bool operator()(nsIFile* aPath) = 0; + ~DirectoryFilter() = default; + }; + void ClearNodeIdAndPlugin(DirectoryFilter& aFilter); + void ClearNodeIdAndPlugin(nsIFile* aPluginStorageDir, + DirectoryFilter& aFilter); + void ForgetThisSiteOnGMPThread( + const nsACString& aSite, + const mozilla::OriginAttributesPattern& aPattern); + void ForgetThisBaseDomainOnGMPThread(const nsACString& aBaseDomain); + void ClearRecentHistoryOnGMPThread(PRTime aSince); + + already_AddRefed GetById(uint32_t aPluginId); + + protected: + friend class GMPParent; + void ReAddOnGMPThread(const RefPtr& aOld); + void PluginTerminated(const RefPtr& aOld); + void InitializePlugins(nsISerialEventTarget* GMPThread) override; + RefPtr LoadFromEnvironment(); + RefPtr AddOnGMPThread(nsString aDirectory); + + RefPtr GetContentParent( + GMPCrashHelper* aHelper, const NodeIdVariant& aNodeIdVariant, + const nsACString& aAPI, const nsTArray& aTags) 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(); + + // Get a string based node ID from a NodeIdVariant. This will + // either fetch the internal string, or convert the internal NodeIdParts to a + // string. The conversion process is fallible, so the return value should be + // checked. + nsresult GetNodeId(const NodeIdVariant& aNodeIdVariant, nsACString& aOutId); + + class PathRunnable : public Runnable { + public: + enum EOperation { + REMOVE, + REMOVE_AND_DELETE_FROM_DISK, + }; + + PathRunnable(GeckoMediaPluginServiceParent* aService, + const nsAString& aPath, EOperation aOperation, + bool aDefer = false) + : Runnable("gmp::GeckoMediaPluginServiceParent::PathRunnable"), + 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; + + // 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 mShuttingDown; + 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. + nsTHashMap mPersistentStorageAllowed; + + // Synchronization for barrier that ensures we've loaded GMPs from + // MOZ_GMP_PATH before allowing GetContentParentFrom() to proceed. + Monitor mInitPromiseMonitor MOZ_UNANNOTATED; + MozMonitoredPromiseHolder mInitPromise; + bool mLoadPluginsFromDiskComplete; + + // Hashes nodeId to the hashtable of storage for that nodeId. + nsRefPtrHashtable mTempGMPStorage; + + // Tracks how many IPC connections to GMPServices running in content + // processes we have. When this is empty we can safely shut down. + // Synchronized across thread via mMutex in base class. + nsTArray mServiceParents; + + uint32_t mDirectoriesAdded = 0; + uint32_t mDirectoriesInProgress = 0; +}; + +nsresult WriteToFile(nsIFile* aPath, const nsACString& aFileName, + const nsACString& aData); +nsresult ReadSalt(nsIFile* aPath, nsACString& aOutData); +bool MatchOrigin(nsIFile* aPath, const nsACString& aSite, + const mozilla::OriginAttributesPattern& aPattern); +bool MatchBaseDomain(nsIFile* aPath, const nsACString& aBaseDomain); + +class GMPServiceParent final : public PGMPServiceParent { + public: + explicit GMPServiceParent(GeckoMediaPluginServiceParent* aService); + + // Our refcounting is thread safe, and when our refcount drops to zero + // we dispatch an event to the main thread to delete the GMPServiceParent. + // Note that this means it's safe for references to this object to be + // released on a non main thread, but the destructor will always run on + // the main thread. + + // Mark AddRef and Release as `final`, as they overload pure virtual + // implementations in PGMPServiceParent. + NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DELETE_ON_MAIN_THREAD( + GMPServiceParent, final); + + ipc::IPCResult RecvGetGMPNodeId(const nsAString& aOrigin, + const nsAString& aTopLevelOrigin, + const nsAString& aGMPName, + nsCString* aID) override; + + static bool Create(Endpoint&& aGMPService); + + ipc::IPCResult RecvLaunchGMP( + const NodeIdVariant& aNodeIdVariant, const nsACString& aAPI, + nsTArray&& aTags, nsTArray&& aAlreadyBridgedTo, + uint32_t* aOutPluginId, GMPPluginType* aOutPluginType, + ProcessId* aOutProcessId, nsCString* aOutDisplayName, + Endpoint* aOutEndpoint, nsresult* aOutRv, + nsCString* aOutErrorDescription) override; + + private: + ~GMPServiceParent(); + + RefPtr mService; +}; + +} // namespace gmp +} // namespace mozilla + +#endif // GMPServiceParent_h_ -- cgit v1.2.3