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