OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/mojo/clients/mojo_cdm.h" | 5 #include "media/mojo/clients/mojo_cdm.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/bind_helpers.h" | 12 #include "base/bind_helpers.h" |
13 #include "base/location.h" | 13 #include "base/location.h" |
14 #include "base/single_thread_task_runner.h" | 14 #include "base/single_thread_task_runner.h" |
15 #include "base/threading/thread_task_runner_handle.h" | 15 #include "base/threading/thread_task_runner_handle.h" |
16 #include "media/base/cdm_context.h" | 16 #include "media/base/cdm_context.h" |
17 #include "media/base/cdm_key_information.h" | 17 #include "media/base/cdm_key_information.h" |
18 #include "media/base/cdm_promise.h" | 18 #include "media/base/cdm_promise.h" |
19 #include "media/mojo/clients/mojo_decryptor.h" | 19 #include "media/mojo/clients/mojo_decryptor.h" |
20 #include "media/mojo/common/media_type_converters.h" | 20 #include "media/mojo/common/media_type_converters.h" |
21 #include "media/mojo/interfaces/decryptor.mojom.h" | 21 #include "media/mojo/interfaces/decryptor.mojom.h" |
22 #include "services/service_manager/public/cpp/connect.h" | 22 #include "services/service_manager/public/cpp/connect.h" |
23 #include "services/service_manager/public/interfaces/interface_provider.mojom.h" | 23 #include "services/service_manager/public/interfaces/interface_provider.mojom.h" |
24 #include "url/gurl.h" | 24 #include "url/gurl.h" |
25 | 25 |
26 namespace media { | 26 namespace media { |
27 | 27 |
28 template <typename PromiseType> | |
29 static void RejectPromise(std::unique_ptr<PromiseType> promise, | |
30 mojom::CdmPromiseResultPtr result) { | |
31 promise->reject(result->exception, result->system_code, | |
32 result->error_message); | |
33 } | |
34 | |
35 // static | 28 // static |
36 void MojoCdm::Create( | 29 void MojoCdm::Create( |
37 const std::string& key_system, | 30 const std::string& key_system, |
38 const GURL& security_origin, | 31 const GURL& security_origin, |
39 const CdmConfig& cdm_config, | 32 const CdmConfig& cdm_config, |
40 mojom::ContentDecryptionModulePtr remote_cdm, | 33 mojom::ContentDecryptionModulePtr remote_cdm, |
41 const SessionMessageCB& session_message_cb, | 34 const SessionMessageCB& session_message_cb, |
42 const SessionClosedCB& session_closed_cb, | 35 const SessionClosedCB& session_closed_cb, |
43 const SessionKeysChangeCB& session_keys_change_cb, | 36 const SessionKeysChangeCB& session_keys_change_cb, |
44 const SessionExpirationUpdateCB& session_expiration_update_cb, | 37 const SessionExpirationUpdateCB& session_expiration_update_cb, |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 // Handle initial connection error. | 126 // Handle initial connection error. |
134 if (pending_init_promise_) { | 127 if (pending_init_promise_) { |
135 DCHECK(!cdm_session_tracker_.HasRemainingSessions()); | 128 DCHECK(!cdm_session_tracker_.HasRemainingSessions()); |
136 pending_init_promise_->reject(CdmPromise::NOT_SUPPORTED_ERROR, 0, | 129 pending_init_promise_->reject(CdmPromise::NOT_SUPPORTED_ERROR, 0, |
137 "Mojo CDM creation failed."); | 130 "Mojo CDM creation failed."); |
138 // Dropping the promise could cause |this| to be destructed. | 131 // Dropping the promise could cause |this| to be destructed. |
139 pending_init_promise_.reset(); | 132 pending_init_promise_.reset(); |
140 return; | 133 return; |
141 } | 134 } |
142 | 135 |
| 136 // As communication with the remote CDM is broken, reject any outstanding |
| 137 // promises and close all the existing sessions. |
| 138 cdm_promise_adapter_.Clear(); |
143 cdm_session_tracker_.CloseRemainingSessions(session_closed_cb_); | 139 cdm_session_tracker_.CloseRemainingSessions(session_closed_cb_); |
144 } | 140 } |
145 | 141 |
146 void MojoCdm::SetServerCertificate(const std::vector<uint8_t>& certificate, | 142 void MojoCdm::SetServerCertificate(const std::vector<uint8_t>& certificate, |
147 std::unique_ptr<SimpleCdmPromise> promise) { | 143 std::unique_ptr<SimpleCdmPromise> promise) { |
148 DVLOG(2) << __func__; | 144 DVLOG(2) << __func__; |
149 DCHECK(thread_checker_.CalledOnValidThread()); | 145 DCHECK(thread_checker_.CalledOnValidThread()); |
150 | 146 |
151 if (!remote_cdm_) { | 147 if (!remote_cdm_) { |
152 promise->reject(media::CdmPromise::INVALID_STATE_ERROR, 0, | 148 promise->reject(media::CdmPromise::INVALID_STATE_ERROR, 0, |
153 "CDM connection lost."); | 149 "CDM connection lost."); |
154 return; | 150 return; |
155 } | 151 } |
156 | 152 |
| 153 uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise)); |
157 remote_cdm_->SetServerCertificate( | 154 remote_cdm_->SetServerCertificate( |
158 certificate, base::Bind(&MojoCdm::OnSimpleCdmPromiseResult, | 155 certificate, base::Bind(&MojoCdm::OnSimpleCdmPromiseResult, |
159 base::Unretained(this), base::Passed(&promise))); | 156 base::Unretained(this), promise_id)); |
160 } | 157 } |
161 | 158 |
162 void MojoCdm::CreateSessionAndGenerateRequest( | 159 void MojoCdm::CreateSessionAndGenerateRequest( |
163 CdmSessionType session_type, | 160 CdmSessionType session_type, |
164 EmeInitDataType init_data_type, | 161 EmeInitDataType init_data_type, |
165 const std::vector<uint8_t>& init_data, | 162 const std::vector<uint8_t>& init_data, |
166 std::unique_ptr<NewSessionCdmPromise> promise) { | 163 std::unique_ptr<NewSessionCdmPromise> promise) { |
167 DVLOG(2) << __func__; | 164 DVLOG(2) << __func__; |
168 DCHECK(thread_checker_.CalledOnValidThread()); | 165 DCHECK(thread_checker_.CalledOnValidThread()); |
169 | 166 |
170 if (!remote_cdm_) { | 167 if (!remote_cdm_) { |
171 promise->reject(media::CdmPromise::INVALID_STATE_ERROR, 0, | 168 promise->reject(media::CdmPromise::INVALID_STATE_ERROR, 0, |
172 "CDM connection lost."); | 169 "CDM connection lost."); |
173 return; | 170 return; |
174 } | 171 } |
175 | 172 |
| 173 uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise)); |
176 remote_cdm_->CreateSessionAndGenerateRequest( | 174 remote_cdm_->CreateSessionAndGenerateRequest( |
177 session_type, init_data_type, init_data, | 175 session_type, init_data_type, init_data, |
178 base::Bind(&MojoCdm::OnNewSessionCdmPromiseResult, base::Unretained(this), | 176 base::Bind(&MojoCdm::OnNewSessionCdmPromiseResult, base::Unretained(this), |
179 base::Passed(&promise))); | 177 promise_id)); |
180 } | 178 } |
181 | 179 |
182 void MojoCdm::LoadSession(CdmSessionType session_type, | 180 void MojoCdm::LoadSession(CdmSessionType session_type, |
183 const std::string& session_id, | 181 const std::string& session_id, |
184 std::unique_ptr<NewSessionCdmPromise> promise) { | 182 std::unique_ptr<NewSessionCdmPromise> promise) { |
185 DVLOG(2) << __func__; | 183 DVLOG(2) << __func__; |
186 DCHECK(thread_checker_.CalledOnValidThread()); | 184 DCHECK(thread_checker_.CalledOnValidThread()); |
187 | 185 |
188 if (!remote_cdm_) { | 186 if (!remote_cdm_) { |
189 promise->reject(media::CdmPromise::INVALID_STATE_ERROR, 0, | 187 promise->reject(media::CdmPromise::INVALID_STATE_ERROR, 0, |
190 "CDM connection lost."); | 188 "CDM connection lost."); |
191 return; | 189 return; |
192 } | 190 } |
193 | 191 |
194 remote_cdm_->LoadSession( | 192 uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise)); |
195 session_type, session_id, | 193 remote_cdm_->LoadSession(session_type, session_id, |
196 base::Bind(&MojoCdm::OnNewSessionCdmPromiseResult, base::Unretained(this), | 194 base::Bind(&MojoCdm::OnNewSessionCdmPromiseResult, |
197 base::Passed(&promise))); | 195 base::Unretained(this), promise_id)); |
198 } | 196 } |
199 | 197 |
200 void MojoCdm::UpdateSession(const std::string& session_id, | 198 void MojoCdm::UpdateSession(const std::string& session_id, |
201 const std::vector<uint8_t>& response, | 199 const std::vector<uint8_t>& response, |
202 std::unique_ptr<SimpleCdmPromise> promise) { | 200 std::unique_ptr<SimpleCdmPromise> promise) { |
203 DVLOG(2) << __func__; | 201 DVLOG(2) << __func__; |
204 DCHECK(thread_checker_.CalledOnValidThread()); | 202 DCHECK(thread_checker_.CalledOnValidThread()); |
205 | 203 |
206 if (!remote_cdm_) { | 204 if (!remote_cdm_) { |
207 promise->reject(media::CdmPromise::INVALID_STATE_ERROR, 0, | 205 promise->reject(media::CdmPromise::INVALID_STATE_ERROR, 0, |
208 "CDM connection lost."); | 206 "CDM connection lost."); |
209 return; | 207 return; |
210 } | 208 } |
211 | 209 |
212 remote_cdm_->UpdateSession( | 210 uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise)); |
213 session_id, response, | 211 remote_cdm_->UpdateSession(session_id, response, |
214 base::Bind(&MojoCdm::OnSimpleCdmPromiseResult, base::Unretained(this), | 212 base::Bind(&MojoCdm::OnSimpleCdmPromiseResult, |
215 base::Passed(&promise))); | 213 base::Unretained(this), promise_id)); |
216 } | 214 } |
217 | 215 |
218 void MojoCdm::CloseSession(const std::string& session_id, | 216 void MojoCdm::CloseSession(const std::string& session_id, |
219 std::unique_ptr<SimpleCdmPromise> promise) { | 217 std::unique_ptr<SimpleCdmPromise> promise) { |
220 DVLOG(2) << __func__; | 218 DVLOG(2) << __func__; |
221 DCHECK(thread_checker_.CalledOnValidThread()); | 219 DCHECK(thread_checker_.CalledOnValidThread()); |
222 | 220 |
223 if (!remote_cdm_) { | 221 if (!remote_cdm_) { |
224 promise->reject(media::CdmPromise::INVALID_STATE_ERROR, 0, | 222 promise->reject(media::CdmPromise::INVALID_STATE_ERROR, 0, |
225 "CDM connection lost."); | 223 "CDM connection lost."); |
226 return; | 224 return; |
227 } | 225 } |
228 | 226 |
229 remote_cdm_->CloseSession( | 227 uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise)); |
230 session_id, base::Bind(&MojoCdm::OnSimpleCdmPromiseResult, | 228 remote_cdm_->CloseSession(session_id, |
231 base::Unretained(this), base::Passed(&promise))); | 229 base::Bind(&MojoCdm::OnSimpleCdmPromiseResult, |
| 230 base::Unretained(this), promise_id)); |
232 } | 231 } |
233 | 232 |
234 void MojoCdm::RemoveSession(const std::string& session_id, | 233 void MojoCdm::RemoveSession(const std::string& session_id, |
235 std::unique_ptr<SimpleCdmPromise> promise) { | 234 std::unique_ptr<SimpleCdmPromise> promise) { |
236 DVLOG(2) << __func__; | 235 DVLOG(2) << __func__; |
237 DCHECK(thread_checker_.CalledOnValidThread()); | 236 DCHECK(thread_checker_.CalledOnValidThread()); |
238 | 237 |
239 if (!remote_cdm_) { | 238 if (!remote_cdm_) { |
240 promise->reject(media::CdmPromise::INVALID_STATE_ERROR, 0, | 239 promise->reject(media::CdmPromise::INVALID_STATE_ERROR, 0, |
241 "CDM connection lost."); | 240 "CDM connection lost."); |
242 return; | 241 return; |
243 } | 242 } |
244 | 243 |
245 remote_cdm_->RemoveSession( | 244 uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise)); |
246 session_id, base::Bind(&MojoCdm::OnSimpleCdmPromiseResult, | 245 remote_cdm_->RemoveSession(session_id, |
247 base::Unretained(this), base::Passed(&promise))); | 246 base::Bind(&MojoCdm::OnSimpleCdmPromiseResult, |
| 247 base::Unretained(this), promise_id)); |
248 } | 248 } |
249 | 249 |
250 CdmContext* MojoCdm::GetCdmContext() { | 250 CdmContext* MojoCdm::GetCdmContext() { |
251 DVLOG(2) << __func__; | 251 DVLOG(2) << __func__; |
252 return this; | 252 return this; |
253 } | 253 } |
254 | 254 |
255 Decryptor* MojoCdm::GetDecryptor() { | 255 Decryptor* MojoCdm::GetDecryptor() { |
256 base::AutoLock auto_lock(lock_); | 256 base::AutoLock auto_lock(lock_); |
257 | 257 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 } | 334 } |
335 | 335 |
336 void MojoCdm::OnCdmInitialized(mojom::CdmPromiseResultPtr result, | 336 void MojoCdm::OnCdmInitialized(mojom::CdmPromiseResultPtr result, |
337 int cdm_id, | 337 int cdm_id, |
338 mojom::DecryptorPtr decryptor) { | 338 mojom::DecryptorPtr decryptor) { |
339 DVLOG(2) << __func__ << " cdm_id: " << cdm_id; | 339 DVLOG(2) << __func__ << " cdm_id: " << cdm_id; |
340 DCHECK(thread_checker_.CalledOnValidThread()); | 340 DCHECK(thread_checker_.CalledOnValidThread()); |
341 DCHECK(pending_init_promise_); | 341 DCHECK(pending_init_promise_); |
342 | 342 |
343 if (!result->success) { | 343 if (!result->success) { |
344 RejectPromise(std::move(pending_init_promise_), std::move(result)); | 344 pending_init_promise_->reject(result->exception, result->system_code, |
| 345 result->error_message); |
| 346 pending_init_promise_.reset(); |
345 return; | 347 return; |
346 } | 348 } |
347 | 349 |
348 { | 350 { |
349 base::AutoLock auto_lock(lock_); | 351 base::AutoLock auto_lock(lock_); |
350 DCHECK_NE(CdmContext::kInvalidCdmId, cdm_id); | 352 DCHECK_NE(CdmContext::kInvalidCdmId, cdm_id); |
351 cdm_id_ = cdm_id; | 353 cdm_id_ = cdm_id; |
352 decryptor_ptr_info_ = decryptor.PassInterface(); | 354 decryptor_ptr_info_ = decryptor.PassInterface(); |
353 } | 355 } |
354 | 356 |
355 pending_init_promise_->resolve(); | 357 pending_init_promise_->resolve(); |
356 pending_init_promise_.reset(); | 358 pending_init_promise_.reset(); |
357 } | 359 } |
358 | 360 |
359 void MojoCdm::OnKeyAdded() { | 361 void MojoCdm::OnKeyAdded() { |
360 base::AutoLock auto_lock(lock_); | 362 base::AutoLock auto_lock(lock_); |
361 | 363 |
362 DCHECK(decryptor_task_runner_); | 364 DCHECK(decryptor_task_runner_); |
363 DCHECK(decryptor_task_runner_->BelongsToCurrentThread()); | 365 DCHECK(decryptor_task_runner_->BelongsToCurrentThread()); |
364 DCHECK(decryptor_); | 366 DCHECK(decryptor_); |
365 | 367 |
366 decryptor_->OnKeyAdded(); | 368 decryptor_->OnKeyAdded(); |
367 } | 369 } |
368 | 370 |
369 void MojoCdm::OnSimpleCdmPromiseResult( | 371 void MojoCdm::OnSimpleCdmPromiseResult(uint32_t promise_id, |
370 std::unique_ptr<SimpleCdmPromise> promise, | 372 mojom::CdmPromiseResultPtr result) { |
371 mojom::CdmPromiseResultPtr result) { | |
372 if (result->success) | 373 if (result->success) |
373 promise->resolve(); | 374 cdm_promise_adapter_.ResolvePromise(promise_id); |
374 else | 375 else { |
375 RejectPromise(std::move(promise), std::move(result)); | 376 cdm_promise_adapter_.RejectPromise(promise_id, result->exception, |
| 377 result->system_code, |
| 378 result->error_message); |
| 379 } |
376 } | 380 } |
377 | 381 |
378 void MojoCdm::OnNewSessionCdmPromiseResult( | 382 void MojoCdm::OnNewSessionCdmPromiseResult(uint32_t promise_id, |
379 std::unique_ptr<NewSessionCdmPromise> promise, | 383 mojom::CdmPromiseResultPtr result, |
380 mojom::CdmPromiseResultPtr result, | 384 const std::string& session_id) { |
381 const std::string& session_id) { | |
382 if (result->success) { | 385 if (result->success) { |
383 cdm_session_tracker_.AddSession(session_id); | 386 cdm_session_tracker_.AddSession(session_id); |
384 promise->resolve(session_id); | 387 cdm_promise_adapter_.ResolvePromise(promise_id, session_id); |
385 } else | 388 } else { |
386 RejectPromise(std::move(promise), std::move(result)); | 389 cdm_promise_adapter_.RejectPromise(promise_id, result->exception, |
| 390 result->system_code, |
| 391 result->error_message); |
| 392 } |
387 } | 393 } |
388 | 394 |
389 } // namespace media | 395 } // namespace media |
OLD | NEW |