Chromium Code Reviews| 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 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 185 ui = ScreenCaptureNotificationUI::Create(l10n_util::GetStringFUTF16( | 186 ui = ScreenCaptureNotificationUI::Create(l10n_util::GetStringFUTF16( |
| 186 IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_TEXT_DELEGATED, | 187 IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_TEXT_DELEGATED, |
| 187 registered_extension_name, | 188 registered_extension_name, |
| 188 application_title)); | 189 application_title)); |
| 189 } | 190 } |
| 190 } | 191 } |
| 191 | 192 |
| 192 return ui.Pass(); | 193 return ui.Pass(); |
| 193 } | 194 } |
| 194 | 195 |
| 196 // Returns the WebContents instance that contains the RenderFrameHost referenced | |
| 197 // by the given |request|. | |
| 198 content::WebContents* GetWebContentsFromRequest( | |
| 199 const content::MediaStreamRequest& request) { | |
| 200 return content::WebContents::FromRenderFrameHost( | |
| 201 content::RenderFrameHost::FromID(request.render_process_id, | |
| 202 request.render_frame_id)); | |
| 203 } | |
| 204 | |
| 195 #if defined(AUDIO_STREAM_MONITORING) | 205 #if defined(AUDIO_STREAM_MONITORING) |
| 196 | 206 |
| 197 AudioStreamMonitor* AudioStreamMonitorFromRenderFrame( | 207 AudioStreamMonitor* AudioStreamMonitorFromRenderFrame( |
| 198 int render_process_id, | 208 int render_process_id, |
| 199 int render_frame_id) { | 209 int render_frame_id) { |
| 200 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 201 content::WebContents* const web_contents = | 211 content::WebContents* const web_contents = |
| 202 content::WebContents::FromRenderFrameHost( | 212 content::WebContents::FromRenderFrameHost( |
| 203 content::RenderFrameHost::FromID(render_process_id, render_frame_id)); | 213 content::RenderFrameHost::FromID(render_process_id, render_frame_id)); |
| 204 if (!web_contents) | 214 if (!web_contents) |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 387 // (i.e. chooseDesktopMedia() API wasn't used to generate device id). | 397 // (i.e. chooseDesktopMedia() API wasn't used to generate device id). |
| 388 if (request.requested_video_device_id.empty()) { | 398 if (request.requested_video_device_id.empty()) { |
| 389 ProcessScreenCaptureAccessRequest( | 399 ProcessScreenCaptureAccessRequest( |
| 390 web_contents, request, callback, extension); | 400 web_contents, request, callback, extension); |
| 391 return; | 401 return; |
| 392 } | 402 } |
| 393 | 403 |
| 394 // The extension name that the stream is registered with. | 404 // The extension name that the stream is registered with. |
| 395 std::string original_extension_name; | 405 std::string original_extension_name; |
| 396 // Resolve DesktopMediaID for the specified device id. | 406 // Resolve DesktopMediaID for the specified device id. |
| 397 content::DesktopMediaID media_id = | 407 content::DesktopMediaID media_id; |
| 398 GetDesktopStreamsRegistry()->RequestMediaForStreamId( | 408 // TODO(miu): Replace "main RenderFrame" IDs with the request's actual |
| 399 request.requested_video_device_id, request.render_process_id, | 409 // RenderFrame IDs once the desktop capture extension API implementation is |
| 400 request.render_view_id, request.security_origin, | 410 // fixed. http://crbug.com/304341 |
| 401 &original_extension_name); | 411 content::WebContents* const web_contents_for_stream = |
| 412 GetWebContentsFromRequest(request); | |
| 413 content::RenderFrameHost* const main_frame = web_contents_for_stream ? | |
| 414 web_contents_for_stream->GetMainFrame() : NULL; | |
| 415 if (main_frame) { | |
| 416 media_id = GetDesktopStreamsRegistry()->RequestMediaForStreamId( | |
| 417 request.requested_video_device_id, | |
| 418 main_frame->GetProcess()->GetID(), | |
| 419 main_frame->GetRoutingID(), | |
|
ncarter (slow)
2014/07/11 22:32:24
This ultimately should be request.render_process_i
miu
2014/07/12 03:16:29
See TODO(miu) comment about 10 lines above. ;-)
ncarter (slow)
2014/07/14 17:51:05
Ah got it now. I'd seen the TODO but it hadn't qui
| |
| 420 request.security_origin, | |
| 421 &original_extension_name); | |
| 422 } | |
| 402 | 423 |
| 403 // Received invalid device id. | 424 // Received invalid device id. |
| 404 if (media_id.type == content::DesktopMediaID::TYPE_NONE) { | 425 if (media_id.type == content::DesktopMediaID::TYPE_NONE) { |
| 405 callback.Run(devices, content::MEDIA_DEVICE_INVALID_STATE, ui.Pass()); | 426 callback.Run(devices, content::MEDIA_DEVICE_INVALID_STATE, ui.Pass()); |
| 406 return; | 427 return; |
| 407 } | 428 } |
| 408 | 429 |
| 409 bool loopback_audio_supported = false; | 430 bool loopback_audio_supported = false; |
| 410 #if defined(USE_CRAS) || defined(OS_WIN) | 431 #if defined(USE_CRAS) || defined(OS_WIN) |
| 411 // Currently loopback audio capture is supported only on Windows and ChromeOS. | 432 // 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) | 559 #if defined(ENABLE_EXTENSIONS) |
| 539 Profile* profile = | 560 Profile* profile = |
| 540 Profile::FromBrowserContext(web_contents->GetBrowserContext()); | 561 Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
| 541 extensions::TabCaptureRegistry* tab_capture_registry = | 562 extensions::TabCaptureRegistry* tab_capture_registry = |
| 542 extensions::TabCaptureRegistry::Get(profile); | 563 extensions::TabCaptureRegistry::Get(profile); |
| 543 if (!tab_capture_registry) { | 564 if (!tab_capture_registry) { |
| 544 NOTREACHED(); | 565 NOTREACHED(); |
| 545 callback.Run(devices, content::MEDIA_DEVICE_INVALID_STATE, ui.Pass()); | 566 callback.Run(devices, content::MEDIA_DEVICE_INVALID_STATE, ui.Pass()); |
| 546 return; | 567 return; |
| 547 } | 568 } |
| 548 bool tab_capture_allowed = | 569 const bool tab_capture_allowed = tab_capture_registry->VerifyRequest( |
| 549 tab_capture_registry->VerifyRequest(request.render_process_id, | 570 GetWebContentsFromRequest(request), extension->id()); |
| 550 request.render_view_id); | |
| 551 | 571 |
| 552 if (request.audio_type == content::MEDIA_TAB_AUDIO_CAPTURE && | 572 if (request.audio_type == content::MEDIA_TAB_AUDIO_CAPTURE && |
| 553 tab_capture_allowed && | 573 tab_capture_allowed && |
| 554 extension->permissions_data()->HasAPIPermission( | 574 extension->permissions_data()->HasAPIPermission( |
| 555 extensions::APIPermission::kTabCapture)) { | 575 extensions::APIPermission::kTabCapture)) { |
| 556 devices.push_back(content::MediaStreamDevice( | 576 devices.push_back(content::MediaStreamDevice( |
| 557 content::MEDIA_TAB_AUDIO_CAPTURE, std::string(), std::string())); | 577 content::MEDIA_TAB_AUDIO_CAPTURE, std::string(), std::string())); |
| 558 } | 578 } |
| 559 | 579 |
| 560 if (request.video_type == content::MEDIA_TAB_VIDEO_CAPTURE && | 580 if (request.video_type == content::MEDIA_TAB_VIDEO_CAPTURE && |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 797 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 817 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 798 BrowserThread::PostTask( | 818 BrowserThread::PostTask( |
| 799 BrowserThread::UI, FROM_HERE, | 819 BrowserThread::UI, FROM_HERE, |
| 800 base::Bind( | 820 base::Bind( |
| 801 &MediaCaptureDevicesDispatcher::NotifyVideoDevicesChangedOnUIThread, | 821 &MediaCaptureDevicesDispatcher::NotifyVideoDevicesChangedOnUIThread, |
| 802 base::Unretained(this))); | 822 base::Unretained(this))); |
| 803 } | 823 } |
| 804 | 824 |
| 805 void MediaCaptureDevicesDispatcher::OnMediaRequestStateChanged( | 825 void MediaCaptureDevicesDispatcher::OnMediaRequestStateChanged( |
| 806 int render_process_id, | 826 int render_process_id, |
| 807 int render_view_id, | 827 int render_frame_id, |
| 808 int page_request_id, | 828 int page_request_id, |
| 809 const GURL& security_origin, | 829 const GURL& security_origin, |
| 810 const content::MediaStreamDevice& device, | 830 content::MediaStreamType stream_type, |
| 811 content::MediaRequestState state) { | 831 content::MediaRequestState state) { |
| 812 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 832 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 813 BrowserThread::PostTask( | 833 BrowserThread::PostTask( |
| 814 BrowserThread::UI, FROM_HERE, | 834 BrowserThread::UI, FROM_HERE, |
| 815 base::Bind( | 835 base::Bind( |
| 816 &MediaCaptureDevicesDispatcher::UpdateMediaRequestStateOnUIThread, | 836 &MediaCaptureDevicesDispatcher::UpdateMediaRequestStateOnUIThread, |
| 817 base::Unretained(this), render_process_id, render_view_id, | 837 base::Unretained(this), render_process_id, render_frame_id, |
| 818 page_request_id, security_origin, device, state)); | 838 page_request_id, security_origin, stream_type, state)); |
| 819 } | 839 } |
| 820 | 840 |
| 821 void MediaCaptureDevicesDispatcher::OnAudioStreamPlaying( | 841 void MediaCaptureDevicesDispatcher::OnAudioStreamPlaying( |
| 822 int render_process_id, | 842 int render_process_id, |
| 823 int render_frame_id, | 843 int render_frame_id, |
| 824 int stream_id, | 844 int stream_id, |
| 825 const ReadPowerAndClipCallback& read_power_callback) { | 845 const ReadPowerAndClipCallback& read_power_callback) { |
| 826 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 846 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 827 #if defined(AUDIO_STREAM_MONITORING) | 847 #if defined(AUDIO_STREAM_MONITORING) |
| 828 BrowserThread::PostTask( | 848 BrowserThread::PostTask( |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 870 } | 890 } |
| 871 | 891 |
| 872 void MediaCaptureDevicesDispatcher::NotifyVideoDevicesChangedOnUIThread() { | 892 void MediaCaptureDevicesDispatcher::NotifyVideoDevicesChangedOnUIThread() { |
| 873 MediaStreamDevices devices = GetVideoCaptureDevices(); | 893 MediaStreamDevices devices = GetVideoCaptureDevices(); |
| 874 FOR_EACH_OBSERVER(Observer, observers_, | 894 FOR_EACH_OBSERVER(Observer, observers_, |
| 875 OnUpdateVideoDevices(devices)); | 895 OnUpdateVideoDevices(devices)); |
| 876 } | 896 } |
| 877 | 897 |
| 878 void MediaCaptureDevicesDispatcher::UpdateMediaRequestStateOnUIThread( | 898 void MediaCaptureDevicesDispatcher::UpdateMediaRequestStateOnUIThread( |
| 879 int render_process_id, | 899 int render_process_id, |
| 880 int render_view_id, | 900 int render_frame_id, |
| 881 int page_request_id, | 901 int page_request_id, |
| 882 const GURL& security_origin, | 902 const GURL& security_origin, |
| 883 const content::MediaStreamDevice& device, | 903 content::MediaStreamType stream_type, |
| 884 content::MediaRequestState state) { | 904 content::MediaRequestState state) { |
| 885 // Track desktop capture sessions. Tracking is necessary to avoid unbalanced | 905 // Track desktop capture sessions. Tracking is necessary to avoid unbalanced |
| 886 // session counts since not all requests will reach MEDIA_REQUEST_STATE_DONE, | 906 // session counts since not all requests will reach MEDIA_REQUEST_STATE_DONE, |
| 887 // but they will all reach MEDIA_REQUEST_STATE_CLOSING. | 907 // but they will all reach MEDIA_REQUEST_STATE_CLOSING. |
| 888 if (device.type == content::MEDIA_DESKTOP_VIDEO_CAPTURE) { | 908 if (stream_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE) { |
| 889 if (state == content::MEDIA_REQUEST_STATE_DONE) { | 909 if (state == content::MEDIA_REQUEST_STATE_DONE) { |
| 890 DesktopCaptureSession session = { render_process_id, render_view_id, | 910 DesktopCaptureSession session = { render_process_id, render_frame_id, |
| 891 page_request_id }; | 911 page_request_id }; |
| 892 desktop_capture_sessions_.push_back(session); | 912 desktop_capture_sessions_.push_back(session); |
| 893 } else if (state == content::MEDIA_REQUEST_STATE_CLOSING) { | 913 } else if (state == content::MEDIA_REQUEST_STATE_CLOSING) { |
| 894 for (DesktopCaptureSessions::iterator it = | 914 for (DesktopCaptureSessions::iterator it = |
| 895 desktop_capture_sessions_.begin(); | 915 desktop_capture_sessions_.begin(); |
| 896 it != desktop_capture_sessions_.end(); | 916 it != desktop_capture_sessions_.end(); |
| 897 ++it) { | 917 ++it) { |
| 898 if (it->render_process_id == render_process_id && | 918 if (it->render_process_id == render_process_id && |
| 899 it->render_view_id == render_view_id && | 919 it->render_frame_id == render_frame_id && |
| 900 it->page_request_id == page_request_id) { | 920 it->page_request_id == page_request_id) { |
| 901 desktop_capture_sessions_.erase(it); | 921 desktop_capture_sessions_.erase(it); |
| 902 break; | 922 break; |
| 903 } | 923 } |
| 904 } | 924 } |
| 905 } | 925 } |
| 906 } | 926 } |
| 907 | 927 |
| 908 // Cancel the request. | 928 // Cancel the request. |
| 909 if (state == content::MEDIA_REQUEST_STATE_CLOSING) { | 929 if (state == content::MEDIA_REQUEST_STATE_CLOSING) { |
| 910 bool found = false; | 930 bool found = false; |
| 911 for (RequestsQueues::iterator rqs_it = pending_requests_.begin(); | 931 for (RequestsQueues::iterator rqs_it = pending_requests_.begin(); |
| 912 rqs_it != pending_requests_.end(); ++rqs_it) { | 932 rqs_it != pending_requests_.end(); ++rqs_it) { |
| 913 RequestsQueue& queue = rqs_it->second; | 933 RequestsQueue& queue = rqs_it->second; |
| 914 for (RequestsQueue::iterator it = queue.begin(); | 934 for (RequestsQueue::iterator it = queue.begin(); |
| 915 it != queue.end(); ++it) { | 935 it != queue.end(); ++it) { |
| 916 if (it->request.render_process_id == render_process_id && | 936 if (it->request.render_process_id == render_process_id && |
| 917 it->request.render_view_id == render_view_id && | 937 it->request.render_frame_id == render_frame_id && |
| 918 it->request.page_request_id == page_request_id) { | 938 it->request.page_request_id == page_request_id) { |
| 919 queue.erase(it); | 939 queue.erase(it); |
| 920 found = true; | 940 found = true; |
| 921 break; | 941 break; |
| 922 } | 942 } |
| 923 } | 943 } |
| 924 if (found) | 944 if (found) |
| 925 break; | 945 break; |
| 926 } | 946 } |
| 927 } | 947 } |
| 928 | 948 |
| 929 #if defined(OS_CHROMEOS) | 949 #if defined(OS_CHROMEOS) |
| 930 if (IsOriginForCasting(security_origin) && IsVideoMediaType(device.type)) { | 950 if (IsOriginForCasting(security_origin) && IsVideoMediaType(stream_type)) { |
| 931 // Notify ash that casting state has changed. | 951 // Notify ash that casting state has changed. |
| 932 if (state == content::MEDIA_REQUEST_STATE_DONE) { | 952 if (state == content::MEDIA_REQUEST_STATE_DONE) { |
| 933 ash::Shell::GetInstance()->OnCastingSessionStartedOrStopped(true); | 953 ash::Shell::GetInstance()->OnCastingSessionStartedOrStopped(true); |
| 934 } else if (state == content::MEDIA_REQUEST_STATE_CLOSING) { | 954 } else if (state == content::MEDIA_REQUEST_STATE_CLOSING) { |
| 935 ash::Shell::GetInstance()->OnCastingSessionStartedOrStopped(false); | 955 ash::Shell::GetInstance()->OnCastingSessionStartedOrStopped(false); |
| 936 } | 956 } |
| 937 } | 957 } |
| 938 #endif | 958 #endif |
| 939 | 959 |
| 940 FOR_EACH_OBSERVER(Observer, observers_, | 960 FOR_EACH_OBSERVER(Observer, observers_, |
| 941 OnRequestUpdate(render_process_id, | 961 OnRequestUpdate(render_process_id, |
| 942 render_view_id, | 962 render_frame_id, |
| 943 device, | 963 stream_type, |
| 944 state)); | 964 state)); |
| 945 } | 965 } |
| 946 | 966 |
| 947 void MediaCaptureDevicesDispatcher::OnCreatingAudioStreamOnUIThread( | 967 void MediaCaptureDevicesDispatcher::OnCreatingAudioStreamOnUIThread( |
| 948 int render_process_id, | 968 int render_process_id, |
| 949 int render_frame_id) { | 969 int render_frame_id) { |
| 950 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 970 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 951 FOR_EACH_OBSERVER(Observer, observers_, | 971 FOR_EACH_OBSERVER(Observer, observers_, |
| 952 OnCreatingAudioStream(render_process_id, render_frame_id)); | 972 OnCreatingAudioStream(render_process_id, render_frame_id)); |
| 953 #if defined(AUDIO_STREAM_MONITORING) | 973 #if defined(AUDIO_STREAM_MONITORING) |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 970 | 990 |
| 971 void MediaCaptureDevicesDispatcher::SetTestAudioCaptureDevices( | 991 void MediaCaptureDevicesDispatcher::SetTestAudioCaptureDevices( |
| 972 const MediaStreamDevices& devices) { | 992 const MediaStreamDevices& devices) { |
| 973 test_audio_devices_ = devices; | 993 test_audio_devices_ = devices; |
| 974 } | 994 } |
| 975 | 995 |
| 976 void MediaCaptureDevicesDispatcher::SetTestVideoCaptureDevices( | 996 void MediaCaptureDevicesDispatcher::SetTestVideoCaptureDevices( |
| 977 const MediaStreamDevices& devices) { | 997 const MediaStreamDevices& devices) { |
| 978 test_video_devices_ = devices; | 998 test_video_devices_ = devices; |
| 979 } | 999 } |
| OLD | NEW |