OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/media/media_capture_devices_dispatcher.h" | 5 #include "chrome/browser/media/media_capture_devices_dispatcher.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/prefs/pref_service.h" | 9 #include "base/prefs/pref_service.h" |
10 #include "base/prefs/scoped_user_pref_update.h" | 10 #include "base/prefs/scoped_user_pref_update.h" |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
293 | 293 |
294 void MediaCaptureDevicesDispatcher::ProcessDesktopCaptureAccessRequest( | 294 void MediaCaptureDevicesDispatcher::ProcessDesktopCaptureAccessRequest( |
295 content::WebContents* web_contents, | 295 content::WebContents* web_contents, |
296 const content::MediaStreamRequest& request, | 296 const content::MediaStreamRequest& request, |
297 const content::MediaResponseCallback& callback, | 297 const content::MediaResponseCallback& callback, |
298 const extensions::Extension* extension) { | 298 const extensions::Extension* extension) { |
299 content::MediaStreamDevices devices; | 299 content::MediaStreamDevices devices; |
300 scoped_ptr<content::MediaStreamUI> ui; | 300 scoped_ptr<content::MediaStreamUI> ui; |
301 | 301 |
302 if (request.video_type != content::MEDIA_DESKTOP_VIDEO_CAPTURE) { | 302 if (request.video_type != content::MEDIA_DESKTOP_VIDEO_CAPTURE) { |
303 callback.Run(devices, ui.Pass()); | 303 callback.Run(devices, content::INVALID_STATE, ui.Pass()); |
304 return; | 304 return; |
305 } | 305 } |
306 | 306 |
307 // If the device id wasn't specified then this is a screen capture request | 307 // If the device id wasn't specified then this is a screen capture request |
308 // (i.e. chooseDesktopMedia() API wasn't used to generate device id). | 308 // (i.e. chooseDesktopMedia() API wasn't used to generate device id). |
309 if (request.requested_video_device_id.empty()) { | 309 if (request.requested_video_device_id.empty()) { |
310 ProcessScreenCaptureAccessRequest( | 310 ProcessScreenCaptureAccessRequest( |
311 web_contents, request, callback, extension); | 311 web_contents, request, callback, extension); |
312 return; | 312 return; |
313 } | 313 } |
314 | 314 |
315 // Resolve DesktopMediaID for the specified device id. | 315 // Resolve DesktopMediaID for the specified device id. |
316 content::DesktopMediaID media_id = | 316 content::DesktopMediaID media_id = |
317 GetDesktopStreamsRegistry()->RequestMediaForStreamId( | 317 GetDesktopStreamsRegistry()->RequestMediaForStreamId( |
318 request.requested_video_device_id, request.render_process_id, | 318 request.requested_video_device_id, request.render_process_id, |
319 request.render_view_id, request.security_origin); | 319 request.render_view_id, request.security_origin); |
320 | 320 |
321 // Received invalid device id. | 321 // Received invalid device id. |
322 if (media_id.type == content::DesktopMediaID::TYPE_NONE) { | 322 if (media_id.type == content::DesktopMediaID::TYPE_NONE) { |
323 callback.Run(devices, ui.Pass()); | 323 callback.Run(devices, content::INVALID_STATE, ui.Pass()); |
324 return; | 324 return; |
325 } | 325 } |
326 | 326 |
327 bool loopback_audio_supported = false; | 327 bool loopback_audio_supported = false; |
328 #if defined(USE_CRAS) || defined(OS_WIN) | 328 #if defined(USE_CRAS) || defined(OS_WIN) |
329 // Currently loopback audio capture is supported only on Windows and ChromeOS. | 329 // Currently loopback audio capture is supported only on Windows and ChromeOS. |
330 loopback_audio_supported = true; | 330 loopback_audio_supported = true; |
331 #endif | 331 #endif |
332 | 332 |
333 // Audio is only supported for screen capture streams. | 333 // Audio is only supported for screen capture streams. |
334 bool capture_audio = | 334 bool capture_audio = |
335 (media_id.type == content::DesktopMediaID::TYPE_SCREEN && | 335 (media_id.type == content::DesktopMediaID::TYPE_SCREEN && |
336 request.audio_type == content::MEDIA_LOOPBACK_AUDIO_CAPTURE && | 336 request.audio_type == content::MEDIA_LOOPBACK_AUDIO_CAPTURE && |
337 loopback_audio_supported); | 337 loopback_audio_supported); |
338 | 338 |
339 ui = GetDevicesForDesktopCapture( | 339 ui = GetDevicesForDesktopCapture( |
340 devices, media_id, capture_audio, true, | 340 devices, media_id, capture_audio, true, |
341 GetApplicationTitle(web_contents, extension)); | 341 GetApplicationTitle(web_contents, extension)); |
342 | 342 |
343 callback.Run(devices, ui.Pass()); | 343 callback.Run(devices, content::OK, ui.Pass()); |
344 } | 344 } |
345 | 345 |
346 void MediaCaptureDevicesDispatcher::ProcessScreenCaptureAccessRequest( | 346 void MediaCaptureDevicesDispatcher::ProcessScreenCaptureAccessRequest( |
347 content::WebContents* web_contents, | 347 content::WebContents* web_contents, |
348 const content::MediaStreamRequest& request, | 348 const content::MediaStreamRequest& request, |
349 const content::MediaResponseCallback& callback, | 349 const content::MediaResponseCallback& callback, |
350 const extensions::Extension* extension) { | 350 const extensions::Extension* extension) { |
351 content::MediaStreamDevices devices; | 351 content::MediaStreamDevices devices; |
352 scoped_ptr<content::MediaStreamUI> ui; | 352 scoped_ptr<content::MediaStreamUI> ui; |
353 | 353 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 | 422 |
423 // Unless we're being invoked from a component extension, register to | 423 // Unless we're being invoked from a component extension, register to |
424 // display the notification for stream capture. | 424 // display the notification for stream capture. |
425 bool display_notification = !component_extension; | 425 bool display_notification = !component_extension; |
426 | 426 |
427 ui = GetDevicesForDesktopCapture(devices, screen_id, capture_audio, | 427 ui = GetDevicesForDesktopCapture(devices, screen_id, capture_audio, |
428 display_notification, application_title); | 428 display_notification, application_title); |
429 } | 429 } |
430 } | 430 } |
431 | 431 |
432 callback.Run(devices, ui.Pass()); | 432 callback.Run( |
| 433 devices, |
| 434 devices.empty() ? content::INVALID_STATE: content::OK, |
| 435 ui.Pass()); |
433 } | 436 } |
434 | 437 |
435 void MediaCaptureDevicesDispatcher::ProcessTabCaptureAccessRequest( | 438 void MediaCaptureDevicesDispatcher::ProcessTabCaptureAccessRequest( |
436 content::WebContents* web_contents, | 439 content::WebContents* web_contents, |
437 const content::MediaStreamRequest& request, | 440 const content::MediaStreamRequest& request, |
438 const content::MediaResponseCallback& callback, | 441 const content::MediaResponseCallback& callback, |
439 const extensions::Extension* extension) { | 442 const extensions::Extension* extension) { |
440 content::MediaStreamDevices devices; | 443 content::MediaStreamDevices devices; |
441 scoped_ptr<content::MediaStreamUI> ui; | 444 scoped_ptr<content::MediaStreamUI> ui; |
442 | 445 |
443 #if defined(OS_ANDROID) | 446 #if defined(OS_ANDROID) |
444 // Tab capture is not supported on Android. | 447 // Tab capture is not supported on Android. |
445 callback.Run(devices, ui.Pass()); | 448 callback.Run(devices, ui.Pass()); |
446 #else // defined(OS_ANDROID) | 449 #else // defined(OS_ANDROID) |
447 Profile* profile = | 450 Profile* profile = |
448 Profile::FromBrowserContext(web_contents->GetBrowserContext()); | 451 Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
449 extensions::TabCaptureRegistry* tab_capture_registry = | 452 extensions::TabCaptureRegistry* tab_capture_registry = |
450 extensions::TabCaptureRegistry::Get(profile); | 453 extensions::TabCaptureRegistry::Get(profile); |
451 if (!tab_capture_registry) { | 454 if (!tab_capture_registry) { |
452 NOTREACHED(); | 455 NOTREACHED(); |
453 callback.Run(devices, ui.Pass()); | 456 callback.Run(devices, content::INVALID_STATE, ui.Pass()); |
454 return; | 457 return; |
455 } | 458 } |
456 bool tab_capture_allowed = | 459 bool tab_capture_allowed = |
457 tab_capture_registry->VerifyRequest(request.render_process_id, | 460 tab_capture_registry->VerifyRequest(request.render_process_id, |
458 request.render_view_id); | 461 request.render_view_id); |
459 | 462 |
460 if (request.audio_type == content::MEDIA_TAB_AUDIO_CAPTURE && | 463 if (request.audio_type == content::MEDIA_TAB_AUDIO_CAPTURE && |
461 tab_capture_allowed && | 464 tab_capture_allowed && |
462 extension->HasAPIPermission(extensions::APIPermission::kTabCapture)) { | 465 extension->HasAPIPermission(extensions::APIPermission::kTabCapture)) { |
463 devices.push_back(content::MediaStreamDevice( | 466 devices.push_back(content::MediaStreamDevice( |
464 content::MEDIA_TAB_AUDIO_CAPTURE, std::string(), std::string())); | 467 content::MEDIA_TAB_AUDIO_CAPTURE, std::string(), std::string())); |
465 } | 468 } |
466 | 469 |
467 if (request.video_type == content::MEDIA_TAB_VIDEO_CAPTURE && | 470 if (request.video_type == content::MEDIA_TAB_VIDEO_CAPTURE && |
468 tab_capture_allowed && | 471 tab_capture_allowed && |
469 extension->HasAPIPermission(extensions::APIPermission::kTabCapture)) { | 472 extension->HasAPIPermission(extensions::APIPermission::kTabCapture)) { |
470 devices.push_back(content::MediaStreamDevice( | 473 devices.push_back(content::MediaStreamDevice( |
471 content::MEDIA_TAB_VIDEO_CAPTURE, std::string(), std::string())); | 474 content::MEDIA_TAB_VIDEO_CAPTURE, std::string(), std::string())); |
472 } | 475 } |
473 | 476 |
474 if (!devices.empty()) { | 477 if (!devices.empty()) { |
475 ui = media_stream_capture_indicator_->RegisterMediaStream( | 478 ui = media_stream_capture_indicator_->RegisterMediaStream( |
476 web_contents, devices); | 479 web_contents, devices); |
477 } | 480 } |
478 callback.Run(devices, ui.Pass()); | 481 callback.Run( |
| 482 devices, |
| 483 devices.empty() ? content::INVALID_STATE: content::OK, |
| 484 ui.Pass()); |
479 #endif // !defined(OS_ANDROID) | 485 #endif // !defined(OS_ANDROID) |
480 } | 486 } |
481 | 487 |
482 void MediaCaptureDevicesDispatcher:: | 488 void MediaCaptureDevicesDispatcher:: |
483 ProcessMediaAccessRequestFromPlatformAppOrExtension( | 489 ProcessMediaAccessRequestFromPlatformAppOrExtension( |
484 content::WebContents* web_contents, | 490 content::WebContents* web_contents, |
485 const content::MediaStreamRequest& request, | 491 const content::MediaStreamRequest& request, |
486 const content::MediaResponseCallback& callback, | 492 const content::MediaResponseCallback& callback, |
487 const extensions::Extension* extension) { | 493 const extensions::Extension* extension) { |
488 content::MediaStreamDevices devices; | 494 content::MediaStreamDevices devices; |
489 Profile* profile = | 495 Profile* profile = |
490 Profile::FromBrowserContext(web_contents->GetBrowserContext()); | 496 Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
491 | 497 |
492 if (request.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE && | 498 if (request.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE && |
493 extension->HasAPIPermission(extensions::APIPermission::kAudioCapture)) { | 499 extension->HasAPIPermission(extensions::APIPermission::kAudioCapture)) { |
494 GetDefaultDevicesForProfile(profile, true, false, &devices); | 500 GetDefaultDevicesForProfile(profile, true, false, &devices); |
495 } | 501 } |
496 | 502 |
497 if (request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE && | 503 if (request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE && |
498 extension->HasAPIPermission(extensions::APIPermission::kVideoCapture)) { | 504 extension->HasAPIPermission(extensions::APIPermission::kVideoCapture)) { |
499 GetDefaultDevicesForProfile(profile, false, true, &devices); | 505 GetDefaultDevicesForProfile(profile, false, true, &devices); |
500 } | 506 } |
501 | 507 |
502 scoped_ptr<content::MediaStreamUI> ui; | 508 scoped_ptr<content::MediaStreamUI> ui; |
503 if (!devices.empty()) { | 509 if (!devices.empty()) { |
504 ui = media_stream_capture_indicator_->RegisterMediaStream( | 510 ui = media_stream_capture_indicator_->RegisterMediaStream( |
505 web_contents, devices); | 511 web_contents, devices); |
506 } | 512 } |
507 callback.Run(devices, ui.Pass()); | 513 callback.Run( |
| 514 devices, |
| 515 devices.empty() ? content::INVALID_STATE: content::OK, |
| 516 ui.Pass()); |
508 } | 517 } |
509 | 518 |
510 void MediaCaptureDevicesDispatcher::ProcessRegularMediaAccessRequest( | 519 void MediaCaptureDevicesDispatcher::ProcessRegularMediaAccessRequest( |
511 content::WebContents* web_contents, | 520 content::WebContents* web_contents, |
512 const content::MediaStreamRequest& request, | 521 const content::MediaStreamRequest& request, |
513 const content::MediaResponseCallback& callback) { | 522 const content::MediaResponseCallback& callback) { |
514 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 523 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
515 | 524 |
516 RequestsQueue& queue = pending_requests_[web_contents]; | 525 RequestsQueue& queue = pending_requests_[web_contents]; |
517 queue.push_back(PendingAccessRequest(request, callback)); | 526 queue.push_back(PendingAccessRequest(request, callback)); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
552 // when we've transitioned to bubbles. (crbug/337458) | 561 // when we've transitioned to bubbles. (crbug/337458) |
553 MediaStreamInfoBarDelegate::Create( | 562 MediaStreamInfoBarDelegate::Create( |
554 web_contents, it->second.front().request, | 563 web_contents, it->second.front().request, |
555 base::Bind(&MediaCaptureDevicesDispatcher::OnAccessRequestResponse, | 564 base::Bind(&MediaCaptureDevicesDispatcher::OnAccessRequestResponse, |
556 base::Unretained(this), web_contents)); | 565 base::Unretained(this), web_contents)); |
557 } | 566 } |
558 | 567 |
559 void MediaCaptureDevicesDispatcher::OnAccessRequestResponse( | 568 void MediaCaptureDevicesDispatcher::OnAccessRequestResponse( |
560 content::WebContents* web_contents, | 569 content::WebContents* web_contents, |
561 const content::MediaStreamDevices& devices, | 570 const content::MediaStreamDevices& devices, |
| 571 content::MediaStreamRequestResult result, |
562 scoped_ptr<content::MediaStreamUI> ui) { | 572 scoped_ptr<content::MediaStreamUI> ui) { |
563 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 573 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
564 | 574 |
565 std::map<content::WebContents*, RequestsQueue>::iterator it = | 575 std::map<content::WebContents*, RequestsQueue>::iterator it = |
566 pending_requests_.find(web_contents); | 576 pending_requests_.find(web_contents); |
567 if (it == pending_requests_.end()) { | 577 if (it == pending_requests_.end()) { |
568 // WebContents has been destroyed. Don't need to do anything. | 578 // WebContents has been destroyed. Don't need to do anything. |
569 return; | 579 return; |
570 } | 580 } |
571 | 581 |
572 RequestsQueue& queue(it->second); | 582 RequestsQueue& queue(it->second); |
573 if (queue.empty()) | 583 if (queue.empty()) |
574 return; | 584 return; |
575 | 585 |
576 content::MediaResponseCallback callback = queue.front().callback; | 586 content::MediaResponseCallback callback = queue.front().callback; |
577 queue.pop_front(); | 587 queue.pop_front(); |
578 | 588 |
579 if (!queue.empty()) { | 589 if (!queue.empty()) { |
580 // Post a task to process next queued request. It has to be done | 590 // Post a task to process next queued request. It has to be done |
581 // asynchronously to make sure that calling infobar is not destroyed until | 591 // asynchronously to make sure that calling infobar is not destroyed until |
582 // after this function returns. | 592 // after this function returns. |
583 BrowserThread::PostTask( | 593 BrowserThread::PostTask( |
584 BrowserThread::UI, FROM_HERE, | 594 BrowserThread::UI, FROM_HERE, |
585 base::Bind(&MediaCaptureDevicesDispatcher::ProcessQueuedAccessRequest, | 595 base::Bind(&MediaCaptureDevicesDispatcher::ProcessQueuedAccessRequest, |
586 base::Unretained(this), web_contents)); | 596 base::Unretained(this), web_contents)); |
587 } | 597 } |
588 | 598 |
589 callback.Run(devices, ui.Pass()); | 599 callback.Run(devices, result, ui.Pass()); |
590 } | 600 } |
591 | 601 |
592 void MediaCaptureDevicesDispatcher::GetDefaultDevicesForProfile( | 602 void MediaCaptureDevicesDispatcher::GetDefaultDevicesForProfile( |
593 Profile* profile, | 603 Profile* profile, |
594 bool audio, | 604 bool audio, |
595 bool video, | 605 bool video, |
596 content::MediaStreamDevices* devices) { | 606 content::MediaStreamDevices* devices) { |
597 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 607 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
598 DCHECK(audio || video); | 608 DCHECK(audio || video); |
599 | 609 |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
824 int render_frame_id) { | 834 int render_frame_id) { |
825 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 835 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
826 FOR_EACH_OBSERVER(Observer, observers_, | 836 FOR_EACH_OBSERVER(Observer, observers_, |
827 OnCreatingAudioStream(render_process_id, render_frame_id)); | 837 OnCreatingAudioStream(render_process_id, render_frame_id)); |
828 } | 838 } |
829 | 839 |
830 bool MediaCaptureDevicesDispatcher::IsDesktopCaptureInProgress() { | 840 bool MediaCaptureDevicesDispatcher::IsDesktopCaptureInProgress() { |
831 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 841 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
832 return desktop_capture_sessions_.size() > 0; | 842 return desktop_capture_sessions_.size() > 0; |
833 } | 843 } |
OLD | NEW |