1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef CDMProxy_h_ 8 #define CDMProxy_h_ 9 10 #include "mozilla/CDMCaps.h" 11 #include "mozilla/MozPromise.h" 12 13 #include "mozilla/dom/MediaKeyMessageEvent.h" 14 #include "mozilla/dom/MediaKeys.h" 15 16 #include "nsIThread.h" 17 18 namespace mozilla { 19 class MediaRawData; 20 21 enum DecryptStatus { 22 Ok = 0, 23 GenericErr = 1, 24 NoKeyErr = 2, 25 AbortedErr = 3, 26 }; 27 28 struct DecryptResult { DecryptResultDecryptResult29 DecryptResult(DecryptStatus aStatus, MediaRawData* aSample) 30 : mStatus(aStatus) 31 , mSample(aSample) 32 {} 33 DecryptStatus mStatus; 34 RefPtr<MediaRawData> mSample; 35 }; 36 37 class CDMKeyInfo { 38 public: CDMKeyInfo(const nsTArray<uint8_t> & aKeyId)39 explicit CDMKeyInfo(const nsTArray<uint8_t>& aKeyId) 40 : mKeyId(aKeyId) 41 , mStatus() 42 {} 43 CDMKeyInfo(const nsTArray<uint8_t> & aKeyId,const dom::Optional<dom::MediaKeyStatus> & aStatus)44 CDMKeyInfo(const nsTArray<uint8_t>& aKeyId, 45 const dom::Optional<dom::MediaKeyStatus>& aStatus) 46 : mKeyId(aKeyId) 47 , mStatus(aStatus.Value()) 48 {} 49 50 // The copy-ctor and copy-assignment operator for Optional<T> are declared as 51 // delete, so override CDMKeyInfo copy-ctor for nsTArray operations. CDMKeyInfo(const CDMKeyInfo & aKeyInfo)52 CDMKeyInfo(const CDMKeyInfo& aKeyInfo) 53 { 54 mKeyId = aKeyInfo.mKeyId; 55 if (aKeyInfo.mStatus.WasPassed()) { 56 mStatus.Construct(aKeyInfo.mStatus.Value()); 57 } 58 } 59 60 nsTArray<uint8_t> mKeyId; 61 dom::Optional<dom::MediaKeyStatus> mStatus; 62 }; 63 64 typedef int64_t UnixTime; 65 66 // Proxies calls CDM, and proxies calls back. 67 // Note: Promises are passed in via a PromiseId, so that the ID can be 68 // passed via IPC to the CDM, which can then signal when to reject or 69 // resolve the promise using its PromiseId. 70 class CDMProxy { 71 protected: 72 typedef dom::PromiseId PromiseId; 73 typedef dom::MediaKeySessionType MediaKeySessionType; 74 public: 75 76 NS_IMETHOD_(MozExternalRefCountType) AddRef(void) = 0; 77 NS_IMETHOD_(MozExternalRefCountType) Release(void) = 0; 78 79 typedef MozPromise<DecryptResult, DecryptResult, /* IsExclusive = */ true> DecryptPromise; 80 81 // Main thread only. CDMProxy(dom::MediaKeys * aKeys,const nsAString & aKeySystem,bool aDistinctiveIdentifierRequired,bool aPersistentStateRequired)82 CDMProxy(dom::MediaKeys* aKeys, 83 const nsAString& aKeySystem, 84 bool aDistinctiveIdentifierRequired, 85 bool aPersistentStateRequired) 86 : mKeys(aKeys) 87 , mKeySystem(aKeySystem) 88 , mDistinctiveIdentifierRequired(aDistinctiveIdentifierRequired) 89 , mPersistentStateRequired(aPersistentStateRequired) 90 {} 91 92 // Main thread only. 93 // Loads the CDM corresponding to mKeySystem. 94 // Calls MediaKeys::OnCDMCreated() when the CDM is created. 95 virtual void Init(PromiseId aPromiseId, 96 const nsAString& aOrigin, 97 const nsAString& aTopLevelOrigin, 98 const nsAString& aName, 99 bool aInPrivateBrowsing) = 0; 100 OnSetDecryptorId(uint32_t aId)101 virtual void OnSetDecryptorId(uint32_t aId) {} 102 103 // Main thread only. 104 // Uses the CDM to create a key session. 105 // Calls MediaKeys::OnSessionActivated() when session is created. 106 // Assumes ownership of (Move()s) aInitData's contents. 107 virtual void CreateSession(uint32_t aCreateSessionToken, 108 MediaKeySessionType aSessionType, 109 PromiseId aPromiseId, 110 const nsAString& aInitDataType, 111 nsTArray<uint8_t>& aInitData) = 0; 112 113 // Main thread only. 114 // Uses the CDM to load a presistent session stored on disk. 115 // Calls MediaKeys::OnSessionActivated() when session is loaded. 116 virtual void LoadSession(PromiseId aPromiseId, 117 const nsAString& aSessionId) = 0; 118 119 // Main thread only. 120 // Sends a new certificate to the CDM. 121 // Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has 122 // processed the request. 123 // Assumes ownership of (Move()s) aCert's contents. 124 virtual void SetServerCertificate(PromiseId aPromiseId, 125 nsTArray<uint8_t>& aCert) = 0; 126 127 // Main thread only. 128 // Sends an update to the CDM. 129 // Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has 130 // processed the request. 131 // Assumes ownership of (Move()s) aResponse's contents. 132 virtual void UpdateSession(const nsAString& aSessionId, 133 PromiseId aPromiseId, 134 nsTArray<uint8_t>& aResponse) = 0; 135 136 // Main thread only. 137 // Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has 138 // processed the request. 139 // If processing this operation results in the session actually closing, 140 // we also call MediaKeySession::OnClosed(), which in turn calls 141 // MediaKeys::OnSessionClosed(). 142 virtual void CloseSession(const nsAString& aSessionId, 143 PromiseId aPromiseId) = 0; 144 145 // Main thread only. 146 // Removes all data for a persisent session. 147 // Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has 148 // processed the request. 149 virtual void RemoveSession(const nsAString& aSessionId, 150 PromiseId aPromiseId) = 0; 151 152 // Main thread only. 153 virtual void Shutdown() = 0; 154 155 // Main thread only. 156 virtual void Terminated() = 0; 157 158 // Threadsafe. 159 virtual const nsCString& GetNodeId() const = 0; 160 161 // Main thread only. 162 virtual void OnSetSessionId(uint32_t aCreateSessionToken, 163 const nsAString& aSessionId) = 0; 164 165 // Main thread only. 166 virtual void OnResolveLoadSessionPromise(uint32_t aPromiseId, 167 bool aSuccess) = 0; 168 169 // Main thread only. 170 virtual void OnSessionMessage(const nsAString& aSessionId, 171 dom::MediaKeyMessageType aMessageType, 172 nsTArray<uint8_t>& aMessage) = 0; 173 174 // Main thread only. 175 virtual void OnExpirationChange(const nsAString& aSessionId, 176 UnixTime aExpiryTime) = 0; 177 178 // Main thread only. 179 virtual void OnSessionClosed(const nsAString& aSessionId) = 0; 180 181 // Main thread only. 182 virtual void OnSessionError(const nsAString& aSessionId, 183 nsresult aException, 184 uint32_t aSystemCode, 185 const nsAString& aMsg) = 0; 186 187 // Main thread only. 188 virtual void OnRejectPromise(uint32_t aPromiseId, 189 nsresult aDOMException, 190 const nsCString& aMsg) = 0; 191 192 virtual RefPtr<DecryptPromise> Decrypt(MediaRawData* aSample) = 0; 193 194 // Owner thread only. 195 virtual void OnDecrypted(uint32_t aId, 196 DecryptStatus aResult, 197 const nsTArray<uint8_t>& aDecryptedData) = 0; 198 199 // Reject promise with DOMException corresponding to aExceptionCode. 200 // Can be called from any thread. 201 virtual void RejectPromise(PromiseId aId, 202 nsresult aExceptionCode, 203 const nsCString& aReason) = 0; 204 205 // Resolves promise with "undefined". 206 // Can be called from any thread. 207 virtual void ResolvePromise(PromiseId aId) = 0; 208 209 // Threadsafe. 210 virtual const nsString& KeySystem() const = 0; 211 212 virtual CDMCaps& Capabilites() = 0; 213 214 // Main thread only. 215 virtual void OnKeyStatusesChange(const nsAString& aSessionId) = 0; 216 217 virtual void GetSessionIdsForKeyId(const nsTArray<uint8_t>& aKeyId, 218 nsTArray<nsCString>& aSessionIds) = 0; 219 220 #ifdef DEBUG 221 virtual bool IsOnOwnerThread() = 0; 222 #endif 223 GetDecryptorId()224 virtual uint32_t GetDecryptorId() { return 0; } 225 226 protected: ~CDMProxy()227 virtual ~CDMProxy() {} 228 229 // Helper to enforce that a raw pointer is only accessed on the main thread. 230 template<class Type> 231 class MainThreadOnlyRawPtr { 232 public: MainThreadOnlyRawPtr(Type * aPtr)233 explicit MainThreadOnlyRawPtr(Type* aPtr) 234 : mPtr(aPtr) 235 { 236 MOZ_ASSERT(NS_IsMainThread()); 237 } 238 IsNull()239 bool IsNull() const { 240 MOZ_ASSERT(NS_IsMainThread()); 241 return !mPtr; 242 } 243 Clear()244 void Clear() { 245 MOZ_ASSERT(NS_IsMainThread()); 246 mPtr = nullptr; 247 } 248 249 Type* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN { 250 MOZ_ASSERT(NS_IsMainThread()); 251 return mPtr; 252 } 253 private: 254 Type* mPtr; 255 }; 256 257 // Our reference back to the MediaKeys object. 258 // WARNING: This is a non-owning reference that is cleared by MediaKeys 259 // destructor. only use on main thread, and always nullcheck before using! 260 MainThreadOnlyRawPtr<dom::MediaKeys> mKeys; 261 262 const nsString mKeySystem; 263 264 // Onwer specified thread. e.g. Gecko Media Plugin thread. 265 // All interactions with the out-of-process EME plugin must come from this thread. 266 RefPtr<nsIThread> mOwnerThread; 267 268 nsCString mNodeId; 269 270 CDMCaps mCapabilites; 271 272 const bool mDistinctiveIdentifierRequired; 273 const bool mPersistentStateRequired; 274 }; 275 276 277 } // namespace mozilla 278 279 #endif // CDMProxy_h_ 280