/src/mozilla-central/dom/media/gmp/ChromiumCDMProxy.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | #include "ChromiumCDMProxy.h" |
8 | | #include "ChromiumCDMCallbackProxy.h" |
9 | | #include "MediaResult.h" |
10 | | #include "mozilla/dom/MediaKeySession.h" |
11 | | #include "GMPUtils.h" |
12 | | #include "nsPrintfCString.h" |
13 | | #include "GMPService.h" |
14 | | #include "content_decryption_module.h" |
15 | | |
16 | | #define NS_DispatchToMainThread(...) CompileError_UseAbstractMainThreadInstead |
17 | | |
18 | | namespace mozilla { |
19 | | |
20 | | ChromiumCDMProxy::ChromiumCDMProxy(dom::MediaKeys* aKeys, |
21 | | const nsAString& aKeySystem, |
22 | | GMPCrashHelper* aCrashHelper, |
23 | | bool aDistinctiveIdentifierRequired, |
24 | | bool aPersistentStateRequired, |
25 | | nsIEventTarget* aMainThread) |
26 | | : CDMProxy(aKeys, |
27 | | aKeySystem, |
28 | | aDistinctiveIdentifierRequired, |
29 | | aPersistentStateRequired, |
30 | | aMainThread) |
31 | | , mCrashHelper(aCrashHelper) |
32 | | , mCDMMutex("ChromiumCDMProxy") |
33 | | , mGMPThread(GetGMPAbstractThread()) |
34 | 0 | { |
35 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
36 | 0 | MOZ_COUNT_CTOR(ChromiumCDMProxy); |
37 | 0 | } |
38 | | |
39 | | ChromiumCDMProxy::~ChromiumCDMProxy() |
40 | 0 | { |
41 | 0 | MOZ_COUNT_DTOR(ChromiumCDMProxy); |
42 | 0 | } |
43 | | |
44 | | void |
45 | | ChromiumCDMProxy::Init(PromiseId aPromiseId, |
46 | | const nsAString& aOrigin, |
47 | | const nsAString& aTopLevelOrigin, |
48 | | const nsAString& aGMPName) |
49 | 0 | { |
50 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
51 | 0 | NS_ENSURE_TRUE_VOID(!mKeys.IsNull()); |
52 | 0 |
|
53 | 0 | EME_LOG( |
54 | 0 | "ChromiumCDMProxy::Init (pid=%u, origin=%s, topLevelOrigin=%s, gmp=%s)", |
55 | 0 | aPromiseId, |
56 | 0 | NS_ConvertUTF16toUTF8(aOrigin).get(), |
57 | 0 | NS_ConvertUTF16toUTF8(aTopLevelOrigin).get(), |
58 | 0 | NS_ConvertUTF16toUTF8(aGMPName).get()); |
59 | 0 |
|
60 | 0 | if (!mGMPThread) { |
61 | 0 | RejectPromise( |
62 | 0 | aPromiseId, |
63 | 0 | NS_ERROR_DOM_INVALID_STATE_ERR, |
64 | 0 | NS_LITERAL_CSTRING("Couldn't get GMP thread ChromiumCDMProxy::Init")); |
65 | 0 | return; |
66 | 0 | } |
67 | 0 |
|
68 | 0 | if (aGMPName.IsEmpty()) { |
69 | 0 | RejectPromise(aPromiseId, |
70 | 0 | NS_ERROR_DOM_INVALID_STATE_ERR, |
71 | 0 | nsPrintfCString("Unknown GMP for keysystem '%s'", |
72 | 0 | NS_ConvertUTF16toUTF8(mKeySystem).get())); |
73 | 0 | return; |
74 | 0 | } |
75 | 0 | |
76 | 0 | gmp::NodeId nodeId(aOrigin, aTopLevelOrigin, aGMPName); |
77 | 0 | RefPtr<AbstractThread> thread = mGMPThread; |
78 | 0 | RefPtr<GMPCrashHelper> helper(mCrashHelper); |
79 | 0 | RefPtr<ChromiumCDMProxy> self(this); |
80 | 0 | nsCString keySystem = NS_ConvertUTF16toUTF8(mKeySystem); |
81 | 0 | RefPtr<Runnable> task(NS_NewRunnableFunction( |
82 | 0 | "ChromiumCDMProxy::Init", |
83 | 0 | [self, nodeId, helper, aPromiseId, thread, keySystem]() -> void { |
84 | 0 | MOZ_ASSERT(self->IsOnOwnerThread()); |
85 | 0 |
|
86 | 0 | RefPtr<gmp::GeckoMediaPluginService> service = |
87 | 0 | gmp::GeckoMediaPluginService::GetGeckoMediaPluginService(); |
88 | 0 | if (!service) { |
89 | 0 | self->RejectPromise( |
90 | 0 | aPromiseId, |
91 | 0 | NS_ERROR_DOM_INVALID_STATE_ERR, |
92 | 0 | NS_LITERAL_CSTRING( |
93 | 0 | "Couldn't get GeckoMediaPluginService in ChromiumCDMProxy::Init")); |
94 | 0 | return; |
95 | 0 | } |
96 | 0 | RefPtr<gmp::GetCDMParentPromise> promise = |
97 | 0 | service->GetCDM(nodeId, { keySystem }, helper); |
98 | 0 | promise->Then( |
99 | 0 | thread, |
100 | 0 | __func__, |
101 | 0 | [self, aPromiseId](RefPtr<gmp::ChromiumCDMParent> cdm) { |
102 | 0 | self->mCallback = |
103 | 0 | MakeUnique<ChromiumCDMCallbackProxy>(self, self->mMainThread); |
104 | 0 | nsCString failureReason; |
105 | 0 | if (!cdm->Init(self->mCallback.get(), |
106 | 0 | self->mDistinctiveIdentifierRequired, |
107 | 0 | self->mPersistentStateRequired, |
108 | 0 | self->mMainThread, |
109 | 0 | failureReason)) { |
110 | 0 | self->RejectPromise(aPromiseId, NS_ERROR_FAILURE, failureReason); |
111 | 0 | return; |
112 | 0 | } |
113 | 0 | { |
114 | 0 | MutexAutoLock lock(self->mCDMMutex); |
115 | 0 | self->mCDM = cdm; |
116 | 0 | } |
117 | 0 | self->OnCDMCreated(aPromiseId); |
118 | 0 | }, |
119 | 0 | [self, aPromiseId](MediaResult rv) { |
120 | 0 | self->RejectPromise( |
121 | 0 | aPromiseId, rv.Code(), rv.Description()); |
122 | 0 | }); |
123 | 0 | })); |
124 | 0 |
|
125 | 0 | mGMPThread->Dispatch(task.forget()); |
126 | 0 | } |
127 | | |
128 | | void |
129 | | ChromiumCDMProxy::OnCDMCreated(uint32_t aPromiseId) |
130 | 0 | { |
131 | 0 | EME_LOG("ChromiumCDMProxy::OnCDMCreated(pid=%u) isMainThread=%d this=%p", |
132 | 0 | aPromiseId, |
133 | 0 | NS_IsMainThread(), |
134 | 0 | this); |
135 | 0 |
|
136 | 0 | if (!NS_IsMainThread()) { |
137 | 0 | mMainThread->Dispatch( |
138 | 0 | NewRunnableMethod<PromiseId>("ChromiumCDMProxy::OnCDMCreated", |
139 | 0 | this, |
140 | 0 | &ChromiumCDMProxy::OnCDMCreated, |
141 | 0 | aPromiseId), |
142 | 0 | NS_DISPATCH_NORMAL); |
143 | 0 | return; |
144 | 0 | } |
145 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
146 | 0 | if (mKeys.IsNull()) { |
147 | 0 | return; |
148 | 0 | } |
149 | 0 | RefPtr<gmp::ChromiumCDMParent> cdm = GetCDMParent(); |
150 | 0 | // This should only be called once the CDM has been created. |
151 | 0 | MOZ_ASSERT(cdm); |
152 | 0 | if (cdm) { |
153 | 0 | mKeys->OnCDMCreated(aPromiseId, cdm->PluginId()); |
154 | 0 | } else { |
155 | 0 | // No CDM? Shouldn't be possible, but reject the promise anyway... |
156 | 0 | mKeys->RejectPromise(aPromiseId, |
157 | 0 | NS_ERROR_DOM_INVALID_STATE_ERR, |
158 | 0 | NS_LITERAL_CSTRING("Null CDM in OnCDMCreated()")); |
159 | 0 | } |
160 | 0 | } |
161 | | |
162 | | #ifdef DEBUG |
163 | | bool |
164 | | ChromiumCDMProxy::IsOnOwnerThread() |
165 | | { |
166 | | return mGMPThread->IsCurrentThreadIn(); |
167 | | } |
168 | | #endif |
169 | | |
170 | | static uint32_t |
171 | | ToCDMSessionType(dom::MediaKeySessionType aSessionType) |
172 | 0 | { |
173 | 0 | switch (aSessionType) { |
174 | 0 | case dom::MediaKeySessionType::Temporary: |
175 | 0 | return static_cast<uint32_t>(cdm::kTemporary); |
176 | 0 | case dom::MediaKeySessionType::Persistent_license: |
177 | 0 | return static_cast<uint32_t>(cdm::kPersistentLicense); |
178 | 0 | default: |
179 | 0 | return static_cast<uint32_t>(cdm::kTemporary); |
180 | 0 | }; |
181 | 0 | }; |
182 | | |
183 | | static uint32_t |
184 | | ToCDMInitDataType(const nsAString& aInitDataType) |
185 | 0 | { |
186 | 0 | if (aInitDataType.EqualsLiteral("cenc")) { |
187 | 0 | return static_cast<uint32_t>(cdm::kCenc); |
188 | 0 | } |
189 | 0 | if (aInitDataType.EqualsLiteral("webm")) { |
190 | 0 | return static_cast<uint32_t>(cdm::kWebM); |
191 | 0 | } |
192 | 0 | if (aInitDataType.EqualsLiteral("keyids")) { |
193 | 0 | return static_cast<uint32_t>(cdm::kKeyIds); |
194 | 0 | } |
195 | 0 | return static_cast<uint32_t>(cdm::kCenc); |
196 | 0 | } |
197 | | |
198 | | void |
199 | | ChromiumCDMProxy::CreateSession(uint32_t aCreateSessionToken, |
200 | | dom::MediaKeySessionType aSessionType, |
201 | | PromiseId aPromiseId, |
202 | | const nsAString& aInitDataType, |
203 | | nsTArray<uint8_t>& aInitData) |
204 | 0 | { |
205 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
206 | 0 | EME_LOG("ChromiumCDMProxy::CreateSession(token=%u, type=%d, pid=%u) " |
207 | 0 | "initDataLen=%zu", |
208 | 0 | aCreateSessionToken, |
209 | 0 | (int)aSessionType, |
210 | 0 | aPromiseId, |
211 | 0 | aInitData.Length()); |
212 | 0 |
|
213 | 0 | uint32_t sessionType = ToCDMSessionType(aSessionType); |
214 | 0 | uint32_t initDataType = ToCDMInitDataType(aInitDataType); |
215 | 0 |
|
216 | 0 | RefPtr<gmp::ChromiumCDMParent> cdm = GetCDMParent(); |
217 | 0 | if (!cdm) { |
218 | 0 | RejectPromise(aPromiseId, |
219 | 0 | NS_ERROR_DOM_INVALID_STATE_ERR, |
220 | 0 | NS_LITERAL_CSTRING("Null CDM in CreateSession")); |
221 | 0 | return; |
222 | 0 | } |
223 | 0 |
|
224 | 0 | mGMPThread->Dispatch(NewRunnableMethod<uint32_t, |
225 | 0 | uint32_t, |
226 | 0 | uint32_t, |
227 | 0 | uint32_t, |
228 | 0 | nsTArray<uint8_t>>( |
229 | 0 | "gmp::ChromiumCDMParent::CreateSession", |
230 | 0 | cdm, |
231 | 0 | &gmp::ChromiumCDMParent::CreateSession, |
232 | 0 | aCreateSessionToken, |
233 | 0 | sessionType, |
234 | 0 | initDataType, |
235 | 0 | aPromiseId, |
236 | 0 | std::move(aInitData))); |
237 | 0 | } |
238 | | |
239 | | void |
240 | | ChromiumCDMProxy::LoadSession(PromiseId aPromiseId, |
241 | | dom::MediaKeySessionType aSessionType, |
242 | | const nsAString& aSessionId) |
243 | 0 | { |
244 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
245 | 0 |
|
246 | 0 | RefPtr<gmp::ChromiumCDMParent> cdm = GetCDMParent(); |
247 | 0 | if (!cdm) { |
248 | 0 | RejectPromise(aPromiseId, |
249 | 0 | NS_ERROR_DOM_INVALID_STATE_ERR, |
250 | 0 | NS_LITERAL_CSTRING("Null CDM in LoadSession")); |
251 | 0 | return; |
252 | 0 | } |
253 | 0 |
|
254 | 0 | mGMPThread->Dispatch(NewRunnableMethod<uint32_t, uint32_t, nsString>( |
255 | 0 | "gmp::ChromiumCDMParent::LoadSession", |
256 | 0 | cdm, |
257 | 0 | &gmp::ChromiumCDMParent::LoadSession, |
258 | 0 | aPromiseId, |
259 | 0 | ToCDMSessionType(aSessionType), |
260 | 0 | aSessionId)); |
261 | 0 | } |
262 | | |
263 | | void |
264 | | ChromiumCDMProxy::SetServerCertificate(PromiseId aPromiseId, |
265 | | nsTArray<uint8_t>& aCert) |
266 | 0 | { |
267 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
268 | 0 | EME_LOG("ChromiumCDMProxy::SetServerCertificate(pid=%u) certLen=%zu", |
269 | 0 | aPromiseId, |
270 | 0 | aCert.Length()); |
271 | 0 |
|
272 | 0 | RefPtr<gmp::ChromiumCDMParent> cdm = GetCDMParent(); |
273 | 0 | if (!cdm) { |
274 | 0 | RejectPromise(aPromiseId, |
275 | 0 | NS_ERROR_DOM_INVALID_STATE_ERR, |
276 | 0 | NS_LITERAL_CSTRING("Null CDM in SetServerCertificate")); |
277 | 0 | return; |
278 | 0 | } |
279 | 0 |
|
280 | 0 | mGMPThread->Dispatch(NewRunnableMethod<uint32_t, nsTArray<uint8_t>>( |
281 | 0 | "gmp::ChromiumCDMParent::SetServerCertificate", |
282 | 0 | cdm, |
283 | 0 | &gmp::ChromiumCDMParent::SetServerCertificate, |
284 | 0 | aPromiseId, |
285 | 0 | std::move(aCert))); |
286 | 0 | } |
287 | | |
288 | | void |
289 | | ChromiumCDMProxy::UpdateSession(const nsAString& aSessionId, |
290 | | PromiseId aPromiseId, |
291 | | nsTArray<uint8_t>& aResponse) |
292 | 0 | { |
293 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
294 | 0 | EME_LOG("ChromiumCDMProxy::UpdateSession(sid='%s', pid=%u) responseLen=%zu", |
295 | 0 | NS_ConvertUTF16toUTF8(aSessionId).get(), |
296 | 0 | aPromiseId, |
297 | 0 | aResponse.Length()); |
298 | 0 |
|
299 | 0 | RefPtr<gmp::ChromiumCDMParent> cdm = GetCDMParent(); |
300 | 0 | if (!cdm) { |
301 | 0 | RejectPromise(aPromiseId, |
302 | 0 | NS_ERROR_DOM_INVALID_STATE_ERR, |
303 | 0 | NS_LITERAL_CSTRING("Null CDM in UpdateSession")); |
304 | 0 | return; |
305 | 0 | } |
306 | 0 | mGMPThread->Dispatch( |
307 | 0 | NewRunnableMethod<nsCString, uint32_t, nsTArray<uint8_t>>( |
308 | 0 | "gmp::ChromiumCDMParent::UpdateSession", |
309 | 0 | cdm, |
310 | 0 | &gmp::ChromiumCDMParent::UpdateSession, |
311 | 0 | NS_ConvertUTF16toUTF8(aSessionId), |
312 | 0 | aPromiseId, |
313 | 0 | std::move(aResponse))); |
314 | 0 | } |
315 | | |
316 | | void |
317 | | ChromiumCDMProxy::CloseSession(const nsAString& aSessionId, |
318 | | PromiseId aPromiseId) |
319 | 0 | { |
320 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
321 | 0 | EME_LOG("ChromiumCDMProxy::CloseSession(sid='%s', pid=%u)", |
322 | 0 | NS_ConvertUTF16toUTF8(aSessionId).get(), |
323 | 0 | aPromiseId); |
324 | 0 |
|
325 | 0 | RefPtr<gmp::ChromiumCDMParent> cdm = GetCDMParent(); |
326 | 0 | if (!cdm) { |
327 | 0 | RejectPromise(aPromiseId, |
328 | 0 | NS_ERROR_DOM_INVALID_STATE_ERR, |
329 | 0 | NS_LITERAL_CSTRING("Null CDM in CloseSession")); |
330 | 0 | return; |
331 | 0 | } |
332 | 0 | mGMPThread->Dispatch(NewRunnableMethod<nsCString, uint32_t>( |
333 | 0 | "gmp::ChromiumCDMParent::CloseSession", |
334 | 0 | cdm, |
335 | 0 | &gmp::ChromiumCDMParent::CloseSession, |
336 | 0 | NS_ConvertUTF16toUTF8(aSessionId), |
337 | 0 | aPromiseId)); |
338 | 0 | } |
339 | | |
340 | | void |
341 | | ChromiumCDMProxy::RemoveSession(const nsAString& aSessionId, |
342 | | PromiseId aPromiseId) |
343 | 0 | { |
344 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
345 | 0 | EME_LOG("ChromiumCDMProxy::RemoveSession(sid='%s', pid=%u)", |
346 | 0 | NS_ConvertUTF16toUTF8(aSessionId).get(), |
347 | 0 | aPromiseId); |
348 | 0 |
|
349 | 0 | RefPtr<gmp::ChromiumCDMParent> cdm = GetCDMParent(); |
350 | 0 | if (!cdm) { |
351 | 0 | RejectPromise(aPromiseId, |
352 | 0 | NS_ERROR_DOM_INVALID_STATE_ERR, |
353 | 0 | NS_LITERAL_CSTRING("Null CDM in RemoveSession")); |
354 | 0 | return; |
355 | 0 | } |
356 | 0 | mGMPThread->Dispatch(NewRunnableMethod<nsCString, uint32_t>( |
357 | 0 | "gmp::ChromiumCDMParent::RemoveSession", |
358 | 0 | cdm, |
359 | 0 | &gmp::ChromiumCDMParent::RemoveSession, |
360 | 0 | NS_ConvertUTF16toUTF8(aSessionId), |
361 | 0 | aPromiseId)); |
362 | 0 | } |
363 | | |
364 | | void |
365 | | ChromiumCDMProxy::Shutdown() |
366 | 0 | { |
367 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
368 | 0 | EME_LOG("ChromiumCDMProxy::Shutdown()"); |
369 | 0 | mKeys.Clear(); |
370 | 0 | RefPtr<gmp::ChromiumCDMParent> cdm; |
371 | 0 | { |
372 | 0 | MutexAutoLock lock(mCDMMutex); |
373 | 0 | cdm.swap(mCDM); |
374 | 0 | } |
375 | 0 | if (cdm) { |
376 | 0 | // We need to keep this proxy alive until the parent has finished its |
377 | 0 | // Shutdown (as it may still try to use the proxy until then). |
378 | 0 | RefPtr<ChromiumCDMProxy> self(this); |
379 | 0 | nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction( |
380 | 0 | "ChromiumCDMProxy::Shutdown", [self, cdm]() { cdm->Shutdown(); }); |
381 | 0 | mGMPThread->Dispatch(task.forget()); |
382 | 0 | } |
383 | 0 | } |
384 | | |
385 | | void |
386 | | ChromiumCDMProxy::RejectPromise(PromiseId aId, |
387 | | nsresult aCode, |
388 | | const nsCString& aReason) |
389 | 0 | { |
390 | 0 | if (!NS_IsMainThread()) { |
391 | 0 | mMainThread->Dispatch( |
392 | 0 | NewRunnableMethod<PromiseId, nsresult, nsCString>( |
393 | 0 | "ChromiumCDMProxy::RejectPromise", |
394 | 0 | this, |
395 | 0 | &ChromiumCDMProxy::RejectPromise, |
396 | 0 | aId, |
397 | 0 | aCode, |
398 | 0 | aReason), |
399 | 0 | NS_DISPATCH_NORMAL); |
400 | 0 | return; |
401 | 0 | } |
402 | 0 | EME_LOG("ChromiumCDMProxy::RejectPromise(pid=%u, code=0x%x, reason='%s')", |
403 | 0 | aId, |
404 | 0 | static_cast<uint32_t>(aCode), |
405 | 0 | aReason.get()); |
406 | 0 | if (!mKeys.IsNull()) { |
407 | 0 | mKeys->RejectPromise(aId, aCode, aReason); |
408 | 0 | } |
409 | 0 | } |
410 | | |
411 | | void |
412 | | ChromiumCDMProxy::ResolvePromise(PromiseId aId) |
413 | 0 | { |
414 | 0 | if (!NS_IsMainThread()) { |
415 | 0 | mMainThread->Dispatch( |
416 | 0 | NewRunnableMethod<PromiseId>("ChromiumCDMProxy::ResolvePromise", |
417 | 0 | this, |
418 | 0 | &ChromiumCDMProxy::ResolvePromise, |
419 | 0 | aId), |
420 | 0 | NS_DISPATCH_NORMAL); |
421 | 0 | return; |
422 | 0 | } |
423 | 0 |
|
424 | 0 | EME_LOG("ChromiumCDMProxy::ResolvePromise(pid=%u)", aId); |
425 | 0 | if (!mKeys.IsNull()) { |
426 | 0 | mKeys->ResolvePromise(aId); |
427 | 0 | } else { |
428 | 0 | NS_WARNING("ChromiumCDMProxy unable to resolve promise!"); |
429 | 0 | } |
430 | 0 | } |
431 | | |
432 | | const nsCString& |
433 | | ChromiumCDMProxy::GetNodeId() const |
434 | 0 | { |
435 | 0 | return mNodeId; |
436 | 0 | } |
437 | | |
438 | | void |
439 | | ChromiumCDMProxy::OnSetSessionId(uint32_t aCreateSessionToken, |
440 | | const nsAString& aSessionId) |
441 | 0 | { |
442 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
443 | 0 | EME_LOG("ChromiumCDMProxy::OnSetSessionId(token=%u, sid='%s')", |
444 | 0 | aCreateSessionToken, |
445 | 0 | NS_ConvertUTF16toUTF8(aSessionId).get()); |
446 | 0 |
|
447 | 0 | if (mKeys.IsNull()) { |
448 | 0 | return; |
449 | 0 | } |
450 | 0 | RefPtr<dom::MediaKeySession> session( |
451 | 0 | mKeys->GetPendingSession(aCreateSessionToken)); |
452 | 0 | if (session) { |
453 | 0 | session->SetSessionId(aSessionId); |
454 | 0 | } |
455 | 0 | } |
456 | | |
457 | | void |
458 | | ChromiumCDMProxy::OnResolveLoadSessionPromise(uint32_t aPromiseId, |
459 | | bool aSuccess) |
460 | 0 | { |
461 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
462 | 0 | if (mKeys.IsNull()) { |
463 | 0 | return; |
464 | 0 | } |
465 | 0 | mKeys->OnSessionLoaded(aPromiseId, aSuccess); |
466 | 0 | } |
467 | | |
468 | | void |
469 | | ChromiumCDMProxy::OnResolvePromiseWithKeyStatus(uint32_t aPromiseId, |
470 | | dom::MediaKeyStatus aKeyStatus) |
471 | 0 | { |
472 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
473 | 0 | if (mKeys.IsNull()) { |
474 | 0 | return; |
475 | 0 | } |
476 | 0 | mKeys->ResolvePromiseWithKeyStatus(aPromiseId, aKeyStatus); |
477 | 0 | } |
478 | | |
479 | | void |
480 | | ChromiumCDMProxy::OnSessionMessage(const nsAString& aSessionId, |
481 | | dom::MediaKeyMessageType aMessageType, |
482 | | const nsTArray<uint8_t>& aMessage) |
483 | 0 | { |
484 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
485 | 0 | if (mKeys.IsNull()) { |
486 | 0 | return; |
487 | 0 | } |
488 | 0 | RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId)); |
489 | 0 | if (session) { |
490 | 0 | session->DispatchKeyMessage(aMessageType, aMessage); |
491 | 0 | } |
492 | 0 | } |
493 | | |
494 | | void |
495 | | ChromiumCDMProxy::OnKeyStatusesChange(const nsAString& aSessionId) |
496 | 0 | { |
497 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
498 | 0 | if (mKeys.IsNull()) { |
499 | 0 | return; |
500 | 0 | } |
501 | 0 | RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId)); |
502 | 0 | if (session) { |
503 | 0 | session->DispatchKeyStatusesChange(); |
504 | 0 | } |
505 | 0 | } |
506 | | |
507 | | void |
508 | | ChromiumCDMProxy::OnExpirationChange(const nsAString& aSessionId, |
509 | | UnixTime aExpiryTime) |
510 | 0 | { |
511 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
512 | 0 | if (mKeys.IsNull()) { |
513 | 0 | return; |
514 | 0 | } |
515 | 0 | RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId)); |
516 | 0 | if (session) { |
517 | 0 | // Expiry of 0 is interpreted as "never expire". See bug 1345341. |
518 | 0 | double t = (aExpiryTime == 0) ? std::numeric_limits<double>::quiet_NaN() |
519 | 0 | : static_cast<double>(aExpiryTime); |
520 | 0 | session->SetExpiration(t); |
521 | 0 | } |
522 | 0 | } |
523 | | |
524 | | void |
525 | | ChromiumCDMProxy::OnSessionClosed(const nsAString& aSessionId) |
526 | 0 | { |
527 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
528 | 0 |
|
529 | 0 | bool keyStatusesChange = false; |
530 | 0 | { |
531 | 0 | auto caps = Capabilites().Lock(); |
532 | 0 | keyStatusesChange = caps->RemoveKeysForSession(nsString(aSessionId)); |
533 | 0 | } |
534 | 0 | if (keyStatusesChange) { |
535 | 0 | OnKeyStatusesChange(aSessionId); |
536 | 0 | } |
537 | 0 | if (mKeys.IsNull()) { |
538 | 0 | return; |
539 | 0 | } |
540 | 0 | RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId)); |
541 | 0 | if (session) { |
542 | 0 | session->OnClosed(); |
543 | 0 | } |
544 | 0 | } |
545 | | |
546 | | void |
547 | | ChromiumCDMProxy::OnDecrypted(uint32_t aId, |
548 | | DecryptStatus aResult, |
549 | | const nsTArray<uint8_t>& aDecryptedData) |
550 | 0 | { |
551 | 0 | } |
552 | | |
553 | | void |
554 | | ChromiumCDMProxy::OnSessionError(const nsAString& aSessionId, |
555 | | nsresult aException, |
556 | | uint32_t aSystemCode, |
557 | | const nsAString& aMsg) |
558 | 0 | { |
559 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
560 | 0 | if (mKeys.IsNull()) { |
561 | 0 | return; |
562 | 0 | } |
563 | 0 | RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId)); |
564 | 0 | if (session) { |
565 | 0 | session->DispatchKeyError(aSystemCode); |
566 | 0 | } |
567 | 0 | LogToConsole(aMsg); |
568 | 0 | } |
569 | | |
570 | | void |
571 | | ChromiumCDMProxy::OnRejectPromise(uint32_t aPromiseId, |
572 | | nsresult aDOMException, |
573 | | const nsCString& aMsg) |
574 | 0 | { |
575 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
576 | 0 | RejectPromise(aPromiseId, aDOMException, aMsg); |
577 | 0 | } |
578 | | |
579 | | const nsString& |
580 | | ChromiumCDMProxy::KeySystem() const |
581 | 0 | { |
582 | 0 | return mKeySystem; |
583 | 0 | } |
584 | | |
585 | | DataMutex<CDMCaps>& |
586 | | ChromiumCDMProxy::Capabilites() |
587 | 0 | { |
588 | 0 | return mCapabilites; |
589 | 0 | } |
590 | | |
591 | | RefPtr<DecryptPromise> |
592 | | ChromiumCDMProxy::Decrypt(MediaRawData* aSample) |
593 | 0 | { |
594 | 0 | RefPtr<gmp::ChromiumCDMParent> cdm = GetCDMParent(); |
595 | 0 | if (!cdm) { |
596 | 0 | return DecryptPromise::CreateAndReject(DecryptResult(eme::AbortedErr, aSample), |
597 | 0 | __func__); |
598 | 0 | } |
599 | 0 | RefPtr<MediaRawData> sample = aSample; |
600 | 0 | return InvokeAsync( |
601 | 0 | mGMPThread, __func__, [cdm, sample]() { return cdm->Decrypt(sample); }); |
602 | 0 | } |
603 | | |
604 | | void |
605 | | ChromiumCDMProxy::GetStatusForPolicy(PromiseId aPromiseId, |
606 | | const nsAString& aMinHdcpVersion) |
607 | 0 | { |
608 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
609 | 0 | EME_LOG("ChromiumCDMProxy::GetStatusForPolicy(pid=%u) minHdcpVersion=%s", |
610 | 0 | aPromiseId, |
611 | 0 | NS_ConvertUTF16toUTF8(aMinHdcpVersion).get()); |
612 | 0 |
|
613 | 0 | RefPtr<gmp::ChromiumCDMParent> cdm = GetCDMParent(); |
614 | 0 | if (!cdm) { |
615 | 0 | RejectPromise(aPromiseId, |
616 | 0 | NS_ERROR_DOM_INVALID_STATE_ERR, |
617 | 0 | NS_LITERAL_CSTRING("Null CDM in GetStatusForPolicy")); |
618 | 0 | return; |
619 | 0 | } |
620 | 0 |
|
621 | 0 | mGMPThread->Dispatch(NewRunnableMethod<uint32_t, nsCString>( |
622 | 0 | "gmp::ChromiumCDMParent::GetStatusForPolicy", |
623 | 0 | cdm, |
624 | 0 | &gmp::ChromiumCDMParent::GetStatusForPolicy, |
625 | 0 | aPromiseId, |
626 | 0 | NS_ConvertUTF16toUTF8(aMinHdcpVersion))); |
627 | 0 | } |
628 | | |
629 | | void |
630 | | ChromiumCDMProxy::Terminated() |
631 | 0 | { |
632 | 0 | if (!mKeys.IsNull()) { |
633 | 0 | mKeys->Terminated(); |
634 | 0 | } |
635 | 0 | } |
636 | | |
637 | | already_AddRefed<gmp::ChromiumCDMParent> |
638 | | ChromiumCDMProxy::GetCDMParent() |
639 | 0 | { |
640 | 0 | MutexAutoLock lock(mCDMMutex); |
641 | 0 | RefPtr<gmp::ChromiumCDMParent> cdm = mCDM; |
642 | 0 | return cdm.forget(); |
643 | 0 | } |
644 | | |
645 | | } // namespace mozilla |
646 | | |
647 | | #undef NS_DispatchToMainThread |