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

Side by Side Diff: content/browser/renderer_host/media/media_stream_manager.cc

Issue 2350693002: Remove device enumeration, caching and monitoring from MediaStreamManager. (Closed)
Patch Set: latest hta@ comments Created 4 years, 3 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 unified diff | Download patch
OLDNEW
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/browser/renderer_host/media/media_stream_manager.h" 5 #include "content/browser/renderer_host/media/media_stream_manager.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 #include <string.h> 9
10 #include <algorithm> 10 #include <algorithm>
11 #include <cctype> 11 #include <cctype>
12 #include <list> 12 #include <list>
13 #include <utility>
14 #include <vector>
15 13
16 #include "base/bind.h" 14 #include "base/bind.h"
17 #include "base/command_line.h" 15 #include "base/command_line.h"
18 #include "base/compiler_specific.h" 16 #include "base/compiler_specific.h"
19 #include "base/logging.h" 17 #include "base/logging.h"
20 #include "base/macros.h" 18 #include "base/macros.h"
21 #include "base/power_monitor/power_monitor.h" 19 #include "base/power_monitor/power_monitor.h"
22 #include "base/profiler/scoped_tracker.h" 20 #include "base/profiler/scoped_tracker.h"
23 #include "base/rand_util.h" 21 #include "base/rand_util.h"
24 #include "base/run_loop.h"
25 #include "base/strings/string_number_conversions.h" 22 #include "base/strings/string_number_conversions.h"
26 #include "base/strings/string_util.h" 23 #include "base/strings/string_util.h"
27 #include "base/strings/stringprintf.h" 24 #include "base/strings/stringprintf.h"
28 #include "base/task_runner_util.h" 25 #include "base/task_runner_util.h"
29 #include "base/threading/thread.h" 26 #include "base/threading/thread.h"
30 #include "base/threading/thread_local.h" 27 #include "base/threading/thread_local.h"
31 #include "build/build_config.h" 28 #include "build/build_config.h"
32 #include "content/browser/browser_main_loop.h"
33 #include "content/browser/child_process_security_policy_impl.h" 29 #include "content/browser/child_process_security_policy_impl.h"
34 #include "content/browser/renderer_host/media/audio_input_device_manager.h" 30 #include "content/browser/renderer_host/media/audio_input_device_manager.h"
35 #include "content/browser/renderer_host/media/audio_output_device_enumerator.h"
36 #include "content/browser/renderer_host/media/media_capture_devices_impl.h" 31 #include "content/browser/renderer_host/media/media_capture_devices_impl.h"
32 #include "content/browser/renderer_host/media/media_devices_manager.h"
37 #include "content/browser/renderer_host/media/media_stream_requester.h" 33 #include "content/browser/renderer_host/media/media_stream_requester.h"
38 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h" 34 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
39 #include "content/browser/renderer_host/media/video_capture_manager.h" 35 #include "content/browser/renderer_host/media/video_capture_manager.h"
40 #include "content/browser/renderer_host/render_process_host_impl.h" 36 #include "content/browser/renderer_host/render_process_host_impl.h"
41 #include "content/public/browser/browser_thread.h" 37 #include "content/public/browser/browser_thread.h"
42 #include "content/public/browser/content_browser_client.h" 38 #include "content/public/browser/content_browser_client.h"
43 #include "content/public/browser/desktop_media_id.h" 39 #include "content/public/browser/desktop_media_id.h"
44 #include "content/public/browser/media_observer.h" 40 #include "content/public/browser/media_observer.h"
45 #include "content/public/browser/media_request_state.h"
46 #include "content/public/browser/render_process_host.h" 41 #include "content/public/browser/render_process_host.h"
47 #include "content/public/browser/web_contents_media_capture_id.h" 42 #include "content/public/browser/web_contents_media_capture_id.h"
48 #include "content/public/common/content_client.h" 43 #include "content/public/common/content_client.h"
49 #include "content/public/common/content_switches.h" 44 #include "content/public/common/content_switches.h"
50 #include "content/public/common/media_stream_request.h" 45 #include "content/public/common/media_stream_request.h"
51 #include "crypto/hmac.h" 46 #include "crypto/hmac.h"
52 #include "media/audio/audio_device_description.h" 47 #include "media/audio/audio_device_description.h"
53 #include "media/audio/audio_manager.h" 48 #include "media/audio/audio_manager.h"
54 #include "media/base/audio_parameters.h" 49 #include "media/base/audio_parameters.h"
55 #include "media/base/channel_layout.h" 50 #include "media/base/channel_layout.h"
56 #include "media/base/media_switches.h" 51 #include "media/base/media_switches.h"
57 #include "media/capture/video/video_capture_device_factory.h" 52 #include "media/capture/video/video_capture_device_factory.h"
58 #include "url/gurl.h" 53 #include "url/gurl.h"
59 #include "url/origin.h" 54 #include "url/origin.h"
60 55
61 #if defined(OS_WIN) 56 #if defined(OS_WIN)
62 #include "base/win/scoped_com_initializer.h" 57 #include "base/win/scoped_com_initializer.h"
63 #endif 58 #endif
64 59
65 #if defined(OS_CHROMEOS) 60 #if defined(OS_CHROMEOS)
66 #include "chromeos/audio/cras_audio_handler.h" 61 #include "chromeos/audio/cras_audio_handler.h"
67 #endif 62 #endif
68 63
69 #if defined(OS_MACOSX)
70 #include "media/device_monitors/device_monitor_mac.h"
71 #endif
72
73 namespace content { 64 namespace content {
74 65
75 base::LazyInstance<base::ThreadLocalPointer<MediaStreamManager>>::Leaky 66 base::LazyInstance<base::ThreadLocalPointer<MediaStreamManager>>::Leaky
76 g_media_stream_manager_tls_ptr = LAZY_INSTANCE_INITIALIZER; 67 g_media_stream_manager_tls_ptr = LAZY_INSTANCE_INITIALIZER;
77 68
78 namespace { 69 namespace {
79 // Creates a random label used to identify requests. 70 // Creates a random label used to identify requests.
80 std::string RandomLabel() { 71 std::string RandomLabel() {
81 // An earlier PeerConnection spec [1] defined MediaStream::label alphabet as 72 // An earlier PeerConnection spec [1] defined MediaStream::label alphabet as
82 // an uuid with characters from range: U+0021, U+0023 to U+0027, U+002A to 73 // an uuid with characters from range: U+0021, U+0023 to U+0027, U+002A to
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 for (const chromeos::AudioDevice& device : devices) { 148 for (const chromeos::AudioDevice& device : devices) {
158 if (device.type == chromeos::AUDIO_TYPE_HOTWORD) { 149 if (device.type == chromeos::AUDIO_TYPE_HOTWORD) {
159 DCHECK(device.is_input); 150 DCHECK(device.is_input);
160 *effects |= media::AudioParameters::HOTWORD; 151 *effects |= media::AudioParameters::HOTWORD;
161 } 152 }
162 } 153 }
163 #endif 154 #endif
164 } 155 }
165 } 156 }
166 157
167 // Private helper method to generate a string for the log message that lists the
168 // human readable names of |devices|.
169 std::string GetLogMessageString(MediaStreamType stream_type,
170 const StreamDeviceInfoArray& device_infos) {
171 std::string output_string =
172 base::StringPrintf("Getting devices for stream type %d:\n", stream_type);
173 if (device_infos.empty())
174 return output_string + "No devices found.";
175 for (const content::StreamDeviceInfo& device_info : device_infos)
176 output_string += " " + device_info.device.name + "\n";
177 return output_string;
178 }
179
180 // Clears the MediaStreamDevice.name from all devices in |devices|. 158 // Clears the MediaStreamDevice.name from all devices in |devices|.
181 void ClearDeviceLabels(content::StreamDeviceInfoArray* devices) { 159 void ClearDeviceLabels(content::StreamDeviceInfoArray* devices) {
182 for (content::StreamDeviceInfo& device_info : *devices) 160 for (content::StreamDeviceInfo& device_info : *devices)
183 device_info.device.name.clear(); 161 device_info.device.name.clear();
184 } 162 }
185 163
186 bool CalledOnIOThread() { 164 bool CalledOnIOThread() {
187 // Check if this function call is on the IO thread, except for unittests where 165 // Check if this function call is on the IO thread, except for unittests where
188 // an IO thread might not have been created. 166 // an IO thread might not have been created.
189 return BrowserThread::CurrentlyOn(BrowserThread::IO) || 167 return BrowserThread::CurrentlyOn(BrowserThread::IO) ||
190 !BrowserThread::IsMessageLoopValid(BrowserThread::IO); 168 !BrowserThread::IsMessageLoopValid(BrowserThread::IO);
191 } 169 }
192 170
193 GURL ConvertToGURL(const url::Origin& origin) { 171 GURL ConvertToGURL(const url::Origin& origin) {
194 return origin.unique() ? GURL() : GURL(origin.Serialize()); 172 return origin.unique() ? GURL() : GURL(origin.Serialize());
195 } 173 }
196 174
175 bool GetDeviceIDFromHMAC(const std::string& salt,
176 const url::Origin& security_origin,
177 const std::string& hmac_device_id,
178 const MediaDeviceInfoArray& devices,
179 std::string* device_id) {
180 // The source_id can be empty if the constraint is set but empty.
181 if (hmac_device_id.empty())
182 return false;
183
184 for (const auto& device_info : devices) {
185 if (MediaStreamManager::DoesMediaDeviceIDMatchHMAC(
186 salt, security_origin, hmac_device_id, device_info.device_id)) {
187 *device_id = device_info.device_id;
188 return true;
189 }
190 }
191 return false;
192 }
193
194 MediaStreamType ConvertToMediaStreamType(MediaDeviceType type) {
195 switch (type) {
196 case MEDIA_DEVICE_TYPE_AUDIO_INPUT:
197 return MEDIA_DEVICE_AUDIO_CAPTURE;
198 case MEDIA_DEVICE_TYPE_VIDEO_INPUT:
199 return MEDIA_DEVICE_VIDEO_CAPTURE;
200 case MEDIA_DEVICE_TYPE_AUDIO_OUTPUT:
201 return MEDIA_DEVICE_AUDIO_OUTPUT;
202 default:
203 NOTREACHED();
204 }
205
206 return MEDIA_NO_SERVICE;
207 }
208
209 MediaDeviceType ConvertToMediaDeviceType(MediaStreamType stream_type) {
210 switch (stream_type) {
211 case MEDIA_DEVICE_AUDIO_CAPTURE:
212 return MEDIA_DEVICE_TYPE_AUDIO_INPUT;
213 case MEDIA_DEVICE_VIDEO_CAPTURE:
214 return MEDIA_DEVICE_TYPE_VIDEO_INPUT;
215 case MEDIA_DEVICE_AUDIO_OUTPUT:
216 return MEDIA_DEVICE_TYPE_AUDIO_OUTPUT;
217 default:
218 NOTREACHED();
219 }
220
221 return NUM_MEDIA_DEVICE_TYPES;
222 }
223
224 StreamDeviceInfoArray ConvertToStreamDeviceInfoArray(
225 MediaStreamType stream_type,
226 const MediaDeviceInfoArray& device_infos) {
227 StreamDeviceInfoArray stream_devices;
228 for (const auto& info : device_infos) {
229 stream_devices.emplace_back(stream_type, info.label, info.device_id,
230 info.group_id);
231 }
232
233 return stream_devices;
234 }
235
236 MediaStreamDevices ConvertToMediaStreamDevices(
237 MediaStreamType stream_type,
238 const MediaDeviceInfoArray& device_infos) {
239 MediaStreamDevices devices;
240 for (const auto& info : device_infos) {
241 devices.emplace_back(stream_type, info.device_id, info.label,
242 info.group_id);
243 }
244
245 return devices;
246 }
247
197 } // namespace 248 } // namespace
198 249
199 250
200 // MediaStreamManager::DeviceRequest represents a request to either enumerate 251 // MediaStreamManager::DeviceRequest represents a request to either enumerate
201 // available devices or open one or more devices. 252 // available devices or open one or more devices.
202 // TODO(perkj): MediaStreamManager still needs refactoring. I propose we create 253 // TODO(perkj): MediaStreamManager still needs refactoring. I propose we create
203 // several subclasses of DeviceRequest and move some of the responsibility of 254 // several subclasses of DeviceRequest and move some of the responsibility of
204 // the MediaStreamManager to the subclasses to get rid of the way too many if 255 // the MediaStreamManager to the subclasses to get rid of the way too many if
205 // statements in MediaStreamManager. 256 // statements in MediaStreamManager.
206 class MediaStreamManager::DeviceRequest { 257 class MediaStreamManager::DeviceRequest {
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 407
357 private: 408 private:
358 std::vector<MediaRequestState> state_; 409 std::vector<MediaRequestState> state_;
359 std::unique_ptr<MediaStreamRequest> ui_request_; 410 std::unique_ptr<MediaStreamRequest> ui_request_;
360 MediaStreamType audio_type_; 411 MediaStreamType audio_type_;
361 MediaStreamType video_type_; 412 MediaStreamType video_type_;
362 int target_process_id_; 413 int target_process_id_;
363 int target_frame_id_; 414 int target_frame_id_;
364 }; 415 };
365 416
366 MediaStreamManager::EnumerationCache::EnumerationCache()
367 : valid(false) {
368 }
369
370 MediaStreamManager::EnumerationCache::~EnumerationCache() {
371 }
372
373 // static 417 // static
374 void MediaStreamManager::SendMessageToNativeLog(const std::string& message) { 418 void MediaStreamManager::SendMessageToNativeLog(const std::string& message) {
375 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { 419 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
376 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 420 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
377 base::Bind(&MediaStreamManager::SendMessageToNativeLog, message)); 421 base::Bind(&MediaStreamManager::SendMessageToNativeLog, message));
378 return; 422 return;
379 } 423 }
380 424
381 MediaStreamManager* msm = g_media_stream_manager_tls_ptr.Pointer()->Get(); 425 MediaStreamManager* msm = g_media_stream_manager_tls_ptr.Pointer()->Get();
382 if (!msm) { 426 if (!msm) {
383 DLOG(ERROR) << "No MediaStreamManager on the IO thread. " << message; 427 DLOG(ERROR) << "No MediaStreamManager on the IO thread. " << message;
384 return; 428 return;
385 } 429 }
386 430
387 msm->AddLogMessageOnIOThread(message); 431 msm->AddLogMessageOnIOThread(message);
388 } 432 }
389 433
390 MediaStreamManager::MediaStreamManager(media::AudioManager* audio_manager) 434 MediaStreamManager::MediaStreamManager(media::AudioManager* audio_manager)
391 : audio_manager_(audio_manager), 435 : audio_manager_(audio_manager),
392 #if defined(OS_WIN) 436 #if defined(OS_WIN)
393 video_capture_thread_("VideoCaptureThread"), 437 video_capture_thread_("VideoCaptureThread"),
394 #endif 438 #endif
395 monitoring_started_(false),
396 use_fake_ui_(base::CommandLine::ForCurrentProcess()->HasSwitch( 439 use_fake_ui_(base::CommandLine::ForCurrentProcess()->HasSwitch(
397 switches::kUseFakeUIForMediaStream)) { 440 switches::kUseFakeUIForMediaStream)) {
398 DCHECK(audio_manager_); 441 DCHECK(audio_manager_);
399 memset(active_enumeration_ref_count_, 0,
400 sizeof(active_enumeration_ref_count_));
401 442
402 // Some unit tests create the MSM in the IO thread and assumes the 443 // Some unit tests create the MSM in the IO thread and assumes the
403 // initialization is done synchronously. 444 // initialization is done synchronously.
404 if (BrowserThread::CurrentlyOn(BrowserThread::IO)) { 445 if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
405 InitializeDeviceManagersOnIOThread(); 446 InitializeDeviceManagersOnIOThread();
406 } else { 447 } else {
407 BrowserThread::PostTask( 448 BrowserThread::PostTask(
408 BrowserThread::IO, FROM_HERE, 449 BrowserThread::IO, FROM_HERE,
409 base::Bind(&MediaStreamManager::InitializeDeviceManagersOnIOThread, 450 base::Bind(&MediaStreamManager::InitializeDeviceManagersOnIOThread,
410 base::Unretained(this))); 451 base::Unretained(this)));
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 return audio_input_device_manager_.get(); 484 return audio_input_device_manager_.get();
444 } 485 }
445 486
446 AudioOutputDeviceEnumerator* 487 AudioOutputDeviceEnumerator*
447 MediaStreamManager::audio_output_device_enumerator() { 488 MediaStreamManager::audio_output_device_enumerator() {
448 DCHECK_CURRENTLY_ON(BrowserThread::IO); 489 DCHECK_CURRENTLY_ON(BrowserThread::IO);
449 DCHECK(audio_output_device_enumerator_.get()); 490 DCHECK(audio_output_device_enumerator_.get());
450 return audio_output_device_enumerator_.get(); 491 return audio_output_device_enumerator_.get();
451 } 492 }
452 493
494 MediaDevicesManager* MediaStreamManager::media_devices_manager() {
495 DCHECK_CURRENTLY_ON(BrowserThread::IO);
496 DCHECK(media_devices_manager_.get());
497 return media_devices_manager_.get();
498 }
499
453 std::string MediaStreamManager::MakeMediaAccessRequest( 500 std::string MediaStreamManager::MakeMediaAccessRequest(
454 int render_process_id, 501 int render_process_id,
455 int render_frame_id, 502 int render_frame_id,
456 int page_request_id, 503 int page_request_id,
457 const StreamControls& controls, 504 const StreamControls& controls,
458 const url::Origin& security_origin, 505 const url::Origin& security_origin,
459 const MediaRequestResponseCallback& callback) { 506 const MediaRequestResponseCallback& callback) {
460 DCHECK_CURRENTLY_ON(BrowserThread::IO); 507 DCHECK_CURRENTLY_ON(BrowserThread::IO);
461 508
462 // TODO(perkj): The argument list with NULL parameters to DeviceRequest 509 // TODO(perkj): The argument list with NULL parameters to DeviceRequest
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
714 } 761 }
715 762
716 void MediaStreamManager::DoEnumerateDevices(const std::string& label) { 763 void MediaStreamManager::DoEnumerateDevices(const std::string& label) {
717 DCHECK_CURRENTLY_ON(BrowserThread::IO); 764 DCHECK_CURRENTLY_ON(BrowserThread::IO);
718 DeviceRequest* request = FindRequest(label); 765 DeviceRequest* request = FindRequest(label);
719 if (!request) 766 if (!request)
720 return; // This can happen if the request has been canceled. 767 return; // This can happen if the request has been canceled.
721 768
722 if (request->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT) { 769 if (request->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT) {
723 DCHECK_EQ(MEDIA_NO_SERVICE, request->video_type()); 770 DCHECK_EQ(MEDIA_NO_SERVICE, request->video_type());
724 DCHECK_GE(active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_OUTPUT], 0);
725 request->SetState(MEDIA_DEVICE_AUDIO_OUTPUT, MEDIA_REQUEST_STATE_REQUESTED); 771 request->SetState(MEDIA_DEVICE_AUDIO_OUTPUT, MEDIA_REQUEST_STATE_REQUESTED);
726 if (active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_OUTPUT] == 0) { 772 media_devices_manager_->EnumerateDevices(
727 ++active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_OUTPUT]; 773 {{false /* audio input */, false /* video input*/,
728 DCHECK(audio_output_device_enumerator_); 774 true /* audio output */}},
729 audio_output_device_enumerator_->Enumerate( 775 base::Bind(&MediaStreamManager::AudioOutputDevicesEnumerated,
730 base::Bind(&MediaStreamManager::AudioOutputDevicesEnumerated, 776 base::Unretained(this), label));
731 base::Unretained(this)));
732 }
733 return; 777 return;
734 } 778 }
735 779
736 MediaStreamType type; 780 StartEnumeration(request, label);
737 EnumerationCache* cache;
738 if (request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE) {
739 DCHECK_EQ(MEDIA_NO_SERVICE, request->video_type());
740 type = MEDIA_DEVICE_AUDIO_CAPTURE;
741 cache = &audio_enumeration_cache_;
742 } else {
743 DCHECK_EQ(MEDIA_DEVICE_VIDEO_CAPTURE, request->video_type());
744 DCHECK_EQ(MEDIA_NO_SERVICE, request->audio_type());
745 type = MEDIA_DEVICE_VIDEO_CAPTURE;
746 cache = &video_enumeration_cache_;
747 }
748
749 if (!EnumerationRequired(cache, type)) {
750 // Cached device list of this type exists. Just send it out.
751 request->SetState(type, MEDIA_REQUEST_STATE_REQUESTED);
752 request->devices = cache->devices;
753 FinalizeEnumerateDevices(label, request);
754 } else {
755 StartEnumeration(request);
756 }
757 DVLOG(1) << "Enumerate Devices ({label = " << label << "})"; 781 DVLOG(1) << "Enumerate Devices ({label = " << label << "})";
758 } 782 }
759 783
760 void MediaStreamManager::AudioOutputDevicesEnumerated( 784 void MediaStreamManager::AudioOutputDevicesEnumerated(
761 const AudioOutputDeviceEnumeration& device_enumeration) { 785 const std::string& label,
786 const MediaDeviceEnumeration& enumeration) {
762 DCHECK_CURRENTLY_ON(BrowserThread::IO); 787 DCHECK_CURRENTLY_ON(BrowserThread::IO);
763 DVLOG(1) << "AudioOutputDevicesEnumerated()";
764 StreamDeviceInfoArray device_infos;
765 788
766 if (device_enumeration.has_actual_devices) { 789 DeviceRequest* request = FindRequest(label);
767 for (const auto& entry : device_enumeration.devices) { 790 if (!request)
768 device_infos.emplace_back(MEDIA_DEVICE_AUDIO_OUTPUT, entry.device_name, 791 return;
769 entry.unique_id, entry.group_id);
770 }
771 }
772 792
773 const std::string log_message = 793 DCHECK_EQ(MEDIA_DEVICE_AUDIO_OUTPUT, request->audio_type());
774 "New device enumeration result:\n" + 794 DCHECK_EQ(MEDIA_REQUEST_STATE_REQUESTED,
775 GetLogMessageString(MEDIA_DEVICE_AUDIO_OUTPUT, device_infos); 795 request->state(MEDIA_DEVICE_AUDIO_OUTPUT));
776 SendMessageToNativeLog(log_message); 796 DCHECK_EQ(MEDIA_ENUMERATE_DEVICES, request->request_type);
777 797 DCHECK(!request->ui_proxy.get());
778 // Publish the result for all requests waiting for device list(s). 798 StreamDeviceInfoArray device_infos = ConvertToStreamDeviceInfoArray(
779 for (const LabeledDeviceRequest& request : requests_) { 799 MEDIA_DEVICE_AUDIO_OUTPUT, enumeration[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT]);
780 if (request.second->state(MEDIA_DEVICE_AUDIO_OUTPUT) == 800 request->devices = device_infos;
781 MEDIA_REQUEST_STATE_REQUESTED && 801 FinalizeEnumerateDevices(label, request);
782 request.second->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT) {
783 DCHECK_EQ(MEDIA_ENUMERATE_DEVICES, request.second->request_type);
784 request.second->SetState(MEDIA_DEVICE_AUDIO_OUTPUT,
785 MEDIA_REQUEST_STATE_PENDING_APPROVAL);
786 request.second->devices = device_infos;
787 FinalizeEnumerateDevices(request.first, request.second);
788 }
789 }
790
791 --active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_OUTPUT];
792 DCHECK_GE(active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_OUTPUT], 0);
793 } 802 }
794 803
795 void MediaStreamManager::OpenDevice(MediaStreamRequester* requester, 804 void MediaStreamManager::OpenDevice(MediaStreamRequester* requester,
796 int render_process_id, 805 int render_process_id,
797 int render_frame_id, 806 int render_frame_id,
798 const std::string& salt, 807 const std::string& salt,
799 int page_request_id, 808 int page_request_id,
800 const std::string& device_id, 809 const std::string& device_id,
801 MediaStreamType type, 810 MediaStreamType type,
802 const url::Origin& security_origin) { 811 const url::Origin& security_origin) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
837 const std::string& salt, 846 const std::string& salt,
838 const url::Origin& security_origin, 847 const url::Origin& security_origin,
839 const std::string& source_id, 848 const std::string& source_id,
840 std::string* device_id) const { 849 std::string* device_id) const {
841 DCHECK(stream_type == MEDIA_DEVICE_AUDIO_CAPTURE || 850 DCHECK(stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ||
842 stream_type == MEDIA_DEVICE_VIDEO_CAPTURE); 851 stream_type == MEDIA_DEVICE_VIDEO_CAPTURE);
843 // The source_id can be empty if the constraint is set but empty. 852 // The source_id can be empty if the constraint is set but empty.
844 if (source_id.empty()) 853 if (source_id.empty())
845 return false; 854 return false;
846 855
847 const EnumerationCache* cache = 856 // TODO(guidou): Change to use MediaDevicesManager::EnumerateDevices.
848 stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ? 857 // See http://crbug.com/648155.
849 &audio_enumeration_cache_ : &video_enumeration_cache_; 858 MediaDeviceInfoArray cached_devices =
850 859 media_devices_manager_->GetCachedDeviceInfo(
851 // If device monitoring hasn't started, the |device_guid| is not valid. 860 ConvertToMediaDeviceType(stream_type));
852 if (!cache->valid) 861 return GetDeviceIDFromHMAC(salt, security_origin, source_id, cached_devices,
853 return false; 862 device_id);
854
855 for (const StreamDeviceInfo& device_info : cache->devices) {
856 if (DoesMediaDeviceIDMatchHMAC(salt, security_origin, source_id,
857 device_info.device.id)) {
858 *device_id = device_info.device.id;
859 return true;
860 }
861 }
862 return false;
863 } 863 }
864 864
865 void MediaStreamManager::EnsureDeviceMonitorStarted() { 865 void MediaStreamManager::EnsureDeviceMonitorStarted() {
866 DCHECK_CURRENTLY_ON(BrowserThread::IO); 866 DCHECK_CURRENTLY_ON(BrowserThread::IO);
867 StartMonitoring(); 867 media_devices_manager_->StartMonitoring();
868 } 868 }
869 869
870 void MediaStreamManager::StopRemovedDevices( 870 void MediaStreamManager::StopRemovedDevice(MediaDeviceType type,
871 const StreamDeviceInfoArray& old_devices, 871 const MediaDeviceInfo& device) {
872 const StreamDeviceInfoArray& new_devices) { 872 DCHECK(type == MEDIA_DEVICE_TYPE_AUDIO_INPUT ||
873 DVLOG(1) << "StopRemovedDevices(" 873 type == MEDIA_DEVICE_TYPE_VIDEO_INPUT);
874 << "{#old_devices = " << old_devices.size() << "} " 874 MediaStreamType stream_type = ConvertToMediaStreamType(type);
875 << "{#new_devices = " << new_devices.size() << "})";
876 for (const StreamDeviceInfo& old_device_info : old_devices) {
877 bool device_found = false;
878 for (const StreamDeviceInfo& new_device_info : new_devices) {
879 if (old_device_info.device.id == new_device_info.device.id) {
880 device_found = true;
881 break;
882 }
883 }
884
885 if (!device_found) {
886 // A device has been removed. We need to check if it is used by a
887 // MediaStream and in that case cleanup and notify the render process.
888 StopRemovedDevice(old_device_info.device);
889 }
890 }
891 }
892
893 void MediaStreamManager::StopRemovedDevice(const MediaStreamDevice& device) {
894 std::vector<int> session_ids; 875 std::vector<int> session_ids;
895 for (const LabeledDeviceRequest& labeled_request : requests_) { 876 for (const LabeledDeviceRequest& labeled_request : requests_) {
896 const DeviceRequest* request = labeled_request.second; 877 const DeviceRequest* request = labeled_request.second;
897 for (const StreamDeviceInfo& device_info : request->devices) { 878 for (const StreamDeviceInfo& device_info : request->devices) {
898 const std::string source_id = GetHMACForMediaDeviceID( 879 const std::string source_id = GetHMACForMediaDeviceID(
899 request->salt, request->security_origin, device.id); 880 request->salt, request->security_origin, device.device_id);
900 if (device_info.device.id == source_id && 881 if (device_info.device.id == source_id &&
901 device_info.device.type == device.type) { 882 device_info.device.type == stream_type) {
902 session_ids.push_back(device_info.session_id); 883 session_ids.push_back(device_info.session_id);
903 if (labeled_request.second->requester) { 884 if (labeled_request.second->requester) {
904 labeled_request.second->requester->DeviceStopped( 885 labeled_request.second->requester->DeviceStopped(
905 labeled_request.second->requesting_frame_id, 886 labeled_request.second->requesting_frame_id,
906 labeled_request.first, device_info); 887 labeled_request.first, device_info);
907 } 888 }
908 } 889 }
909 } 890 }
910 } 891 }
911 for (const int session_id : session_ids) 892 for (const int session_id : session_ids)
912 StopDevice(device.type, session_id); 893 StopDevice(stream_type, session_id);
913 894
914 AddLogMessageOnIOThread( 895 AddLogMessageOnIOThread(
915 base::StringPrintf( 896 base::StringPrintf(
916 "Media input device removed: type = %s, id = %s, name = %s ", 897 "Media input device removed: type=%s, id=%s, name=%s ",
917 (device.type == MEDIA_DEVICE_AUDIO_CAPTURE ? "audio" : "video"), 898 (stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ? "audio" : "video"),
918 device.id.c_str(), device.name.c_str()).c_str()); 899 device.device_id.c_str(), device.label.c_str())
900 .c_str());
919 } 901 }
920 902
921 void MediaStreamManager::StartMonitoring() { 903 bool MediaStreamManager::PickDeviceId(const std::string& salt,
922 DCHECK_CURRENTLY_ON(BrowserThread::IO);
923 if (monitoring_started_)
924 return;
925
926 if (!base::SystemMonitor::Get())
927 return;
928
929 monitoring_started_ = true;
930 base::SystemMonitor::Get()->AddDevicesChangedObserver(this);
931
932 // Enumerate both the audio and video input devices to cache the device lists
933 // and send them to media observer.
934 ++active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_CAPTURE];
935 audio_input_device_manager_->EnumerateDevices(MEDIA_DEVICE_AUDIO_CAPTURE);
936 ++active_enumeration_ref_count_[MEDIA_DEVICE_VIDEO_CAPTURE];
937 video_capture_manager_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
938
939 #if defined(OS_MACOSX)
940 BrowserThread::PostTask(
941 BrowserThread::UI, FROM_HERE,
942 base::Bind(&MediaStreamManager::StartMonitoringOnUIThread,
943 base::Unretained(this)));
944 #endif
945 }
946
947 void MediaStreamManager::StopMonitoring() {
948 DCHECK(CalledOnIOThread());
949 if (!monitoring_started_)
950 return;
951 base::SystemMonitor::Get()->RemoveDevicesChangedObserver(this);
952 monitoring_started_ = false;
953 ClearEnumerationCache(&audio_enumeration_cache_);
954 ClearEnumerationCache(&video_enumeration_cache_);
955 audio_output_device_enumerator_->SetCachePolicy(
956 AudioOutputDeviceEnumerator::CACHE_POLICY_NO_CACHING);
957 }
958
959 #if defined(OS_MACOSX)
960 void MediaStreamManager::StartMonitoringOnUIThread() {
961 DCHECK_CURRENTLY_ON(BrowserThread::UI);
962 // TODO(erikchen): Remove ScopedTracker below once crbug.com/458404 is fixed.
963 tracked_objects::ScopedTracker tracking_profile1(
964 FROM_HERE_WITH_EXPLICIT_FUNCTION(
965 "458404 MediaStreamManager::GetBrowserMainLoop"));
966 BrowserMainLoop* browser_main_loop = content::BrowserMainLoop::GetInstance();
967 if (!browser_main_loop)
968 return;
969
970 // TODO(erikchen): Remove ScopedTracker below once crbug.com/458404 is
971 // fixed.
972 tracked_objects::ScopedTracker tracking_profile2(
973 FROM_HERE_WITH_EXPLICIT_FUNCTION(
974 "458404 MediaStreamManager::GetTaskRunner"));
975 const scoped_refptr<base::SingleThreadTaskRunner> task_runner =
976 audio_manager_->GetTaskRunner();
977 // TODO(erikchen): Remove ScopedTracker below once crbug.com/458404 is
978 // fixed.
979 tracked_objects::ScopedTracker tracking_profile3(
980 FROM_HERE_WITH_EXPLICIT_FUNCTION(
981 "458404 MediaStreamManager::DeviceMonitorMac::StartMonitoring"));
982 browser_main_loop->device_monitor_mac()->StartMonitoring(task_runner);
983 }
984 #endif
985
986 // Pick the first valid (translatable) device ID from lists of required
987 // and optional IDs.
988 bool MediaStreamManager::PickDeviceId(MediaStreamType type,
989 const std::string& salt,
990 const url::Origin& security_origin, 904 const url::Origin& security_origin,
991 const TrackControls& controls, 905 const TrackControls& controls,
906 const MediaDeviceInfoArray& devices,
992 std::string* device_id) const { 907 std::string* device_id) const {
993 if (!controls.device_ids.empty()) { 908 if (!controls.device_ids.empty()) {
994 if (controls.device_ids.size() > 1) { 909 if (controls.device_ids.size() > 1) {
995 LOG(ERROR) << "Only one required device ID is supported"; 910 LOG(ERROR) << "Only one required device ID is supported";
996 return false; 911 return false;
997 } 912 }
998 const std::string& candidate_id = controls.device_ids[0]; 913 const std::string& candidate_id = controls.device_ids[0];
999 if (!TranslateSourceIdToDeviceId(type, salt, security_origin, candidate_id, 914 if (!GetDeviceIDFromHMAC(salt, security_origin, candidate_id, devices,
1000 device_id)) { 915 device_id)) {
1001 LOG(WARNING) << "Invalid mandatory capture ID = " << candidate_id; 916 LOG(WARNING) << "Invalid mandatory capture ID = " << candidate_id;
1002 return false; 917 return false;
1003 } 918 }
1004 return true; 919 return true;
1005 } 920 }
1006 // We don't have a required ID. Look at the alternates. 921 // We don't have a required ID. Look at the alternates.
1007 for (const std::string& candidate_id : controls.alternate_device_ids) { 922 for (const std::string& candidate_id : controls.alternate_device_ids) {
1008 if (TranslateSourceIdToDeviceId(type, salt, security_origin, candidate_id, 923 if (GetDeviceIDFromHMAC(salt, security_origin, candidate_id, devices,
1009 device_id)) { 924 device_id)) {
1010 return true; 925 return true;
1011 } else { 926 } else {
1012 LOG(WARNING) << "Invalid optional capture ID = " << candidate_id; 927 LOG(WARNING) << "Invalid optional capture ID = " << candidate_id;
1013 } 928 }
1014 } 929 }
1015 return true; // If we get here, device_id is empty. 930 return true; // If we get here, device_id is empty.
1016 } 931 }
1017 932
1018 bool MediaStreamManager::GetRequestedDeviceCaptureId( 933 bool MediaStreamManager::GetRequestedDeviceCaptureId(
1019 const DeviceRequest* request, 934 const DeviceRequest* request,
1020 MediaStreamType type, 935 MediaStreamType type,
936 const MediaDeviceInfoArray& devices,
1021 std::string* device_id) const { 937 std::string* device_id) const {
1022 if (type == MEDIA_DEVICE_AUDIO_CAPTURE) { 938 if (type == MEDIA_DEVICE_AUDIO_CAPTURE) {
1023 return PickDeviceId(type, request->salt, request->security_origin, 939 return PickDeviceId(request->salt, request->security_origin,
1024 request->controls.audio, device_id); 940 request->controls.audio, devices, device_id);
1025 } else if (type == MEDIA_DEVICE_VIDEO_CAPTURE) { 941 } else if (type == MEDIA_DEVICE_VIDEO_CAPTURE) {
1026 return PickDeviceId(type, request->salt, request->security_origin, 942 return PickDeviceId(request->salt, request->security_origin,
1027 request->controls.video, device_id); 943 request->controls.video, devices, device_id);
1028 } else { 944 } else {
1029 NOTREACHED(); 945 NOTREACHED();
1030 } 946 }
1031 return false; 947 return false;
1032 } 948 }
1033 949
1034 void MediaStreamManager::TranslateDeviceIdToSourceId( 950 void MediaStreamManager::TranslateDeviceIdToSourceId(
1035 DeviceRequest* request, 951 DeviceRequest* request,
1036 MediaStreamDevice* device) { 952 MediaStreamDevice* device) {
1037 if (request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE || 953 if (request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE ||
1038 request->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT || 954 request->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT ||
1039 request->video_type() == MEDIA_DEVICE_VIDEO_CAPTURE) { 955 request->video_type() == MEDIA_DEVICE_VIDEO_CAPTURE) {
1040 device->id = GetHMACForMediaDeviceID(request->salt, 956 device->id = GetHMACForMediaDeviceID(request->salt,
1041 request->security_origin, device->id); 957 request->security_origin, device->id);
1042 if (!device->group_id.empty()) 958 if (!device->group_id.empty())
1043 device->group_id = GetHMACForMediaDeviceID( 959 device->group_id = GetHMACForMediaDeviceID(
1044 request->salt, request->security_origin, device->group_id); 960 request->salt, request->security_origin, device->group_id);
1045 } 961 }
1046 } 962 }
1047 963
1048 void MediaStreamManager::ClearEnumerationCache(EnumerationCache* cache) { 964 void MediaStreamManager::StartEnumeration(DeviceRequest* request,
1049 DCHECK(CalledOnIOThread()); 965 const std::string& label) {
1050 cache->valid = false;
1051 }
1052
1053 bool MediaStreamManager::EnumerationRequired(EnumerationCache* cache,
1054 MediaStreamType stream_type) {
1055 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1056 if (stream_type == MEDIA_NO_SERVICE)
1057 return false;
1058
1059 DCHECK(stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ||
1060 stream_type == MEDIA_DEVICE_VIDEO_CAPTURE);
1061
1062 #if defined(OS_ANDROID)
1063 // There's no SystemMonitor on Android that notifies us when devices are
1064 // added or removed, so we need to populate the cache on every request.
1065 // Fortunately, there is an already up-to-date cache in the browser side
1066 // audio manager that we can rely on, so the performance impact of
1067 // invalidating the cache like this, is minimal.
1068 if (stream_type == MEDIA_DEVICE_AUDIO_CAPTURE) {
1069 // Make sure the cache is marked as invalid so that FinalizeEnumerateDevices
1070 // will be called at the end of the enumeration.
1071 ClearEnumerationCache(cache);
1072 }
1073 #endif
1074 // If the cache isn't valid, we need to start a full enumeration.
1075 return !cache->valid;
1076 }
1077
1078 void MediaStreamManager::StartEnumeration(DeviceRequest* request) {
1079 DCHECK_CURRENTLY_ON(BrowserThread::IO); 966 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1080 967
1081 // Start monitoring the devices when doing the first enumeration. 968 // Start monitoring the devices when doing the first enumeration.
1082 StartMonitoring(); 969 media_devices_manager_->StartMonitoring();
1083 970
1084 // Start enumeration for devices of all requested device types. 971 // Start enumeration for devices of all requested device types.
1085 const MediaStreamType stream_types[] = {request->audio_type(), 972 bool request_audio_input = request->audio_type() != MEDIA_NO_SERVICE;
1086 request->video_type()}; 973 if (request_audio_input)
1087 for (const MediaStreamType stream_type : stream_types) { 974 request->SetState(request->audio_type(), MEDIA_REQUEST_STATE_REQUESTED);
1088 if (stream_type == MEDIA_NO_SERVICE) 975
1089 continue; 976 bool request_video_input = request->video_type() != MEDIA_NO_SERVICE;
1090 request->SetState(stream_type, MEDIA_REQUEST_STATE_REQUESTED); 977 if (request_video_input)
1091 DCHECK_GE(active_enumeration_ref_count_[stream_type], 0); 978 request->SetState(request->video_type(), MEDIA_REQUEST_STATE_REQUESTED);
1092 if (active_enumeration_ref_count_[stream_type] == 0) { 979
1093 ++active_enumeration_ref_count_[stream_type]; 980 // base::Unretained is safe here because MediaStreamManager is deleted on the
1094 GetDeviceManager(stream_type)->EnumerateDevices(stream_type); 981 // UI thread, after the IO thread has been stopped.
1095 } 982 DCHECK(request_audio_input || request_video_input);
1096 } 983 media_devices_manager_->EnumerateDevices(
984 {{request_audio_input, request_video_input, false /* no audio output */}},
985 base::Bind(&MediaStreamManager::DevicesEnumerated, base::Unretained(this),
986 request_audio_input, request_video_input, label));
1097 } 987 }
1098 988
1099 std::string MediaStreamManager::AddRequest(DeviceRequest* request) { 989 std::string MediaStreamManager::AddRequest(DeviceRequest* request) {
1100 DCHECK_CURRENTLY_ON(BrowserThread::IO); 990 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1101 991
1102 // Create a label for this request and verify it is unique. 992 // Create a label for this request and verify it is unique.
1103 std::string unique_label; 993 std::string unique_label;
1104 do { 994 do {
1105 unique_label = RandomLabel(); 995 unique_label = RandomLabel();
1106 } while (FindRequest(unique_label) != NULL); 996 } while (FindRequest(unique_label) != NULL);
(...skipping 20 matching lines...) Expand all
1127 std::unique_ptr<DeviceRequest> request(request_it->second); 1017 std::unique_ptr<DeviceRequest> request(request_it->second);
1128 requests_.erase(request_it); 1018 requests_.erase(request_it);
1129 return; 1019 return;
1130 } 1020 }
1131 } 1021 }
1132 NOTREACHED(); 1022 NOTREACHED();
1133 } 1023 }
1134 1024
1135 void MediaStreamManager::ReadOutputParamsAndPostRequestToUI( 1025 void MediaStreamManager::ReadOutputParamsAndPostRequestToUI(
1136 const std::string& label, 1026 const std::string& label,
1137 DeviceRequest* request) { 1027 DeviceRequest* request,
1028 const MediaDeviceEnumeration& enumeration) {
1138 DCHECK_CURRENTLY_ON(BrowserThread::IO); 1029 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1139 1030
1140 // Actual audio parameters are required only for MEDIA_TAB_AUDIO_CAPTURE. 1031 // Actual audio parameters are required only for MEDIA_TAB_AUDIO_CAPTURE.
1141 // TODO(guidou): MEDIA_TAB_AUDIO_CAPTURE should not be a special case. See 1032 // TODO(guidou): MEDIA_TAB_AUDIO_CAPTURE should not be a special case. See
1142 // crbug.com/584287. 1033 // crbug.com/584287.
1143 if (request->audio_type() == MEDIA_TAB_AUDIO_CAPTURE) { 1034 if (request->audio_type() == MEDIA_TAB_AUDIO_CAPTURE) {
1144 // Read output parameters on the correct thread for native audio OS calls. 1035 // Read output parameters on the correct thread for native audio OS calls.
1145 // Using base::Unretained is safe since |audio_manager_| is deleted after 1036 // Using base::Unretained is safe since |audio_manager_| is deleted after
1146 // its task runner, and MediaStreamManager is deleted on the UI thread, 1037 // its task runner, and MediaStreamManager is deleted on the UI thread,
1147 // after the IO thread has been stopped. 1038 // after the IO thread has been stopped.
1148 base::PostTaskAndReplyWithResult( 1039 base::PostTaskAndReplyWithResult(
1149 audio_manager_->GetTaskRunner(), FROM_HERE, 1040 audio_manager_->GetTaskRunner(), FROM_HERE,
1150 base::Bind(&media::AudioManager::GetDefaultOutputStreamParameters, 1041 base::Bind(&media::AudioManager::GetDefaultOutputStreamParameters,
1151 base::Unretained(audio_manager_)), 1042 base::Unretained(audio_manager_)),
1152 base::Bind(&MediaStreamManager::PostRequestToUI, base::Unretained(this), 1043 base::Bind(&MediaStreamManager::PostRequestToUI, base::Unretained(this),
1153 label, request)); 1044 label, request, enumeration));
1154 } else { 1045 } else {
1155 PostRequestToUI(label, request, media::AudioParameters()); 1046 PostRequestToUI(label, request, enumeration, media::AudioParameters());
1156 } 1047 }
1157 } 1048 }
1158 1049
1159 void MediaStreamManager::PostRequestToUI( 1050 void MediaStreamManager::PostRequestToUI(
1160 const std::string& label, 1051 const std::string& label,
1161 DeviceRequest* request, 1052 DeviceRequest* request,
1053 const MediaDeviceEnumeration& enumeration,
1162 const media::AudioParameters& output_parameters) { 1054 const media::AudioParameters& output_parameters) {
1163 DCHECK_CURRENTLY_ON(BrowserThread::IO); 1055 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1164 DCHECK(request->HasUIRequest()); 1056 DCHECK(request->HasUIRequest());
1165 DVLOG(1) << "PostRequestToUI({label= " << label << "})"; 1057 DVLOG(1) << "PostRequestToUI({label= " << label << "})";
1166 1058
1167 const MediaStreamType audio_type = request->audio_type(); 1059 const MediaStreamType audio_type = request->audio_type();
1168 const MediaStreamType video_type = request->video_type(); 1060 const MediaStreamType video_type = request->video_type();
1169 1061
1170 // Post the request to UI and set the state. 1062 // Post the request to UI and set the state.
1171 if (IsAudioInputMediaType(audio_type)) 1063 if (IsAudioInputMediaType(audio_type))
1172 request->SetState(audio_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL); 1064 request->SetState(audio_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
1173 if (IsVideoMediaType(video_type)) 1065 if (IsVideoMediaType(video_type))
1174 request->SetState(video_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL); 1066 request->SetState(video_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
1175 1067
1176 // If using the fake UI, it will just auto-select from the available devices. 1068 // If using the fake UI, it will just auto-select from the available devices.
1177 // The fake UI doesn't work for desktop sharing requests since we can't see 1069 // The fake UI doesn't work for desktop sharing requests since we can't see
1178 // its devices from here; always use the real UI for such requests. 1070 // its devices from here; always use the real UI for such requests.
1179 if (use_fake_ui_ && request->video_type() != MEDIA_DESKTOP_VIDEO_CAPTURE) { 1071 if (use_fake_ui_ && request->video_type() != MEDIA_DESKTOP_VIDEO_CAPTURE) {
1180 if (!fake_ui_) 1072 if (!fake_ui_)
1181 fake_ui_.reset(new FakeMediaStreamUIProxy()); 1073 fake_ui_.reset(new FakeMediaStreamUIProxy());
1182 1074
1183 MediaStreamDevices devices; 1075 MediaStreamDevices devices;
1184 if (audio_enumeration_cache_.valid) { 1076 for (const auto& info : enumeration[MEDIA_DEVICE_TYPE_AUDIO_INPUT]) {
1185 for (const StreamDeviceInfo& device_info : 1077 devices.emplace_back(audio_type, info.device_id, info.label,
1186 audio_enumeration_cache_.devices) { 1078 info.group_id);
1187 devices.push_back(device_info.device);
1188 }
1189 } 1079 }
1190 if (video_enumeration_cache_.valid) { 1080 for (const auto& info : enumeration[MEDIA_DEVICE_TYPE_VIDEO_INPUT]) {
1191 for (const StreamDeviceInfo& device_info : 1081 devices.emplace_back(video_type, info.device_id, info.label,
1192 video_enumeration_cache_.devices) { 1082 info.group_id);
1193 devices.push_back(device_info.device);
1194 }
1195 } 1083 }
1196 1084
1197 fake_ui_->SetAvailableDevices(devices); 1085 fake_ui_->SetAvailableDevices(devices);
1198 1086
1199 request->ui_proxy = std::move(fake_ui_); 1087 request->ui_proxy = std::move(fake_ui_);
1200 } else { 1088 } else {
1201 request->ui_proxy = MediaStreamUIProxy::Create(); 1089 request->ui_proxy = MediaStreamUIProxy::Create();
1202 } 1090 }
1203 1091
1204 request->ui_proxy->RequestAccess( 1092 request->ui_proxy->RequestAccess(
(...skipping 27 matching lines...) Expand all
1232 1120
1233 const bool is_screen_capture = video_type == MEDIA_DESKTOP_VIDEO_CAPTURE; 1121 const bool is_screen_capture = video_type == MEDIA_DESKTOP_VIDEO_CAPTURE;
1234 if (is_screen_capture && !SetupScreenCaptureRequest(request)) { 1122 if (is_screen_capture && !SetupScreenCaptureRequest(request)) {
1235 FinalizeRequestFailed(label, 1123 FinalizeRequestFailed(label,
1236 request, 1124 request,
1237 MEDIA_DEVICE_SCREEN_CAPTURE_FAILURE); 1125 MEDIA_DEVICE_SCREEN_CAPTURE_FAILURE);
1238 return; 1126 return;
1239 } 1127 }
1240 1128
1241 if (!is_web_contents_capture && !is_screen_capture) { 1129 if (!is_web_contents_capture && !is_screen_capture) {
1242 if (EnumerationRequired(&audio_enumeration_cache_, audio_type) || 1130 if (audio_type == MEDIA_DEVICE_AUDIO_CAPTURE ||
1243 EnumerationRequired(&video_enumeration_cache_, video_type)) { 1131 video_type == MEDIA_DEVICE_VIDEO_CAPTURE) {
1244 // Enumerate the devices if there is no valid device lists to be used. 1132 StartEnumeration(request, label);
1245 StartEnumeration(request);
1246 return; 1133 return;
1247 } else {
1248 // Cache is valid, so log the cached devices for MediaStream requests.
1249 if (request->request_type == MEDIA_GENERATE_STREAM) {
1250 std::string log_message("Using cached devices for request.\n");
1251 if (audio_type != MEDIA_NO_SERVICE) {
1252 log_message +=
1253 GetLogMessageString(audio_type, audio_enumeration_cache_.devices);
1254 }
1255 if (video_type != MEDIA_NO_SERVICE) {
1256 log_message +=
1257 GetLogMessageString(video_type, video_enumeration_cache_.devices);
1258 }
1259 SendMessageToNativeLog(log_message);
1260 }
1261 } 1134 }
1262 1135 // If no actual device capture is requested, set up the request with an
1263 if (!SetupDeviceCaptureRequest(request)) { 1136 // empty device list.
1137 if (!SetupDeviceCaptureRequest(request, MediaDeviceEnumeration())) {
1264 FinalizeRequestFailed(label, request, MEDIA_DEVICE_NO_HARDWARE); 1138 FinalizeRequestFailed(label, request, MEDIA_DEVICE_NO_HARDWARE);
1265 return; 1139 return;
1266 } 1140 }
1267 } 1141 }
1268 ReadOutputParamsAndPostRequestToUI(label, request); 1142 ReadOutputParamsAndPostRequestToUI(label, request, MediaDeviceEnumeration());
1269 } 1143 }
1270 1144
1271 bool MediaStreamManager::SetupDeviceCaptureRequest(DeviceRequest* request) { 1145 bool MediaStreamManager::SetupDeviceCaptureRequest(
1146 DeviceRequest* request,
1147 const MediaDeviceEnumeration& enumeration) {
1272 DCHECK((request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE || 1148 DCHECK((request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE ||
1273 request->audio_type() == MEDIA_NO_SERVICE) && 1149 request->audio_type() == MEDIA_NO_SERVICE) &&
1274 (request->video_type() == MEDIA_DEVICE_VIDEO_CAPTURE || 1150 (request->video_type() == MEDIA_DEVICE_VIDEO_CAPTURE ||
1275 request->video_type() == MEDIA_NO_SERVICE)); 1151 request->video_type() == MEDIA_NO_SERVICE));
1276 std::string audio_device_id; 1152 std::string audio_device_id;
1277 if (request->controls.audio.requested && 1153 if (request->controls.audio.requested &&
1278 !GetRequestedDeviceCaptureId(request, request->audio_type(), 1154 !GetRequestedDeviceCaptureId(request, request->audio_type(),
1155 enumeration[MEDIA_DEVICE_TYPE_AUDIO_INPUT],
1279 &audio_device_id)) { 1156 &audio_device_id)) {
1280 return false; 1157 return false;
1281 } 1158 }
1282 1159
1283 std::string video_device_id; 1160 std::string video_device_id;
1284 if (request->controls.video.requested && 1161 if (request->controls.video.requested &&
1285 !GetRequestedDeviceCaptureId(request, request->video_type(), 1162 !GetRequestedDeviceCaptureId(request, request->video_type(),
1163 enumeration[MEDIA_DEVICE_TYPE_VIDEO_INPUT],
1286 &video_device_id)) { 1164 &video_device_id)) {
1287 return false; 1165 return false;
1288 } 1166 }
1289 request->CreateUIRequest(audio_device_id, video_device_id); 1167 request->CreateUIRequest(audio_device_id, video_device_id);
1290 DVLOG(3) << "Audio requested " << request->controls.audio.requested 1168 DVLOG(3) << "Audio requested " << request->controls.audio.requested
1291 << " device id = " << audio_device_id << "Video requested " 1169 << " device id = " << audio_device_id << "Video requested "
1292 << request->controls.video.requested 1170 << request->controls.video.requested
1293 << " device id = " << video_device_id; 1171 << " device id = " << video_device_id;
1294 return true; 1172 return true;
1295 } 1173 }
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
1465 request->video_type() == MEDIA_DEVICE_VIDEO_CAPTURE)); 1343 request->video_type() == MEDIA_DEVICE_VIDEO_CAPTURE));
1466 1344
1467 for (StreamDeviceInfo& device_info : request->devices) 1345 for (StreamDeviceInfo& device_info : request->devices)
1468 TranslateDeviceIdToSourceId(request, &device_info.device); 1346 TranslateDeviceIdToSourceId(request, &device_info.device);
1469 1347
1470 if (use_fake_ui_) { 1348 if (use_fake_ui_) {
1471 if (!fake_ui_) 1349 if (!fake_ui_)
1472 fake_ui_.reset(new FakeMediaStreamUIProxy()); 1350 fake_ui_.reset(new FakeMediaStreamUIProxy());
1473 request->ui_proxy = std::move(fake_ui_); 1351 request->ui_proxy = std::move(fake_ui_);
1474 } else { 1352 } else {
1353 DCHECK(!request->ui_proxy);
1475 request->ui_proxy = MediaStreamUIProxy::Create(); 1354 request->ui_proxy = MediaStreamUIProxy::Create();
1476 } 1355 }
1477 1356
1478 // Output label permissions are based on input permission. 1357 // Output label permissions are based on input permission.
1479 const MediaStreamType type = 1358 const MediaStreamType type =
1480 request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE || 1359 request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE ||
1481 request->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT 1360 request->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT
1482 ? MEDIA_DEVICE_AUDIO_CAPTURE 1361 ? MEDIA_DEVICE_AUDIO_CAPTURE
1483 : MEDIA_DEVICE_VIDEO_CAPTURE; 1362 : MEDIA_DEVICE_VIDEO_CAPTURE;
1484 1363
(...skipping 21 matching lines...) Expand all
1506 1385
1507 if (!have_access) 1386 if (!have_access)
1508 ClearDeviceLabels(&request->devices); 1387 ClearDeviceLabels(&request->devices);
1509 1388
1510 request->requester->DevicesEnumerated( 1389 request->requester->DevicesEnumerated(
1511 request->requesting_frame_id, 1390 request->requesting_frame_id,
1512 request->page_request_id, 1391 request->page_request_id,
1513 label, 1392 label,
1514 request->devices); 1393 request->devices);
1515 1394
1516 // TODO(tommi): 1395 // TODO(guidou):
1517 // Ideally enumeration requests should be deleted once they have been served 1396 // Ideally enumeration requests should be deleted once they have been served
1518 // (as any request). However, this implementation mixes requests and 1397 // (as any request). However, this implementation mixes requests and
1519 // notifications together so enumeration requests are kept open by some 1398 // notifications together so enumeration requests are kept open by some
1520 // implementations (only Pepper?) and enumerations are done again when 1399 // implementations (only Pepper?) and enumerations are done again when
1521 // device notifications are fired. 1400 // device notifications are fired.
1522 // Implementations that just want to request the device list and be done 1401 // Implementations that just want to request the device list and be done
1523 // (e.g. DeviceRequestMessageFilter), they must (confusingly) call 1402 // (e.g. DeviceRequestMessageFilter), they must (confusingly) call
1524 // CancelRequest() after the request has been fulfilled. This is not 1403 // CancelRequest() after the request has been fulfilled. This is not
1525 // obvious, not consistent in this class (see e.g. FinalizeMediaAccessRequest) 1404 // obvious, not consistent in this class (see e.g. FinalizeMediaAccessRequest)
1526 // and can lead to subtle bugs (requests not deleted at all deleted too 1405 // and can lead to subtle bugs (requests not deleted at all deleted too
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1582 1461
1583 // TODO(dalecurtis): Remove ScopedTracker below once crbug.com/457525 is 1462 // TODO(dalecurtis): Remove ScopedTracker below once crbug.com/457525 is
1584 // fixed. 1463 // fixed.
1585 tracked_objects::ScopedTracker tracking_profile3( 1464 tracked_objects::ScopedTracker tracking_profile3(
1586 FROM_HERE_WITH_EXPLICIT_FUNCTION( 1465 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1587 "457525 MediaStreamManager::InitializeDeviceManagersOnIOThread 3")); 1466 "457525 MediaStreamManager::InitializeDeviceManagersOnIOThread 3"));
1588 // We want to be notified of IO message loop destruction to delete the thread 1467 // We want to be notified of IO message loop destruction to delete the thread
1589 // and the device managers. 1468 // and the device managers.
1590 base::MessageLoop::current()->AddDestructionObserver(this); 1469 base::MessageLoop::current()->AddDestructionObserver(this);
1591 1470
1592 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
1593 switches::kUseFakeDeviceForMediaStream)) {
1594 audio_input_device_manager()->UseFakeDevice();
1595 }
1596
1597 // TODO(dalecurtis): Remove ScopedTracker below once crbug.com/457525 is 1471 // TODO(dalecurtis): Remove ScopedTracker below once crbug.com/457525 is
1598 // fixed. 1472 // fixed.
1599 tracked_objects::ScopedTracker tracking_profile4( 1473 tracked_objects::ScopedTracker tracking_profile4(
1600 FROM_HERE_WITH_EXPLICIT_FUNCTION( 1474 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1601 "457525 MediaStreamManager::InitializeDeviceManagersOnIOThread 4")); 1475 "457525 MediaStreamManager::InitializeDeviceManagersOnIOThread 4"));
1602 video_capture_manager_ = 1476 video_capture_manager_ =
1603 new VideoCaptureManager(media::VideoCaptureDeviceFactory::CreateFactory( 1477 new VideoCaptureManager(media::VideoCaptureDeviceFactory::CreateFactory(
1604 BrowserThread::GetTaskRunnerForThread(BrowserThread::UI))); 1478 BrowserThread::GetTaskRunnerForThread(BrowserThread::UI)));
1605 #if defined(OS_WIN) 1479 #if defined(OS_WIN)
1606 // Use an STA Video Capture Thread to try to avoid crashes on enumeration of 1480 // Use an STA Video Capture Thread to try to avoid crashes on enumeration of
1607 // buggy third party Direct Show modules, http://crbug.com/428958. 1481 // buggy third party Direct Show modules, http://crbug.com/428958.
1608 video_capture_thread_.init_com_with_mta(false); 1482 video_capture_thread_.init_com_with_mta(false);
1609 CHECK(video_capture_thread_.Start()); 1483 CHECK(video_capture_thread_.Start());
1610 video_capture_manager_->Register(this, video_capture_thread_.task_runner()); 1484 video_capture_manager_->Register(this, video_capture_thread_.task_runner());
1611 #else 1485 #else
1612 video_capture_manager_->Register(this, device_task_runner_); 1486 video_capture_manager_->Register(this, device_task_runner_);
1613 #endif 1487 #endif
1614 1488
1615 audio_output_device_enumerator_.reset(new AudioOutputDeviceEnumerator( 1489 audio_output_device_enumerator_.reset(new AudioOutputDeviceEnumerator(
1616 audio_manager_, AudioOutputDeviceEnumerator::CACHE_POLICY_NO_CACHING)); 1490 audio_manager_, AudioOutputDeviceEnumerator::CACHE_POLICY_NO_CACHING));
1491
1492 media_devices_manager_.reset(
1493 new MediaDevicesManager(audio_manager_, video_capture_manager_, this));
1617 } 1494 }
1618 1495
1619 void MediaStreamManager::Opened(MediaStreamType stream_type, 1496 void MediaStreamManager::Opened(MediaStreamType stream_type,
1620 int capture_session_id) { 1497 int capture_session_id) {
1621 DCHECK_CURRENTLY_ON(BrowserThread::IO); 1498 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1622 DVLOG(1) << "Opened({stream_type = " << stream_type << "} " 1499 DVLOG(1) << "Opened({stream_type = " << stream_type << "} "
1623 << "{capture_session_id = " << capture_session_id << "})"; 1500 << "{capture_session_id = " << capture_session_id << "})";
1624 // Find the request(s) containing this device and mark it as used. 1501 // Find the request(s) containing this device and mark it as used.
1625 // It can be used in several requests since the same device can be 1502 // It can be used in several requests since the same device can be
1626 // requested from the same web page. 1503 // requested from the same web page.
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1695 request->devices)); 1572 request->devices));
1696 } 1573 }
1697 } 1574 }
1698 1575
1699 void MediaStreamManager::Closed(MediaStreamType stream_type, 1576 void MediaStreamManager::Closed(MediaStreamType stream_type,
1700 int capture_session_id) { 1577 int capture_session_id) {
1701 DCHECK_CURRENTLY_ON(BrowserThread::IO); 1578 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1702 } 1579 }
1703 1580
1704 void MediaStreamManager::DevicesEnumerated( 1581 void MediaStreamManager::DevicesEnumerated(
1705 MediaStreamType stream_type, const StreamDeviceInfoArray& devices) { 1582 bool requested_audio_input,
1583 bool requested_video_input,
1584 const std::string& label,
1585 const MediaDeviceEnumeration& enumeration) {
1706 DCHECK_CURRENTLY_ON(BrowserThread::IO); 1586 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1707 DVLOG(1) << "DevicesEnumerated("
1708 << "{stream_type = " << stream_type << "})";
1709 1587
1710 std::string log_message = "New device enumeration result:\n" + 1588 DeviceRequest* request = FindRequest(label);
1711 GetLogMessageString(stream_type, devices); 1589 if (!request)
1712 SendMessageToNativeLog(log_message); 1590 return;
1713 1591
1714 // Only cache the device list when the device list has been changed. 1592 bool requested[] = {requested_audio_input, requested_video_input};
1715 bool need_update_clients = false; 1593 MediaStreamType stream_types[] = {MEDIA_DEVICE_AUDIO_CAPTURE,
1716 bool need_update_device_change_subscribers = false; 1594 MEDIA_DEVICE_VIDEO_CAPTURE};
1717 EnumerationCache* cache = stream_type == MEDIA_DEVICE_AUDIO_CAPTURE 1595 MediaDeviceType device_types[] = {MEDIA_DEVICE_TYPE_AUDIO_INPUT,
1718 ? &audio_enumeration_cache_ 1596 MEDIA_DEVICE_TYPE_VIDEO_INPUT};
1719 : &video_enumeration_cache_;
1720 if (!cache->valid || devices.size() != cache->devices.size() ||
1721 !std::equal(devices.begin(), devices.end(), cache->devices.begin(),
1722 StreamDeviceInfo::IsEqual)) {
1723 StopRemovedDevices(cache->devices, devices);
1724 need_update_clients = true;
1725 // Device-change subscribers should not be notified the first time the cache
1726 // is loaded , as this is not a change in the set of devices. The same
1727 // applies to enumerations listing no devices when the cache is empty.
1728 need_update_device_change_subscribers =
1729 cache->valid && (devices.size() != 0 || cache->devices.size() != 0);
1730 cache->devices = devices;
1731 1597
1732 // The device might not be able to be enumerated when it is not warmed up, 1598 for (size_t i = 0; i < arraysize(requested); ++i) {
1733 // for example, when the machine just wakes up from sleep. We set the cache 1599 if (!requested[i])
1734 // to be invalid so that the next media request will trigger the 1600 continue;
1735 // enumeration again. See issue/317673.
1736 cache->valid = !devices.empty();
1737 }
1738 1601
1739 if (need_update_clients && monitoring_started_) 1602 DCHECK(request->audio_type() == stream_types[i] ||
1740 NotifyDevicesChanged(stream_type, devices); 1603 request->video_type() == stream_types[i]);
1741 1604 if (request->state(stream_types[i]) == MEDIA_REQUEST_STATE_REQUESTED) {
1742 if (need_update_device_change_subscribers) 1605 if (request->request_type == MEDIA_ENUMERATE_DEVICES) {
1743 NotifyDeviceChangeSubscribers(stream_type); 1606 // MEDIA_ENUMERATE_DEVICES requests are always for a single type, so it
1744 1607 // is OK to ignore any remaining iteration in this loop.
1745 // Publish the result for all requests waiting for device list(s). 1608 ProcessEnumerationRequest(label, request, stream_types[i],
1746 // Find the requests waiting for this device list, store their labels and 1609 enumeration[device_types[i]]);
1747 // release the iterator before calling device settings. We might get a call 1610 return;
1748 // back from device_settings that will need to iterate through devices. 1611 }
1749 std::list<std::string> label_list; 1612 // Not a MEDIA_ENUMERATE_DEVICES request.
1750 for (const LabeledDeviceRequest& labeled_request : requests_) { 1613 request->SetState(stream_types[i], MEDIA_REQUEST_STATE_PENDING_APPROVAL);
1751 DeviceRequest* const request = labeled_request.second;
1752 if (request->state(stream_type) == MEDIA_REQUEST_STATE_REQUESTED &&
1753 (request->audio_type() == stream_type ||
1754 request->video_type() == stream_type)) {
1755 if (request->request_type != MEDIA_ENUMERATE_DEVICES)
1756 request->SetState(stream_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
1757 label_list.push_back(labeled_request.first);
1758 } 1614 }
1759 } 1615 }
1760 1616
1761 for (const std::string& label : label_list) { 1617 if (!SetupDeviceCaptureRequest(request, enumeration))
1762 DeviceRequest* const request = FindRequest(label); 1618 FinalizeRequestFailed(label, request, MEDIA_DEVICE_NO_HARDWARE);
1763 switch (request->request_type) { 1619 else
1764 case MEDIA_ENUMERATE_DEVICES: 1620 ReadOutputParamsAndPostRequestToUI(label, request, enumeration);
1765 if (need_update_clients && request->requester) {
1766 request->devices = devices;
1767 FinalizeEnumerateDevices(label, request);
1768 }
1769 break;
1770 default:
1771 if (request->state(request->audio_type()) ==
1772 MEDIA_REQUEST_STATE_REQUESTED ||
1773 request->state(request->video_type()) ==
1774 MEDIA_REQUEST_STATE_REQUESTED) {
1775 // We are doing enumeration for other type of media, wait until it is
1776 // all done before posting the request to UI because UI needs
1777 // the device lists to handle the request.
1778 break;
1779 }
1780 if (!SetupDeviceCaptureRequest(request))
1781 FinalizeRequestFailed(label, request, MEDIA_DEVICE_NO_HARDWARE);
1782 else
1783 ReadOutputParamsAndPostRequestToUI(label, request);
1784 break;
1785 }
1786 }
1787 label_list.clear();
1788 --active_enumeration_ref_count_[stream_type];
1789 DCHECK_GE(active_enumeration_ref_count_[stream_type], 0);
1790 } 1621 }
1791 1622
1792 void MediaStreamManager::Aborted(MediaStreamType stream_type, 1623 void MediaStreamManager::Aborted(MediaStreamType stream_type,
1793 int capture_session_id) { 1624 int capture_session_id) {
1794 DCHECK_CURRENTLY_ON(BrowserThread::IO); 1625 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1795 DVLOG(1) << "Aborted({stream_type = " << stream_type << "} " 1626 DVLOG(1) << "Aborted({stream_type = " << stream_type << "} "
1796 << "{capture_session_id = " << capture_session_id << "})"; 1627 << "{capture_session_id = " << capture_session_id << "})";
1797 StopDevice(stream_type, capture_session_id); 1628 StopDevice(stream_type, capture_session_id);
1798 } 1629 }
1799 1630
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
1950 } 1781 }
1951 1782
1952 CancelRequest(label); 1783 CancelRequest(label);
1953 } 1784 }
1954 1785
1955 void MediaStreamManager::WillDestroyCurrentMessageLoop() { 1786 void MediaStreamManager::WillDestroyCurrentMessageLoop() {
1956 DVLOG(3) << "MediaStreamManager::WillDestroyCurrentMessageLoop()"; 1787 DVLOG(3) << "MediaStreamManager::WillDestroyCurrentMessageLoop()";
1957 DCHECK(CalledOnIOThread()); 1788 DCHECK(CalledOnIOThread());
1958 DCHECK(requests_.empty()); 1789 DCHECK(requests_.empty());
1959 if (device_task_runner_.get()) { 1790 if (device_task_runner_.get()) {
1960 StopMonitoring(); 1791 media_devices_manager_->StopMonitoring();
1961 1792
1962 video_capture_manager_->Unregister(); 1793 video_capture_manager_->Unregister();
1963 audio_input_device_manager_->Unregister(); 1794 audio_input_device_manager_->Unregister();
1964 device_task_runner_ = NULL; 1795 device_task_runner_ = NULL;
1965 } 1796 }
1966 1797
1967 audio_input_device_manager_ = NULL; 1798 audio_input_device_manager_ = NULL;
1968 video_capture_manager_ = NULL; 1799 video_capture_manager_ = NULL;
1969 audio_output_device_enumerator_ = NULL; 1800 audio_output_device_enumerator_ = NULL;
1801 media_devices_manager_ = NULL;
1970 g_media_stream_manager_tls_ptr.Pointer()->Set(NULL); 1802 g_media_stream_manager_tls_ptr.Pointer()->Set(NULL);
1971 } 1803 }
1972 1804
1973 void MediaStreamManager::NotifyDevicesChanged( 1805 void MediaStreamManager::NotifyDevicesChanged(
1974 MediaStreamType stream_type, 1806 MediaDeviceType device_type,
1975 const StreamDeviceInfoArray& devices) { 1807 const MediaDeviceInfoArray& devices) {
1976 DCHECK_CURRENTLY_ON(BrowserThread::IO); 1808 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1977 MediaObserver* media_observer = 1809 MediaObserver* media_observer =
1978 GetContentClient()->browser()->GetMediaObserver(); 1810 GetContentClient()->browser()->GetMediaObserver();
1979 1811
1980 // Map the devices to MediaStreamDevices. 1812 MediaStreamType stream_type = ConvertToMediaStreamType(device_type);
1981 MediaStreamDevices new_devices; 1813 MediaStreamDevices new_devices =
1982 for (const StreamDeviceInfo& device_info : devices) 1814 ConvertToMediaStreamDevices(stream_type, devices);
1983 new_devices.push_back(device_info.device);
1984 1815
1985 if (IsAudioInputMediaType(stream_type)) { 1816 if (IsAudioInputMediaType(stream_type)) {
1986 MediaCaptureDevicesImpl::GetInstance()->OnAudioCaptureDevicesChanged( 1817 MediaCaptureDevicesImpl::GetInstance()->OnAudioCaptureDevicesChanged(
1987 new_devices); 1818 new_devices);
1988 if (media_observer) 1819 if (media_observer)
1989 media_observer->OnAudioCaptureDevicesChanged(); 1820 media_observer->OnAudioCaptureDevicesChanged();
1990 } else if (IsVideoMediaType(stream_type)) { 1821 } else if (IsVideoMediaType(stream_type)) {
1991 MediaCaptureDevicesImpl::GetInstance()->OnVideoCaptureDevicesChanged( 1822 MediaCaptureDevicesImpl::GetInstance()->OnVideoCaptureDevicesChanged(
1992 new_devices); 1823 new_devices);
1993 if (media_observer) 1824 if (media_observer)
1994 media_observer->OnVideoCaptureDevicesChanged(); 1825 media_observer->OnVideoCaptureDevicesChanged();
1995 } else { 1826 } else {
1996 NOTREACHED(); 1827 NOTREACHED();
1997 } 1828 }
1829
1830 ProcessOpenEnumerationRequests(stream_type, devices);
1998 } 1831 }
1999 1832
2000 bool MediaStreamManager::RequestDone(const DeviceRequest& request) const { 1833 bool MediaStreamManager::RequestDone(const DeviceRequest& request) const {
2001 DCHECK_CURRENTLY_ON(BrowserThread::IO); 1834 DCHECK_CURRENTLY_ON(BrowserThread::IO);
2002 1835
2003 const bool requested_audio = IsAudioInputMediaType(request.audio_type()); 1836 const bool requested_audio = IsAudioInputMediaType(request.audio_type());
2004 const bool requested_video = IsVideoMediaType(request.video_type()); 1837 const bool requested_video = IsVideoMediaType(request.video_type());
2005 1838
2006 const bool audio_done = 1839 const bool audio_done =
2007 !requested_audio || 1840 !requested_audio ||
(...skipping 15 matching lines...) Expand all
2023 MediaStreamProvider* MediaStreamManager::GetDeviceManager( 1856 MediaStreamProvider* MediaStreamManager::GetDeviceManager(
2024 MediaStreamType stream_type) { 1857 MediaStreamType stream_type) {
2025 if (IsVideoMediaType(stream_type)) 1858 if (IsVideoMediaType(stream_type))
2026 return video_capture_manager(); 1859 return video_capture_manager();
2027 else if (IsAudioInputMediaType(stream_type)) 1860 else if (IsAudioInputMediaType(stream_type))
2028 return audio_input_device_manager(); 1861 return audio_input_device_manager();
2029 NOTREACHED(); 1862 NOTREACHED();
2030 return NULL; 1863 return NULL;
2031 } 1864 }
2032 1865
2033 void MediaStreamManager::OnDevicesChanged(
2034 base::SystemMonitor::DeviceType device_type) {
2035 DCHECK_CURRENTLY_ON(BrowserThread::IO);
2036
2037 // NOTE: This method is only called in response to physical audio/video device
2038 // changes (from the operating system).
2039
2040 MediaStreamType stream_type;
2041 if (device_type == base::SystemMonitor::DEVTYPE_AUDIO) {
2042 stream_type = MEDIA_DEVICE_AUDIO_CAPTURE;
2043 } else if (device_type == base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE) {
2044 stream_type = MEDIA_DEVICE_VIDEO_CAPTURE;
2045 } else {
2046 return; // Uninteresting device change.
2047 }
2048
2049 // Always do enumeration even though some enumeration is in progress, because
2050 // those enumeration commands could be sent before these devices change.
2051 ++active_enumeration_ref_count_[stream_type];
2052 GetDeviceManager(stream_type)->EnumerateDevices(stream_type);
2053 }
2054
2055 void MediaStreamManager::OnMediaStreamUIWindowId(MediaStreamType video_type, 1866 void MediaStreamManager::OnMediaStreamUIWindowId(MediaStreamType video_type,
2056 StreamDeviceInfoArray devices, 1867 StreamDeviceInfoArray devices,
2057 gfx::NativeViewId window_id) { 1868 gfx::NativeViewId window_id) {
2058 DCHECK_CURRENTLY_ON(BrowserThread::IO); 1869 DCHECK_CURRENTLY_ON(BrowserThread::IO);
2059 if (!window_id) 1870 if (!window_id)
2060 return; 1871 return;
2061 1872
2062 if (video_type != MEDIA_DESKTOP_VIDEO_CAPTURE) 1873 if (video_type != MEDIA_DESKTOP_VIDEO_CAPTURE)
2063 return; 1874 return;
2064 1875
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
2166 } 1977 }
2167 1978
2168 return true; 1979 return true;
2169 } 1980 }
2170 1981
2171 void MediaStreamManager::SetCapturingLinkSecured(int render_process_id, 1982 void MediaStreamManager::SetCapturingLinkSecured(int render_process_id,
2172 int session_id, 1983 int session_id,
2173 content::MediaStreamType type, 1984 content::MediaStreamType type,
2174 bool is_secure) { 1985 bool is_secure) {
2175 DCHECK_CURRENTLY_ON(BrowserThread::IO); 1986 DCHECK_CURRENTLY_ON(BrowserThread::IO);
2176
2177 for (LabeledDeviceRequest& labeled_request : requests_) { 1987 for (LabeledDeviceRequest& labeled_request : requests_) {
2178 DeviceRequest* request = labeled_request.second; 1988 DeviceRequest* request = labeled_request.second;
2179 if (request->requesting_process_id != render_process_id) 1989 if (request->requesting_process_id != render_process_id)
2180 continue; 1990 continue;
2181 1991
2182 for (const StreamDeviceInfo& device_info : request->devices) { 1992 for (const StreamDeviceInfo& device_info : request->devices) {
2183 if (device_info.session_id == session_id && 1993 if (device_info.session_id == session_id &&
2184 device_info.device.type == type) { 1994 device_info.device.type == type) {
2185 request->SetCapturingLinkSecured(is_secure); 1995 request->SetCapturingLinkSecured(is_secure);
2186 return; 1996 return;
2187 } 1997 }
2188 } 1998 }
2189 } 1999 }
2190 } 2000 }
2191 2001
2002 void MediaStreamManager::ProcessEnumerationRequest(
2003 const std::string& label,
2004 DeviceRequest* request,
2005 MediaStreamType stream_type,
2006 const MediaDeviceInfoArray& device_infos) {
2007 DCHECK_CURRENTLY_ON(BrowserThread::IO);
2008 DCHECK_EQ(MEDIA_REQUEST_STATE_REQUESTED, request->state(stream_type));
2009 DCHECK(request->audio_type() == stream_type ||
2010 request->video_type() == stream_type);
2011 DCHECK(request->audio_type() == MEDIA_NO_SERVICE ||
2012 request->video_type() == MEDIA_NO_SERVICE);
2013 DCHECK_EQ(MEDIA_ENUMERATE_DEVICES, request->request_type);
2014
2015 if (request->requester && !request->ui_proxy) {
2016 request->devices =
2017 ConvertToStreamDeviceInfoArray(stream_type, device_infos);
2018 FinalizeEnumerateDevices(label, request);
2019 }
2020 }
2021
2022 // This function is intended to support subscription-style device enumerations.
2023 // It is only supported for media capture devices and will be removed once
2024 // handling of enumeration requests and device-change notifications is migrated
2025 // out of MediaStreamManager.
2026 void MediaStreamManager::ProcessOpenEnumerationRequests(
2027 MediaStreamType stream_type,
2028 const MediaDeviceInfoArray& device_infos) {
2029 DCHECK_CURRENTLY_ON(BrowserThread::IO);
2030 DCHECK(stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ||
2031 stream_type == MEDIA_DEVICE_VIDEO_CAPTURE);
2032
2033 for (const LabeledDeviceRequest& labeled_request : requests_) {
2034 DeviceRequest* request = labeled_request.second;
2035 if (request->request_type == MEDIA_ENUMERATE_DEVICES &&
2036 request->state(stream_type) == MEDIA_REQUEST_STATE_REQUESTED &&
2037 (request->audio_type() == stream_type ||
2038 request->video_type() == stream_type)) {
2039 ProcessEnumerationRequest(labeled_request.first, request, stream_type,
2040 device_infos);
2041 }
2042 }
2043 }
2044
2192 } // namespace content 2045 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698