Chromium Code Reviews| Index: content/renderer/media/user_media_client_impl.cc |
| diff --git a/content/renderer/media/user_media_client_impl.cc b/content/renderer/media/user_media_client_impl.cc |
| index c490a1c36117ccfaf9168a8893e34afd7b1cad7d..1ff102e63cf2d33cf5ea60318325dac991b6a813 100644 |
| --- a/content/renderer/media/user_media_client_impl.cc |
| +++ b/content/renderer/media/user_media_client_impl.cc |
| @@ -18,12 +18,15 @@ |
| #include "base/strings/string_util.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/strings/utf_string_conversions.h" |
| +#include "base/task_runner.h" |
| +#include "base/task_runner_util.h" |
| #include "base/threading/thread_task_runner_handle.h" |
| #include "build/build_config.h" |
| #include "content/public/renderer/render_frame.h" |
| #include "content/renderer/media/local_media_stream_audio_source.h" |
| #include "content/renderer/media/media_stream.h" |
| #include "content/renderer/media/media_stream_constraints_util.h" |
| +#include "content/renderer/media/media_stream_constraints_util_video_source.h" |
| #include "content/renderer/media/media_stream_dispatcher.h" |
| #include "content/renderer/media/media_stream_video_capturer_source.h" |
| #include "content/renderer/media/media_stream_video_track.h" |
| @@ -33,6 +36,7 @@ |
| #include "content/renderer/media/webrtc_logging.h" |
| #include "content/renderer/media/webrtc_uma_histograms.h" |
| #include "content/renderer/render_thread_impl.h" |
| +#include "media/capture/video_capture_types.h" |
| #include "third_party/WebKit/public/platform/URLConversion.h" |
| #include "third_party/WebKit/public/platform/WebMediaConstraints.h" |
| #include "third_party/WebKit/public/platform/WebMediaDeviceInfo.h" |
| @@ -40,6 +44,7 @@ |
| #include "third_party/WebKit/public/platform/WebString.h" |
| #include "third_party/WebKit/public/web/WebDocument.h" |
| #include "third_party/WebKit/public/web/WebLocalFrame.h" |
| +#include "third_party/WebKit/public/web/WebUserGestureIndicator.h" |
| namespace content { |
| namespace { |
| @@ -214,13 +219,27 @@ static int g_next_request_id = 0; |
| } // namespace |
| +struct UserMediaClientImpl::RequestSettings { |
| + RequestSettings(bool is_processing_user_gesture, url::Origin security_origin) |
| + : enable_automatic_audio_output_device_selection(false), |
| + is_processing_user_gesture(is_processing_user_gesture), |
| + security_origin(security_origin) {} |
| + ~RequestSettings() = default; |
| + |
| + bool enable_automatic_audio_output_device_selection; |
| + bool is_processing_user_gesture; |
| + url::Origin security_origin; |
| +}; |
| + |
| UserMediaClientImpl::UserMediaClientImpl( |
| RenderFrame* render_frame, |
| PeerConnectionDependencyFactory* dependency_factory, |
| - std::unique_ptr<MediaStreamDispatcher> media_stream_dispatcher) |
| + std::unique_ptr<MediaStreamDispatcher> media_stream_dispatcher, |
| + const scoped_refptr<base::TaskRunner>& worker_task_runner) |
| : RenderFrameObserver(render_frame), |
| dependency_factory_(dependency_factory), |
| media_stream_dispatcher_(std::move(media_stream_dispatcher)), |
| + worker_task_runner_(worker_task_runner), |
|
tommi (sloooow) - chröme
2017/02/03 18:03:06
can worker_task_runner_ be const?
Guido Urdaneta
2017/02/03 21:33:04
Done.
|
| weak_factory_(this) { |
| DCHECK(dependency_factory_); |
| DCHECK(media_stream_dispatcher_.get()); |
| @@ -256,9 +275,16 @@ void UserMediaClientImpl::requestUserMedia( |
| int request_id = g_next_request_id++; |
| std::unique_ptr<StreamControls> controls = base::MakeUnique<StreamControls>(); |
| - bool enable_automatic_output_device_selection = false; |
| - bool request_audio_input_devices = false; |
| + // The value returned by isProcessingUserGesture() is used by the browser to |
| + // make decisions about the permissions UI. Its value can be lost while |
| + // switching threads, so saving its value here. |
| + RequestSettings request_settings( |
| + blink::WebUserGestureIndicator::isProcessingUserGesture(), |
| + static_cast<url::Origin>(user_media_request.getSecurityOrigin())); |
| if (user_media_request.audio()) { |
| + bool request_audio_input_devices = false; |
| + // TODO(guidou): Implement spec-compliant device selection for audio. See |
| + // http://crbug.com/623104. |
| CopyConstraintsToTrackControls(user_media_request.audioConstraints(), |
| &controls->audio, |
| &request_audio_input_devices); |
| @@ -269,73 +295,122 @@ void UserMediaClientImpl::requestUserMedia( |
| GetConstraintValueAsBoolean( |
| user_media_request.audioConstraints(), |
| &blink::WebMediaTrackConstraintSet::renderToAssociatedSink, |
| - &enable_automatic_output_device_selection); |
| - } |
| - bool request_video_input_devices = false; |
| - if (user_media_request.video()) { |
| - CopyConstraintsToTrackControls(user_media_request.videoConstraints(), |
| - &controls->video, |
| - &request_video_input_devices); |
| + &request_settings.enable_automatic_audio_output_device_selection); |
| + |
| + if (request_audio_input_devices) { |
| + GetMediaDevicesDispatcher()->EnumerateDevices( |
| + true /* audio_input */, false /* video_input */, |
| + false /* audio_output */, request_settings.security_origin, |
| + base::Bind(&UserMediaClientImpl::SelectAudioInputDevice, |
| + weak_factory_.GetWeakPtr(), request_id, user_media_request, |
| + base::Passed(&controls), request_settings)); |
| + return; |
| + } |
| } |
| - url::Origin security_origin = user_media_request.getSecurityOrigin(); |
| - if (request_audio_input_devices || request_video_input_devices) { |
| - GetMediaDevicesDispatcher()->EnumerateDevices( |
| - request_audio_input_devices, request_video_input_devices, |
| - false /* request_audio_output_devices */, security_origin, |
| - base::Bind(&UserMediaClientImpl::SelectUserMediaDevice, |
| - weak_factory_.GetWeakPtr(), request_id, user_media_request, |
| - base::Passed(&controls), |
| - enable_automatic_output_device_selection, security_origin)); |
| - } else { |
| - FinalizeRequestUserMedia( |
| - request_id, user_media_request, std::move(controls), |
| - enable_automatic_output_device_selection, security_origin); |
| - } |
| + SetupVideoInput(request_id, user_media_request, std::move(controls), |
| + request_settings); |
| } |
| -void UserMediaClientImpl::SelectUserMediaDevice( |
| +void UserMediaClientImpl::SelectAudioInputDevice( |
| int request_id, |
| const blink::WebUserMediaRequest& user_media_request, |
| std::unique_ptr<StreamControls> controls, |
| - bool enable_automatic_output_device_selection, |
| - const url::Origin& security_origin, |
| + const RequestSettings& request_settings, |
| const EnumerationResult& device_enumeration) { |
| DCHECK(CalledOnValidThread()); |
| + DCHECK(controls->audio.requested); |
| + DCHECK(IsDeviceSource(controls->audio.stream_source)); |
| - if (controls->audio.requested && |
| - IsDeviceSource(controls->audio.stream_source)) { |
| - if (!PickDeviceId(user_media_request.audioConstraints(), |
| - device_enumeration[MEDIA_DEVICE_TYPE_AUDIO_INPUT], |
| - &controls->audio.device_id)) { |
| - GetUserMediaRequestFailed(user_media_request, MEDIA_DEVICE_NO_HARDWARE, |
| - ""); |
| - return; |
| - } |
| + if (!PickDeviceId(user_media_request.audioConstraints(), |
| + device_enumeration[MEDIA_DEVICE_TYPE_AUDIO_INPUT], |
| + &controls->audio.device_id)) { |
| + GetUserMediaRequestFailed(user_media_request, MEDIA_DEVICE_NO_HARDWARE, ""); |
| + return; |
| } |
| - if (controls->video.requested && |
| - IsDeviceSource(controls->video.stream_source)) { |
| - if (!PickDeviceId(user_media_request.videoConstraints(), |
| - device_enumeration[MEDIA_DEVICE_TYPE_VIDEO_INPUT], |
| - &controls->video.device_id)) { |
| - GetUserMediaRequestFailed(user_media_request, MEDIA_DEVICE_NO_HARDWARE, |
| - ""); |
| + SetupVideoInput(request_id, user_media_request, std::move(controls), |
| + request_settings); |
| +} |
| + |
| +void UserMediaClientImpl::SetupVideoInput( |
| + int request_id, |
| + const blink::WebUserMediaRequest& user_media_request, |
| + std::unique_ptr<StreamControls> controls, |
| + const RequestSettings& request_settings) { |
| + if (user_media_request.video()) { |
| + bool ignore; |
| + CopyConstraintsToTrackControls(user_media_request.videoConstraints(), |
| + &controls->video, &ignore); |
| + if (IsDeviceSource(controls->video.stream_source)) { |
| + GetMediaDevicesDispatcher()->GetVideoInputCapabilities( |
| + request_settings.security_origin, |
| + base::Bind(&UserMediaClientImpl::SelectVideoDeviceSourceSettings, |
| + weak_factory_.GetWeakPtr(), request_id, user_media_request, |
| + base::Passed(&controls), request_settings)); |
| return; |
| } |
| } |
| + FinalizeRequestUserMedia(request_id, user_media_request, std::move(controls), |
| + request_settings); |
| +} |
| +void UserMediaClientImpl::SelectVideoDeviceSourceSettings( |
| + int request_id, |
| + const blink::WebUserMediaRequest& user_media_request, |
| + std::unique_ptr<StreamControls> controls, |
| + const RequestSettings& request_settings, |
| + std::vector<::mojom::VideoInputDeviceCapabilitiesPtr> |
| + video_input_capabilities) { |
| + DCHECK(CalledOnValidThread()); |
| + DCHECK(controls->video.requested); |
| + DCHECK(IsDeviceSource(controls->video.stream_source)); |
| + |
| + VideoCaptureCapabilities capabilities; |
| + capabilities.device_capabilities = std::move(video_input_capabilities); |
| + capabilities.power_line_capabilities = { |
| + media::PowerLineFrequency::FREQUENCY_DEFAULT, |
| + media::PowerLineFrequency::FREQUENCY_50HZ, |
| + media::PowerLineFrequency::FREQUENCY_60HZ}; |
| + |
| + base::PostTaskAndReplyWithResult( |
| + worker_task_runner_.get(), FROM_HERE, |
| + base::Bind(&SelectVideoCaptureSourceSettings, std::move(capabilities), |
| + user_media_request.videoConstraints()), |
| + base::Bind(&UserMediaClientImpl::FinalizeSelectVideoDeviceSourceSettings, |
| + weak_factory_.GetWeakPtr(), request_id, user_media_request, |
| + base::Passed(&controls), request_settings)); |
| +} |
| + |
| +void UserMediaClientImpl::FinalizeSelectVideoDeviceSourceSettings( |
| + int request_id, |
| + const blink::WebUserMediaRequest& user_media_request, |
| + std::unique_ptr<StreamControls> controls, |
| + const RequestSettings& request_settings, |
| + const VideoCaptureSourceSelectionResult& selection_result) { |
| + DCHECK(CalledOnValidThread()); |
| + // Select video device. |
| + if (!selection_result.has_value()) { |
| + blink::WebString failed_constraint_name = |
| + blink::WebString::fromASCII(selection_result.failed_constraint_name); |
| + MediaStreamRequestResult result = |
| + failed_constraint_name.isEmpty() |
| + ? MEDIA_DEVICE_NO_HARDWARE |
| + : MEDIA_DEVICE_CONSTRAINT_NOT_SATISFIED; |
| + GetUserMediaRequestFailed(user_media_request, result, |
| + failed_constraint_name); |
| + return; |
| + } |
| + controls->video.device_id = selection_result.settings.device_id(); |
| FinalizeRequestUserMedia(request_id, user_media_request, std::move(controls), |
| - enable_automatic_output_device_selection, |
| - security_origin); |
| + request_settings); |
| } |
| void UserMediaClientImpl::FinalizeRequestUserMedia( |
| int request_id, |
| const blink::WebUserMediaRequest& user_media_request, |
| std::unique_ptr<StreamControls> controls, |
| - bool enable_automatic_output_device_selection, |
| - const url::Origin& security_origin) { |
| + const RequestSettings& request_settings) { |
| DCHECK(CalledOnValidThread()); |
| WebRtcLogMessage( |
| @@ -345,12 +420,14 @@ void UserMediaClientImpl::FinalizeRequestUserMedia( |
| request_id, controls->audio.device_id.c_str(), |
| controls->video.device_id.c_str())); |
| - user_media_requests_.push_back(std::unique_ptr<UserMediaRequestInfo>( |
| - new UserMediaRequestInfo(request_id, user_media_request, |
| - enable_automatic_output_device_selection))); |
| + user_media_requests_.push_back(base::MakeUnique<UserMediaRequestInfo>( |
| + request_id, user_media_request, |
| + request_settings.enable_automatic_audio_output_device_selection)); |
| media_stream_dispatcher_->GenerateStream( |
| - request_id, weak_factory_.GetWeakPtr(), *controls, security_origin); |
| + request_id, weak_factory_.GetWeakPtr(), *controls, |
| + request_settings.security_origin, |
| + request_settings.is_processing_user_gesture); |
| } |
| void UserMediaClientImpl::cancelUserMediaRequest( |