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 "content/renderer/media/user_media_client_impl.h" | 5 #include "content/renderer/media/user_media_client_impl.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <algorithm> | |
| 9 #include <utility> | 10 #include <utility> |
| 10 #include <vector> | |
| 11 | 11 |
| 12 #include "base/hash.h" | 12 #include "base/hash.h" |
| 13 #include "base/location.h" | 13 #include "base/location.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/memory/ptr_util.h" | |
| 15 #include "base/single_thread_task_runner.h" | 16 #include "base/single_thread_task_runner.h" |
| 16 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
| 17 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| 18 #include "base/strings/stringprintf.h" | 19 #include "base/strings/stringprintf.h" |
| 19 #include "base/strings/utf_string_conversions.h" | 20 #include "base/strings/utf_string_conversions.h" |
| 20 #include "base/threading/thread_task_runner_handle.h" | 21 #include "base/threading/thread_task_runner_handle.h" |
| 21 #include "build/build_config.h" | 22 #include "build/build_config.h" |
| 22 #include "content/public/renderer/render_frame.h" | 23 #include "content/public/renderer/render_frame.h" |
| 23 #include "content/renderer/media/local_media_stream_audio_source.h" | 24 #include "content/renderer/media/local_media_stream_audio_source.h" |
| 24 #include "content/renderer/media/media_stream.h" | 25 #include "content/renderer/media/media_stream.h" |
| 25 #include "content/renderer/media/media_stream_constraints_util.h" | 26 #include "content/renderer/media/media_stream_constraints_util.h" |
| 26 #include "content/renderer/media/media_stream_dispatcher.h" | 27 #include "content/renderer/media/media_stream_dispatcher.h" |
| 27 #include "content/renderer/media/media_stream_video_capturer_source.h" | 28 #include "content/renderer/media/media_stream_video_capturer_source.h" |
| 28 #include "content/renderer/media/media_stream_video_track.h" | 29 #include "content/renderer/media/media_stream_video_track.h" |
| 29 #include "content/renderer/media/peer_connection_tracker.h" | 30 #include "content/renderer/media/peer_connection_tracker.h" |
| 30 #include "content/renderer/media/webrtc/processed_local_audio_source.h" | 31 #include "content/renderer/media/webrtc/processed_local_audio_source.h" |
| 31 #include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h" | 32 #include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h" |
| 32 #include "content/renderer/media/webrtc_logging.h" | 33 #include "content/renderer/media/webrtc_logging.h" |
| 33 #include "content/renderer/media/webrtc_uma_histograms.h" | 34 #include "content/renderer/media/webrtc_uma_histograms.h" |
| 34 #include "content/renderer/render_thread_impl.h" | 35 #include "content/renderer/render_thread_impl.h" |
| 35 #include "third_party/WebKit/public/platform/URLConversion.h" | 36 #include "third_party/WebKit/public/platform/URLConversion.h" |
| 36 #include "third_party/WebKit/public/platform/WebMediaConstraints.h" | 37 #include "third_party/WebKit/public/platform/WebMediaConstraints.h" |
| 37 #include "third_party/WebKit/public/platform/WebMediaDeviceInfo.h" | 38 #include "third_party/WebKit/public/platform/WebMediaDeviceInfo.h" |
| 38 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" | 39 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" |
| 40 #include "third_party/WebKit/public/platform/WebString.h" | |
| 39 #include "third_party/WebKit/public/web/WebDocument.h" | 41 #include "third_party/WebKit/public/web/WebDocument.h" |
| 40 #include "third_party/WebKit/public/web/WebLocalFrame.h" | 42 #include "third_party/WebKit/public/web/WebLocalFrame.h" |
| 41 | 43 |
| 42 namespace content { | 44 namespace content { |
| 43 namespace { | 45 namespace { |
| 44 | 46 |
| 45 void CopyVector(const blink::WebVector<blink::WebString>& source, | 47 void CopyFirstString(const blink::StringConstraint& constraint, |
| 46 std::vector<std::string>* destination) { | 48 std::string* destination) { |
| 47 for (const auto& web_string : source) { | 49 if (!constraint.exact().isEmpty()) |
| 48 destination->push_back(web_string.utf8()); | 50 *destination = constraint.exact()[0].utf8(); |
| 51 } | |
| 52 | |
| 53 bool FindDeviceId(const blink::WebVector<blink::WebString> candidates, | |
| 54 const MediaDeviceInfoArray& device_infos, | |
| 55 std::string* device_id) { | |
| 56 for (const auto& candidate : candidates) { | |
| 57 auto it = std::find_if(device_infos.begin(), device_infos.end(), | |
| 58 [&candidate](const MediaDeviceInfo& info) { | |
| 59 return info.device_id == candidate.utf8(); | |
| 60 }); | |
| 61 | |
| 62 if (it != device_infos.end()) { | |
| 63 *device_id = it->device_id; | |
| 64 return true; | |
| 65 } | |
| 66 } | |
| 67 | |
| 68 return false; | |
| 69 } | |
| 70 | |
| 71 // Returns false if an device ID requested as mandatory is not found in | |
| 72 // |device_infos| is . Otherwise, if a valid device is found, its ID is copied | |
| 73 // to |*device_id|; if no valid device is found, |*device_id| is left unmodified | |
| 74 // and true is returned. | |
|
hta - Chromium
2016/11/30 18:51:43
Suggested reword:
If a deviceId requested as mand
Guido Urdaneta
2016/12/01 10:28:53
Done.
| |
| 75 bool PickDeviceId(const blink::WebMediaConstraints& constraints, | |
| 76 const MediaDeviceInfoArray& device_infos, | |
| 77 std::string* device_id) { | |
| 78 DCHECK(!constraints.isNull()); | |
| 79 DCHECK(device_id->empty()); | |
| 80 | |
| 81 if (constraints.basic().deviceId.exact().size() > 1) { | |
| 82 LOG(ERROR) << "Only one required device ID is supported"; | |
| 83 return false; | |
| 84 } | |
| 85 | |
| 86 if (constraints.basic().deviceId.exact().size() == 1 && | |
| 87 !FindDeviceId(constraints.basic().deviceId.exact(), device_infos, | |
| 88 device_id)) { | |
| 89 LOG(ERROR) << "Invalid mandatory device ID = " | |
| 90 << constraints.basic().deviceId.exact()[0].utf8(); | |
| 91 return false; | |
| 92 } | |
| 93 | |
| 94 // There is no required device ID. Look at the alternates. | |
| 95 if (FindDeviceId(constraints.basic().deviceId.ideal(), device_infos, | |
| 96 device_id)) { | |
| 97 return true; | |
| 98 } | |
| 99 | |
| 100 for (const auto& advanced : constraints.advanced()) { | |
| 101 if (FindDeviceId(advanced.deviceId.exact(), device_infos, device_id)) { | |
| 102 return true; | |
| 103 } | |
| 104 if (FindDeviceId(advanced.deviceId.ideal(), device_infos, device_id)) { | |
| 105 return true; | |
| 106 } | |
| 107 } | |
| 108 | |
| 109 // No valid alternate device ID found. Select default device. | |
| 110 return true; | |
| 111 } | |
| 112 | |
| 113 bool IsDeviceSource(const std::string& source) { | |
| 114 return source.empty(); | |
| 115 } | |
| 116 | |
| 117 void CopyConstraintsToTrackControls( | |
| 118 const blink::WebMediaConstraints& constraints, | |
| 119 TrackControls* track_controls, | |
| 120 bool* request_devices) { | |
| 121 DCHECK(!constraints.isNull()); | |
| 122 track_controls->requested = true; | |
| 123 CopyFirstString(constraints.basic().mediaStreamSource, | |
| 124 &track_controls->stream_source); | |
| 125 if (IsDeviceSource(track_controls->stream_source)) { | |
| 126 bool request_devices_advanced = false; | |
| 127 for (const auto& advanced : constraints.advanced()) { | |
| 128 if (!advanced.deviceId.isEmpty()) { | |
| 129 request_devices_advanced = true; | |
| 130 break; | |
| 131 } | |
| 132 } | |
| 133 *request_devices = | |
| 134 request_devices_advanced || !constraints.basic().deviceId.isEmpty(); | |
| 135 } else { | |
| 136 CopyFirstString(constraints.basic().deviceId, &track_controls->device_id); | |
| 137 *request_devices = false; | |
| 49 } | 138 } |
| 50 } | 139 } |
| 51 | 140 |
| 52 void CopyFirstString(const blink::WebVector<blink::WebString>& source, | 141 void CopyHotwordAndLocalEchoToStreamControls( |
| 53 std::string* destination) { | 142 const blink::WebMediaConstraints& audio_constraints, |
| 54 if (!source.isEmpty()) | 143 StreamControls* controls) { |
| 55 *destination = source[0].utf8(); | 144 if (audio_constraints.isNull()) |
| 56 } | 145 return; |
| 57 | 146 |
| 58 void CopyBlinkRequestToStreamControls(const blink::WebUserMediaRequest& request, | 147 if (audio_constraints.basic().hotwordEnabled.hasExact()) { |
|
hta - Chromium
2016/11/30 18:51:43
This looks like you should be using the constraint
Guido Urdaneta
2016/12/01 10:28:53
This part is copied practically verbatim from the
| |
| 59 StreamControls* controls) { | 148 controls->hotword_enabled = |
| 60 if (request.isNull()) { | 149 audio_constraints.basic().hotwordEnabled.exact(); |
| 61 return; | 150 } else { |
| 62 } | 151 for (const auto& audio_advanced : audio_constraints.advanced()) { |
| 63 if (!request.audioConstraints().isNull()) { | 152 if (audio_advanced.hotwordEnabled.hasExact()) { |
| 64 const blink::WebMediaTrackConstraintSet& audio_basic = | 153 controls->hotword_enabled = audio_advanced.hotwordEnabled.exact(); |
| 65 request.audioConstraints().basic(); | 154 break; |
| 66 CopyFirstString(audio_basic.mediaStreamSource.exact(), | |
| 67 &controls->audio.stream_source); | |
| 68 CopyVector(audio_basic.deviceId.exact(), &(controls->audio.device_ids)); | |
| 69 // Optionals. They may be either in ideal or in advanced.exact. | |
| 70 CopyVector(audio_basic.deviceId.ideal(), | |
| 71 &controls->audio.alternate_device_ids); | |
| 72 for (const auto& constraint : request.audioConstraints().advanced()) { | |
| 73 CopyVector(constraint.deviceId.exact(), | |
| 74 &controls->audio.alternate_device_ids); | |
| 75 CopyVector(constraint.deviceId.ideal(), | |
| 76 &controls->audio.alternate_device_ids); | |
| 77 } | |
| 78 if (audio_basic.hotwordEnabled.hasExact()) { | |
| 79 controls->hotword_enabled = audio_basic.hotwordEnabled.exact(); | |
| 80 } else { | |
| 81 for (const auto& audio_advanced : request.audioConstraints().advanced()) { | |
| 82 if (audio_advanced.hotwordEnabled.hasExact()) { | |
| 83 controls->hotword_enabled = audio_advanced.hotwordEnabled.exact(); | |
| 84 break; | |
| 85 } | |
| 86 } | 155 } |
| 87 } | 156 } |
| 157 } | |
| 88 | 158 |
| 89 if (request.audioConstraints().basic().disableLocalEcho.hasExact()) { | 159 if (audio_constraints.basic().disableLocalEcho.hasExact()) { |
| 90 controls->disable_local_echo = | 160 controls->disable_local_echo = |
| 91 request.audioConstraints().basic().disableLocalEcho.exact(); | 161 audio_constraints.basic().disableLocalEcho.exact(); |
| 92 } else { | 162 } else { |
| 93 controls->disable_local_echo = | 163 controls->disable_local_echo = |
| 94 controls->audio.stream_source != kMediaStreamSourceDesktop; | 164 controls->audio.stream_source != kMediaStreamSourceDesktop; |
| 95 } | |
| 96 } | |
| 97 if (!request.videoConstraints().isNull()) { | |
| 98 const blink::WebMediaTrackConstraintSet& video_basic = | |
| 99 request.videoConstraints().basic(); | |
| 100 CopyFirstString(video_basic.mediaStreamSource.exact(), | |
| 101 &(controls->video.stream_source)); | |
| 102 CopyVector(video_basic.deviceId.exact(), &(controls->video.device_ids)); | |
| 103 CopyVector(video_basic.deviceId.ideal(), | |
| 104 &(controls->video.alternate_device_ids)); | |
| 105 for (const auto& constraint : request.videoConstraints().advanced()) { | |
| 106 CopyVector(constraint.deviceId.exact(), | |
| 107 &controls->video.alternate_device_ids); | |
| 108 CopyVector(constraint.deviceId.ideal(), | |
| 109 &controls->video.alternate_device_ids); | |
| 110 } | |
| 111 } | 165 } |
| 112 } | 166 } |
| 113 | 167 |
| 114 bool IsSameDevice(const StreamDeviceInfo& device, | 168 bool IsSameDevice(const StreamDeviceInfo& device, |
| 115 const StreamDeviceInfo& other_device) { | 169 const StreamDeviceInfo& other_device) { |
| 116 return device.device.id == other_device.device.id && | 170 return device.device.id == other_device.device.id && |
| 117 device.device.type == other_device.device.type && | 171 device.device.type == other_device.device.type && |
| 118 device.session_id == other_device.session_id; | 172 device.session_id == other_device.session_id; |
| 119 } | 173 } |
| 120 | 174 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 176 // webGetUserMedia. | 230 // webGetUserMedia. |
| 177 UpdateWebRTCMethodCount(WEBKIT_GET_USER_MEDIA); | 231 UpdateWebRTCMethodCount(WEBKIT_GET_USER_MEDIA); |
| 178 DCHECK(CalledOnValidThread()); | 232 DCHECK(CalledOnValidThread()); |
| 179 | 233 |
| 180 if (RenderThreadImpl::current()) { | 234 if (RenderThreadImpl::current()) { |
| 181 RenderThreadImpl::current()->peer_connection_tracker()->TrackGetUserMedia( | 235 RenderThreadImpl::current()->peer_connection_tracker()->TrackGetUserMedia( |
| 182 user_media_request); | 236 user_media_request); |
| 183 } | 237 } |
| 184 | 238 |
| 185 int request_id = g_next_request_id++; | 239 int request_id = g_next_request_id++; |
| 186 StreamControls controls; | 240 std::unique_ptr<StreamControls> controls = base::MakeUnique<StreamControls>(); |
| 187 url::Origin security_origin; | |
| 188 bool enable_automatic_output_device_selection = false; | |
| 189 | 241 |
| 190 // |user_media_request| can't be mocked. So in order to test at all we check | 242 // |user_media_request| can't be mocked. So in order to test at all we check |
| 191 // if it isNull. | 243 // if it isNull. |
| 192 if (user_media_request.isNull()) { | 244 if (user_media_request.isNull()) { |
| 193 // We are in a test. | 245 // We are in a test. |
| 194 controls.audio.requested = true; | 246 controls->audio.requested = true; |
| 195 controls.video.requested = true; | 247 controls->video.requested = true; |
|
hta - Chromium
2016/11/30 18:51:43
I added the ability to initialize an UserMediaRequ
Guido Urdaneta
2016/12/01 10:28:53
Added TODO. Will try to do that when implementing
| |
| 248 FinalizeRequestUserMedia( | |
| 249 request_id, user_media_request, std::move(controls), | |
| 250 false /* automatic_output_device_selection */, url::Origin()); | |
| 196 } else { | 251 } else { |
| 252 // ownerDocument may be null if we are in a test. | |
| 253 // In that case, it's OK to not check frame(). | |
| 254 DCHECK(user_media_request.ownerDocument().isNull() || | |
| 255 render_frame()->GetWebFrame() == | |
| 256 static_cast<blink::WebFrame*>( | |
| 257 user_media_request.ownerDocument().frame())); | |
| 258 | |
| 259 bool enable_automatic_output_device_selection = false; | |
| 260 bool request_audio_input_devices = false; | |
| 197 if (user_media_request.audio()) { | 261 if (user_media_request.audio()) { |
| 198 controls.audio.requested = true; | 262 CopyConstraintsToTrackControls(user_media_request.audioConstraints(), |
| 263 &controls->audio, | |
| 264 &request_audio_input_devices); | |
| 265 CopyHotwordAndLocalEchoToStreamControls( | |
| 266 user_media_request.audioConstraints(), controls.get()); | |
| 199 // Check if this input device should be used to select a matching output | 267 // Check if this input device should be used to select a matching output |
| 200 // device for audio rendering. | 268 // device for audio rendering. |
| 201 GetConstraintValueAsBoolean( | 269 GetConstraintValueAsBoolean( |
| 202 user_media_request.audioConstraints(), | 270 user_media_request.audioConstraints(), |
| 203 &blink::WebMediaTrackConstraintSet::renderToAssociatedSink, | 271 &blink::WebMediaTrackConstraintSet::renderToAssociatedSink, |
| 204 &enable_automatic_output_device_selection); | 272 &enable_automatic_output_device_selection); |
| 205 } | 273 } |
| 274 bool request_video_input_devices = false; | |
| 206 if (user_media_request.video()) { | 275 if (user_media_request.video()) { |
| 207 controls.video.requested = true; | 276 CopyConstraintsToTrackControls(user_media_request.videoConstraints(), |
| 277 &controls->video, | |
| 278 &request_video_input_devices); | |
| 208 } | 279 } |
| 209 CopyBlinkRequestToStreamControls(user_media_request, &controls); | 280 |
| 210 security_origin = user_media_request.getSecurityOrigin(); | 281 url::Origin security_origin = user_media_request.getSecurityOrigin(); |
| 211 // ownerDocument may be null if we are in a test. | 282 if (request_audio_input_devices || request_video_input_devices) { |
| 212 // In that case, it's OK to not check frame(). | 283 GetMediaDevicesDispatcher()->EnumerateDevices( |
|
hta - Chromium
2016/11/30 18:51:43
Will this use a cache if it's available?
Guido Urdaneta
2016/12/01 10:28:53
Yes, it will. At the moment the cache is on the br
| |
| 213 DCHECK(user_media_request.ownerDocument().isNull() || | 284 request_audio_input_devices, request_video_input_devices, |
| 214 render_frame()->GetWebFrame() == | 285 false /* request_audio_output_devices */, security_origin, |
| 215 static_cast<blink::WebFrame*>( | 286 base::Bind(&UserMediaClientImpl::SelectUserMediaDevice, |
| 216 user_media_request.ownerDocument().frame())); | 287 weak_factory_.GetWeakPtr(), request_id, user_media_request, |
| 288 base::Passed(&controls), | |
| 289 enable_automatic_output_device_selection, | |
| 290 security_origin)); | |
| 291 } else { | |
| 292 FinalizeRequestUserMedia( | |
| 293 request_id, user_media_request, std::move(controls), | |
| 294 enable_automatic_output_device_selection, security_origin); | |
| 295 } | |
| 296 } | |
| 297 } | |
| 298 | |
| 299 void UserMediaClientImpl::SelectUserMediaDevice( | |
| 300 int request_id, | |
| 301 const blink::WebUserMediaRequest& user_media_request, | |
| 302 std::unique_ptr<StreamControls> controls, | |
| 303 bool enable_automatic_output_device_selection, | |
| 304 const url::Origin& security_origin, | |
| 305 const EnumerationResult& device_enumeration) { | |
| 306 DCHECK(CalledOnValidThread()); | |
| 307 | |
| 308 if (controls->audio.requested && | |
| 309 IsDeviceSource(controls->audio.stream_source)) { | |
| 310 if (!PickDeviceId(user_media_request.audioConstraints(), | |
| 311 device_enumeration[MEDIA_DEVICE_TYPE_AUDIO_INPUT], | |
| 312 &controls->audio.device_id)) { | |
| 313 GetUserMediaRequestFailed(user_media_request, MEDIA_DEVICE_NO_HARDWARE, | |
| 314 ""); | |
| 315 return; | |
| 316 } | |
| 217 } | 317 } |
| 218 | 318 |
| 219 DVLOG(1) << "UserMediaClientImpl::requestUserMedia(" << request_id << ", [ " | 319 if (controls->video.requested && |
| 220 << "audio=" << (controls.audio.requested) | 320 IsDeviceSource(controls->video.stream_source)) { |
| 221 << " select associated sink: " | 321 if (!PickDeviceId(user_media_request.videoConstraints(), |
| 222 << enable_automatic_output_device_selection | 322 device_enumeration[MEDIA_DEVICE_TYPE_VIDEO_INPUT], |
| 223 << ", video=" << (controls.video.requested) << " ], " | 323 &controls->video.device_id)) { |
| 224 << security_origin << ")"; | 324 GetUserMediaRequestFailed(user_media_request, MEDIA_DEVICE_NO_HARDWARE, |
| 225 | 325 ""); |
| 226 std::string audio_device_id; | 326 return; |
| 227 if (!user_media_request.isNull() && user_media_request.audio()) { | 327 } |
| 228 GetConstraintValueAsString(user_media_request.audioConstraints(), | |
| 229 &blink::WebMediaTrackConstraintSet::deviceId, | |
| 230 &audio_device_id); | |
| 231 } | 328 } |
| 232 | 329 |
| 233 std::string video_device_id; | 330 FinalizeRequestUserMedia(request_id, user_media_request, std::move(controls), |
| 234 if (!user_media_request.isNull() && user_media_request.video()) { | 331 enable_automatic_output_device_selection, |
| 235 GetConstraintValueAsString(user_media_request.videoConstraints(), | 332 security_origin); |
| 236 &blink::WebMediaTrackConstraintSet::deviceId, | 333 } |
| 237 &video_device_id); | |
| 238 } | |
| 239 | 334 |
| 240 WebRtcLogMessage(base::StringPrintf( | 335 void UserMediaClientImpl::FinalizeRequestUserMedia( |
| 241 "MSI::requestUserMedia. request_id=%d" | 336 int request_id, |
| 242 ", audio source id=%s" | 337 const blink::WebUserMediaRequest& user_media_request, |
| 243 ", video source id=%s", | 338 std::unique_ptr<StreamControls> controls, |
| 244 request_id, audio_device_id.c_str(), video_device_id.c_str())); | 339 bool enable_automatic_output_device_selection, |
| 340 const url::Origin& security_origin) { | |
| 341 DCHECK(CalledOnValidThread()); | |
| 342 | |
| 343 WebRtcLogMessage( | |
| 344 base::StringPrintf("MSI::requestUserMedia. request_id=%d" | |
| 345 ", audio source id=%s" | |
| 346 ", video source id=%s", | |
| 347 request_id, controls->audio.device_id.c_str(), | |
| 348 controls->video.device_id.c_str())); | |
| 245 | 349 |
| 246 user_media_requests_.push_back( | 350 user_media_requests_.push_back( |
| 247 new UserMediaRequestInfo(request_id, user_media_request, | 351 new UserMediaRequestInfo(request_id, user_media_request, |
| 248 enable_automatic_output_device_selection)); | 352 enable_automatic_output_device_selection)); |
| 249 | 353 |
| 250 media_stream_dispatcher_->GenerateStream( | 354 media_stream_dispatcher_->GenerateStream( |
| 251 request_id, weak_factory_.GetWeakPtr(), controls, security_origin); | 355 request_id, weak_factory_.GetWeakPtr(), *controls, security_origin); |
| 252 } | 356 } |
| 253 | 357 |
| 254 void UserMediaClientImpl::cancelUserMediaRequest( | 358 void UserMediaClientImpl::cancelUserMediaRequest( |
| 255 const blink::WebUserMediaRequest& user_media_request) { | 359 const blink::WebUserMediaRequest& user_media_request) { |
| 256 DCHECK(CalledOnValidThread()); | 360 DCHECK(CalledOnValidThread()); |
| 257 UserMediaRequestInfo* request = FindUserMediaRequestInfo(user_media_request); | 361 UserMediaRequestInfo* request = FindUserMediaRequestInfo(user_media_request); |
| 258 if (request) { | 362 if (request) { |
| 259 // We can't abort the stream generation process. | 363 // We can't abort the stream generation process. |
| 260 // Instead, erase the request. Once the stream is generated we will stop the | 364 // Instead, erase the request. Once the stream is generated we will stop the |
| 261 // stream if the request does not exist. | 365 // stream if the request does not exist. |
| (...skipping 716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 978 | 1082 |
| 979 bool UserMediaClientImpl::UserMediaRequestInfo::HasPendingSources() const { | 1083 bool UserMediaClientImpl::UserMediaRequestInfo::HasPendingSources() const { |
| 980 return !sources_waiting_for_callback_.empty(); | 1084 return !sources_waiting_for_callback_.empty(); |
| 981 } | 1085 } |
| 982 | 1086 |
| 983 void UserMediaClientImpl::OnDestruct() { | 1087 void UserMediaClientImpl::OnDestruct() { |
| 984 delete this; | 1088 delete this; |
| 985 } | 1089 } |
| 986 | 1090 |
| 987 } // namespace content | 1091 } // namespace content |
| OLD | NEW |