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 DCHECK(cdm_factory_); |
| 287 return cdm_factory_.get(); |
| 288 } |
| 289 |
272 void BrowserCdmManager::OnSessionMessage(int render_frame_id, | 290 void BrowserCdmManager::OnSessionMessage(int render_frame_id, |
273 int cdm_id, | 291 int cdm_id, |
274 const std::string& session_id, | 292 const std::string& session_id, |
275 MediaKeys::MessageType message_type, | 293 MediaKeys::MessageType message_type, |
276 const std::vector<uint8>& message, | 294 const std::vector<uint8>& message, |
277 const GURL& legacy_destination_url) { | 295 const GURL& legacy_destination_url) { |
278 GURL verified_gurl = legacy_destination_url; | 296 GURL verified_gurl = legacy_destination_url; |
279 if (!verified_gurl.is_valid() && !verified_gurl.is_empty()) { | 297 if (!verified_gurl.is_valid() && !verified_gurl.is_empty()) { |
280 DLOG(WARNING) << "SessionMessage legacy_destination_url is invalid : " | 298 DLOG(WARNING) << "SessionMessage legacy_destination_url is invalid : " |
281 << legacy_destination_url.possibly_invalid_spec(); | 299 << legacy_destination_url.possibly_invalid_spec(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 | 338 |
321 void BrowserCdmManager::OnSessionExpirationUpdate( | 339 void BrowserCdmManager::OnSessionExpirationUpdate( |
322 int render_frame_id, | 340 int render_frame_id, |
323 int cdm_id, | 341 int cdm_id, |
324 const std::string& session_id, | 342 const std::string& session_id, |
325 const base::Time& new_expiry_time) { | 343 const base::Time& new_expiry_time) { |
326 Send(new CdmMsg_SessionExpirationUpdate(render_frame_id, cdm_id, session_id, | 344 Send(new CdmMsg_SessionExpirationUpdate(render_frame_id, cdm_id, session_id, |
327 new_expiry_time)); | 345 new_expiry_time)); |
328 } | 346 } |
329 | 347 |
| 348 // Use a weak pointer here instead of |this| to avoid circular references. |
| 349 #define BROWSER_CDM_MANAGER_CB(func, ...) \ |
| 350 base::Bind(&BrowserCdmManager::func, weak_ptr_factory_.GetWeakPtr(), \ |
| 351 render_frame_id, cdm_id, ##__VA_ARGS__) |
| 352 |
330 void BrowserCdmManager::OnInitializeCdm( | 353 void BrowserCdmManager::OnInitializeCdm( |
331 int render_frame_id, | 354 int render_frame_id, |
332 int cdm_id, | 355 int cdm_id, |
333 uint32_t promise_id, | 356 uint32_t promise_id, |
334 const CdmHostMsg_InitializeCdm_Params& params) { | 357 const CdmHostMsg_InitializeCdm_Params& params) { |
| 358 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 359 DCHECK(!GetCdm(render_frame_id, cdm_id)); |
| 360 |
| 361 scoped_ptr<SimplePromise> promise(new SimplePromise( |
| 362 weak_ptr_factory_.GetWeakPtr(), render_frame_id, cdm_id, promise_id)); |
| 363 |
335 if (params.key_system.size() > media::limits::kMaxKeySystemLength) { | 364 if (params.key_system.size() > media::limits::kMaxKeySystemLength) { |
336 NOTREACHED() << "Invalid key system: " << params.key_system; | 365 NOTREACHED() << "Invalid key system: " << params.key_system; |
337 RejectPromise(render_frame_id, cdm_id, promise_id, | 366 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Invalid key system."); |
338 MediaKeys::INVALID_ACCESS_ERROR, 0, "Invalid key system."); | |
339 return; | 367 return; |
340 } | 368 } |
341 | 369 |
342 AddCdm(render_frame_id, cdm_id, promise_id, params.key_system, | 370 // The render process makes sure |allow_distinctive_identifier| and |
343 params.security_origin, params.use_hw_secure_codecs); | 371 // |allow_persistent_state| are true. See RenderCdmFactory::Create(). |
| 372 // TODO(xhwang): Pass |allow_distinctive_identifier| and |
| 373 // |allow_persistent_state| from the render process. |
| 374 media::CdmConfig cdm_config; |
| 375 cdm_config.allow_distinctive_identifier = true; |
| 376 cdm_config.allow_persistent_state = true; |
| 377 cdm_config.use_hw_secure_codecs = params.use_hw_secure_codecs; |
| 378 |
| 379 GetCdmFactory()->Create( |
| 380 params.key_system, params.security_origin, cdm_config, |
| 381 BROWSER_CDM_MANAGER_CB(OnSessionMessage), |
| 382 BROWSER_CDM_MANAGER_CB(OnSessionClosed), |
| 383 BROWSER_CDM_MANAGER_CB(OnLegacySessionError), |
| 384 BROWSER_CDM_MANAGER_CB(OnSessionKeysChange), |
| 385 BROWSER_CDM_MANAGER_CB(OnSessionExpirationUpdate), |
| 386 BROWSER_CDM_MANAGER_CB(OnCdmCreated, params.security_origin, |
| 387 base::Passed(&promise))); |
344 } | 388 } |
345 | 389 |
346 void BrowserCdmManager::OnSetServerCertificate( | 390 void BrowserCdmManager::OnSetServerCertificate( |
347 int render_frame_id, | 391 int render_frame_id, |
348 int cdm_id, | 392 int cdm_id, |
349 uint32_t promise_id, | 393 uint32_t promise_id, |
350 const std::vector<uint8_t>& certificate) { | 394 const std::vector<uint8_t>& certificate) { |
351 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 395 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
352 | 396 |
353 scoped_ptr<SimplePromise> promise(new SimplePromise( | 397 scoped_ptr<SimplePromise> promise(new SimplePromise( |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
515 } | 559 } |
516 | 560 |
517 cdm->RemoveSession(session_id, promise.Pass()); | 561 cdm->RemoveSession(session_id, promise.Pass()); |
518 } | 562 } |
519 | 563 |
520 void BrowserCdmManager::OnDestroyCdm(int render_frame_id, int cdm_id) { | 564 void BrowserCdmManager::OnDestroyCdm(int render_frame_id, int cdm_id) { |
521 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 565 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
522 RemoveCdm(GetId(render_frame_id, cdm_id)); | 566 RemoveCdm(GetId(render_frame_id, cdm_id)); |
523 } | 567 } |
524 | 568 |
525 // Use a weak pointer here instead of |this| to avoid circular references. | 569 void BrowserCdmManager::OnCdmCreated( |
526 #define BROWSER_CDM_MANAGER_CB(func) \ | 570 int render_frame_id, |
527 base::Bind(&BrowserCdmManager::func, weak_ptr_factory_.GetWeakPtr(), \ | 571 int cdm_id, |
528 render_frame_id, cdm_id) | 572 const GURL& security_origin, |
529 | 573 scoped_ptr<media::SimpleCdmPromise> promise, |
530 void BrowserCdmManager::AddCdm(int render_frame_id, | 574 const scoped_refptr<media::MediaKeys>& cdm, |
531 int cdm_id, | 575 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) { | 576 if (!cdm) { |
551 DVLOG(1) << "failed to create CDM."; | 577 DVLOG(1) << "Failed to create CDM: " << error_message; |
552 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "Failed to create CDM."); | 578 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, error_message); |
553 return; | 579 return; |
554 } | 580 } |
555 | 581 |
556 uint64 id = GetId(render_frame_id, cdm_id); | 582 uint64 id = GetId(render_frame_id, cdm_id); |
557 cdm_map_[id] = cdm; | 583 cdm_map_[id] = cdm; |
558 cdm_security_origin_map_[id] = security_origin; | 584 cdm_security_origin_map_[id] = security_origin; |
559 promise->resolve(); | 585 promise->resolve(); |
560 } | 586 } |
561 | 587 |
562 void BrowserCdmManager::RemoveAllCdmForFrame(int render_frame_id) { | 588 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); | 704 scoped_refptr<MediaKeys> cdm = GetCdm(render_frame_id, cdm_id); |
679 if (!cdm) { | 705 if (!cdm) { |
680 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); | 706 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); |
681 return; | 707 return; |
682 } | 708 } |
683 | 709 |
684 cdm->LoadSession(session_type, session_id, promise.Pass()); | 710 cdm->LoadSession(session_type, session_id, promise.Pass()); |
685 } | 711 } |
686 | 712 |
687 } // namespace content | 713 } // namespace content |
OLD | NEW |