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 "apps/app_window.h" | 7 #include "apps/app_window.h" |
8 #include "apps/app_window_registry.h" | 8 #include "apps/app_window_registry.h" |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 18 matching lines...) Expand all Loading... |
29 #include "chrome/common/chrome_version_info.h" | 29 #include "chrome/common/chrome_version_info.h" |
30 #include "chrome/common/pref_names.h" | 30 #include "chrome/common/pref_names.h" |
31 #include "components/pref_registry/pref_registry_syncable.h" | 31 #include "components/pref_registry/pref_registry_syncable.h" |
32 #include "content/public/browser/browser_thread.h" | 32 #include "content/public/browser/browser_thread.h" |
33 #include "content/public/browser/desktop_media_id.h" | 33 #include "content/public/browser/desktop_media_id.h" |
34 #include "content/public/browser/media_capture_devices.h" | 34 #include "content/public/browser/media_capture_devices.h" |
35 #include "content/public/browser/notification_service.h" | 35 #include "content/public/browser/notification_service.h" |
36 #include "content/public/browser/notification_source.h" | 36 #include "content/public/browser/notification_source.h" |
37 #include "content/public/browser/notification_types.h" | 37 #include "content/public/browser/notification_types.h" |
38 #include "content/public/browser/render_frame_host.h" | 38 #include "content/public/browser/render_frame_host.h" |
| 39 #include "content/public/browser/render_process_host.h" |
39 #include "content/public/browser/web_contents.h" | 40 #include "content/public/browser/web_contents.h" |
40 #include "content/public/common/media_stream_request.h" | 41 #include "content/public/common/media_stream_request.h" |
41 #include "extensions/common/constants.h" | 42 #include "extensions/common/constants.h" |
42 #include "extensions/common/extension.h" | 43 #include "extensions/common/extension.h" |
43 #include "extensions/common/permissions/permissions_data.h" | 44 #include "extensions/common/permissions/permissions_data.h" |
44 #include "grit/generated_resources.h" | 45 #include "grit/generated_resources.h" |
45 #include "media/audio/audio_manager_base.h" | 46 #include "media/audio/audio_manager_base.h" |
46 #include "media/base/media_switches.h" | 47 #include "media/base/media_switches.h" |
47 #include "net/base/net_util.h" | 48 #include "net/base/net_util.h" |
48 #include "third_party/webrtc/modules/desktop_capture/desktop_capture_types.h" | 49 #include "third_party/webrtc/modules/desktop_capture/desktop_capture_types.h" |
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
387 // (i.e. chooseDesktopMedia() API wasn't used to generate device id). | 388 // (i.e. chooseDesktopMedia() API wasn't used to generate device id). |
388 if (request.requested_video_device_id.empty()) { | 389 if (request.requested_video_device_id.empty()) { |
389 ProcessScreenCaptureAccessRequest( | 390 ProcessScreenCaptureAccessRequest( |
390 web_contents, request, callback, extension); | 391 web_contents, request, callback, extension); |
391 return; | 392 return; |
392 } | 393 } |
393 | 394 |
394 // The extension name that the stream is registered with. | 395 // The extension name that the stream is registered with. |
395 std::string original_extension_name; | 396 std::string original_extension_name; |
396 // Resolve DesktopMediaID for the specified device id. | 397 // Resolve DesktopMediaID for the specified device id. |
397 content::DesktopMediaID media_id = | 398 content::DesktopMediaID media_id; |
398 GetDesktopStreamsRegistry()->RequestMediaForStreamId( | 399 // TODO(miu): Replace "main RenderFrame" IDs with the request's actual |
399 request.requested_video_device_id, request.render_process_id, | 400 // RenderFrame IDs once the desktop capture extension API implementation is |
400 request.render_view_id, request.security_origin, | 401 // fixed. http://crbug.com/304341 |
401 &original_extension_name); | 402 content::WebContents* const web_contents_for_stream = |
| 403 content::WebContents::FromRenderFrameHost( |
| 404 content::RenderFrameHost::FromID(request.render_process_id, |
| 405 request.render_frame_id)); |
| 406 content::RenderFrameHost* const main_frame = web_contents_for_stream ? |
| 407 web_contents_for_stream->GetMainFrame() : NULL; |
| 408 if (main_frame) { |
| 409 media_id = GetDesktopStreamsRegistry()->RequestMediaForStreamId( |
| 410 request.requested_video_device_id, |
| 411 main_frame->GetProcess()->GetID(), |
| 412 main_frame->GetRoutingID(), |
| 413 request.security_origin, |
| 414 &original_extension_name); |
| 415 } |
402 | 416 |
403 // Received invalid device id. | 417 // Received invalid device id. |
404 if (media_id.type == content::DesktopMediaID::TYPE_NONE) { | 418 if (media_id.type == content::DesktopMediaID::TYPE_NONE) { |
405 callback.Run(devices, content::MEDIA_DEVICE_INVALID_STATE, ui.Pass()); | 419 callback.Run(devices, content::MEDIA_DEVICE_INVALID_STATE, ui.Pass()); |
406 return; | 420 return; |
407 } | 421 } |
408 | 422 |
409 bool loopback_audio_supported = false; | 423 bool loopback_audio_supported = false; |
410 #if defined(USE_CRAS) || defined(OS_WIN) | 424 #if defined(USE_CRAS) || defined(OS_WIN) |
411 // Currently loopback audio capture is supported only on Windows and ChromeOS. | 425 // Currently loopback audio capture is supported only on Windows and ChromeOS. |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
538 #if defined(ENABLE_EXTENSIONS) | 552 #if defined(ENABLE_EXTENSIONS) |
539 Profile* profile = | 553 Profile* profile = |
540 Profile::FromBrowserContext(web_contents->GetBrowserContext()); | 554 Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
541 extensions::TabCaptureRegistry* tab_capture_registry = | 555 extensions::TabCaptureRegistry* tab_capture_registry = |
542 extensions::TabCaptureRegistry::Get(profile); | 556 extensions::TabCaptureRegistry::Get(profile); |
543 if (!tab_capture_registry) { | 557 if (!tab_capture_registry) { |
544 NOTREACHED(); | 558 NOTREACHED(); |
545 callback.Run(devices, content::MEDIA_DEVICE_INVALID_STATE, ui.Pass()); | 559 callback.Run(devices, content::MEDIA_DEVICE_INVALID_STATE, ui.Pass()); |
546 return; | 560 return; |
547 } | 561 } |
548 bool tab_capture_allowed = | 562 const bool tab_capture_allowed = tab_capture_registry->VerifyRequest( |
549 tab_capture_registry->VerifyRequest(request.render_process_id, | 563 request.render_process_id, request.render_frame_id, extension->id()); |
550 request.render_view_id); | |
551 | 564 |
552 if (request.audio_type == content::MEDIA_TAB_AUDIO_CAPTURE && | 565 if (request.audio_type == content::MEDIA_TAB_AUDIO_CAPTURE && |
553 tab_capture_allowed && | 566 tab_capture_allowed && |
554 extension->permissions_data()->HasAPIPermission( | 567 extension->permissions_data()->HasAPIPermission( |
555 extensions::APIPermission::kTabCapture)) { | 568 extensions::APIPermission::kTabCapture)) { |
556 devices.push_back(content::MediaStreamDevice( | 569 devices.push_back(content::MediaStreamDevice( |
557 content::MEDIA_TAB_AUDIO_CAPTURE, std::string(), std::string())); | 570 content::MEDIA_TAB_AUDIO_CAPTURE, std::string(), std::string())); |
558 } | 571 } |
559 | 572 |
560 if (request.video_type == content::MEDIA_TAB_VIDEO_CAPTURE && | 573 if (request.video_type == content::MEDIA_TAB_VIDEO_CAPTURE && |
561 tab_capture_allowed && | 574 tab_capture_allowed && |
562 extension->permissions_data()->HasAPIPermission( | 575 extension->permissions_data()->HasAPIPermission( |
563 extensions::APIPermission::kTabCapture)) { | 576 extensions::APIPermission::kTabCapture)) { |
564 devices.push_back(content::MediaStreamDevice( | 577 devices.push_back(content::MediaStreamDevice( |
565 content::MEDIA_TAB_VIDEO_CAPTURE, std::string(), std::string())); | 578 content::MEDIA_TAB_VIDEO_CAPTURE, std::string(), std::string())); |
566 } | 579 } |
567 | 580 |
568 if (!devices.empty()) { | 581 if (!devices.empty()) { |
569 ui = media_stream_capture_indicator_->RegisterMediaStream( | 582 ui = media_stream_capture_indicator_->RegisterMediaStream( |
570 web_contents, devices); | 583 web_contents, devices); |
571 } | 584 } |
572 callback.Run( | 585 callback.Run( |
573 devices, | 586 devices, |
574 devices.empty() ? content::MEDIA_DEVICE_INVALID_STATE : | 587 devices.empty() ? content::MEDIA_DEVICE_INVALID_STATE : |
575 content::MEDIA_DEVICE_OK, | 588 content::MEDIA_DEVICE_OK, |
576 ui.Pass()); | 589 ui.Pass()); |
577 #else // defined(ENABLE_EXTENSIONS) | 590 #else // defined(ENABLE_EXTENSIONS) |
578 callback.Run(devices, content::MEDIA_DEVICE_TAB_CAPTURE_FAILURE, ui.Pass()); | 591 callback.Run(devices, content::MEDIA_DEVICE_TAB_CAPTURE_FAILURE, ui.Pass()); |
579 #endif // !defined(OS_ANDROID) | 592 #endif // defined(ENABLE_EXTENSIONS) |
580 } | 593 } |
581 | 594 |
582 void MediaCaptureDevicesDispatcher:: | 595 void MediaCaptureDevicesDispatcher:: |
583 ProcessMediaAccessRequestFromPlatformAppOrExtension( | 596 ProcessMediaAccessRequestFromPlatformAppOrExtension( |
584 content::WebContents* web_contents, | 597 content::WebContents* web_contents, |
585 const content::MediaStreamRequest& request, | 598 const content::MediaStreamRequest& request, |
586 const content::MediaResponseCallback& callback, | 599 const content::MediaResponseCallback& callback, |
587 const extensions::Extension* extension) { | 600 const extensions::Extension* extension) { |
588 content::MediaStreamDevices devices; | 601 content::MediaStreamDevices devices; |
589 Profile* profile = | 602 Profile* profile = |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
797 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 810 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
798 BrowserThread::PostTask( | 811 BrowserThread::PostTask( |
799 BrowserThread::UI, FROM_HERE, | 812 BrowserThread::UI, FROM_HERE, |
800 base::Bind( | 813 base::Bind( |
801 &MediaCaptureDevicesDispatcher::NotifyVideoDevicesChangedOnUIThread, | 814 &MediaCaptureDevicesDispatcher::NotifyVideoDevicesChangedOnUIThread, |
802 base::Unretained(this))); | 815 base::Unretained(this))); |
803 } | 816 } |
804 | 817 |
805 void MediaCaptureDevicesDispatcher::OnMediaRequestStateChanged( | 818 void MediaCaptureDevicesDispatcher::OnMediaRequestStateChanged( |
806 int render_process_id, | 819 int render_process_id, |
807 int render_view_id, | 820 int render_frame_id, |
808 int page_request_id, | 821 int page_request_id, |
809 const GURL& security_origin, | 822 const GURL& security_origin, |
810 const content::MediaStreamDevice& device, | 823 content::MediaStreamType stream_type, |
811 content::MediaRequestState state) { | 824 content::MediaRequestState state) { |
812 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 825 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
813 BrowserThread::PostTask( | 826 BrowserThread::PostTask( |
814 BrowserThread::UI, FROM_HERE, | 827 BrowserThread::UI, FROM_HERE, |
815 base::Bind( | 828 base::Bind( |
816 &MediaCaptureDevicesDispatcher::UpdateMediaRequestStateOnUIThread, | 829 &MediaCaptureDevicesDispatcher::UpdateMediaRequestStateOnUIThread, |
817 base::Unretained(this), render_process_id, render_view_id, | 830 base::Unretained(this), render_process_id, render_frame_id, |
818 page_request_id, security_origin, device, state)); | 831 page_request_id, security_origin, stream_type, state)); |
819 } | 832 } |
820 | 833 |
821 void MediaCaptureDevicesDispatcher::OnAudioStreamPlaying( | 834 void MediaCaptureDevicesDispatcher::OnAudioStreamPlaying( |
822 int render_process_id, | 835 int render_process_id, |
823 int render_frame_id, | 836 int render_frame_id, |
824 int stream_id, | 837 int stream_id, |
825 const ReadPowerAndClipCallback& read_power_callback) { | 838 const ReadPowerAndClipCallback& read_power_callback) { |
826 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 839 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
827 #if defined(AUDIO_STREAM_MONITORING) | 840 #if defined(AUDIO_STREAM_MONITORING) |
828 BrowserThread::PostTask( | 841 BrowserThread::PostTask( |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
870 } | 883 } |
871 | 884 |
872 void MediaCaptureDevicesDispatcher::NotifyVideoDevicesChangedOnUIThread() { | 885 void MediaCaptureDevicesDispatcher::NotifyVideoDevicesChangedOnUIThread() { |
873 MediaStreamDevices devices = GetVideoCaptureDevices(); | 886 MediaStreamDevices devices = GetVideoCaptureDevices(); |
874 FOR_EACH_OBSERVER(Observer, observers_, | 887 FOR_EACH_OBSERVER(Observer, observers_, |
875 OnUpdateVideoDevices(devices)); | 888 OnUpdateVideoDevices(devices)); |
876 } | 889 } |
877 | 890 |
878 void MediaCaptureDevicesDispatcher::UpdateMediaRequestStateOnUIThread( | 891 void MediaCaptureDevicesDispatcher::UpdateMediaRequestStateOnUIThread( |
879 int render_process_id, | 892 int render_process_id, |
880 int render_view_id, | 893 int render_frame_id, |
881 int page_request_id, | 894 int page_request_id, |
882 const GURL& security_origin, | 895 const GURL& security_origin, |
883 const content::MediaStreamDevice& device, | 896 content::MediaStreamType stream_type, |
884 content::MediaRequestState state) { | 897 content::MediaRequestState state) { |
885 // Track desktop capture sessions. Tracking is necessary to avoid unbalanced | 898 // Track desktop capture sessions. Tracking is necessary to avoid unbalanced |
886 // session counts since not all requests will reach MEDIA_REQUEST_STATE_DONE, | 899 // session counts since not all requests will reach MEDIA_REQUEST_STATE_DONE, |
887 // but they will all reach MEDIA_REQUEST_STATE_CLOSING. | 900 // but they will all reach MEDIA_REQUEST_STATE_CLOSING. |
888 if (device.type == content::MEDIA_DESKTOP_VIDEO_CAPTURE) { | 901 if (stream_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE) { |
889 if (state == content::MEDIA_REQUEST_STATE_DONE) { | 902 if (state == content::MEDIA_REQUEST_STATE_DONE) { |
890 DesktopCaptureSession session = { render_process_id, render_view_id, | 903 DesktopCaptureSession session = { render_process_id, render_frame_id, |
891 page_request_id }; | 904 page_request_id }; |
892 desktop_capture_sessions_.push_back(session); | 905 desktop_capture_sessions_.push_back(session); |
893 } else if (state == content::MEDIA_REQUEST_STATE_CLOSING) { | 906 } else if (state == content::MEDIA_REQUEST_STATE_CLOSING) { |
894 for (DesktopCaptureSessions::iterator it = | 907 for (DesktopCaptureSessions::iterator it = |
895 desktop_capture_sessions_.begin(); | 908 desktop_capture_sessions_.begin(); |
896 it != desktop_capture_sessions_.end(); | 909 it != desktop_capture_sessions_.end(); |
897 ++it) { | 910 ++it) { |
898 if (it->render_process_id == render_process_id && | 911 if (it->render_process_id == render_process_id && |
899 it->render_view_id == render_view_id && | 912 it->render_frame_id == render_frame_id && |
900 it->page_request_id == page_request_id) { | 913 it->page_request_id == page_request_id) { |
901 desktop_capture_sessions_.erase(it); | 914 desktop_capture_sessions_.erase(it); |
902 break; | 915 break; |
903 } | 916 } |
904 } | 917 } |
905 } | 918 } |
906 } | 919 } |
907 | 920 |
908 // Cancel the request. | 921 // Cancel the request. |
909 if (state == content::MEDIA_REQUEST_STATE_CLOSING) { | 922 if (state == content::MEDIA_REQUEST_STATE_CLOSING) { |
910 bool found = false; | 923 bool found = false; |
911 for (RequestsQueues::iterator rqs_it = pending_requests_.begin(); | 924 for (RequestsQueues::iterator rqs_it = pending_requests_.begin(); |
912 rqs_it != pending_requests_.end(); ++rqs_it) { | 925 rqs_it != pending_requests_.end(); ++rqs_it) { |
913 RequestsQueue& queue = rqs_it->second; | 926 RequestsQueue& queue = rqs_it->second; |
914 for (RequestsQueue::iterator it = queue.begin(); | 927 for (RequestsQueue::iterator it = queue.begin(); |
915 it != queue.end(); ++it) { | 928 it != queue.end(); ++it) { |
916 if (it->request.render_process_id == render_process_id && | 929 if (it->request.render_process_id == render_process_id && |
917 it->request.render_view_id == render_view_id && | 930 it->request.render_frame_id == render_frame_id && |
918 it->request.page_request_id == page_request_id) { | 931 it->request.page_request_id == page_request_id) { |
919 queue.erase(it); | 932 queue.erase(it); |
920 found = true; | 933 found = true; |
921 break; | 934 break; |
922 } | 935 } |
923 } | 936 } |
924 if (found) | 937 if (found) |
925 break; | 938 break; |
926 } | 939 } |
927 } | 940 } |
928 | 941 |
929 #if defined(OS_CHROMEOS) | 942 #if defined(OS_CHROMEOS) |
930 if (IsOriginForCasting(security_origin) && IsVideoMediaType(device.type)) { | 943 if (IsOriginForCasting(security_origin) && IsVideoMediaType(stream_type)) { |
931 // Notify ash that casting state has changed. | 944 // Notify ash that casting state has changed. |
932 if (state == content::MEDIA_REQUEST_STATE_DONE) { | 945 if (state == content::MEDIA_REQUEST_STATE_DONE) { |
933 ash::Shell::GetInstance()->OnCastingSessionStartedOrStopped(true); | 946 ash::Shell::GetInstance()->OnCastingSessionStartedOrStopped(true); |
934 } else if (state == content::MEDIA_REQUEST_STATE_CLOSING) { | 947 } else if (state == content::MEDIA_REQUEST_STATE_CLOSING) { |
935 ash::Shell::GetInstance()->OnCastingSessionStartedOrStopped(false); | 948 ash::Shell::GetInstance()->OnCastingSessionStartedOrStopped(false); |
936 } | 949 } |
937 } | 950 } |
938 #endif | 951 #endif |
939 | 952 |
940 FOR_EACH_OBSERVER(Observer, observers_, | 953 FOR_EACH_OBSERVER(Observer, observers_, |
941 OnRequestUpdate(render_process_id, | 954 OnRequestUpdate(render_process_id, |
942 render_view_id, | 955 render_frame_id, |
943 device, | 956 stream_type, |
944 state)); | 957 state)); |
945 } | 958 } |
946 | 959 |
947 void MediaCaptureDevicesDispatcher::OnCreatingAudioStreamOnUIThread( | 960 void MediaCaptureDevicesDispatcher::OnCreatingAudioStreamOnUIThread( |
948 int render_process_id, | 961 int render_process_id, |
949 int render_frame_id) { | 962 int render_frame_id) { |
950 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 963 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
951 FOR_EACH_OBSERVER(Observer, observers_, | 964 FOR_EACH_OBSERVER(Observer, observers_, |
952 OnCreatingAudioStream(render_process_id, render_frame_id)); | 965 OnCreatingAudioStream(render_process_id, render_frame_id)); |
953 #if defined(AUDIO_STREAM_MONITORING) | 966 #if defined(AUDIO_STREAM_MONITORING) |
(...skipping 16 matching lines...) Expand all Loading... |
970 | 983 |
971 void MediaCaptureDevicesDispatcher::SetTestAudioCaptureDevices( | 984 void MediaCaptureDevicesDispatcher::SetTestAudioCaptureDevices( |
972 const MediaStreamDevices& devices) { | 985 const MediaStreamDevices& devices) { |
973 test_audio_devices_ = devices; | 986 test_audio_devices_ = devices; |
974 } | 987 } |
975 | 988 |
976 void MediaCaptureDevicesDispatcher::SetTestVideoCaptureDevices( | 989 void MediaCaptureDevicesDispatcher::SetTestVideoCaptureDevices( |
977 const MediaStreamDevices& devices) { | 990 const MediaStreamDevices& devices) { |
978 test_video_devices_ = devices; | 991 test_video_devices_ = devices; |
979 } | 992 } |
OLD | NEW |