GMPParent.h (8567B)
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 GMPParent_h_ 7 #define GMPParent_h_ 8 9 #include "GMPNativeTypes.h" 10 #include "GMPProcessParent.h" 11 #include "GMPServiceParent.h" 12 #include "GMPStorageParent.h" 13 #include "GMPTimerParent.h" 14 #include "GMPVideoDecoderParent.h" 15 #include "GMPVideoEncoderParent.h" 16 #include "mozilla/Atomics.h" 17 #include "mozilla/MozPromise.h" 18 #include "mozilla/gmp/PGMPParent.h" 19 #include "mozilla/ipc/CrashReporterHelper.h" 20 #include "nsCOMPtr.h" 21 #include "nsIFile.h" 22 #include "nsISupports.h" 23 #include "nsString.h" 24 #include "nsTArray.h" 25 #include "nscore.h" 26 27 namespace mozilla::gmp { 28 29 class GMPCapability { 30 public: 31 explicit GMPCapability() = default; 32 GMPCapability(GMPCapability&& aOther) 33 : mAPIName(std::move(aOther.mAPIName)), 34 mAPITags(std::move(aOther.mAPITags)) {} 35 explicit GMPCapability(const nsACString& aAPIName) : mAPIName(aAPIName) {} 36 explicit GMPCapability(const GMPCapability& aOther) = default; 37 nsCString mAPIName; 38 CopyableTArray<nsCString> mAPITags; 39 40 static bool Supports(const nsTArray<GMPCapability>& aCapabilities, 41 const nsACString& aAPI, 42 const nsTArray<nsCString>& aTags); 43 44 static bool Supports(const nsTArray<GMPCapability>& aCapabilities, 45 const nsACString& aAPI, const nsCString& aTag); 46 }; 47 48 enum class GMPState : uint32_t { 49 NotLoaded, 50 Loaded, 51 Unloading, 52 Closing, 53 Closed 54 }; 55 56 class GMPContentParent; 57 58 class GMPParent final : public PGMPParent, 59 public ipc::CrashReporterHelper<GMPParent> { 60 friend class PGMPParent; 61 62 public: 63 static constexpr GeckoProcessType PROCESS_TYPE = GeckoProcessType_GMPlugin; 64 65 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPParent, final) 66 67 GMPParent(); 68 69 #ifdef MOZ_WIDGET_ANDROID 70 void InitForClearkey(GeckoMediaPluginServiceParent* aService); 71 #endif 72 73 RefPtr<GenericPromise> Init(GeckoMediaPluginServiceParent* aService, 74 nsIFile* aPluginDir); 75 void CloneFrom(const GMPParent* aOther); 76 77 void Crash(); 78 79 nsresult LoadProcess(); 80 81 // Called internally to close this if we don't need it 82 void CloseIfUnused(); 83 84 // Notify all active de/encoders that we are closing, either because of 85 // normal shutdown or unexpected shutdown/crash. 86 void CloseActive(bool aDieWhenUnloaded); 87 88 // Tell the plugin to die after shutdown. 89 void MarkForDeletion(); 90 bool IsMarkedForDeletion(); 91 92 // Called by the GMPService to forcibly close active de/encoders at shutdown 93 void Shutdown(); 94 95 // This must not be called while we're in the middle of abnormal ActorDestroy 96 void DeleteProcess(); 97 98 GMPState State() const; 99 nsCOMPtr<nsISerialEventTarget> GMPEventTarget(); 100 101 void OnPreferenceChange(const mozilla::dom::Pref& aPref); 102 103 // A GMP can either be a single instance shared across all NodeIds (like 104 // in the OpenH264 case), or we can require a new plugin instance for every 105 // NodeIds running the plugin (as in the EME plugin case). 106 // 107 // A NodeId is a hash of the ($urlBarOrigin, $ownerDocOrigin) pair. 108 // 109 // Plugins are associated with an NodeIds by calling SetNodeId() before 110 // loading. 111 // 112 // If a plugin has no NodeId specified and it is loaded, it is assumed to 113 // be shared across NodeIds. 114 115 // Specifies that a GMP can only work with the specified NodeIds. 116 void SetNodeId(const nsACString& aNodeId); 117 const nsACString& GetNodeId() const { return mNodeId; } 118 119 const nsCString& GetDisplayName() const; 120 const nsCString& GetVersion() const; 121 uint32_t GetPluginId() const; 122 GMPPluginType GetPluginType() const { return mPluginType; } 123 nsString GetPluginBaseName() const; 124 125 // Returns true if a plugin can be or is being used across multiple NodeIds. 126 bool CanBeSharedCrossNodeIds() const; 127 128 // A GMP can be used from a NodeId if it's already been set to work with 129 // that NodeId, or if it's not been set to work with any NodeId and has 130 // not yet been loaded (i.e. it's not shared across NodeIds). 131 bool CanBeUsedFrom(const nsACString& aNodeId) const; 132 133 already_AddRefed<nsIFile> GetDirectory() { 134 return nsCOMPtr<nsIFile>(mDirectory).forget(); 135 } 136 137 // Called when the child process has died. 138 void ChildTerminated(); 139 140 bool OpenPGMPContent(); 141 142 void GetGMPContentParent( 143 UniquePtr<MozPromiseHolder<GetGMPContentParentPromise>>&& aPromiseHolder); 144 already_AddRefed<GMPContentParent> ForgetGMPContentParent(); 145 146 bool EnsureProcessLoaded(base::ProcessId* aID); 147 148 void IncrementGMPContentChildCount(); 149 150 const nsTArray<GMPCapability>& GetCapabilities() const { 151 return mCapabilities; 152 } 153 154 private: 155 ~GMPParent(); 156 void UpdatePluginType(); 157 158 RefPtr<GeckoMediaPluginServiceParent> mService; 159 bool EnsureProcessLoaded(); 160 RefPtr<GenericPromise> ReadGMPMetaData(); 161 RefPtr<GenericPromise> ReadGMPInfoFile(nsIFile* aFile); 162 RefPtr<GenericPromise> ParseChromiumManifest( 163 const nsAString& aJSON); // Worker thread. 164 RefPtr<GenericPromise> ReadChromiumManifestFile( 165 nsIFile* aFile); // GMP thread. 166 void AddCrashAnnotations(); 167 void GetCrashID(nsString& aResult); 168 void ActorDestroy(ActorDestroyReason aWhy) override; 169 170 mozilla::ipc::IPCResult RecvPGMPStorageConstructor( 171 PGMPStorageParent* actor) override; 172 PGMPStorageParent* AllocPGMPStorageParent(); 173 bool DeallocPGMPStorageParent(PGMPStorageParent* aActor); 174 175 mozilla::ipc::IPCResult RecvPGMPTimerConstructor( 176 PGMPTimerParent* actor) override; 177 PGMPTimerParent* AllocPGMPTimerParent(); 178 bool DeallocPGMPTimerParent(PGMPTimerParent* aActor); 179 180 mozilla::ipc::IPCResult RecvPGMPContentChildDestroyed(); 181 182 mozilla::ipc::IPCResult RecvFOGData(ByteBuf&& aBuf); 183 184 #if defined(XP_WIN) 185 mozilla::ipc::IPCResult RecvGetModulesTrust( 186 ModulePaths&& aModPaths, bool aRunAtNormalPriority, 187 GetModulesTrustResolver&& aResolver); 188 #endif // defined(XP_WIN) 189 190 bool IsUsed() { 191 return mGMPContentChildCount > 0 || !mGetContentParentPromises.IsEmpty(); 192 } 193 194 void ResolveGetContentParentPromises(); 195 void RejectGetContentParentPromises(); 196 197 #if defined(XP_MACOSX) && defined(__aarch64__) 198 // We pre-translate XUL and our plugin file to avoid x64 child process 199 // startup delays caused by translation for instances when the child 200 // process binary translations have not already been cached. i.e., the 201 // first time we launch an x64 child process after installation or 202 // update. Measured by binary size of a recent XUL and Widevine plugin, 203 // this makes up 94% of the translation needed. Re-translating the 204 // same binary does not cause translation to occur again. 205 void PreTranslateBins(); 206 void PreTranslateBinsWorker(); 207 #endif 208 209 #if defined(XP_WIN) || defined(XP_MACOSX) 210 nsresult GetPluginFileArch(nsIFile* aPluginDir, const nsString& aBaseName, 211 uint32_t& aArchSet); 212 #endif 213 214 Atomic<GMPState> mState; 215 nsCOMPtr<nsIFile> mDirectory; // plugin directory on disk 216 nsString mName; // base name of plugin on disk, UTF-16 because used for paths 217 nsCString mDisplayName; // name of plugin displayed to users 218 nsCString mDescription; // description of plugin for display to users 219 nsCString mVersion; 220 #if defined(XP_WIN) || defined(XP_LINUX) 221 nsCString mLibs; 222 #endif 223 nsString mAdapter; 224 const uint32_t mPluginId; 225 GMPPluginType mPluginType = GMPPluginType::Unknown; 226 nsTArray<GMPCapability> mCapabilities; 227 GMPProcessParent* mProcess; 228 bool mDeleteProcessOnlyOnUnload; 229 bool mAbnormalShutdownInProgress; 230 bool mIsBlockingDeletion; 231 232 bool mCanDecrypt; 233 234 nsTArray<RefPtr<GMPTimerParent>> mTimers; 235 nsTArray<RefPtr<GMPStorageParent>> mStorage; 236 // NodeId the plugin is assigned to, or empty if the the plugin is not 237 // assigned to a NodeId. 238 nsCString mNodeId; 239 // This is used for GMP content in the parent, there may be more of these in 240 // the content processes. 241 RefPtr<GMPContentParent> mGMPContentParent; 242 nsTArray<UniquePtr<MozPromiseHolder<GetGMPContentParentPromise>>> 243 mGetContentParentPromises; 244 uint32_t mGMPContentChildCount; 245 246 int mChildPid; 247 248 #ifdef ALLOW_GECKO_CHILD_PROCESS_ARCH 249 // The child process architecture to use. 250 uint32_t mChildLaunchArch; 251 #endif 252 #if defined(XP_MACOSX) && defined(__aarch64__) 253 nsCString mPluginFilePath; 254 #endif 255 256 const nsCOMPtr<nsISerialEventTarget> mMainThread; 257 }; 258 259 } // namespace mozilla::gmp 260 261 #endif // GMPParent_h_