| 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/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 338 scoped_ptr<NewSessionPromise> promise( | 338 scoped_ptr<NewSessionPromise> promise( |
| 339 new NewSessionPromise(this, render_frame_id, cdm_id, promise_id)); | 339 new NewSessionPromise(this, render_frame_id, cdm_id, promise_id)); |
| 340 | 340 |
| 341 if (init_data.size() > kMaxInitDataLength) { | 341 if (init_data.size() > kMaxInitDataLength) { |
| 342 LOG(WARNING) << "InitData for ID: " << cdm_id | 342 LOG(WARNING) << "InitData for ID: " << cdm_id |
| 343 << " too long: " << init_data.size(); | 343 << " too long: " << init_data.size(); |
| 344 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Init data too long."); | 344 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Init data too long."); |
| 345 return; | 345 return; |
| 346 } | 346 } |
| 347 | 347 |
| 348 // Convert the session content type into a MIME type. "audio" and "video" | 348 media::EmeInitDataType eme_init_data_type = media::EME_INIT_DATA_TYPE_NONE; |
| 349 // don't matter, so using "video" for the MIME type. | |
| 350 // Ref: | |
| 351 // https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypte
d-media.html#dom-createsession | |
| 352 std::string mime_type; | |
| 353 switch (init_data_type) { | 349 switch (init_data_type) { |
| 354 case CREATE_SESSION_TYPE_WEBM: | 350 case INIT_DATA_TYPE_WEBM: |
| 355 mime_type = "video/webm"; | 351 eme_init_data_type = media::EME_INIT_DATA_TYPE_WEBM; |
| 356 break; | 352 break; |
| 357 case CREATE_SESSION_TYPE_MP4: | 353 #if defined(USE_PROPRIETARY_CODECS) |
| 358 mime_type = "video/mp4"; | 354 case INIT_DATA_TYPE_CENC: |
| 355 eme_init_data_type = media::EME_INIT_DATA_TYPE_CENC; |
| 359 break; | 356 break; |
| 357 #endif |
| 360 default: | 358 default: |
| 361 NOTREACHED(); | 359 NOTREACHED(); |
| 362 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, | 360 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, |
| 363 "Invalid init data type."); | 361 "Invalid init data type."); |
| 364 return; | 362 return; |
| 365 } | 363 } |
| 366 | 364 |
| 367 #if defined(OS_ANDROID) | 365 #if defined(OS_ANDROID) |
| 368 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 366 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 369 switches::kDisableInfobarForProtectedMediaIdentifier)) { | 367 switches::kDisableInfobarForProtectedMediaIdentifier)) { |
| 370 GenerateRequestIfPermitted(render_frame_id, cdm_id, mime_type, init_data, | 368 GenerateRequestIfPermitted(render_frame_id, cdm_id, eme_init_data_type, |
| 371 promise.Pass(), true); | 369 init_data, promise.Pass(), true); |
| 372 return; | 370 return; |
| 373 } | 371 } |
| 374 #endif | 372 #endif |
| 375 | 373 |
| 376 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); | 374 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); |
| 377 if (!cdm) { | 375 if (!cdm) { |
| 378 DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id; | 376 DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id; |
| 379 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); | 377 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); |
| 380 return; | 378 return; |
| 381 } | 379 } |
| 382 | 380 |
| 383 std::map<uint64, GURL>::const_iterator iter = | 381 std::map<uint64, GURL>::const_iterator iter = |
| 384 cdm_security_origin_map_.find(GetId(render_frame_id, cdm_id)); | 382 cdm_security_origin_map_.find(GetId(render_frame_id, cdm_id)); |
| 385 if (iter == cdm_security_origin_map_.end()) { | 383 if (iter == cdm_security_origin_map_.end()) { |
| 386 NOTREACHED(); | 384 NOTREACHED(); |
| 387 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); | 385 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); |
| 388 return; | 386 return; |
| 389 } | 387 } |
| 390 GURL security_origin = iter->second; | 388 GURL security_origin = iter->second; |
| 391 | 389 |
| 392 RequestSessionPermission(render_frame_id, security_origin, cdm_id, mime_type, | 390 RequestSessionPermission(render_frame_id, security_origin, cdm_id, |
| 393 init_data, promise.Pass()); | 391 eme_init_data_type, init_data, promise.Pass()); |
| 394 } | 392 } |
| 395 | 393 |
| 396 void BrowserCdmManager::OnUpdateSession(int render_frame_id, | 394 void BrowserCdmManager::OnUpdateSession(int render_frame_id, |
| 397 int cdm_id, | 395 int cdm_id, |
| 398 uint32_t promise_id, | 396 uint32_t promise_id, |
| 399 const std::string& session_id, | 397 const std::string& session_id, |
| 400 const std::vector<uint8>& response) { | 398 const std::vector<uint8>& response) { |
| 401 scoped_ptr<SimplePromise> promise( | 399 scoped_ptr<SimplePromise> promise( |
| 402 new SimplePromise(this, render_frame_id, cdm_id, promise_id)); | 400 new SimplePromise(this, render_frame_id, cdm_id, promise_id)); |
| 403 | 401 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 494 if (cdm_cancel_permission_map_.count(id)) { | 492 if (cdm_cancel_permission_map_.count(id)) { |
| 495 cdm_cancel_permission_map_[id].Run(); | 493 cdm_cancel_permission_map_[id].Run(); |
| 496 cdm_cancel_permission_map_.erase(id); | 494 cdm_cancel_permission_map_.erase(id); |
| 497 } | 495 } |
| 498 } | 496 } |
| 499 | 497 |
| 500 void BrowserCdmManager::RequestSessionPermission( | 498 void BrowserCdmManager::RequestSessionPermission( |
| 501 int render_frame_id, | 499 int render_frame_id, |
| 502 const GURL& security_origin, | 500 const GURL& security_origin, |
| 503 int cdm_id, | 501 int cdm_id, |
| 504 const std::string& init_data_type, | 502 media::EmeInitDataType init_data_type, |
| 505 const std::vector<uint8>& init_data, | 503 const std::vector<uint8>& init_data, |
| 506 scoped_ptr<media::NewSessionCdmPromise> promise) { | 504 scoped_ptr<media::NewSessionCdmPromise> promise) { |
| 507 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 505 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 508 BrowserThread::PostTask( | 506 BrowserThread::PostTask( |
| 509 BrowserThread::UI, FROM_HERE, | 507 BrowserThread::UI, FROM_HERE, |
| 510 base::Bind(&BrowserCdmManager::RequestSessionPermission, this, | 508 base::Bind(&BrowserCdmManager::RequestSessionPermission, this, |
| 511 render_frame_id, security_origin, cdm_id, init_data_type, | 509 render_frame_id, security_origin, cdm_id, init_data_type, |
| 512 init_data, base::Passed(&promise))); | 510 init_data, base::Passed(&promise))); |
| 513 return; | 511 return; |
| 514 } | 512 } |
| 515 | 513 |
| 516 RenderFrameHost* rfh = | 514 RenderFrameHost* rfh = |
| 517 RenderFrameHost::FromID(render_process_id_, render_frame_id); | 515 RenderFrameHost::FromID(render_process_id_, render_frame_id); |
| 518 WebContents* web_contents = WebContents::FromRenderFrameHost(rfh); | 516 WebContents* web_contents = WebContents::FromRenderFrameHost(rfh); |
| 519 DCHECK(web_contents); | 517 DCHECK(web_contents); |
| 520 GetContentClient()->browser()->RequestPermission( | 518 GetContentClient()->browser()->RequestPermission( |
| 521 content::PERMISSION_PROTECTED_MEDIA_IDENTIFIER, web_contents, | 519 content::PERMISSION_PROTECTED_MEDIA_IDENTIFIER, web_contents, |
| 522 0, // bridge id | 520 0, // bridge id |
| 523 security_origin, | 521 security_origin, |
| 524 // Only implemented for Android infobars which do not support | 522 // Only implemented for Android infobars which do not support |
| 525 // user gestures. | 523 // user gestures. |
| 526 true, base::Bind(&BrowserCdmManager::GenerateRequestIfPermitted, this, | 524 true, base::Bind(&BrowserCdmManager::GenerateRequestIfPermitted, this, |
| 527 render_frame_id, cdm_id, init_data_type, init_data, | 525 render_frame_id, cdm_id, init_data_type, init_data, |
| 528 base::Passed(&promise))); | 526 base::Passed(&promise))); |
| 529 } | 527 } |
| 530 | 528 |
| 531 void BrowserCdmManager::GenerateRequestIfPermitted( | 529 void BrowserCdmManager::GenerateRequestIfPermitted( |
| 532 int render_frame_id, | 530 int render_frame_id, |
| 533 int cdm_id, | 531 int cdm_id, |
| 534 const std::string& init_data_type, | 532 media::EmeInitDataType init_data_type, |
| 535 const std::vector<uint8>& init_data, | 533 const std::vector<uint8>& init_data, |
| 536 scoped_ptr<media::NewSessionCdmPromise> promise, | 534 scoped_ptr<media::NewSessionCdmPromise> promise, |
| 537 bool permitted) { | 535 bool permitted) { |
| 538 cdm_cancel_permission_map_.erase(GetId(render_frame_id, cdm_id)); | 536 cdm_cancel_permission_map_.erase(GetId(render_frame_id, cdm_id)); |
| 539 if (!permitted) { | 537 if (!permitted) { |
| 540 promise->reject(MediaKeys::NOT_SUPPORTED_ERROR, 0, "Permission denied."); | 538 promise->reject(MediaKeys::NOT_SUPPORTED_ERROR, 0, "Permission denied."); |
| 541 return; | 539 return; |
| 542 } | 540 } |
| 543 | 541 |
| 544 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); | 542 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); |
| 545 if (!cdm) { | 543 if (!cdm) { |
| 546 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); | 544 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); |
| 547 return; | 545 return; |
| 548 } | 546 } |
| 549 | 547 |
| 548 // TODO(ddorwin): Move this conversion to MediaDrmBridge when fixing |
| 549 // crbug.com/417440. |
| 550 // "audio"/"video" does not matter, so use "video". |
| 551 std::string init_data_type_string; |
| 552 switch (init_data_type) { |
| 553 case media::EME_INIT_DATA_TYPE_WEBM: |
| 554 init_data_type_string = "video/webm"; |
| 555 break; |
| 556 #if defined(USE_PROPRIETARY_CODECS) |
| 557 case media::EME_INIT_DATA_TYPE_CENC: |
| 558 init_data_type_string = "video/mp4"; |
| 559 break; |
| 560 #endif |
| 561 default: |
| 562 NOTREACHED(); |
| 563 } |
| 564 |
| 550 // Only the temporary session type is supported in browser CDM path. | 565 // Only the temporary session type is supported in browser CDM path. |
| 551 // TODO(xhwang): Add SessionType support if needed. | 566 // TODO(xhwang): Add SessionType support if needed. |
| 552 cdm->CreateSessionAndGenerateRequest(media::MediaKeys::TEMPORARY_SESSION, | 567 cdm->CreateSessionAndGenerateRequest(media::MediaKeys::TEMPORARY_SESSION, |
| 553 init_data_type, &init_data[0], | 568 init_data_type_string, &init_data[0], |
| 554 init_data.size(), promise.Pass()); | 569 init_data.size(), promise.Pass()); |
| 555 } | 570 } |
| 556 | 571 |
| 557 } // namespace content | 572 } // namespace content |
| OLD | NEW |