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

Unified Diff: content/renderer/media/user_media_client_impl.cc

Issue 2764043002: Serialize processing of getUserMedia() requests. (Closed)
Patch Set: Address tommi's comments Created 3 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 side-by-side diff with in-line comments
Download patch
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 e1be3642700464332012ecb35b1602dd699a1930..a05ad28a5402febe7f4ef3a9a92fdfa02e30fe26 100644
--- a/content/renderer/media/user_media_client_impl.cc
+++ b/content/renderer/media/user_media_client_impl.cc
@@ -9,19 +9,14 @@
#include <algorithm>
#include <utility>
-#include "base/hash.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
-#include "base/strings/string_number_conversions.h"
-#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"
@@ -33,12 +28,10 @@
#include "content/renderer/media/media_stream_video_track.h"
#include "content/renderer/media/peer_connection_tracker.h"
#include "content/renderer/media/webrtc/processed_local_audio_source.h"
-#include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h"
#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"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
@@ -230,16 +223,92 @@ 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;
+// Class for storing information about a Blink request to create a
+// MediaStream.
+class UserMediaClientImpl::UserMediaRequestInfo
+ : public base::SupportsWeakPtr<UserMediaRequestInfo> {
+ public:
+ using ResourcesReady =
+ base::Callback<void(UserMediaRequestInfo* request_info,
+ MediaStreamRequestResult result,
+ const blink::WebString& result_name)>;
+ enum class State {
+ NOT_SENT_FOR_GENERATION,
+ SENT_FOR_GENERATION,
+ GENERATED,
+ };
+
+ UserMediaRequestInfo(int request_id,
+ const blink::WebUserMediaRequest& request,
+ bool is_processing_user_gesture,
+ const url::Origin& security_origin);
+
+ void StartAudioTrack(const blink::WebMediaStreamTrack& track,
+ bool is_pending);
+
+ blink::WebMediaStreamTrack CreateAndStartVideoTrack(
+ const blink::WebMediaStreamSource& source,
+ const blink::WebMediaConstraints& constraints);
+
+ // Triggers |callback| when all sources used in this request have either
+ // successfully started, or a source has failed to start.
+ void CallbackOnTracksStarted(const ResourcesReady& callback);
+
+ bool HasPendingSources() const;
+
+ // Called when a local audio source has finished (or failed) initializing.
+ void OnAudioSourceStarted(MediaStreamSource* source,
+ MediaStreamRequestResult result,
+ const blink::WebString& result_name);
+
+ int request_id() const { return request_id_; }
+
+ State state() const { return state_; }
+ void set_state(State state) { state_ = state; }
+
+ bool enable_automatic_output_device_selection() const {
+ return enable_automatic_output_device_selection_;
+ }
+ void set_enable_automatic_output_device_selection(bool value) {
+ enable_automatic_output_device_selection_ = value;
+ }
- bool enable_automatic_audio_output_device_selection;
- bool is_processing_user_gesture;
- url::Origin security_origin;
+ blink::WebMediaStream* web_stream() { return &web_stream_; }
+
+ const blink::WebUserMediaRequest& request() const { return request_; }
+
+ StreamControls* stream_controls() { return &stream_controls_; }
+
+ bool is_processing_user_gesture() const {
+ return is_processing_user_gesture_;
+ }
+
+ const url::Origin& security_origin() const { return security_origin_; }
+
+ private:
+ void OnTrackStarted(MediaStreamSource* source,
+ MediaStreamRequestResult result,
+ const blink::WebString& result_name);
+
+ // Cheks if the sources for all tracks have been started and if so,
+ // invoke the |ready_callback_|. Note that the caller should expect
+ // that |this| might be deleted when the function returns.
+ void CheckAllTracksStarted();
+
+ const int request_id_;
+ State state_;
+ bool enable_automatic_output_device_selection_;
+ blink::WebMediaStream web_stream_;
+ const blink::WebUserMediaRequest request_;
+ StreamControls stream_controls_;
+ const bool is_processing_user_gesture_;
+ const url::Origin security_origin_;
+ ResourcesReady ready_callback_;
+ MediaStreamRequestResult request_result_;
+ blink::WebString request_result_name_;
+ // Sources used in this request.
+ std::vector<blink::WebMediaStreamSource> sources_;
+ std::vector<MediaStreamSource*> sources_waiting_for_callback_;
};
UserMediaClientImpl::UserMediaClientImpl(
@@ -285,84 +354,106 @@ void UserMediaClientImpl::requestUserMedia(
}
int request_id = g_next_request_id++;
- std::unique_ptr<StreamControls> controls = base::MakeUnique<StreamControls>();
// 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()) {
+ std::unique_ptr<UserMediaRequestInfo> request_info =
+ base::MakeUnique<UserMediaRequestInfo>(
+ request_id, user_media_request,
+ blink::WebUserGestureIndicator::isProcessingUserGesture(),
+ static_cast<url::Origin>(user_media_request.getSecurityOrigin()));
+ pending_request_infos_.push_back(std::move(request_info));
+ if (!current_request_info_) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(&UserMediaClientImpl::MaybeProcessNextRequestInfo,
+ weak_factory_.GetWeakPtr()));
+ }
+}
+
+void UserMediaClientImpl::MaybeProcessNextRequestInfo() {
+ DCHECK(CalledOnValidThread());
+ if (current_request_info_ || pending_request_infos_.empty())
+ return;
+
+ current_request_info_ = std::move(pending_request_infos_.front());
+ pending_request_infos_.pop_front();
+
+ // TODO(guidou): Request audio and video capabilities in parallel.
+ if (current_request_info_->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);
+ CopyConstraintsToTrackControls(
+ current_request_info_->request().audioConstraints(),
+ &current_request_info_->stream_controls()->audio,
+ &request_audio_input_devices);
CopyHotwordAndLocalEchoToStreamControls(
- user_media_request.audioConstraints(), controls.get());
+ current_request_info_->request().audioConstraints(),
+ current_request_info_->stream_controls());
// Check if this input device should be used to select a matching output
// device for audio rendering.
+ bool enable_automatic_output_device_selection = false;
GetConstraintValueAsBoolean(
- user_media_request.audioConstraints(),
+ current_request_info_->request().audioConstraints(),
&blink::WebMediaTrackConstraintSet::renderToAssociatedSink,
- &request_settings.enable_automatic_audio_output_device_selection);
+ &enable_automatic_output_device_selection);
+ current_request_info_->set_enable_automatic_output_device_selection(
+ enable_automatic_output_device_selection);
if (request_audio_input_devices) {
GetMediaDevicesDispatcher()->EnumerateDevices(
true /* audio_input */, false /* video_input */,
- false /* audio_output */, request_settings.security_origin,
+ false /* audio_output */, current_request_info_->security_origin(),
base::Bind(&UserMediaClientImpl::SelectAudioInputDevice,
- weak_factory_.GetWeakPtr(), request_id, user_media_request,
- base::Passed(&controls), request_settings));
+ weak_factory_.GetWeakPtr(),
+ current_request_info_->request()));
return;
}
}
- SetupVideoInput(request_id, user_media_request, std::move(controls),
- request_settings);
+ SetupVideoInput(current_request_info_->request());
}
void UserMediaClientImpl::SelectAudioInputDevice(
- int request_id,
const blink::WebUserMediaRequest& user_media_request,
- std::unique_ptr<StreamControls> controls,
- const RequestSettings& request_settings,
const EnumerationResult& device_enumeration) {
DCHECK(CalledOnValidThread());
- DCHECK(controls->audio.requested);
- DCHECK(IsDeviceSource(controls->audio.stream_source));
+ if (!IsCurrentRequestInfo(user_media_request))
+ return;
+
+ auto& audio_controls = current_request_info_->stream_controls()->audio;
+ DCHECK(audio_controls.requested);
+ DCHECK(IsDeviceSource(audio_controls.stream_source));
if (!PickDeviceId(user_media_request.audioConstraints(),
device_enumeration[MEDIA_DEVICE_TYPE_AUDIO_INPUT],
- &controls->audio.device_id)) {
+ &audio_controls.device_id)) {
GetUserMediaRequestFailed(user_media_request, MEDIA_DEVICE_NO_HARDWARE, "");
return;
}
- SetupVideoInput(request_id, user_media_request, std::move(controls),
- request_settings);
+ SetupVideoInput(user_media_request);
}
void UserMediaClientImpl::SetupVideoInput(
- int request_id,
- const blink::WebUserMediaRequest& user_media_request,
- std::unique_ptr<StreamControls> controls,
- const RequestSettings& request_settings) {
+ const blink::WebUserMediaRequest& user_media_request) {
+ DCHECK(CalledOnValidThread());
+ if (!IsCurrentRequestInfo(user_media_request))
+ return;
+
if (!user_media_request.video()) {
- FinalizeRequestUserMedia(request_id, user_media_request,
- std::move(controls), request_settings);
+ GenerateStreamForCurrentRequestInfo();
return;
}
+ auto& video_controls = current_request_info_->stream_controls()->video;
InitializeTrackControls(user_media_request.videoConstraints(),
- &controls->video);
- if (IsDeviceSource(controls->video.stream_source)) {
+ &video_controls);
+ if (IsDeviceSource(video_controls.stream_source)) {
GetMediaDevicesDispatcher()->GetVideoInputCapabilities(
- request_settings.security_origin,
+ current_request_info_->security_origin(),
base::Bind(&UserMediaClientImpl::SelectVideoDeviceSourceSettings,
- weak_factory_.GetWeakPtr(), request_id, user_media_request,
- base::Passed(&controls), request_settings));
+ weak_factory_.GetWeakPtr(), user_media_request));
} else {
base::PostTaskAndReplyWithResult(
worker_task_runner_.get(), FROM_HERE,
@@ -370,21 +461,21 @@ void UserMediaClientImpl::SetupVideoInput(
user_media_request.videoConstraints()),
base::Bind(
&UserMediaClientImpl::FinalizeSelectVideoContentSourceSettings,
- weak_factory_.GetWeakPtr(), request_id, user_media_request,
- base::Passed(&controls), request_settings));
+ weak_factory_.GetWeakPtr(), user_media_request));
}
}
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));
+ if (!IsCurrentRequestInfo(user_media_request))
+ return;
+
+ DCHECK(current_request_info_->stream_controls()->video.requested);
+ DCHECK(IsDeviceSource(
+ current_request_info_->stream_controls()->video.stream_source));
VideoDeviceCaptureCapabilities capabilities;
capabilities.device_capabilities = std::move(video_input_capabilities);
@@ -395,24 +486,22 @@ void UserMediaClientImpl::SelectVideoDeviceSourceSettings(
capabilities.noise_reduction_capabilities = {rtc::Optional<bool>(),
rtc::Optional<bool>(true),
rtc::Optional<bool>(false)};
-
base::PostTaskAndReplyWithResult(
worker_task_runner_.get(), FROM_HERE,
base::Bind(&SelectVideoDeviceCaptureSourceSettings,
std::move(capabilities),
user_media_request.videoConstraints()),
base::Bind(&UserMediaClientImpl::FinalizeSelectVideoDeviceSourceSettings,
- weak_factory_.GetWeakPtr(), request_id, user_media_request,
- base::Passed(&controls), request_settings));
+ weak_factory_.GetWeakPtr(), user_media_request));
}
void UserMediaClientImpl::FinalizeSelectVideoDeviceSourceSettings(
- int request_id,
const blink::WebUserMediaRequest& user_media_request,
- std::unique_ptr<StreamControls> controls,
- const RequestSettings& request_settings,
const VideoDeviceCaptureSourceSelectionResult& selection_result) {
DCHECK(CalledOnValidThread());
+ if (!IsCurrentRequestInfo(user_media_request))
+ return;
+
if (!selection_result.HasValue()) {
blink::WebString failed_constraint_name =
blink::WebString::fromASCII(selection_result.failed_constraint_name());
@@ -424,18 +513,18 @@ void UserMediaClientImpl::FinalizeSelectVideoDeviceSourceSettings(
failed_constraint_name);
return;
}
- controls->video.device_id = selection_result.device_id();
- FinalizeRequestUserMedia(request_id, user_media_request, std::move(controls),
- request_settings);
+ current_request_info_->stream_controls()->video.device_id =
+ selection_result.device_id();
+ GenerateStreamForCurrentRequestInfo();
}
void UserMediaClientImpl::FinalizeSelectVideoContentSourceSettings(
- int request_id,
const blink::WebUserMediaRequest& user_media_request,
- std::unique_ptr<StreamControls> controls,
- const RequestSettings& request_settings,
const VideoContentCaptureSourceSelectionResult& selection_result) {
DCHECK(CalledOnValidThread());
+ if (!IsCurrentRequestInfo(user_media_request))
+ return;
+
if (!selection_result.HasValue()) {
blink::WebString failed_constraint_name =
blink::WebString::fromASCII(selection_result.failed_constraint_name());
@@ -447,45 +536,40 @@ void UserMediaClientImpl::FinalizeSelectVideoContentSourceSettings(
failed_constraint_name);
return;
}
- controls->video.device_id = selection_result.device_id();
- FinalizeRequestUserMedia(request_id, user_media_request, std::move(controls),
- request_settings);
+ current_request_info_->stream_controls()->video.device_id =
+ selection_result.device_id();
+ GenerateStreamForCurrentRequestInfo();
}
-void UserMediaClientImpl::FinalizeRequestUserMedia(
- int request_id,
- const blink::WebUserMediaRequest& user_media_request,
- std::unique_ptr<StreamControls> controls,
- const RequestSettings& request_settings) {
+void UserMediaClientImpl::GenerateStreamForCurrentRequestInfo() {
DCHECK(CalledOnValidThread());
-
- WebRtcLogMessage(
- base::StringPrintf("MSI::requestUserMedia. request_id=%d"
- ", audio source id=%s"
- ", video source id=%s",
- request_id, controls->audio.device_id.c_str(),
- controls->video.device_id.c_str()));
-
- user_media_requests_.push_back(base::MakeUnique<UserMediaRequestInfo>(
- request_id, user_media_request,
- request_settings.enable_automatic_audio_output_device_selection));
-
+ DCHECK(current_request_info_);
+
+ WebRtcLogMessage(base::StringPrintf(
+ "MSI::requestUserMedia. request_id=%d"
+ ", audio source id=%s"
+ ", video source id=%s",
+ current_request_info_->request_id(),
+ current_request_info_->stream_controls()->audio.device_id.c_str(),
+ current_request_info_->stream_controls()->video.device_id.c_str()));
+
+ current_request_info_->set_state(
+ UserMediaRequestInfo::State::SENT_FOR_GENERATION);
media_stream_dispatcher_->GenerateStream(
- request_id, weak_factory_.GetWeakPtr(), *controls,
- request_settings.security_origin,
- request_settings.is_processing_user_gesture);
+ current_request_info_->request_id(), weak_factory_.GetWeakPtr(),
+ *current_request_info_->stream_controls(),
+ current_request_info_->security_origin(),
+ current_request_info_->is_processing_user_gesture());
}
void UserMediaClientImpl::cancelUserMediaRequest(
const blink::WebUserMediaRequest& user_media_request) {
DCHECK(CalledOnValidThread());
- UserMediaRequestInfo* request = FindUserMediaRequestInfo(user_media_request);
- if (request) {
+ if (DeleteRequestInfo(user_media_request)) {
// We can't abort the stream generation process.
// Instead, erase the request. Once the stream is generated we will stop the
// stream if the request does not exist.
LogUserMediaRequestWithNoResult(MEDIA_STREAM_REQUEST_EXPLICITLY_CANCELLED);
- DeleteUserMediaRequestInfo(request);
}
}
@@ -543,17 +627,14 @@ void UserMediaClientImpl::OnStreamGenerated(
const StreamDeviceInfoArray& audio_array,
const StreamDeviceInfoArray& video_array) {
DCHECK(CalledOnValidThread());
- DVLOG(1) << "UserMediaClientImpl::OnStreamGenerated stream:" << label;
-
- UserMediaRequestInfo* request_info = FindUserMediaRequestInfo(request_id);
- if (!request_info) {
- // This can happen if the request is canceled or the frame reloads while
+ if (!IsCurrentRequestInfo(request_id)) {
+ // This can happen if the request is cancelled or the frame reloads while
// MediaStreamDispatcher is processing the request.
DVLOG(1) << "Request ID not found";
OnStreamGeneratedForCancelledRequest(audio_array, video_array);
return;
}
- request_info->generated = true;
+ current_request_info_->set_state(UserMediaRequestInfo::State::GENERATED);
for (const auto* array : {&audio_array, &video_array}) {
for (const auto& info : *array) {
@@ -563,25 +644,26 @@ void UserMediaClientImpl::OnStreamGenerated(
}
}
- DCHECK(!request_info->request.isNull());
+ DCHECK(!current_request_info_->request().isNull());
blink::WebVector<blink::WebMediaStreamTrack> audio_track_vector(
audio_array.size());
- CreateAudioTracks(audio_array, request_info->request.audioConstraints(),
- &audio_track_vector, request_info);
+ CreateAudioTracks(audio_array,
+ current_request_info_->request().audioConstraints(),
+ &audio_track_vector);
blink::WebVector<blink::WebMediaStreamTrack> video_track_vector(
video_array.size());
- CreateVideoTracks(video_array, request_info->request.videoConstraints(),
- &video_track_vector, request_info);
-
- blink::WebString webkit_id = blink::WebString::fromUTF8(label);
- blink::WebMediaStream* web_stream = &(request_info->web_stream);
+ CreateVideoTracks(video_array,
+ current_request_info_->request().videoConstraints(),
+ &video_track_vector);
- web_stream->initialize(webkit_id, audio_track_vector, video_track_vector);
- web_stream->setExtraData(new MediaStream());
+ blink::WebString blink_id = blink::WebString::fromUTF8(label);
+ current_request_info_->web_stream()->initialize(blink_id, audio_track_vector,
+ video_track_vector);
+ current_request_info_->web_stream()->setExtraData(new MediaStream());
// Wait for the tracks to be started successfully or to fail.
- request_info->CallbackOnTracksStarted(
+ current_request_info_->CallbackOnTracksStarted(
base::Bind(&UserMediaClientImpl::OnCreateNativeTracksCompleted,
weak_factory_.GetWeakPtr(), label));
}
@@ -631,27 +713,19 @@ void UserMediaClientImpl::OnAudioSourceStarted(
local_sources_.push_back((*it));
pending_local_sources_.erase(it);
- NotifyAllRequestsOfAudioSourceStarted(source, result, result_name);
+ NotifyCurrentRequestInfoOfAudioSourceStarted(source, result, result_name);
return;
}
NOTREACHED();
}
-void UserMediaClientImpl::NotifyAllRequestsOfAudioSourceStarted(
+void UserMediaClientImpl::NotifyCurrentRequestInfoOfAudioSourceStarted(
MediaStreamSource* source,
MediaStreamRequestResult result,
const blink::WebString& result_name) {
- // Since a request object that receives the OnAudioSourceStarted event,
- // might get deleted and removed from the |user_media_requests_| array while
- // we iterate through it, we need to jump through this hoop here, copy
- // pointers to the objects we're notifying and avoid using
- // user_media_requests_ as we iterate+notify.
- std::vector<UserMediaRequestInfo*> requests;
- requests.reserve(user_media_requests_.size());
- for (const auto& request : user_media_requests_)
- requests.push_back(request.get());
- for (auto* request : requests)
- request->OnAudioSourceStarted(source, result, result_name);
+ // The only request possibly being processed is |current_request_info_|.
+ if (current_request_info_)
+ current_request_info_->OnAudioSourceStarted(source, result, result_name);
}
void UserMediaClientImpl::FinalizeEnumerateDevices(
@@ -684,18 +758,14 @@ void UserMediaClientImpl::OnStreamGenerationFailed(
int request_id,
MediaStreamRequestResult result) {
DCHECK(CalledOnValidThread());
- DVLOG(1) << "UserMediaClientImpl::OnStreamGenerationFailed("
- << request_id << ")";
- UserMediaRequestInfo* request_info = FindUserMediaRequestInfo(request_id);
- if (!request_info) {
- // This can happen if the request is canceled or the frame reloads while
+ if (!IsCurrentRequestInfo(request_id)) {
+ // This can happen if the request is cancelled or the frame reloads while
// MediaStreamDispatcher is processing the request.
- DVLOG(1) << "Request ID not found";
return;
}
- GetUserMediaRequestFailed(request_info->request, result, "");
- DeleteUserMediaRequestInfo(request_info);
+ GetUserMediaRequestFailed(current_request_info_->request(), result, "");
+ DeleteRequestInfo(current_request_info_->request());
}
// Callback from MediaStreamDispatcher.
@@ -809,29 +879,29 @@ MediaStreamVideoSource* UserMediaClientImpl::CreateVideoSource(
void UserMediaClientImpl::CreateVideoTracks(
const StreamDeviceInfoArray& devices,
const blink::WebMediaConstraints& constraints,
- blink::WebVector<blink::WebMediaStreamTrack>* webkit_tracks,
- UserMediaRequestInfo* request) {
+ blink::WebVector<blink::WebMediaStreamTrack>* webkit_tracks) {
DCHECK(CalledOnValidThread());
+ DCHECK(current_request_info_);
DCHECK_EQ(devices.size(), webkit_tracks->size());
for (size_t i = 0; i < devices.size(); ++i) {
blink::WebMediaStreamSource source =
InitializeVideoSourceObject(devices[i], constraints);
(*webkit_tracks)[i] =
- request->CreateAndStartVideoTrack(source, constraints);
+ current_request_info_->CreateAndStartVideoTrack(source, constraints);
}
}
void UserMediaClientImpl::CreateAudioTracks(
const StreamDeviceInfoArray& devices,
const blink::WebMediaConstraints& constraints,
- blink::WebVector<blink::WebMediaStreamTrack>* webkit_tracks,
- UserMediaRequestInfo* request) {
+ blink::WebVector<blink::WebMediaStreamTrack>* webkit_tracks) {
DCHECK(CalledOnValidThread());
+ DCHECK(current_request_info_);
DCHECK_EQ(devices.size(), webkit_tracks->size());
StreamDeviceInfoArray overridden_audio_array = devices;
- if (!request->enable_automatic_output_device_selection) {
+ if (!current_request_info_->enable_automatic_output_device_selection()) {
// If the GetUserMedia request did not explicitly set the constraint
// kMediaStreamRenderToAssociatedSink, the output device parameters must
// be removed.
@@ -847,34 +917,31 @@ void UserMediaClientImpl::CreateAudioTracks(
blink::WebMediaStreamSource source = InitializeAudioSourceObject(
overridden_audio_array[i], constraints, &is_pending);
(*webkit_tracks)[i].initialize(source);
- request->StartAudioTrack((*webkit_tracks)[i], is_pending);
+ current_request_info_->StartAudioTrack((*webkit_tracks)[i], is_pending);
}
}
void UserMediaClientImpl::OnCreateNativeTracksCompleted(
const std::string& label,
- UserMediaRequestInfo* request,
+ UserMediaRequestInfo* request_info,
MediaStreamRequestResult result,
const blink::WebString& result_name) {
DCHECK(CalledOnValidThread());
- DVLOG(1) << "UserMediaClientImpl::OnCreateNativeTracksComplete("
- << "{request_id = " << request->request_id << "} "
- << "{result = " << result << "})";
-
if (result == content::MEDIA_DEVICE_OK) {
- GetUserMediaRequestSucceeded(request->web_stream, request->request);
+ GetUserMediaRequestSucceeded(*request_info->web_stream(),
+ request_info->request());
media_stream_dispatcher_->OnStreamStarted(label);
} else {
- GetUserMediaRequestFailed(request->request, result, result_name);
+ GetUserMediaRequestFailed(request_info->request(), result, result_name);
blink::WebVector<blink::WebMediaStreamTrack> tracks;
- request->web_stream.audioTracks(tracks);
+ request_info->web_stream()->audioTracks(tracks);
for (auto& web_track : tracks) {
MediaStreamTrack* track = MediaStreamTrack::GetTrack(web_track);
if (track)
track->Stop();
}
- request->web_stream.videoTracks(tracks);
+ request_info->web_stream()->videoTracks(tracks);
for (auto& web_track : tracks) {
MediaStreamTrack* track = MediaStreamTrack::GetTrack(web_track);
if (track)
@@ -882,7 +949,7 @@ void UserMediaClientImpl::OnCreateNativeTracksCompleted(
}
}
- DeleteUserMediaRequestInfo(request);
+ DeleteRequestInfo(request_info->request());
}
void UserMediaClientImpl::OnDeviceOpened(
@@ -909,7 +976,7 @@ void UserMediaClientImpl::DevicesChanged(
void UserMediaClientImpl::GetUserMediaRequestSucceeded(
const blink::WebMediaStream& stream,
- blink::WebUserMediaRequest request_info) {
+ blink::WebUserMediaRequest request) {
// Completing the getUserMedia request can lead to that the RenderFrame and
// the UserMediaClientImpl is destroyed if the JavaScript code request the
// frame to be destroyed within the scope of the callback. Therefore,
@@ -917,19 +984,20 @@ void UserMediaClientImpl::GetUserMediaRequestSucceeded(
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::Bind(&UserMediaClientImpl::DelayedGetUserMediaRequestSucceeded,
- weak_factory_.GetWeakPtr(), stream, request_info));
+ weak_factory_.GetWeakPtr(), stream, request));
}
void UserMediaClientImpl::DelayedGetUserMediaRequestSucceeded(
const blink::WebMediaStream& stream,
- blink::WebUserMediaRequest request_info) {
+ blink::WebUserMediaRequest request) {
DVLOG(1) << "UserMediaClientImpl::DelayedGetUserMediaRequestSucceeded";
LogUserMediaRequestResult(MEDIA_DEVICE_OK);
- request_info.requestSucceeded(stream);
+ DeleteRequestInfo(request);
+ request.requestSucceeded(stream);
}
void UserMediaClientImpl::GetUserMediaRequestFailed(
- blink::WebUserMediaRequest request_info,
+ blink::WebUserMediaRequest request,
MediaStreamRequestResult result,
const blink::WebString& result_name) {
// Completing the getUserMedia request can lead to that the RenderFrame and
@@ -939,62 +1007,62 @@ void UserMediaClientImpl::GetUserMediaRequestFailed(
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::Bind(&UserMediaClientImpl::DelayedGetUserMediaRequestFailed,
- weak_factory_.GetWeakPtr(), request_info, result,
- result_name));
+ weak_factory_.GetWeakPtr(), request, result, result_name));
}
void UserMediaClientImpl::DelayedGetUserMediaRequestFailed(
- blink::WebUserMediaRequest request_info,
+ blink::WebUserMediaRequest request,
MediaStreamRequestResult result,
const blink::WebString& result_name) {
LogUserMediaRequestResult(result);
+ DeleteRequestInfo(request);
switch (result) {
case MEDIA_DEVICE_OK:
case NUM_MEDIA_REQUEST_RESULTS:
NOTREACHED();
return;
case MEDIA_DEVICE_PERMISSION_DENIED:
- request_info.requestDenied();
+ request.requestDenied();
return;
case MEDIA_DEVICE_PERMISSION_DISMISSED:
- request_info.requestFailedUASpecific("PermissionDismissedError");
+ request.requestFailedUASpecific("PermissionDismissedError");
return;
case MEDIA_DEVICE_INVALID_STATE:
- request_info.requestFailedUASpecific("InvalidStateError");
+ request.requestFailedUASpecific("InvalidStateError");
return;
case MEDIA_DEVICE_NO_HARDWARE:
- request_info.requestFailedUASpecific("DevicesNotFoundError");
+ request.requestFailedUASpecific("DevicesNotFoundError");
return;
case MEDIA_DEVICE_INVALID_SECURITY_ORIGIN:
- request_info.requestFailedUASpecific("InvalidSecurityOriginError");
+ request.requestFailedUASpecific("InvalidSecurityOriginError");
return;
case MEDIA_DEVICE_TAB_CAPTURE_FAILURE:
- request_info.requestFailedUASpecific("TabCaptureError");
+ request.requestFailedUASpecific("TabCaptureError");
return;
case MEDIA_DEVICE_SCREEN_CAPTURE_FAILURE:
- request_info.requestFailedUASpecific("ScreenCaptureError");
+ request.requestFailedUASpecific("ScreenCaptureError");
return;
case MEDIA_DEVICE_CAPTURE_FAILURE:
- request_info.requestFailedUASpecific("DeviceCaptureError");
+ request.requestFailedUASpecific("DeviceCaptureError");
return;
case MEDIA_DEVICE_CONSTRAINT_NOT_SATISFIED:
- request_info.requestFailedConstraint(result_name);
+ request.requestFailedConstraint(result_name);
return;
case MEDIA_DEVICE_TRACK_START_FAILURE:
- request_info.requestFailedUASpecific("TrackStartError");
+ request.requestFailedUASpecific("TrackStartError");
return;
case MEDIA_DEVICE_NOT_SUPPORTED:
- request_info.requestFailedUASpecific("MediaDeviceNotSupported");
+ request.requestFailedUASpecific("MediaDeviceNotSupported");
return;
case MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN:
- request_info.requestFailedUASpecific("MediaDeviceFailedDueToShutdown");
+ request.requestFailedUASpecific("MediaDeviceFailedDueToShutdown");
return;
case MEDIA_DEVICE_KILL_SWITCH_ON:
- request_info.requestFailedUASpecific("MediaDeviceKillSwitchOn");
+ request.requestFailedUASpecific("MediaDeviceKillSwitchOn");
return;
}
NOTREACHED();
- request_info.requestFailed();
+ request.requestFailed();
}
void UserMediaClientImpl::EnumerateDevicesSucceded(
@@ -1058,7 +1126,7 @@ bool UserMediaClientImpl::RemoveLocalSource(
if (IsSameSource(*device_it, source)) {
MediaStreamSource* const source_extra_data =
static_cast<MediaStreamSource*>(source.getExtraData());
- NotifyAllRequestsOfAudioSourceStarted(
+ NotifyCurrentRequestInfoOfAudioSourceStarted(
source_extra_data, MEDIA_DEVICE_TRACK_START_FAILURE,
"Failed to access audio capture device");
pending_local_sources_.erase(device_it);
@@ -1069,60 +1137,66 @@ bool UserMediaClientImpl::RemoveLocalSource(
return false;
}
-UserMediaClientImpl::UserMediaRequestInfo*
-UserMediaClientImpl::FindUserMediaRequestInfo(int request_id) {
+bool UserMediaClientImpl::IsCurrentRequestInfo(int request_id) const {
DCHECK(CalledOnValidThread());
- for (auto& r : user_media_requests_) {
- if (r->request_id == request_id)
- return r.get();
- }
- return nullptr;
+ return current_request_info_ &&
+ current_request_info_->request_id() == request_id;
}
-UserMediaClientImpl::UserMediaRequestInfo*
-UserMediaClientImpl::FindUserMediaRequestInfo(
- const blink::WebUserMediaRequest& request) {
+bool UserMediaClientImpl::IsCurrentRequestInfo(
+ const blink::WebUserMediaRequest& request) const {
DCHECK(CalledOnValidThread());
- for (auto& r : user_media_requests_) {
- if (r->request == request)
- return r.get();
- }
- return nullptr;
+ return current_request_info_ && current_request_info_->request() == request;
}
-void UserMediaClientImpl::DeleteUserMediaRequestInfo(
- UserMediaRequestInfo* request) {
+bool UserMediaClientImpl::DeleteRequestInfo(
+ const blink::WebUserMediaRequest& user_media_request) {
DCHECK(CalledOnValidThread());
- auto new_end =
- std::remove_if(user_media_requests_.begin(), user_media_requests_.end(),
- [&](std::unique_ptr<UserMediaRequestInfo>& r) {
- return r.get() == request;
- });
- DCHECK(new_end != user_media_requests_.end());
- user_media_requests_.erase(new_end, user_media_requests_.end());
+ if (current_request_info_ &&
+ current_request_info_->request() == user_media_request) {
+ current_request_info_.reset();
+ if (!pending_request_infos_.empty()) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(&UserMediaClientImpl::MaybeProcessNextRequestInfo,
+ weak_factory_.GetWeakPtr()));
+ }
+ return true;
+ }
+
+ for (auto it = pending_request_infos_.begin();
+ it != pending_request_infos_.end(); ++it) {
+ if ((*it)->request() == user_media_request) {
+ pending_request_infos_.erase(it);
+ return true;
+ }
+ }
+
+ return false;
}
void UserMediaClientImpl::DeleteAllUserMediaRequests() {
- UserMediaRequests::iterator request_it = user_media_requests_.begin();
- while (request_it != user_media_requests_.end()) {
- DVLOG(1) << "UserMediaClientImpl@" << this
- << "::DeleteAllUserMediaRequests: "
- << "Cancel user media request " << (*request_it)->request_id;
+ if (current_request_info_) {
// If the request is not generated, it means that a request
// has been sent to the MediaStreamDispatcher to generate a stream
// but MediaStreamDispatcher has not yet responded and we need to cancel
// the request.
- if (!(*request_it)->generated) {
- DCHECK(!(*request_it)->HasPendingSources());
- media_stream_dispatcher_->CancelGenerateStream(
- (*request_it)->request_id, weak_factory_.GetWeakPtr());
- LogUserMediaRequestWithNoResult(MEDIA_STREAM_REQUEST_NOT_GENERATED);
- } else {
- DCHECK((*request_it)->HasPendingSources());
+ if (current_request_info_->state() ==
+ UserMediaRequestInfo::State::GENERATED) {
+ DCHECK(current_request_info_->HasPendingSources());
LogUserMediaRequestWithNoResult(
MEDIA_STREAM_REQUEST_PENDING_MEDIA_TRACKS);
+ } else {
+ DCHECK(!current_request_info_->HasPendingSources());
+ if (current_request_info_->state() ==
+ UserMediaRequestInfo::State::SENT_FOR_GENERATION) {
+ media_stream_dispatcher_->CancelGenerateStream(
+ current_request_info_->request_id(), weak_factory_.GetWeakPtr());
+ }
+ LogUserMediaRequestWithNoResult(MEDIA_STREAM_REQUEST_NOT_GENERATED);
}
- request_it = user_media_requests_.erase(request_it);
+ current_request_info_.reset();
+ pending_request_infos_.clear();
}
}
@@ -1181,22 +1255,32 @@ UserMediaClientImpl::GetMediaDevicesDispatcher() {
return media_devices_dispatcher_;
}
+base::Optional<bool>
+UserMediaClientImpl::AutomaticOutputDeviceSelectionEnabledForCurrentRequest() {
+ if (!current_request_info_)
+ return base::Optional<bool>();
+
+ return base::Optional<bool>(
+ current_request_info_->enable_automatic_output_device_selection());
+}
+
+void UserMediaClientImpl::OnDestruct() {
+ delete this;
+}
+
UserMediaClientImpl::UserMediaRequestInfo::UserMediaRequestInfo(
int request_id,
const blink::WebUserMediaRequest& request,
- bool enable_automatic_output_device_selection)
- : request_id(request_id),
- generated(false),
- enable_automatic_output_device_selection(
- enable_automatic_output_device_selection),
- request(request),
+ bool is_processing_user_gesture,
+ const url::Origin& security_origin)
+ : request_id_(request_id),
+ state_(State::NOT_SENT_FOR_GENERATION),
+ enable_automatic_output_device_selection_(false),
+ request_(request),
+ is_processing_user_gesture_(is_processing_user_gesture),
+ security_origin_(security_origin),
request_result_(MEDIA_DEVICE_OK),
- request_result_name_("") {
-}
-
-UserMediaClientImpl::UserMediaRequestInfo::~UserMediaRequestInfo() {
- DVLOG(1) << "~UserMediaRequestInfo";
-}
+ request_result_name_("") {}
void UserMediaClientImpl::UserMediaRequestInfo::StartAudioTrack(
const blink::WebMediaStreamTrack& track,
@@ -1284,8 +1368,4 @@ void UserMediaClientImpl::UserMediaRequestInfo::OnAudioSourceStarted(
OnTrackStarted(source, result, result_name);
}
-void UserMediaClientImpl::OnDestruct() {
- delete this;
-}
-
} // namespace content
« no previous file with comments | « content/renderer/media/user_media_client_impl.h ('k') | content/renderer/media/user_media_client_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698