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 "content/browser/media/cdm/browser_cdm_manager.h" | 5 #include "content/browser/media/cdm/browser_cdm_manager.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" |
10 #include "base/lazy_instance.h" | 11 #include "base/lazy_instance.h" |
11 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
12 #include "base/task_runner.h" | 13 #include "base/task_runner.h" |
13 #include "content/public/browser/browser_context.h" | 14 #include "content/public/browser/browser_context.h" |
14 #include "content/public/browser/browser_thread.h" | 15 #include "content/public/browser/browser_thread.h" |
15 #include "content/public/browser/content_browser_client.h" | 16 #include "content/public/browser/content_browser_client.h" |
16 #include "content/public/browser/permission_manager.h" | 17 #include "content/public/browser/permission_manager.h" |
17 #include "content/public/browser/permission_type.h" | 18 #include "content/public/browser/permission_type.h" |
18 #include "content/public/browser/render_frame_host.h" | 19 #include "content/public/browser/render_frame_host.h" |
19 #include "content/public/browser/render_process_host.h" | 20 #include "content/public/browser/render_process_host.h" |
20 #include "content/public/browser/render_process_host_observer.h" | 21 #include "content/public/browser/render_process_host_observer.h" |
21 #include "content/public/browser/web_contents.h" | 22 #include "content/public/browser/web_contents.h" |
22 #include "media/base/browser_cdm_factory.h" | 23 #include "media/base/cdm_config.h" |
| 24 #include "media/base/cdm_factory.h" |
23 #include "media/base/cdm_promise.h" | 25 #include "media/base/cdm_promise.h" |
24 #include "media/base/limits.h" | 26 #include "media/base/limits.h" |
25 | 27 |
26 #if defined(OS_ANDROID) | 28 #if defined(OS_ANDROID) |
27 #include "content/public/common/renderer_preferences.h" | 29 #include "content/public/common/renderer_preferences.h" |
| 30 #include "media/base/android/android_cdm_factory.h" |
28 #endif | 31 #endif |
29 | 32 |
30 namespace content { | 33 namespace content { |
31 | 34 |
32 using media::MediaKeys; | 35 using media::MediaKeys; |
33 | 36 |
34 namespace { | 37 namespace { |
35 | 38 |
36 #if defined(OS_ANDROID) | 39 #if defined(OS_ANDROID) |
37 // Android only supports 128-bit key IDs. | 40 // Android only supports 128-bit key IDs. |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 void BrowserCdmManager::RejectPromise(int render_frame_id, | 265 void BrowserCdmManager::RejectPromise(int render_frame_id, |
263 int cdm_id, | 266 int cdm_id, |
264 uint32_t promise_id, | 267 uint32_t promise_id, |
265 MediaKeys::Exception exception, | 268 MediaKeys::Exception exception, |
266 uint32_t system_code, | 269 uint32_t system_code, |
267 const std::string& error_message) { | 270 const std::string& error_message) { |
268 Send(new CdmMsg_RejectPromise(render_frame_id, cdm_id, promise_id, exception, | 271 Send(new CdmMsg_RejectPromise(render_frame_id, cdm_id, promise_id, exception, |
269 system_code, error_message)); | 272 system_code, error_message)); |
270 } | 273 } |
271 | 274 |
| 275 media::CdmFactory* BrowserCdmManager::GetCdmFactory() { |
| 276 if (!cdm_factory_) { |
| 277 // Create a new CdmFactory. |
| 278 cdm_factory_ = GetContentClient()->browser()->CreateCdmFactory(); |
| 279 |
| 280 #if defined(OS_ANDROID) |
| 281 if (!cdm_factory_) |
| 282 cdm_factory_.reset(new media::AndroidCdmFactory()); |
| 283 #endif |
| 284 } |
| 285 |
| 286 return cdm_factory_.get(); |
| 287 } |
| 288 |
272 void BrowserCdmManager::OnSessionMessage(int render_frame_id, | 289 void BrowserCdmManager::OnSessionMessage(int render_frame_id, |
273 int cdm_id, | 290 int cdm_id, |
274 const std::string& session_id, | 291 const std::string& session_id, |
275 MediaKeys::MessageType message_type, | 292 MediaKeys::MessageType message_type, |
276 const std::vector<uint8>& message, | 293 const std::vector<uint8>& message, |
277 const GURL& legacy_destination_url) { | 294 const GURL& legacy_destination_url) { |
278 GURL verified_gurl = legacy_destination_url; | 295 GURL verified_gurl = legacy_destination_url; |
279 if (!verified_gurl.is_valid() && !verified_gurl.is_empty()) { | 296 if (!verified_gurl.is_valid() && !verified_gurl.is_empty()) { |
280 DLOG(WARNING) << "SessionMessage legacy_destination_url is invalid : " | 297 DLOG(WARNING) << "SessionMessage legacy_destination_url is invalid : " |
281 << legacy_destination_url.possibly_invalid_spec(); | 298 << legacy_destination_url.possibly_invalid_spec(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 | 337 |
321 void BrowserCdmManager::OnSessionExpirationUpdate( | 338 void BrowserCdmManager::OnSessionExpirationUpdate( |
322 int render_frame_id, | 339 int render_frame_id, |
323 int cdm_id, | 340 int cdm_id, |
324 const std::string& session_id, | 341 const std::string& session_id, |
325 const base::Time& new_expiry_time) { | 342 const base::Time& new_expiry_time) { |
326 Send(new CdmMsg_SessionExpirationUpdate(render_frame_id, cdm_id, session_id, | 343 Send(new CdmMsg_SessionExpirationUpdate(render_frame_id, cdm_id, session_id, |
327 new_expiry_time)); | 344 new_expiry_time)); |
328 } | 345 } |
329 | 346 |
| 347 // Use a weak pointer here instead of |this| to avoid circular references. |
| 348 #define BROWSER_CDM_MANAGER_CB(func, ...) \ |
| 349 base::Bind(&BrowserCdmManager::func, weak_ptr_factory_.GetWeakPtr(), \ |
| 350 render_frame_id, cdm_id, ##__VA_ARGS__) |
| 351 |
330 void BrowserCdmManager::OnInitializeCdm( | 352 void BrowserCdmManager::OnInitializeCdm( |
331 int render_frame_id, | 353 int render_frame_id, |
332 int cdm_id, | 354 int cdm_id, |
333 uint32_t promise_id, | 355 uint32_t promise_id, |
334 const CdmHostMsg_InitializeCdm_Params& params) { | 356 const CdmHostMsg_InitializeCdm_Params& params) { |
| 357 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 358 DCHECK(!GetCdm(render_frame_id, cdm_id)); |
| 359 |
| 360 scoped_ptr<SimplePromise> promise(new SimplePromise( |
| 361 weak_ptr_factory_.GetWeakPtr(), render_frame_id, cdm_id, promise_id)); |
| 362 |
335 if (params.key_system.size() > media::limits::kMaxKeySystemLength) { | 363 if (params.key_system.size() > media::limits::kMaxKeySystemLength) { |
336 NOTREACHED() << "Invalid key system: " << params.key_system; | 364 NOTREACHED() << "Invalid key system: " << params.key_system; |
337 RejectPromise(render_frame_id, cdm_id, promise_id, | 365 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Invalid key system."); |
338 MediaKeys::INVALID_ACCESS_ERROR, 0, "Invalid key system."); | |
339 return; | 366 return; |
340 } | 367 } |
341 | 368 |
342 AddCdm(render_frame_id, cdm_id, promise_id, params.key_system, | 369 if (!GetCdmFactory()) { |
343 params.security_origin, params.use_hw_secure_codecs); | 370 NOTREACHED() << "CDM not supported."; |
| 371 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "CDM not supported."); |
| 372 return; |
| 373 } |
| 374 |
| 375 // The render process makes sure |allow_distinctive_identifier| and |
| 376 // |allow_persistent_state| are true. See RenderCdmFactory::Create(). |
| 377 // TODO(xhwang): Pass |allow_distinctive_identifier| and |
| 378 // |allow_persistent_state| from the render process. |
| 379 media::CdmConfig cdm_config; |
| 380 cdm_config.allow_distinctive_identifier = true; |
| 381 cdm_config.allow_persistent_state = true; |
| 382 cdm_config.use_hw_secure_codecs = params.use_hw_secure_codecs; |
| 383 |
| 384 GetCdmFactory()->Create( |
| 385 params.key_system, params.security_origin, cdm_config, |
| 386 BROWSER_CDM_MANAGER_CB(OnSessionMessage), |
| 387 BROWSER_CDM_MANAGER_CB(OnSessionClosed), |
| 388 BROWSER_CDM_MANAGER_CB(OnLegacySessionError), |
| 389 BROWSER_CDM_MANAGER_CB(OnSessionKeysChange), |
| 390 BROWSER_CDM_MANAGER_CB(OnSessionExpirationUpdate), |
| 391 BROWSER_CDM_MANAGER_CB(OnCdmCreated, params.security_origin, |
| 392 base::Passed(&promise))); |
344 } | 393 } |
345 | 394 |
346 void BrowserCdmManager::OnSetServerCertificate( | 395 void BrowserCdmManager::OnSetServerCertificate( |
347 int render_frame_id, | 396 int render_frame_id, |
348 int cdm_id, | 397 int cdm_id, |
349 uint32_t promise_id, | 398 uint32_t promise_id, |
350 const std::vector<uint8_t>& certificate) { | 399 const std::vector<uint8_t>& certificate) { |
351 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 400 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
352 | 401 |
353 scoped_ptr<SimplePromise> promise(new SimplePromise( | 402 scoped_ptr<SimplePromise> promise(new SimplePromise( |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
515 } | 564 } |
516 | 565 |
517 cdm->RemoveSession(session_id, promise.Pass()); | 566 cdm->RemoveSession(session_id, promise.Pass()); |
518 } | 567 } |
519 | 568 |
520 void BrowserCdmManager::OnDestroyCdm(int render_frame_id, int cdm_id) { | 569 void BrowserCdmManager::OnDestroyCdm(int render_frame_id, int cdm_id) { |
521 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 570 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
522 RemoveCdm(GetId(render_frame_id, cdm_id)); | 571 RemoveCdm(GetId(render_frame_id, cdm_id)); |
523 } | 572 } |
524 | 573 |
525 // Use a weak pointer here instead of |this| to avoid circular references. | 574 void BrowserCdmManager::OnCdmCreated( |
526 #define BROWSER_CDM_MANAGER_CB(func) \ | 575 int render_frame_id, |
527 base::Bind(&BrowserCdmManager::func, weak_ptr_factory_.GetWeakPtr(), \ | 576 int cdm_id, |
528 render_frame_id, cdm_id) | 577 const GURL& security_origin, |
529 | 578 scoped_ptr<media::SimpleCdmPromise> promise, |
530 void BrowserCdmManager::AddCdm(int render_frame_id, | 579 const scoped_refptr<media::MediaKeys>& cdm, |
531 int cdm_id, | 580 const std::string& error_message) { |
532 uint32_t promise_id, | |
533 const std::string& key_system, | |
534 const GURL& security_origin, | |
535 bool use_hw_secure_codecs) { | |
536 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | |
537 DCHECK(!GetCdm(render_frame_id, cdm_id)); | |
538 | |
539 scoped_ptr<SimplePromise> promise(new SimplePromise( | |
540 weak_ptr_factory_.GetWeakPtr(), render_frame_id, cdm_id, promise_id)); | |
541 | |
542 scoped_refptr<MediaKeys> cdm(media::CreateBrowserCdm( | |
543 key_system, use_hw_secure_codecs, | |
544 BROWSER_CDM_MANAGER_CB(OnSessionMessage), | |
545 BROWSER_CDM_MANAGER_CB(OnSessionClosed), | |
546 BROWSER_CDM_MANAGER_CB(OnLegacySessionError), | |
547 BROWSER_CDM_MANAGER_CB(OnSessionKeysChange), | |
548 BROWSER_CDM_MANAGER_CB(OnSessionExpirationUpdate))); | |
549 | |
550 if (!cdm) { | 581 if (!cdm) { |
551 DVLOG(1) << "failed to create CDM."; | 582 DVLOG(1) << "Failed to create CDM: " << error_message; |
552 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "Failed to create CDM."); | 583 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, error_message); |
553 return; | 584 return; |
554 } | 585 } |
555 | 586 |
556 uint64 id = GetId(render_frame_id, cdm_id); | 587 uint64 id = GetId(render_frame_id, cdm_id); |
557 cdm_map_[id] = cdm; | 588 cdm_map_[id] = cdm; |
558 cdm_security_origin_map_[id] = security_origin; | 589 cdm_security_origin_map_[id] = security_origin; |
559 promise->resolve(); | 590 promise->resolve(); |
560 } | 591 } |
561 | 592 |
562 void BrowserCdmManager::RemoveAllCdmForFrame(int render_frame_id) { | 593 void BrowserCdmManager::RemoveAllCdmForFrame(int render_frame_id) { |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
678 scoped_refptr<MediaKeys> cdm = GetCdm(render_frame_id, cdm_id); | 709 scoped_refptr<MediaKeys> cdm = GetCdm(render_frame_id, cdm_id); |
679 if (!cdm) { | 710 if (!cdm) { |
680 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); | 711 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); |
681 return; | 712 return; |
682 } | 713 } |
683 | 714 |
684 cdm->LoadSession(session_type, session_id, promise.Pass()); | 715 cdm->LoadSession(session_type, session_id, promise.Pass()); |
685 } | 716 } |
686 | 717 |
687 } // namespace content | 718 } // namespace content |
OLD | NEW |