Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(471)

Side by Side Diff: content/browser/media/cdm/browser_cdm_manager.cc

Issue 1013913002: media: Fix permission request/check for EME on Android. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: comments addressed Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 } 304 }
305 305
306 AddCdm(render_frame_id, cdm_id, key_system, security_origin); 306 AddCdm(render_frame_id, cdm_id, key_system, security_origin);
307 } 307 }
308 308
309 void BrowserCdmManager::OnSetServerCertificate( 309 void BrowserCdmManager::OnSetServerCertificate(
310 int render_frame_id, 310 int render_frame_id,
311 int cdm_id, 311 int cdm_id,
312 uint32_t promise_id, 312 uint32_t promise_id,
313 const std::vector<uint8_t>& certificate) { 313 const std::vector<uint8_t>& certificate) {
314 DCHECK(task_runner_->RunsTasksOnCurrentThread());
315
314 scoped_ptr<SimplePromise> promise( 316 scoped_ptr<SimplePromise> promise(
315 new SimplePromise(this, render_frame_id, cdm_id, promise_id)); 317 new SimplePromise(this, render_frame_id, cdm_id, promise_id));
316 318
317 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); 319 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
318 if (!cdm) { 320 if (!cdm) {
319 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); 321 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
320 return; 322 return;
321 } 323 }
322 324
323 if (certificate.empty()) { 325 if (certificate.empty()) {
324 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Empty certificate."); 326 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Empty certificate.");
325 return; 327 return;
326 } 328 }
327 329
328 cdm->SetServerCertificate(&certificate[0], certificate.size(), 330 cdm->SetServerCertificate(&certificate[0], certificate.size(),
329 promise.Pass()); 331 promise.Pass());
330 } 332 }
331 333
332 void BrowserCdmManager::OnCreateSessionAndGenerateRequest( 334 void BrowserCdmManager::OnCreateSessionAndGenerateRequest(
333 int render_frame_id, 335 int render_frame_id,
334 int cdm_id, 336 int cdm_id,
335 uint32_t promise_id, 337 uint32_t promise_id,
336 CdmHostMsg_CreateSession_InitDataType init_data_type, 338 CdmHostMsg_CreateSession_InitDataType init_data_type,
337 const std::vector<uint8>& init_data) { 339 const std::vector<uint8>& init_data) {
340 DCHECK(task_runner_->RunsTasksOnCurrentThread());
341
338 scoped_ptr<NewSessionPromise> promise( 342 scoped_ptr<NewSessionPromise> promise(
339 new NewSessionPromise(this, render_frame_id, cdm_id, promise_id)); 343 new NewSessionPromise(this, render_frame_id, cdm_id, promise_id));
340 344
341 if (init_data.size() > kMaxInitDataLength) { 345 if (init_data.size() > kMaxInitDataLength) {
342 LOG(WARNING) << "InitData for ID: " << cdm_id 346 LOG(WARNING) << "InitData for ID: " << cdm_id
343 << " too long: " << init_data.size(); 347 << " too long: " << init_data.size();
344 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Init data too long."); 348 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Init data too long.");
345 return; 349 return;
346 } 350 }
347 351
(...skipping 10 matching lines...) Expand all
358 default: 362 default:
359 NOTREACHED(); 363 NOTREACHED();
360 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, 364 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0,
361 "Invalid init data type."); 365 "Invalid init data type.");
362 return; 366 return;
363 } 367 }
364 368
365 #if defined(OS_ANDROID) 369 #if defined(OS_ANDROID)
366 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 370 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
367 switches::kDisableInfobarForProtectedMediaIdentifier)) { 371 switches::kDisableInfobarForProtectedMediaIdentifier)) {
368 GenerateRequestIfPermitted( 372 CreateSessionAndGenerateRequestIfPermitted(
ddorwin 2015/03/17 20:09:59 Note: This code goes away with your other CL, so w
xhwang 2015/03/17 20:16:01 Acknowledged.
369 render_frame_id, cdm_id, eme_init_data_type, 373 render_frame_id, cdm_id, eme_init_data_type, init_data, promise.Pass(),
370 init_data, promise.Pass(), PERMISSION_STATUS_GRANTED); 374 true /* allowed */);
371 return; 375 return;
372 } 376 }
373 #endif 377 #endif
374 378
375 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); 379 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
376 if (!cdm) { 380 if (!cdm) {
377 DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id; 381 DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id;
378 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); 382 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
379 return; 383 return;
380 } 384 }
381 385
382 std::map<uint64, GURL>::const_iterator iter = 386 CheckPermissionStatus(
383 cdm_security_origin_map_.find(GetId(render_frame_id, cdm_id)); 387 render_frame_id, cdm_id,
384 if (iter == cdm_security_origin_map_.end()) { 388 base::Bind(&BrowserCdmManager::CreateSessionAndGenerateRequestIfPermitted,
385 NOTREACHED(); 389 this, render_frame_id, cdm_id, eme_init_data_type, init_data,
386 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); 390 base::Passed(&promise)));
387 return;
388 }
389 GURL security_origin = iter->second;
390
391 RequestSessionPermission(render_frame_id, security_origin, cdm_id,
392 eme_init_data_type, init_data, promise.Pass());
393 } 391 }
394 392
395 void BrowserCdmManager::OnUpdateSession(int render_frame_id, 393 void BrowserCdmManager::OnUpdateSession(int render_frame_id,
396 int cdm_id, 394 int cdm_id,
397 uint32_t promise_id, 395 uint32_t promise_id,
398 const std::string& session_id, 396 const std::string& session_id,
399 const std::vector<uint8>& response) { 397 const std::vector<uint8>& response) {
398 DCHECK(task_runner_->RunsTasksOnCurrentThread());
399
400 scoped_ptr<SimplePromise> promise( 400 scoped_ptr<SimplePromise> promise(
401 new SimplePromise(this, render_frame_id, cdm_id, promise_id)); 401 new SimplePromise(this, render_frame_id, cdm_id, promise_id));
402 402
403 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); 403 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
404 if (!cdm) { 404 if (!cdm) {
405 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); 405 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
406 return; 406 return;
407 } 407 }
408 408
409 if (response.size() > kMaxSessionResponseLength) { 409 if (response.size() > kMaxSessionResponseLength) {
410 LOG(WARNING) << "Response for ID " << cdm_id 410 LOG(WARNING) << "Response for ID " << cdm_id
411 << " is too long: " << response.size(); 411 << " is too long: " << response.size();
412 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Response too long."); 412 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Response too long.");
413 return; 413 return;
414 } 414 }
415 415
416 if (response.empty()) { 416 if (response.empty()) {
417 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Response is empty."); 417 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Response is empty.");
418 return; 418 return;
419 } 419 }
420 420
421 cdm->UpdateSession(session_id, &response[0], response.size(), promise.Pass()); 421 cdm->UpdateSession(session_id, &response[0], response.size(), promise.Pass());
422 } 422 }
423 423
424 void BrowserCdmManager::OnCloseSession(int render_frame_id, 424 void BrowserCdmManager::OnCloseSession(int render_frame_id,
425 int cdm_id, 425 int cdm_id,
426 uint32_t promise_id, 426 uint32_t promise_id,
427 const std::string& session_id) { 427 const std::string& session_id) {
428 DCHECK(task_runner_->RunsTasksOnCurrentThread());
429
428 scoped_ptr<SimplePromise> promise( 430 scoped_ptr<SimplePromise> promise(
429 new SimplePromise(this, render_frame_id, cdm_id, promise_id)); 431 new SimplePromise(this, render_frame_id, cdm_id, promise_id));
430 432
431 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); 433 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
432 if (!cdm) { 434 if (!cdm) {
433 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); 435 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
434 return; 436 return;
435 } 437 }
436 438
437 cdm->CloseSession(session_id, promise.Pass()); 439 cdm->CloseSession(session_id, promise.Pass());
438 } 440 }
439 441
440 void BrowserCdmManager::OnDestroyCdm(int render_frame_id, int cdm_id) { 442 void BrowserCdmManager::OnDestroyCdm(int render_frame_id, int cdm_id) {
443 DCHECK(task_runner_->RunsTasksOnCurrentThread());
441 RemoveCdm(GetId(render_frame_id, cdm_id)); 444 RemoveCdm(GetId(render_frame_id, cdm_id));
442 } 445 }
443 446
444 // Use a weak pointer here instead of |this| to avoid circular references. 447 // Use a weak pointer here instead of |this| to avoid circular references.
445 #define BROWSER_CDM_MANAGER_CB(func) \ 448 #define BROWSER_CDM_MANAGER_CB(func) \
446 base::Bind(&BrowserCdmManager::func, weak_ptr_factory_.GetWeakPtr(), \ 449 base::Bind(&BrowserCdmManager::func, weak_ptr_factory_.GetWeakPtr(), \
447 render_frame_id, cdm_id) 450 render_frame_id, cdm_id)
448 451
449 void BrowserCdmManager::AddCdm(int render_frame_id, 452 void BrowserCdmManager::AddCdm(int render_frame_id,
450 int cdm_id, 453 int cdm_id,
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 486
484 for (size_t i = 0; i < ids_to_remove.size(); ++i) 487 for (size_t i = 0; i < ids_to_remove.size(); ++i)
485 RemoveCdm(ids_to_remove[i]); 488 RemoveCdm(ids_to_remove[i]);
486 } 489 }
487 490
488 void BrowserCdmManager::RemoveCdm(uint64 id) { 491 void BrowserCdmManager::RemoveCdm(uint64 id) {
489 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 492 DCHECK(task_runner_->RunsTasksOnCurrentThread());
490 493
491 cdm_map_.erase(id); 494 cdm_map_.erase(id);
492 cdm_security_origin_map_.erase(id); 495 cdm_security_origin_map_.erase(id);
493 if (cdm_cancel_permission_map_.count(id)) { 496 }
494 cdm_cancel_permission_map_[id].Run(); 497
495 cdm_cancel_permission_map_.erase(id); 498 void BrowserCdmManager::CheckPermissionStatus(
499 int render_frame_id,
500 int cdm_id,
501 const PermissionStatusCB& permission_status_cb) {
502 // Always called on |task_runner_|, which may not be on the UI thread.
503 DCHECK(task_runner_->RunsTasksOnCurrentThread());
504
505 GURL security_origin;
506 std::map<uint64, GURL>::const_iterator iter =
507 cdm_security_origin_map_.find(GetId(render_frame_id, cdm_id));
508 DCHECK(iter != cdm_security_origin_map_.end());
509 if (iter != cdm_security_origin_map_.end())
510 security_origin = iter->second;
511
512 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
513 BrowserThread::PostTask(
514 BrowserThread::UI, FROM_HERE,
515 base::Bind(&BrowserCdmManager::CheckPermissionStatusOnUIThread, this,
516 render_frame_id, security_origin, permission_status_cb));
517 } else {
518 CheckPermissionStatusOnUIThread(render_frame_id, security_origin,
519 permission_status_cb);
496 } 520 }
497 } 521 }
498 522
499 void BrowserCdmManager::RequestSessionPermission( 523 // Note: This function runs on the UI thread, which may be different from
524 // |task_runner_|. Be careful about thread safety!
525 void BrowserCdmManager::CheckPermissionStatusOnUIThread(
500 int render_frame_id, 526 int render_frame_id,
501 const GURL& security_origin, 527 const GURL& security_origin,
502 int cdm_id, 528 const base::Callback<void(bool)>& permission_status_cb) {
503 media::EmeInitDataType init_data_type, 529 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
504 const std::vector<uint8>& init_data,
505 scoped_ptr<media::NewSessionCdmPromise> promise) {
506 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
507 BrowserThread::PostTask(
508 BrowserThread::UI, FROM_HERE,
509 base::Bind(&BrowserCdmManager::RequestSessionPermission, this,
510 render_frame_id, security_origin, cdm_id, init_data_type,
511 init_data, base::Passed(&promise)));
512 return;
513 }
514 530
515 RenderFrameHost* rfh = 531 RenderFrameHost* rfh =
516 RenderFrameHost::FromID(render_process_id_, render_frame_id); 532 RenderFrameHost::FromID(render_process_id_, render_frame_id);
517 WebContents* web_contents = WebContents::FromRenderFrameHost(rfh); 533 WebContents* web_contents = WebContents::FromRenderFrameHost(rfh);
518 DCHECK(web_contents); 534 GURL embedding_origin = web_contents->GetLastCommittedURL().GetOrigin();
519 GetContentClient()->browser()->RequestPermission( 535
520 content::PERMISSION_PROTECTED_MEDIA_IDENTIFIER, web_contents, 536 PermissionStatus permission_status =
521 0, // bridge id 537 GetContentClient()->browser()->GetPermissionStatus(
522 security_origin, 538 content::PERMISSION_PROTECTED_MEDIA_IDENTIFIER,
523 // Only implemented for Android infobars which do not support 539 web_contents->GetBrowserContext(), security_origin, embedding_origin);
524 // user gestures. 540
525 true, base::Bind(&BrowserCdmManager::GenerateRequestIfPermitted, this, 541 bool allowed = (permission_status == PERMISSION_STATUS_GRANTED);
526 render_frame_id, cdm_id, init_data_type, init_data, 542 if (!task_runner_->RunsTasksOnCurrentThread()) {
527 base::Passed(&promise))); 543 task_runner_->PostTask(FROM_HERE,
544 base::Bind(permission_status_cb, allowed));
545 } else {
546 permission_status_cb.Run(allowed);
547 }
528 } 548 }
529 549
530 void BrowserCdmManager::GenerateRequestIfPermitted( 550 void BrowserCdmManager::CreateSessionAndGenerateRequestIfPermitted(
531 int render_frame_id, 551 int render_frame_id,
532 int cdm_id, 552 int cdm_id,
533 media::EmeInitDataType init_data_type, 553 media::EmeInitDataType init_data_type,
534 const std::vector<uint8>& init_data, 554 const std::vector<uint8>& init_data,
535 scoped_ptr<media::NewSessionCdmPromise> promise, 555 scoped_ptr<media::NewSessionCdmPromise> promise,
536 PermissionStatus permission) { 556 bool permission_allowed) {
ddorwin 2015/03/17 20:09:59 nit: was_...
xhwang 2015/03/17 20:16:01 Done.
537 cdm_cancel_permission_map_.erase(GetId(render_frame_id, cdm_id)); 557 DCHECK(task_runner_->RunsTasksOnCurrentThread());
538 if (permission != PERMISSION_STATUS_GRANTED) { 558
559 if (!permission_allowed) {
539 promise->reject(MediaKeys::NOT_SUPPORTED_ERROR, 0, "Permission denied."); 560 promise->reject(MediaKeys::NOT_SUPPORTED_ERROR, 0, "Permission denied.");
540 return; 561 return;
541 } 562 }
542 563
543 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); 564 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
544 if (!cdm) { 565 if (!cdm) {
545 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); 566 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
546 return; 567 return;
547 } 568 }
548 569
(...skipping 15 matching lines...) Expand all
564 } 585 }
565 586
566 // Only the temporary session type is supported in browser CDM path. 587 // Only the temporary session type is supported in browser CDM path.
567 // TODO(xhwang): Add SessionType support if needed. 588 // TODO(xhwang): Add SessionType support if needed.
568 cdm->CreateSessionAndGenerateRequest(media::MediaKeys::TEMPORARY_SESSION, 589 cdm->CreateSessionAndGenerateRequest(media::MediaKeys::TEMPORARY_SESSION,
569 init_data_type_string, &init_data[0], 590 init_data_type_string, &init_data[0],
570 init_data.size(), promise.Pass()); 591 init_data.size(), promise.Pass());
571 } 592 }
572 593
573 } // namespace content 594 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698