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