Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / media / media_stream_manager.cc
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
3 // found in the LICENSE file.
4
5 #include "content/browser/renderer_host/media/media_stream_manager.h"
6
7 #include <list>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/compiler_specific.h"
13 #include "base/logging.h"
14 #include "base/rand_util.h"
15 #include "base/run_loop.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/threading/thread.h"
18 #include "content/browser/browser_main_loop.h"
19 #include "content/browser/renderer_host/media/audio_input_device_manager.h"
20 #include "content/browser/renderer_host/media/device_request_message_filter.h"
21 #include "content/browser/renderer_host/media/media_stream_requester.h"
22 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
23 #include "content/browser/renderer_host/media/video_capture_manager.h"
24 #include "content/browser/renderer_host/media/web_contents_capture_util.h"
25 #include "content/browser/renderer_host/render_process_host_impl.h"
26 #include "content/public/browser/browser_thread.h"
27 #include "content/public/browser/content_browser_client.h"
28 #include "content/public/browser/media_device_id.h"
29 #include "content/public/browser/media_observer.h"
30 #include "content/public/browser/media_request_state.h"
31 #include "content/public/browser/render_process_host.h"
32 #include "content/public/common/content_switches.h"
33 #include "content/public/common/media_stream_request.h"
34 #include "media/audio/audio_manager_base.h"
35 #include "media/audio/audio_parameters.h"
36 #include "media/base/channel_layout.h"
37 #include "url/gurl.h"
38
39 #if defined(OS_WIN)
40 #include "base/win/scoped_com_initializer.h"
41 #endif
42
43 namespace content {
44
45 namespace {
46 // Creates a random label used to identify requests.
47 std::string RandomLabel() {
48   // An earlier PeerConnection spec,
49   // http://dev.w3.org/2011/webrtc/editor/webrtc.html, specified the
50   // MediaStream::label alphabet as containing 36 characters from
51   // range: U+0021, U+0023 to U+0027, U+002A to U+002B, U+002D to U+002E,
52   // U+0030 to U+0039, U+0041 to U+005A, U+005E to U+007E.
53   // Here we use a safe subset.
54   static const char kAlphabet[] = "0123456789"
55       "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
56
57   std::string label(36, ' ');
58   for (size_t i = 0; i < label.size(); ++i) {
59     int random_char = base::RandGenerator(sizeof(kAlphabet) - 1);
60     label[i] = kAlphabet[random_char];
61   }
62   return label;
63 }
64
65 void ParseStreamType(const StreamOptions& options,
66                      MediaStreamType* audio_type,
67                      MediaStreamType* video_type) {
68   *audio_type = MEDIA_NO_SERVICE;
69   *video_type = MEDIA_NO_SERVICE;
70   if (options.audio_requested) {
71      std::string audio_stream_source;
72      bool mandatory = false;
73      if (options.GetFirstAudioConstraintByName(kMediaStreamSource,
74                                                &audio_stream_source,
75                                                &mandatory)) {
76        DCHECK(mandatory);
77        // This is tab or screen capture.
78        if (audio_stream_source == kMediaStreamSourceTab) {
79          *audio_type = content::MEDIA_TAB_AUDIO_CAPTURE;
80        } else if (audio_stream_source == kMediaStreamSourceSystem) {
81          *audio_type = content::MEDIA_LOOPBACK_AUDIO_CAPTURE;
82        }
83      } else {
84        // This is normal audio device capture.
85        *audio_type = content::MEDIA_DEVICE_AUDIO_CAPTURE;
86      }
87   }
88   if (options.video_requested) {
89      std::string video_stream_source;
90      bool mandatory = false;
91      if (options.GetFirstVideoConstraintByName(kMediaStreamSource,
92                                                &video_stream_source,
93                                                &mandatory)) {
94        DCHECK(mandatory);
95        // This is tab or screen capture.
96        if (video_stream_source == kMediaStreamSourceTab) {
97          *video_type = content::MEDIA_TAB_VIDEO_CAPTURE;
98        } else if (video_stream_source == kMediaStreamSourceScreen) {
99          *video_type = content::MEDIA_DESKTOP_VIDEO_CAPTURE;
100        } else if (video_stream_source == kMediaStreamSourceDesktop) {
101          *video_type = content::MEDIA_DESKTOP_VIDEO_CAPTURE;
102        }
103      } else {
104        // This is normal video device capture.
105        *video_type = content::MEDIA_DEVICE_VIDEO_CAPTURE;
106      }
107   }
108 }
109
110 // Private helper method for SendMessageToNativeLog() that obtains the global
111 // MediaStreamManager instance on the UI thread before sending |message| to the
112 // webrtcLoggingPrivate API.
113 void DoAddLogMessage(const std::string& message) {
114   // Must be on the UI thread to access BrowserMainLoop.
115   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
116   // May be null in tests.
117   // TODO(vrk): Handle this more elegantly by having native log messages become
118   // no-ops until MediaStreamManager is aware that a renderer process has
119   // started logging. crbug.com/333894
120   if (content::BrowserMainLoop::GetInstance()) {
121     BrowserThread::PostTask(
122         BrowserThread::IO,
123         FROM_HERE,
124         base::Bind(&MediaStreamManager::AddLogMessageOnIOThread,
125                    base::Unretained(content::BrowserMainLoop::GetInstance()
126                                         ->media_stream_manager()),
127                    message));
128   }
129 }
130
131 // Private helper method to generate a string for the log message that lists the
132 // human readable names of |devices|.
133 std::string GetLogMessageString(MediaStreamType stream_type,
134                                 const StreamDeviceInfoArray& devices) {
135   std::string output_string =
136       base::StringPrintf("Getting devices for stream type %d:\n", stream_type);
137   if (devices.empty()) {
138     output_string += "No devices found.";
139   } else {
140     for (StreamDeviceInfoArray::const_iterator it = devices.begin();
141          it != devices.end(); ++it) {
142       output_string += "  " + it->device.name + "\n";
143     }
144   }
145   return output_string;
146 }
147
148 // Needed for MediaStreamManager::GenerateStream below.
149 std::string ReturnEmptySalt() {
150   return std::string();
151 }
152
153 }  // namespace
154
155
156 // MediaStreamManager::DeviceRequest represents a request to either enumerate
157 // available devices or open one or more devices.
158 // TODO(perkj): MediaStreamManager still needs refactoring. I propose we create
159 // several subclasses of DeviceRequest and move some of the responsibility of
160 // the MediaStreamManager to the subclasses to get rid of the way too many if
161 // statements in MediaStreamManager.
162 class MediaStreamManager::DeviceRequest {
163  public:
164   DeviceRequest(MediaStreamRequester* requester,
165                 int requesting_process_id,
166                 int requesting_view_id,
167                 int page_request_id,
168                 const GURL& security_origin,
169                 MediaStreamRequestType request_type,
170                 const StreamOptions& options,
171                 const ResourceContext::SaltCallback& salt_callback)
172       : requester(requester),
173         requesting_process_id(requesting_process_id),
174         requesting_view_id(requesting_view_id),
175         page_request_id(page_request_id),
176         security_origin(security_origin),
177         request_type(request_type),
178         options(options),
179         salt_callback(salt_callback),
180         state_(NUM_MEDIA_TYPES, MEDIA_REQUEST_STATE_NOT_REQUESTED),
181         audio_type_(MEDIA_NO_SERVICE),
182         video_type_(MEDIA_NO_SERVICE) {
183   }
184
185   ~DeviceRequest() {}
186
187   void SetAudioType(MediaStreamType audio_type) {
188     DCHECK(IsAudioMediaType(audio_type) || audio_type == MEDIA_NO_SERVICE);
189     audio_type_ = audio_type;
190   }
191
192   MediaStreamType audio_type() const { return audio_type_; }
193
194   void SetVideoType(MediaStreamType video_type) {
195     DCHECK(IsVideoMediaType(video_type) || video_type == MEDIA_NO_SERVICE);
196     video_type_ = video_type;
197   }
198
199   MediaStreamType video_type() const { return video_type_; }
200
201   // Creates a MediaStreamRequest object that is used by this request when UI
202   // is asked for permission and device selection.
203   void CreateUIRequest(const std::string& requested_audio_device_id,
204                        const std::string& requested_video_device_id) {
205     DCHECK(!ui_request_);
206     ui_request_.reset(new MediaStreamRequest(requesting_process_id,
207                                              requesting_view_id,
208                                              page_request_id,
209                                              security_origin,
210                                              request_type,
211                                              requested_audio_device_id,
212                                              requested_video_device_id,
213                                              audio_type_,
214                                              video_type_));
215   }
216
217   // Creates a tab capture specific MediaStreamRequest object that is used by
218   // this request when UI is asked for permission and device selection.
219   void CreateTabCatureUIRequest(int target_render_process_id,
220                                 int target_render_view_id,
221                                 const std::string& tab_capture_id) {
222     DCHECK(!ui_request_);
223     ui_request_.reset(new MediaStreamRequest(target_render_process_id,
224                                              target_render_view_id,
225                                              page_request_id,
226                                              security_origin,
227                                              request_type,
228                                              "",
229                                              "",
230                                              audio_type_,
231                                              video_type_));
232     ui_request_->tab_capture_device_id = tab_capture_id;
233   }
234
235   const MediaStreamRequest* UIRequest() const { return ui_request_.get(); }
236
237   // Update the request state and notify observers.
238   void SetState(MediaStreamType stream_type, MediaRequestState new_state) {
239     if (stream_type == NUM_MEDIA_TYPES) {
240       for (int i = MEDIA_NO_SERVICE + 1; i < NUM_MEDIA_TYPES; ++i) {
241         const MediaStreamType stream_type = static_cast<MediaStreamType>(i);
242         state_[stream_type] = new_state;
243       }
244     } else {
245       state_[stream_type] = new_state;
246     }
247
248     MediaObserver* media_observer =
249         GetContentClient()->browser()->GetMediaObserver();
250     if (!media_observer)
251       return;
252
253     // If |ui_request_| doesn't exist, it means that the request has not yet
254     // been setup fully and there are no valid observers.
255     if (!ui_request_)
256       return;
257
258     // If we appended a device_id scheme, we want to remove it when notifying
259     // observers which may be in different modules since this scheme is only
260     // used internally within the content module.
261     std::string device_id =
262         WebContentsCaptureUtil::StripWebContentsDeviceScheme(
263             ui_request_->tab_capture_device_id);
264
265     media_observer->OnMediaRequestStateChanged(
266         ui_request_->render_process_id, ui_request_->render_view_id,
267         ui_request_->page_request_id, ui_request_->security_origin,
268         MediaStreamDevice(stream_type, device_id, device_id), new_state);
269   }
270
271   MediaRequestState state(MediaStreamType stream_type) const {
272     return state_[stream_type];
273   }
274
275   MediaStreamRequester* const requester;  // Can be NULL.
276
277
278   // The render process id that requested this stream to be generated and that
279   // will receive a handle to the MediaStream. This may be different from
280   // MediaStreamRequest::render_process_id which in the tab capture case
281   // specifies the target renderer from which audio and video is captured.
282   const int requesting_process_id;
283
284   // The render view id that requested this stream to be generated and that
285   // will receive a handle to the MediaStream. This may be different from
286   // MediaStreamRequest::render_view_id which in the tab capture case
287   // specifies the target renderer from which audio and video is captured.
288   const int requesting_view_id;
289
290   // An ID the render view provided to identify this request.
291   const int page_request_id;
292
293   const GURL security_origin;
294
295   const MediaStreamRequestType request_type;
296
297   const StreamOptions options;
298
299   ResourceContext::SaltCallback salt_callback;
300
301   StreamDeviceInfoArray devices;
302
303   // Callback to the requester which audio/video devices have been selected.
304   // It can be null if the requester has no interest to know the result.
305   // Currently it is only used by |DEVICE_ACCESS| type.
306   MediaStreamManager::MediaRequestResponseCallback callback;
307
308   scoped_ptr<MediaStreamUIProxy> ui_proxy;
309
310  private:
311   std::vector<MediaRequestState> state_;
312   scoped_ptr<MediaStreamRequest> ui_request_;
313   MediaStreamType audio_type_;
314   MediaStreamType video_type_;
315 };
316
317 MediaStreamManager::EnumerationCache::EnumerationCache()
318     : valid(false) {
319 }
320
321 MediaStreamManager::EnumerationCache::~EnumerationCache() {
322 }
323
324 MediaStreamManager::MediaStreamManager()
325     : audio_manager_(NULL),
326       monitoring_started_(false),
327       io_loop_(NULL),
328       use_fake_ui_(false) {}
329
330 MediaStreamManager::MediaStreamManager(media::AudioManager* audio_manager)
331     : audio_manager_(audio_manager),
332       monitoring_started_(false),
333       io_loop_(NULL),
334       use_fake_ui_(false) {
335   DCHECK(audio_manager_);
336   memset(active_enumeration_ref_count_, 0,
337          sizeof(active_enumeration_ref_count_));
338
339   // Some unit tests create the MSM in the IO thread and assumes the
340   // initialization is done synchronously.
341   if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
342     InitializeDeviceManagersOnIOThread();
343   } else {
344     BrowserThread::PostTask(
345         BrowserThread::IO, FROM_HERE,
346         base::Bind(&MediaStreamManager::InitializeDeviceManagersOnIOThread,
347                    base::Unretained(this)));
348   }
349 }
350
351 MediaStreamManager::~MediaStreamManager() {
352   DVLOG(1) << "~MediaStreamManager";
353   DCHECK(requests_.empty());
354   DCHECK(!device_task_runner_);
355 }
356
357 VideoCaptureManager* MediaStreamManager::video_capture_manager() {
358   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
359   DCHECK(video_capture_manager_.get());
360   return video_capture_manager_.get();
361 }
362
363 AudioInputDeviceManager* MediaStreamManager::audio_input_device_manager() {
364   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
365   DCHECK(audio_input_device_manager_.get());
366   return audio_input_device_manager_.get();
367 }
368
369 std::string MediaStreamManager::MakeMediaAccessRequest(
370     int render_process_id,
371     int render_view_id,
372     int page_request_id,
373     const StreamOptions& options,
374     const GURL& security_origin,
375     const MediaRequestResponseCallback& callback) {
376   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
377
378   // TODO(perkj): The argument list with NULL parameters to DeviceRequest
379   // suggests that this is the wrong design. Can this be refactored?
380   DeviceRequest* request = new DeviceRequest(NULL,
381                                              render_process_id,
382                                              render_view_id,
383                                              page_request_id,
384                                              security_origin,
385                                              MEDIA_DEVICE_ACCESS,
386                                              options,
387                                              base::Bind(&ReturnEmptySalt));
388
389   const std::string& label = AddRequest(request);
390
391   request->callback = callback;
392   // Post a task and handle the request asynchronously. The reason is that the
393   // requester won't have a label for the request until this function returns
394   // and thus can not handle a response. Using base::Unretained is safe since
395   // MediaStreamManager is deleted on the UI thread, after the IO thread has
396   // been stopped.
397   BrowserThread::PostTask(
398       BrowserThread::IO, FROM_HERE,
399       base::Bind(&MediaStreamManager::SetupRequest,
400                  base::Unretained(this), label));
401   return label;
402 }
403
404 void MediaStreamManager::GenerateStream(MediaStreamRequester* requester,
405                                         int render_process_id,
406                                         int render_view_id,
407                                         const ResourceContext::SaltCallback& sc,
408                                         int page_request_id,
409                                         const StreamOptions& options,
410                                         const GURL& security_origin) {
411   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
412   DVLOG(1) << "GenerateStream()";
413   if (CommandLine::ForCurrentProcess()->HasSwitch(
414           switches::kUseFakeUIForMediaStream)) {
415     UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy>());
416   }
417
418   DeviceRequest* request = new DeviceRequest(requester,
419                                              render_process_id,
420                                              render_view_id,
421                                              page_request_id,
422                                              security_origin,
423                                              MEDIA_GENERATE_STREAM,
424                                              options,
425                                              sc);
426
427   const std::string& label = AddRequest(request);
428
429   // Post a task and handle the request asynchronously. The reason is that the
430   // requester won't have a label for the request until this function returns
431   // and thus can not handle a response. Using base::Unretained is safe since
432   // MediaStreamManager is deleted on the UI thread, after the IO thread has
433   // been stopped.
434   BrowserThread::PostTask(
435       BrowserThread::IO, FROM_HERE,
436       base::Bind(&MediaStreamManager::SetupRequest,
437                  base::Unretained(this), label));
438 }
439
440 void MediaStreamManager::CancelRequest(int render_process_id,
441                                        int render_view_id,
442                                        int page_request_id) {
443   for (DeviceRequests::const_iterator request_it = requests_.begin();
444        request_it != requests_.end(); ++request_it) {
445     const DeviceRequest* request = request_it->second;
446     if (request->requesting_process_id == render_process_id &&
447         request->requesting_view_id == render_view_id &&
448         request->page_request_id == page_request_id) {
449       CancelRequest(request_it->first);
450       return;
451     }
452   }
453   NOTREACHED();
454 }
455
456 void MediaStreamManager::CancelRequest(const std::string& label) {
457   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
458   DVLOG(1) << "CancelRequest({label = " << label <<  "})";
459   DeviceRequest* request = FindRequest(label);
460   if (!request) {
461     // The request does not exist.
462     LOG(ERROR) << "The request with label = " << label  << " does not exist.";
463     return;
464   }
465
466   if (request->request_type == MEDIA_ENUMERATE_DEVICES) {
467     // It isn't an ideal use of "CancelRequest" to make it a requirement
468     // for enumeration requests to be deleted via "CancelRequest" _after_
469     // the request has been successfully fulfilled.
470     // See note in FinalizeEnumerateDevices for a recommendation on how
471     // we should refactor this.
472     DeleteRequest(label);
473     return;
474   }
475
476   // This is a request for opening one or more devices.
477   for (StreamDeviceInfoArray::iterator device_it = request->devices.begin();
478        device_it != request->devices.end(); ++device_it) {
479     MediaRequestState state = request->state(device_it->device.type);
480     // If we have not yet requested the device to be opened - just ignore it.
481     if (state != MEDIA_REQUEST_STATE_OPENING &&
482         state != MEDIA_REQUEST_STATE_DONE) {
483       continue;
484     }
485     // Stop the opening/opened devices of the requests.
486     CloseDevice(device_it->device.type, device_it->session_id);
487   }
488
489   // Cancel the request if still pending at UI side.
490   request->SetState(NUM_MEDIA_TYPES, MEDIA_REQUEST_STATE_CLOSING);
491   DeleteRequest(label);
492 }
493
494 void MediaStreamManager::CancelAllRequests(int render_process_id) {
495   DeviceRequests::iterator request_it = requests_.begin();
496   while (request_it != requests_.end()) {
497     if (request_it->second->requesting_process_id != render_process_id) {
498       ++request_it;
499       continue;
500     }
501
502     std::string label = request_it->first;
503     ++request_it;
504     CancelRequest(label);
505   }
506 }
507
508 void MediaStreamManager::StopStreamDevice(int render_process_id,
509                                           int render_view_id,
510                                           const std::string& device_id) {
511   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
512   DVLOG(1) << "StopStreamDevice({render_view_id = " << render_view_id <<  "} "
513            << ", {device_id = " << device_id << "})";
514   // Find the first request for this |render_process_id| and |render_view_id|
515   // of type MEDIA_GENERATE_STREAM that has requested to use |device_id| and
516   // stop it.
517   for (DeviceRequests::iterator request_it = requests_.begin();
518        request_it  != requests_.end(); ++request_it) {
519     DeviceRequest* request = request_it->second;
520     if (request->requesting_process_id != render_process_id ||
521         request->requesting_view_id != render_view_id ||
522         request->request_type != MEDIA_GENERATE_STREAM) {
523       continue;
524     }
525
526     StreamDeviceInfoArray& devices = request->devices;
527     for (StreamDeviceInfoArray::iterator device_it = devices.begin();
528          device_it != devices.end(); ++device_it) {
529       if (device_it->device.id == device_id) {
530         StopDevice(device_it->device.type, device_it->session_id);
531         return;
532       }
533     }
534   }
535 }
536
537 void MediaStreamManager::StopDevice(MediaStreamType type, int session_id) {
538   DVLOG(1) << "StopDevice"
539            << "{type = " << type << "}"
540            << "{session_id = " << session_id << "}";
541   DeviceRequests::iterator request_it = requests_.begin();
542   while (request_it != requests_.end()) {
543     DeviceRequest* request = request_it->second;
544     StreamDeviceInfoArray* devices = &request->devices;
545     if (devices->empty()) {
546       // There is no device in use yet by this request.
547       ++request_it;
548       continue;
549     }
550     StreamDeviceInfoArray::iterator device_it = devices->begin();
551     while (device_it != devices->end()) {
552       if (device_it->device.type != type ||
553           device_it->session_id != session_id) {
554         ++device_it;
555         continue;
556       }
557
558       if (request->state(type) == MEDIA_REQUEST_STATE_DONE)
559         CloseDevice(type, session_id);
560       device_it = devices->erase(device_it);
561     }
562
563     // If this request doesn't have any active devices after a device
564     // has been stopped above, remove the request. Note that the request is
565     // only deleted if a device as been removed from |devices|.
566     if (devices->empty()) {
567       std::string label = request_it->first;
568       ++request_it;
569       DeleteRequest(label);
570     } else {
571       ++request_it;
572     }
573   }
574 }
575
576 void MediaStreamManager::CloseDevice(MediaStreamType type, int session_id) {
577   DVLOG(1) << "CloseDevice("
578            << "{type = " << type <<  "} "
579            << "{session_id = " << session_id << "})";
580   GetDeviceManager(type)->Close(session_id);
581
582   for (DeviceRequests::iterator request_it = requests_.begin();
583        request_it != requests_.end() ; ++request_it) {
584     StreamDeviceInfoArray* devices = &request_it->second->devices;
585     for (StreamDeviceInfoArray::iterator device_it = devices->begin();
586          device_it != devices->end(); ++device_it) {
587       if (device_it->session_id == session_id &&
588           device_it->device.type == type) {
589         // Notify observers that this device is being closed.
590         // Note that only one device per type can be opened.
591         request_it->second->SetState(type, MEDIA_REQUEST_STATE_CLOSING);
592       }
593     }
594   }
595 }
596
597 std::string MediaStreamManager::EnumerateDevices(
598     MediaStreamRequester* requester,
599     int render_process_id,
600     int render_view_id,
601     const ResourceContext::SaltCallback& sc,
602     int page_request_id,
603     MediaStreamType type,
604     const GURL& security_origin) {
605   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
606   DCHECK(requester);
607   DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
608          type == MEDIA_DEVICE_VIDEO_CAPTURE);
609
610   DeviceRequest* request = new DeviceRequest(requester,
611                                              render_process_id,
612                                              render_view_id,
613                                              page_request_id,
614                                              security_origin,
615                                              MEDIA_ENUMERATE_DEVICES,
616                                              StreamOptions(),
617                                              sc);
618   if (IsAudioMediaType(type))
619     request->SetAudioType(type);
620   else if (IsVideoMediaType(type))
621     request->SetVideoType(type);
622
623   const std::string& label = AddRequest(request);
624   // Post a task and handle the request asynchronously. The reason is that the
625   // requester won't have a label for the request until this function returns
626   // and thus can not handle a response. Using base::Unretained is safe since
627   // MediaStreamManager is deleted on the UI thread, after the IO thread has
628   // been stopped.
629   BrowserThread::PostTask(
630       BrowserThread::IO, FROM_HERE,
631       base::Bind(&MediaStreamManager::DoEnumerateDevices,
632                  base::Unretained(this), label));
633   return label;
634 }
635
636 void MediaStreamManager::DoEnumerateDevices(const std::string& label) {
637   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
638   DeviceRequest* request = FindRequest(label);
639   if (!request)
640     return;  // This can happen if the request has been canceled.
641
642   MediaStreamType type;
643   EnumerationCache* cache;
644   if (request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE) {
645     DCHECK_EQ(MEDIA_NO_SERVICE, request->video_type());
646     type = MEDIA_DEVICE_AUDIO_CAPTURE;
647     cache = &audio_enumeration_cache_;
648   } else {
649     DCHECK_EQ(MEDIA_DEVICE_VIDEO_CAPTURE, request->video_type());
650     type = MEDIA_DEVICE_VIDEO_CAPTURE;
651     cache = &video_enumeration_cache_;
652   }
653
654   if (!EnumerationRequired(cache, type)) {
655     // Cached device list of this type exists. Just send it out.
656     request->SetState(type, MEDIA_REQUEST_STATE_REQUESTED);
657     request->devices = cache->devices;
658     FinalizeEnumerateDevices(label, request);
659   } else {
660     StartEnumeration(request);
661   }
662   DVLOG(1) << "Enumerate Devices ({label = " << label <<  "})";
663 }
664
665 void MediaStreamManager::OpenDevice(MediaStreamRequester* requester,
666                                     int render_process_id,
667                                     int render_view_id,
668                                     const ResourceContext::SaltCallback& sc,
669                                     int page_request_id,
670                                     const std::string& device_id,
671                                     MediaStreamType type,
672                                     const GURL& security_origin) {
673   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
674   DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
675          type == MEDIA_DEVICE_VIDEO_CAPTURE);
676   DVLOG(1) << "OpenDevice ({page_request_id = " << page_request_id <<  "})";
677   StreamOptions options;
678   if (IsAudioMediaType(type)) {
679     options.audio_requested = true;
680     options.mandatory_audio.push_back(
681         StreamOptions::Constraint(kMediaStreamSourceInfoId, device_id));
682   } else if (IsVideoMediaType(type)) {
683     options.video_requested = true;
684     options.mandatory_video.push_back(
685         StreamOptions::Constraint(kMediaStreamSourceInfoId, device_id));
686   } else {
687     NOTREACHED();
688   }
689   DeviceRequest* request = new DeviceRequest(requester,
690                                              render_process_id,
691                                              render_view_id,
692                                              page_request_id,
693                                              security_origin,
694                                              MEDIA_OPEN_DEVICE,
695                                              options,
696                                              sc);
697
698   const std::string& label = AddRequest(request);
699   // Post a task and handle the request asynchronously. The reason is that the
700   // requester won't have a label for the request until this function returns
701   // and thus can not handle a response. Using base::Unretained is safe since
702   // MediaStreamManager is deleted on the UI thread, after the IO thread has
703   // been stopped.
704   BrowserThread::PostTask(
705       BrowserThread::IO, FROM_HERE,
706       base::Bind(&MediaStreamManager::SetupRequest,
707                  base::Unretained(this), label));
708 }
709
710 void MediaStreamManager::EnsureDeviceMonitorStarted() {
711   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
712   StartMonitoring();
713 }
714
715 void MediaStreamManager::StopRemovedDevices(
716     const StreamDeviceInfoArray& old_devices,
717     const StreamDeviceInfoArray& new_devices) {
718   DVLOG(1) << "StopRemovedDevices("
719            << "{#old_devices = " << old_devices.size() <<  "} "
720            << "{#new_devices = " << new_devices.size() << "})";
721   for (StreamDeviceInfoArray::const_iterator old_dev_it = old_devices.begin();
722        old_dev_it != old_devices.end(); ++old_dev_it) {
723     bool device_found = false;
724     StreamDeviceInfoArray::const_iterator new_dev_it = new_devices.begin();
725     for (; new_dev_it != new_devices.end(); ++new_dev_it) {
726       if (old_dev_it->device.id == new_dev_it->device.id) {
727         device_found = true;
728         break;
729       }
730     }
731
732     if (!device_found) {
733       // A device has been removed. We need to check if it is used by a
734       // MediaStream and in that case cleanup and notify the render process.
735       StopRemovedDevice(old_dev_it->device);
736     }
737   }
738 }
739
740 void MediaStreamManager::StopRemovedDevice(const MediaStreamDevice& device) {
741   std::vector<int> session_ids;
742   for (DeviceRequests::const_iterator it = requests_.begin();
743        it != requests_.end() ; ++it) {
744     const DeviceRequest* request = it->second;
745     for (StreamDeviceInfoArray::const_iterator device_it =
746              request->devices.begin();
747          device_it != request->devices.end(); ++device_it) {
748       std::string source_id = content::GetHMACForMediaDeviceID(
749           request->salt_callback,
750           request->security_origin,
751           device.id);
752       if (device_it->device.id == source_id &&
753           device_it->device.type == device.type) {
754         session_ids.push_back(device_it->session_id);
755         if (it->second->requester) {
756           it->second->requester->DeviceStopped(
757               it->second->requesting_view_id,
758               it->first,
759               *device_it);
760         }
761       }
762     }
763   }
764   for (std::vector<int>::const_iterator it = session_ids.begin();
765        it != session_ids.end(); ++it) {
766     StopDevice(device.type, *it);
767   }
768 }
769
770 void MediaStreamManager::StartMonitoring() {
771   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
772   if (monitoring_started_)
773     return;
774
775   if (!base::SystemMonitor::Get())
776     return;
777
778   monitoring_started_ = true;
779   base::SystemMonitor::Get()->AddDevicesChangedObserver(this);
780
781   // Enumerate both the audio and video devices to cache the device lists
782   // and send them to media observer.
783   ++active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_CAPTURE];
784   audio_input_device_manager_->EnumerateDevices(MEDIA_DEVICE_AUDIO_CAPTURE);
785   ++active_enumeration_ref_count_[MEDIA_DEVICE_VIDEO_CAPTURE];
786   video_capture_manager_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
787 }
788
789 void MediaStreamManager::StopMonitoring() {
790   DCHECK_EQ(base::MessageLoop::current(), io_loop_);
791   if (monitoring_started_) {
792     base::SystemMonitor::Get()->RemoveDevicesChangedObserver(this);
793     monitoring_started_ = false;
794     ClearEnumerationCache(&audio_enumeration_cache_);
795     ClearEnumerationCache(&video_enumeration_cache_);
796   }
797 }
798
799 bool MediaStreamManager::GetRequestedDeviceCaptureId(
800     const DeviceRequest* request,
801     MediaStreamType type,
802     std::string* device_id) const {
803   DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
804          type == MEDIA_DEVICE_VIDEO_CAPTURE);
805   const StreamOptions::Constraints* mandatory =
806       (type == MEDIA_DEVICE_AUDIO_CAPTURE) ?
807           &request->options.mandatory_audio : &request->options.mandatory_video;
808   const StreamOptions::Constraints* optional =
809       (type == MEDIA_DEVICE_AUDIO_CAPTURE) ?
810           &request->options.optional_audio : &request->options.optional_video;
811
812   std::vector<std::string> source_ids;
813   StreamOptions::GetConstraintsByName(*mandatory,
814                                       kMediaStreamSourceInfoId, &source_ids);
815   if (source_ids.size() > 1) {
816     LOG(ERROR) << "Only one mandatory " << kMediaStreamSourceInfoId
817         << " is supported.";
818     return false;
819   }
820   // If a specific device has been requested we need to find the real device
821   // id.
822   if (source_ids.size() == 1 &&
823       !TranslateSourceIdToDeviceId(type,
824                                    request->salt_callback,
825                                    request->security_origin,
826                                    source_ids[0], device_id)) {
827     LOG(WARNING) << "Invalid mandatory " << kMediaStreamSourceInfoId
828                  << " = " << source_ids[0] << ".";
829     return false;
830   }
831   // Check for optional audio sourceIDs.
832   if (device_id->empty()) {
833     StreamOptions::GetConstraintsByName(*optional,
834                                         kMediaStreamSourceInfoId,
835                                         &source_ids);
836     // Find the first sourceID that translates to device. Note that only one
837     // device per type can call to GenerateStream is ever opened.
838     for (std::vector<std::string>::const_iterator it = source_ids.begin();
839          it != source_ids.end(); ++it) {
840       if (TranslateSourceIdToDeviceId(type,
841                                       request->salt_callback,
842                                       request->security_origin,
843                                       *it,
844                                       device_id)) {
845         break;
846       }
847     }
848   }
849   return true;
850 }
851
852 void MediaStreamManager::TranslateDeviceIdToSourceId(
853     DeviceRequest* request,
854     MediaStreamDevice* device) {
855   if (request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE ||
856       request->video_type() == MEDIA_DEVICE_VIDEO_CAPTURE) {
857     device->id = content::GetHMACForMediaDeviceID(
858         request->salt_callback,
859         request->security_origin,
860         device->id);
861   }
862 }
863
864 bool MediaStreamManager::TranslateSourceIdToDeviceId(
865     MediaStreamType stream_type,
866     const ResourceContext::SaltCallback& sc,
867     const GURL& security_origin,
868     const std::string& source_id,
869     std::string* device_id) const {
870   DCHECK(stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ||
871          stream_type == MEDIA_DEVICE_VIDEO_CAPTURE);
872   // The source_id can be empty if the constraint is set but empty.
873   if (source_id.empty())
874     return false;
875
876   const EnumerationCache* cache =
877       stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ?
878       &audio_enumeration_cache_ : &video_enumeration_cache_;
879
880   // If device monitoring hasn't started, the |device_guid| is not valid.
881   if (!cache->valid)
882     return false;
883
884   for (StreamDeviceInfoArray::const_iterator it = cache->devices.begin();
885        it != cache->devices.end();
886        ++it) {
887     if (content::DoesMediaDeviceIDMatchHMAC(sc, security_origin, source_id,
888                                             it->device.id)) {
889       *device_id = it->device.id;
890       return true;
891     }
892   }
893   return false;
894 }
895
896 void MediaStreamManager::ClearEnumerationCache(EnumerationCache* cache) {
897   DCHECK_EQ(base::MessageLoop::current(), io_loop_);
898   cache->valid = false;
899 }
900
901 bool MediaStreamManager::EnumerationRequired(EnumerationCache* cache,
902                                              MediaStreamType stream_type) {
903   DCHECK_EQ(base::MessageLoop::current(), io_loop_);
904   if (stream_type == MEDIA_NO_SERVICE)
905     return false;
906
907   DCHECK(stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ||
908          stream_type == MEDIA_DEVICE_VIDEO_CAPTURE);
909
910 #if defined(OS_ANDROID)
911   // There's no SystemMonitor on Android that notifies us when devices are
912   // added or removed, so we need to populate the cache on every request.
913   // Fortunately, there is an already up-to-date cache in the browser side
914   // audio manager that we can rely on, so the performance impact of
915   // invalidating the cache like this, is minimal.
916   if (stream_type == MEDIA_DEVICE_AUDIO_CAPTURE) {
917     // Make sure the cache is marked as invalid so that FinalizeEnumerateDevices
918     // will be called at the end of the enumeration.
919     ClearEnumerationCache(cache);
920   }
921 #endif
922   // If the cache isn't valid, we need to start a full enumeration.
923   return !cache->valid;
924 }
925
926 void MediaStreamManager::StartEnumeration(DeviceRequest* request) {
927   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
928
929   // Start monitoring the devices when doing the first enumeration.
930   StartMonitoring();
931
932   // Start enumeration for devices of all requested device types.
933   const MediaStreamType streams[] = { request->audio_type(),
934                                       request->video_type() };
935   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(streams); ++i) {
936     if (streams[i] == MEDIA_NO_SERVICE)
937       continue;
938     request->SetState(streams[i], MEDIA_REQUEST_STATE_REQUESTED);
939     DCHECK_GE(active_enumeration_ref_count_[streams[i]], 0);
940     if (active_enumeration_ref_count_[streams[i]] == 0) {
941       ++active_enumeration_ref_count_[streams[i]];
942       GetDeviceManager(streams[i])->EnumerateDevices(streams[i]);
943     }
944   }
945 }
946
947 std::string MediaStreamManager::AddRequest(DeviceRequest* request) {
948   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
949
950   // Create a label for this request and verify it is unique.
951   std::string unique_label;
952   do {
953     unique_label = RandomLabel();
954   } while (requests_.find(unique_label) != requests_.end());
955
956   requests_.insert(std::make_pair(unique_label, request));
957
958   return unique_label;
959 }
960
961 MediaStreamManager::DeviceRequest*
962 MediaStreamManager::FindRequest(const std::string& label) const {
963   DeviceRequests::const_iterator request_it = requests_.find(label);
964   return request_it == requests_.end() ? NULL : request_it->second;
965 }
966
967 void MediaStreamManager::DeleteRequest(const std::string& label) {
968   DVLOG(1) << "DeleteRequest({label= " << label << "})";
969   DeviceRequests::iterator it = requests_.find(label);
970   scoped_ptr<DeviceRequest> request(it->second);
971   requests_.erase(it);
972 }
973
974 void MediaStreamManager::PostRequestToUI(const std::string& label,
975                                          DeviceRequest* request) {
976   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
977   DCHECK(request->UIRequest());
978   DVLOG(1) << "PostRequestToUI({label= " << label << "})";
979
980   const MediaStreamType audio_type = request->audio_type();
981   const MediaStreamType video_type = request->video_type();
982
983   // Post the request to UI and set the state.
984   if (IsAudioMediaType(audio_type))
985     request->SetState(audio_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
986   if (IsVideoMediaType(video_type))
987     request->SetState(video_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
988
989   if (use_fake_ui_) {
990     if (!fake_ui_)
991       fake_ui_.reset(new FakeMediaStreamUIProxy());
992
993     MediaStreamDevices devices;
994     if (audio_enumeration_cache_.valid) {
995       for (StreamDeviceInfoArray::const_iterator it =
996                audio_enumeration_cache_.devices.begin();
997            it != audio_enumeration_cache_.devices.end(); ++it) {
998         devices.push_back(it->device);
999       }
1000     }
1001     if (video_enumeration_cache_.valid) {
1002       for (StreamDeviceInfoArray::const_iterator it =
1003                video_enumeration_cache_.devices.begin();
1004            it != video_enumeration_cache_.devices.end(); ++it) {
1005         devices.push_back(it->device);
1006       }
1007     }
1008
1009     fake_ui_->SetAvailableDevices(devices);
1010
1011     request->ui_proxy = fake_ui_.Pass();
1012   } else {
1013     request->ui_proxy = MediaStreamUIProxy::Create();
1014   }
1015
1016   request->ui_proxy->RequestAccess(
1017       *request->UIRequest(),
1018       base::Bind(&MediaStreamManager::HandleAccessRequestResponse,
1019                  base::Unretained(this), label));
1020 }
1021
1022 void MediaStreamManager::SetupRequest(const std::string& label) {
1023   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1024   DeviceRequest* request = FindRequest(label);
1025   if (!request) {
1026     DVLOG(1) << "SetupRequest label " << label << " doesn't exist!!";
1027     return;  // This can happen if the request has been canceled.
1028   }
1029
1030   if (!request->security_origin.is_valid()) {
1031     LOG(ERROR) << "Invalid security origin. "
1032                << request->security_origin;
1033     FinalizeRequestFailed(label, request);
1034     return;
1035   }
1036
1037   MediaStreamType audio_type = MEDIA_NO_SERVICE;
1038   MediaStreamType video_type = MEDIA_NO_SERVICE;
1039   ParseStreamType(request->options, &audio_type, &video_type);
1040   request->SetAudioType(audio_type);
1041   request->SetVideoType(video_type);
1042
1043   bool is_web_contents_capture =
1044       audio_type == MEDIA_TAB_AUDIO_CAPTURE ||
1045       video_type == MEDIA_TAB_VIDEO_CAPTURE;
1046   if (is_web_contents_capture && !SetupTabCaptureRequest(request)) {
1047     FinalizeRequestFailed(label, request);
1048     return;
1049   }
1050
1051   bool is_screen_capture =
1052       video_type == MEDIA_DESKTOP_VIDEO_CAPTURE;
1053   if (is_screen_capture && !SetupScreenCaptureRequest(request)) {
1054     FinalizeRequestFailed(label, request);
1055     return;
1056   }
1057
1058   if (!is_web_contents_capture && !is_screen_capture) {
1059     if (EnumerationRequired(&audio_enumeration_cache_, audio_type) ||
1060         EnumerationRequired(&video_enumeration_cache_, video_type)) {
1061       // Enumerate the devices if there is no valid device lists to be used.
1062       StartEnumeration(request);
1063       return;
1064     } else {
1065         // Cache is valid, so log the cached devices for MediaStream requests.
1066       if (request->request_type == MEDIA_GENERATE_STREAM) {
1067         std::string log_message("Using cached devices for request.\n");
1068         if (audio_type != MEDIA_NO_SERVICE) {
1069           log_message +=
1070               GetLogMessageString(audio_type, audio_enumeration_cache_.devices);
1071         }
1072         if (video_type != MEDIA_NO_SERVICE) {
1073           log_message +=
1074               GetLogMessageString(video_type, video_enumeration_cache_.devices);
1075         }
1076         SendMessageToNativeLog(log_message);
1077       }
1078     }
1079
1080     if (!SetupDeviceCaptureRequest(request)) {
1081       FinalizeRequestFailed(label, request);
1082       return;
1083     }
1084   }
1085   PostRequestToUI(label, request);
1086 }
1087
1088 bool MediaStreamManager::SetupDeviceCaptureRequest(DeviceRequest* request) {
1089   DCHECK((request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE ||
1090           request->audio_type() == MEDIA_NO_SERVICE) &&
1091          (request->video_type() == MEDIA_DEVICE_VIDEO_CAPTURE ||
1092           request->video_type() == MEDIA_NO_SERVICE));
1093   std::string audio_device_id;
1094   if (request->options.audio_requested &&
1095       !GetRequestedDeviceCaptureId(request, request->audio_type(),
1096                                    &audio_device_id)) {
1097     return false;
1098   }
1099
1100   std::string video_device_id;
1101   if (request->options.video_requested &&
1102       !GetRequestedDeviceCaptureId(request, request->video_type(),
1103                                    &video_device_id)) {
1104     return false;
1105   }
1106   request->CreateUIRequest(audio_device_id, video_device_id);
1107   DVLOG(3) << "Audio requested " << request->options.audio_requested
1108            << " device id = " << audio_device_id
1109            << "Video requested " << request->options.video_requested
1110            << " device id = " << video_device_id;
1111   return true;
1112 }
1113
1114 bool MediaStreamManager::SetupTabCaptureRequest(DeviceRequest* request) {
1115   DCHECK(request->audio_type() == MEDIA_TAB_AUDIO_CAPTURE ||
1116          request->video_type() == MEDIA_TAB_VIDEO_CAPTURE);
1117
1118   std::string capture_device_id;
1119   bool mandatory_audio = false;
1120   bool mandatory_video = false;
1121   if (!request->options.GetFirstAudioConstraintByName(kMediaStreamSourceId,
1122                                                       &capture_device_id,
1123                                                       &mandatory_audio) &&
1124       !request->options.GetFirstVideoConstraintByName(kMediaStreamSourceId,
1125                                                       &capture_device_id,
1126                                                       &mandatory_video)) {
1127     return false;
1128   }
1129   DCHECK(mandatory_audio || mandatory_video);
1130
1131   // Customize options for a WebContents based capture.
1132   int target_render_process_id = 0;
1133   int target_render_view_id = 0;
1134
1135   // TODO(justinlin): Can't plumb audio mirroring using stream type right
1136   // now, so plumbing by device_id. Will revisit once it's refactored.
1137   // http://crbug.com/163100
1138   std::string tab_capture_device_id =
1139       WebContentsCaptureUtil::AppendWebContentsDeviceScheme(capture_device_id);
1140
1141   bool has_valid_device_id = WebContentsCaptureUtil::ExtractTabCaptureTarget(
1142       tab_capture_device_id, &target_render_process_id,
1143       &target_render_view_id);
1144   if (!has_valid_device_id ||
1145       (request->audio_type() != MEDIA_TAB_AUDIO_CAPTURE &&
1146        request->audio_type() != MEDIA_NO_SERVICE) ||
1147       (request->video_type() != MEDIA_TAB_VIDEO_CAPTURE &&
1148        request->video_type() != MEDIA_NO_SERVICE)) {
1149     return false;
1150   }
1151
1152   request->CreateTabCatureUIRequest(target_render_process_id,
1153                                     target_render_view_id,
1154                                     tab_capture_device_id);
1155
1156   DVLOG(3) << "SetupTabCaptureRequest "
1157            << ", {tab_capture_device_id = " << tab_capture_device_id <<  "}"
1158            << ", {target_render_process_id = " << target_render_process_id
1159            << "}"
1160            << ", {target_render_view_id = " << target_render_view_id << "}";
1161   return true;
1162 }
1163
1164 bool MediaStreamManager::SetupScreenCaptureRequest(DeviceRequest* request) {
1165   DCHECK(request->audio_type() == MEDIA_LOOPBACK_AUDIO_CAPTURE ||
1166          request->video_type() == MEDIA_DESKTOP_VIDEO_CAPTURE);
1167
1168   // For screen capture we only support two valid combinations:
1169   // (1) screen video capture only, or
1170   // (2) screen video capture with loopback audio capture.
1171   if (request->video_type() != MEDIA_DESKTOP_VIDEO_CAPTURE ||
1172       (request->audio_type() != MEDIA_NO_SERVICE &&
1173        request->audio_type() != MEDIA_LOOPBACK_AUDIO_CAPTURE)) {
1174     LOG(ERROR) << "Invalid screen capture request.";
1175     return false;
1176   }
1177
1178   std::string video_device_id;
1179   if (request->video_type() == MEDIA_DESKTOP_VIDEO_CAPTURE) {
1180     std::string video_stream_source;
1181     bool mandatory = false;
1182     if (!request->options.GetFirstVideoConstraintByName(
1183         kMediaStreamSource,
1184         &video_stream_source,
1185         &mandatory)) {
1186       LOG(ERROR) << kMediaStreamSource << " not found.";
1187       return false;
1188     }
1189     DCHECK(mandatory);
1190
1191     if (video_stream_source == kMediaStreamSourceDesktop) {
1192       if (!request->options.GetFirstVideoConstraintByName(
1193           kMediaStreamSourceId,
1194           &video_device_id,
1195           &mandatory)) {
1196         LOG(ERROR) << kMediaStreamSourceId << " not found.";
1197         return false;
1198       }
1199       DCHECK(mandatory);
1200     }
1201   }
1202
1203   request->CreateUIRequest("", video_device_id);
1204   return true;
1205 }
1206
1207 StreamDeviceInfoArray MediaStreamManager::GetDevicesOpenedByRequest(
1208     const std::string& label) const {
1209   DeviceRequest* request = FindRequest(label);
1210   if (!request)
1211     return StreamDeviceInfoArray();
1212   return request->devices;
1213 }
1214
1215 bool MediaStreamManager::FindExistingRequestedDeviceInfo(
1216     const DeviceRequest& new_request,
1217     const MediaStreamDevice& new_device_info,
1218     StreamDeviceInfo* existing_device_info,
1219     MediaRequestState* existing_request_state) const {
1220   DCHECK(existing_device_info);
1221   DCHECK(existing_request_state);
1222
1223   std::string source_id = content::GetHMACForMediaDeviceID(
1224       new_request.salt_callback,
1225       new_request.security_origin,
1226       new_device_info.id);
1227
1228   for (DeviceRequests::const_iterator it = requests_.begin();
1229        it != requests_.end() ; ++it) {
1230     const DeviceRequest* request = it->second;
1231     if (request->requesting_process_id == new_request.requesting_process_id &&
1232         request->requesting_view_id == new_request.requesting_view_id &&
1233         request->request_type == new_request.request_type) {
1234       for (StreamDeviceInfoArray::const_iterator device_it =
1235                request->devices.begin();
1236            device_it != request->devices.end(); ++device_it) {
1237         if (device_it->device.id == source_id &&
1238             device_it->device.type == new_device_info.type) {
1239             *existing_device_info = *device_it;
1240             *existing_request_state = request->state(device_it->device.type);
1241           return true;
1242         }
1243       }
1244     }
1245   }
1246   return false;
1247 }
1248
1249 void MediaStreamManager::FinalizeGenerateStream(const std::string& label,
1250                                                 DeviceRequest* request) {
1251   DVLOG(1) << "FinalizeGenerateStream label " << label;
1252   const StreamDeviceInfoArray& requested_devices = request->devices;
1253
1254   // Partition the array of devices into audio vs video.
1255   StreamDeviceInfoArray audio_devices, video_devices;
1256   for (StreamDeviceInfoArray::const_iterator device_it =
1257            requested_devices.begin();
1258        device_it != requested_devices.end(); ++device_it) {
1259     if (IsAudioMediaType(device_it->device.type)) {
1260       audio_devices.push_back(*device_it);
1261     } else if (IsVideoMediaType(device_it->device.type)) {
1262       video_devices.push_back(*device_it);
1263     } else {
1264       NOTREACHED();
1265     }
1266   }
1267
1268   request->requester->StreamGenerated(
1269       request->requesting_view_id,
1270       request->page_request_id,
1271       label, audio_devices, video_devices);
1272 }
1273
1274 void MediaStreamManager::FinalizeRequestFailed(
1275     const std::string& label,
1276     DeviceRequest* request) {
1277   if (request->requester)
1278     request->requester->StreamGenerationFailed(
1279         request->requesting_view_id,
1280         request->page_request_id);
1281
1282   if (request->request_type == MEDIA_DEVICE_ACCESS &&
1283       !request->callback.is_null()) {
1284     request->callback.Run(MediaStreamDevices(), request->ui_proxy.Pass());
1285   }
1286
1287   DeleteRequest(label);
1288 }
1289
1290 void MediaStreamManager::FinalizeOpenDevice(const std::string& label,
1291                                             DeviceRequest* request) {
1292   const StreamDeviceInfoArray& requested_devices = request->devices;
1293   request->requester->DeviceOpened(request->requesting_view_id,
1294                                    request->page_request_id,
1295                                    label, requested_devices.front());
1296 }
1297
1298 void MediaStreamManager::FinalizeEnumerateDevices(const std::string& label,
1299                                                   DeviceRequest* request) {
1300   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1301   DCHECK_EQ(request->request_type, MEDIA_ENUMERATE_DEVICES);
1302
1303   if (request->security_origin.is_valid()) {
1304     for (StreamDeviceInfoArray::iterator it = request->devices.begin();
1305          it != request->devices.end(); ++it) {
1306       TranslateDeviceIdToSourceId(request, &it->device);
1307     }
1308   } else {
1309     request->devices.clear();
1310   }
1311
1312   request->requester->DevicesEnumerated(
1313       request->requesting_view_id,
1314       request->page_request_id,
1315       label,
1316       request->devices);
1317
1318   // TODO(tommi):
1319   // Ideally enumeration requests should be deleted once they have been served
1320   // (as any request).  However, this implementation mixes requests and
1321   // notifications together so enumeration requests are kept open by some
1322   // implementations (only Pepper?) and enumerations are done again when
1323   // device notifications are fired.
1324   // Implementations that just want to request the device list and be done
1325   // (e.g. DeviceRequestMessageFilter), they must (confusingly) call
1326   // CancelRequest() after the request has been fulfilled.  This is not
1327   // obvious, not consistent in this class (see e.g. FinalizeMediaAccessRequest)
1328   // and can lead to subtle bugs (requests not deleted at all deleted too
1329   // early).
1330   //
1331   // Basically, it is not clear that using requests as an additional layer on
1332   // top of device notifications is necessary or good.
1333   //
1334   // To add to this, MediaStreamManager currently relies on the external
1335   // implementations of MediaStreamRequester to delete enumeration requests via
1336   // CancelRequest and e.g. DeviceRequestMessageFilter does this.  However the
1337   // Pepper implementation does not seem to to this at all (and from what I can
1338   // see, it is the only implementation that uses an enumeration request as a
1339   // notification mechanism).
1340   //
1341   // We should decouple notifications from enumeration requests and once that
1342   // has been done, remove the requirement to call CancelRequest() to delete
1343   // enumeration requests and uncomment the following line:
1344   //
1345   // DeleteRequest(label);
1346 }
1347
1348 void MediaStreamManager::FinalizeMediaAccessRequest(
1349     const std::string& label,
1350     DeviceRequest* request,
1351     const MediaStreamDevices& devices) {
1352   if (!request->callback.is_null())
1353     request->callback.Run(devices, request->ui_proxy.Pass());
1354
1355   // Delete the request since it is done.
1356   DeleteRequest(label);
1357 }
1358
1359 void MediaStreamManager::InitializeDeviceManagersOnIOThread() {
1360   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1361   if (device_task_runner_)
1362     return;
1363
1364   device_task_runner_ = audio_manager_->GetWorkerTaskRunner();
1365
1366   audio_input_device_manager_ = new AudioInputDeviceManager(audio_manager_);
1367   audio_input_device_manager_->Register(this, device_task_runner_);
1368
1369   video_capture_manager_ = new VideoCaptureManager();
1370   video_capture_manager_->Register(this, device_task_runner_);
1371
1372   // We want to be notified of IO message loop destruction to delete the thread
1373   // and the device managers.
1374   io_loop_ = base::MessageLoop::current();
1375   io_loop_->AddDestructionObserver(this);
1376
1377   if (CommandLine::ForCurrentProcess()->HasSwitch(
1378           switches::kUseFakeDeviceForMediaStream)) {
1379     DVLOG(1) << "Using fake device";
1380     UseFakeDevice();
1381   }
1382 }
1383
1384 void MediaStreamManager::Opened(MediaStreamType stream_type,
1385                                 int capture_session_id) {
1386   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1387   DVLOG(1) << "Opened({stream_type = " << stream_type <<  "} "
1388            << "{capture_session_id = " << capture_session_id << "})";
1389   // Find the request(s) containing this device and mark it as used.
1390   // It can be used in several requests since the same device can be
1391   // requested from the same web page.
1392   for (DeviceRequests::iterator request_it = requests_.begin();
1393        request_it != requests_.end(); ++request_it) {
1394     const std::string& label = request_it->first;
1395     DeviceRequest* request = request_it->second;
1396     StreamDeviceInfoArray* devices = &(request->devices);
1397     for (StreamDeviceInfoArray::iterator device_it = devices->begin();
1398          device_it != devices->end(); ++device_it) {
1399       if (device_it->device.type == stream_type &&
1400           device_it->session_id == capture_session_id) {
1401         CHECK(request->state(device_it->device.type) ==
1402             MEDIA_REQUEST_STATE_OPENING);
1403         // We've found a matching request.
1404         request->SetState(device_it->device.type, MEDIA_REQUEST_STATE_DONE);
1405
1406         if (IsAudioMediaType(device_it->device.type)) {
1407           // Store the native audio parameters in the device struct.
1408           // TODO(xians): Handle the tab capture sample rate/channel layout
1409           // in AudioInputDeviceManager::Open().
1410           if (device_it->device.type != content::MEDIA_TAB_AUDIO_CAPTURE) {
1411             const StreamDeviceInfo* info =
1412                 audio_input_device_manager_->GetOpenedDeviceInfoById(
1413                     device_it->session_id);
1414             device_it->device.input = info->device.input;
1415             device_it->device.matched_output = info->device.matched_output;
1416           }
1417         }
1418         if (RequestDone(*request))
1419           HandleRequestDone(label, request);
1420         break;
1421       }
1422     }
1423   }
1424 }
1425
1426 void MediaStreamManager::HandleRequestDone(const std::string& label,
1427                                            DeviceRequest* request) {
1428   DCHECK(RequestDone(*request));
1429   DVLOG(1) << "HandleRequestDone("
1430            << ", {label = " << label <<  "})";
1431
1432   switch (request->request_type) {
1433     case MEDIA_OPEN_DEVICE:
1434       FinalizeOpenDevice(label, request);
1435       break;
1436     case MEDIA_GENERATE_STREAM: {
1437       FinalizeGenerateStream(label, request);
1438       break;
1439     }
1440     default:
1441       NOTREACHED();
1442       break;
1443   }
1444
1445   if (request->ui_proxy.get()) {
1446     request->ui_proxy->OnStarted(
1447         base::Bind(&MediaStreamManager::StopMediaStreamFromBrowser,
1448                    base::Unretained(this), label));
1449   }
1450 }
1451
1452 void MediaStreamManager::Closed(MediaStreamType stream_type,
1453                                 int capture_session_id) {
1454   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1455 }
1456
1457 void MediaStreamManager::DevicesEnumerated(
1458     MediaStreamType stream_type, const StreamDeviceInfoArray& devices) {
1459   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1460   DVLOG(1) << "DevicesEnumerated("
1461            << "{stream_type = " << stream_type << "})" << std::endl;
1462
1463   std::string log_message = "New device enumeration result:\n" +
1464                             GetLogMessageString(stream_type, devices);
1465   SendMessageToNativeLog(log_message);
1466
1467   // Only cache the device list when the device list has been changed.
1468   bool need_update_clients = false;
1469   EnumerationCache* cache =
1470       stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ?
1471       &audio_enumeration_cache_ : &video_enumeration_cache_;
1472   if (!cache->valid ||
1473       devices.size() != cache->devices.size() ||
1474       !std::equal(devices.begin(), devices.end(), cache->devices.begin(),
1475                   StreamDeviceInfo::IsEqual)) {
1476     StopRemovedDevices(cache->devices, devices);
1477     cache->devices = devices;
1478     need_update_clients = true;
1479
1480     // The device might not be able to be enumerated when it is not warmed up,
1481     // for example, when the machine just wakes up from sleep. We set the cache
1482     // to be invalid so that the next media request will trigger the
1483     // enumeration again. See issue/317673.
1484     cache->valid = !devices.empty();
1485  }
1486
1487   if (need_update_clients && monitoring_started_)
1488     NotifyDevicesChanged(stream_type, devices);
1489
1490   // Publish the result for all requests waiting for device list(s).
1491   // Find the requests waiting for this device list, store their labels and
1492   // release the iterator before calling device settings. We might get a call
1493   // back from device_settings that will need to iterate through devices.
1494   std::list<std::string> label_list;
1495   for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end();
1496        ++it) {
1497     if (it->second->state(stream_type) == MEDIA_REQUEST_STATE_REQUESTED &&
1498         (it->second->audio_type() == stream_type ||
1499          it->second->video_type() == stream_type)) {
1500       if (it->second->request_type != MEDIA_ENUMERATE_DEVICES)
1501         it->second->SetState(stream_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
1502       label_list.push_back(it->first);
1503     }
1504   }
1505
1506   for (std::list<std::string>::iterator it = label_list.begin();
1507        it != label_list.end(); ++it) {
1508     DeviceRequest* request = FindRequest(*it);
1509     switch (request->request_type) {
1510       case MEDIA_ENUMERATE_DEVICES:
1511         if (need_update_clients && request->requester) {
1512           request->devices = devices;
1513           FinalizeEnumerateDevices(*it, request);
1514         }
1515         break;
1516       default:
1517         if (request->state(request->audio_type()) ==
1518                 MEDIA_REQUEST_STATE_REQUESTED ||
1519             request->state(request->video_type()) ==
1520                 MEDIA_REQUEST_STATE_REQUESTED) {
1521           // We are doing enumeration for other type of media, wait until it is
1522           // all done before posting the request to UI because UI needs
1523           // the device lists to handle the request.
1524           break;
1525         }
1526         if (!SetupDeviceCaptureRequest(request))
1527           FinalizeRequestFailed(*it, request);
1528         else
1529           PostRequestToUI(*it, request);
1530         break;
1531     }
1532   }
1533   label_list.clear();
1534   --active_enumeration_ref_count_[stream_type];
1535   DCHECK_GE(active_enumeration_ref_count_[stream_type], 0);
1536 }
1537
1538 // static
1539 void MediaStreamManager::SendMessageToNativeLog(const std::string& message) {
1540   BrowserThread::PostTask(
1541       BrowserThread::UI, FROM_HERE,
1542       base::Bind(DoAddLogMessage, message));
1543 }
1544
1545 void MediaStreamManager::AddLogMessageOnIOThread(const std::string& message) {
1546   // Get render process ids on the IO thread.
1547   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1548
1549   // Grab all unique process ids that request a MediaStream or have a
1550   // MediaStream running.
1551   std::set<int> requesting_process_ids;
1552   for (DeviceRequests::const_iterator it = requests_.begin();
1553        it != requests_.end(); ++it) {
1554     DeviceRequest* request = it->second;
1555     if (request->request_type == MEDIA_GENERATE_STREAM)
1556       requesting_process_ids.insert(request->requesting_process_id);
1557   }
1558
1559   // MediaStreamManager is a singleton in BrowserMainLoop, which owns the UI
1560   // thread. MediaStreamManager has the same lifetime as the UI thread, so it is
1561   // safe to use base::Unretained.
1562   BrowserThread::PostTask(
1563       BrowserThread::UI,
1564       FROM_HERE,
1565       base::Bind(&MediaStreamManager::AddLogMessageOnUIThread,
1566                  base::Unretained(this),
1567                  requesting_process_ids,
1568                  message));
1569 }
1570
1571 void MediaStreamManager::AddLogMessageOnUIThread(
1572     const std::set<int>& requesting_process_ids,
1573     const std::string& message) {
1574 #if defined(ENABLE_WEBRTC)
1575   // Must be on the UI thread to access RenderProcessHost from process ID.
1576   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1577
1578   for (std::set<int>::const_iterator it = requesting_process_ids.begin();
1579        it != requesting_process_ids.end(); ++it) {
1580     // Log the message to all renderers that are requesting a MediaStream or
1581     // have a MediaStream running.
1582     content::RenderProcessHostImpl* render_process_host_impl =
1583         static_cast<content::RenderProcessHostImpl*>(
1584             content::RenderProcessHost::FromID(*it));
1585     if (render_process_host_impl)
1586       render_process_host_impl->WebRtcLogMessage(message);
1587   }
1588 #endif
1589 }
1590
1591 void MediaStreamManager::HandleAccessRequestResponse(
1592     const std::string& label,
1593     const MediaStreamDevices& devices) {
1594   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1595   DVLOG(1) << "HandleAccessRequestResponse("
1596            << ", {label = " << label <<  "})";
1597
1598   DeviceRequest* request = FindRequest(label);
1599   if (!request) {
1600     // The request has been canceled before the UI returned.
1601     return;
1602   }
1603
1604   if (request->request_type == MEDIA_DEVICE_ACCESS) {
1605     FinalizeMediaAccessRequest(label, request, devices);
1606     return;
1607   }
1608
1609   // Handle the case when the request was denied.
1610   if (devices.empty()) {
1611     FinalizeRequestFailed(label, request);
1612     return;
1613   }
1614
1615   // Process all newly-accepted devices for this request.
1616   bool found_audio = false;
1617   bool found_video = false;
1618   for (MediaStreamDevices::const_iterator device_it = devices.begin();
1619        device_it != devices.end(); ++device_it) {
1620     StreamDeviceInfo device_info;
1621     device_info.device = *device_it;
1622
1623     // TODO(justinlin): Nicer way to do this?
1624     // Re-append the device's id since we lost it when posting request to UI.
1625     if (device_info.device.type == content::MEDIA_TAB_VIDEO_CAPTURE ||
1626         device_info.device.type == content::MEDIA_TAB_AUDIO_CAPTURE) {
1627       device_info.device.id = request->UIRequest()->tab_capture_device_id;
1628
1629       // Initialize the sample_rate and channel_layout here since for audio
1630       // mirroring, we don't go through EnumerateDevices where these are usually
1631       // initialized.
1632       if (device_info.device.type == content::MEDIA_TAB_AUDIO_CAPTURE) {
1633         const media::AudioParameters parameters =
1634             audio_manager_->GetDefaultOutputStreamParameters();
1635         int sample_rate = parameters.sample_rate();
1636         // If we weren't able to get the native sampling rate or the sample_rate
1637         // is outside the valid range for input devices set reasonable defaults.
1638         if (sample_rate <= 0 || sample_rate > 96000)
1639           sample_rate = 44100;
1640
1641         device_info.device.input.sample_rate = sample_rate;
1642         device_info.device.input.channel_layout = media::CHANNEL_LAYOUT_STEREO;
1643       }
1644     }
1645
1646     if (device_info.device.type == request->audio_type()) {
1647       found_audio = true;
1648     } else if (device_info.device.type == request->video_type()) {
1649       found_video = true;
1650     }
1651
1652     // If this is request for a new MediaStream, a device is only opened once
1653     // per render view. This is so that the permission to use a device can be
1654     // revoked by a single call to StopStreamDevice regardless of how many
1655     // MediaStreams it is being used in.
1656     if (request->request_type == MEDIA_GENERATE_STREAM) {
1657       MediaRequestState state;
1658       if (FindExistingRequestedDeviceInfo(*request,
1659                                           device_info.device,
1660                                           &device_info,
1661                                           &state)) {
1662         request->devices.push_back(device_info);
1663         request->SetState(device_info.device.type, state);
1664         DVLOG(1) << "HandleAccessRequestResponse - device already opened "
1665                  << ", {label = " << label <<  "}"
1666                  << ", device_id = " << device_it->id << "}";
1667         continue;
1668       }
1669     }
1670     device_info.session_id =
1671         GetDeviceManager(device_info.device.type)->Open(device_info);
1672     TranslateDeviceIdToSourceId(request, &device_info.device);
1673     request->devices.push_back(device_info);
1674
1675     request->SetState(device_info.device.type, MEDIA_REQUEST_STATE_OPENING);
1676     DVLOG(1) << "HandleAccessRequestResponse - opening device "
1677              << ", {label = " << label <<  "}"
1678              << ", {device_id = " << device_info.device.id << "}"
1679              << ", {session_id = " << device_info.session_id << "}";
1680   }
1681
1682   // Check whether we've received all stream types requested.
1683   if (!found_audio && IsAudioMediaType(request->audio_type())) {
1684     request->SetState(request->audio_type(), MEDIA_REQUEST_STATE_ERROR);
1685     DVLOG(1) << "Set no audio found label " << label;
1686   }
1687
1688   if (!found_video && IsVideoMediaType(request->video_type()))
1689     request->SetState(request->video_type(), MEDIA_REQUEST_STATE_ERROR);
1690
1691   if (RequestDone(*request))
1692     HandleRequestDone(label, request);
1693 }
1694
1695 void MediaStreamManager::StopMediaStreamFromBrowser(const std::string& label) {
1696   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1697
1698   DeviceRequest* request = FindRequest(label);
1699   if (!request)
1700     return;
1701
1702   // Notify renderers that the devices in the stream will be stopped.
1703   if (request->requester) {
1704     for (StreamDeviceInfoArray::iterator device_it = request->devices.begin();
1705          device_it != request->devices.end(); ++device_it) {
1706       request->requester->DeviceStopped(request->requesting_view_id,
1707                                         label,
1708                                         *device_it);
1709     }
1710   }
1711
1712   CancelRequest(label);
1713 }
1714
1715 void MediaStreamManager::UseFakeDevice() {
1716   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1717   video_capture_manager()->UseFakeDevice();
1718   audio_input_device_manager()->UseFakeDevice();
1719 }
1720
1721 void MediaStreamManager::UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy> fake_ui) {
1722   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1723   use_fake_ui_ = true;
1724   fake_ui_ = fake_ui.Pass();
1725 }
1726
1727 void MediaStreamManager::WillDestroyCurrentMessageLoop() {
1728   DVLOG(3) << "MediaStreamManager::WillDestroyCurrentMessageLoop()";
1729   DCHECK_EQ(base::MessageLoop::current(), io_loop_);
1730   DCHECK(requests_.empty());
1731   if (device_task_runner_) {
1732     StopMonitoring();
1733
1734     video_capture_manager_->Unregister();
1735     audio_input_device_manager_->Unregister();
1736     device_task_runner_ = NULL;
1737   }
1738
1739   audio_input_device_manager_ = NULL;
1740   video_capture_manager_ = NULL;
1741 }
1742
1743 void MediaStreamManager::NotifyDevicesChanged(
1744     MediaStreamType stream_type,
1745     const StreamDeviceInfoArray& devices) {
1746   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1747   MediaObserver* media_observer =
1748       GetContentClient()->browser()->GetMediaObserver();
1749   if (media_observer == NULL)
1750     return;
1751
1752   // Map the devices to MediaStreamDevices.
1753   MediaStreamDevices new_devices;
1754   for (StreamDeviceInfoArray::const_iterator it = devices.begin();
1755        it != devices.end(); ++it) {
1756     new_devices.push_back(it->device);
1757   }
1758
1759   if (IsAudioMediaType(stream_type)) {
1760     media_observer->OnAudioCaptureDevicesChanged(new_devices);
1761   } else if (IsVideoMediaType(stream_type)) {
1762     media_observer->OnVideoCaptureDevicesChanged(new_devices);
1763   } else {
1764     NOTREACHED();
1765   }
1766 }
1767
1768 bool MediaStreamManager::RequestDone(const DeviceRequest& request) const {
1769   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1770
1771   const bool requested_audio = IsAudioMediaType(request.audio_type());
1772   const bool requested_video = IsVideoMediaType(request.video_type());
1773
1774   const bool audio_done =
1775       !requested_audio ||
1776       request.state(request.audio_type()) == MEDIA_REQUEST_STATE_DONE ||
1777       request.state(request.audio_type()) == MEDIA_REQUEST_STATE_ERROR;
1778   if (!audio_done)
1779     return false;
1780
1781   const bool video_done =
1782       !requested_video ||
1783       request.state(request.video_type()) == MEDIA_REQUEST_STATE_DONE ||
1784       request.state(request.video_type()) == MEDIA_REQUEST_STATE_ERROR;
1785   if (!video_done)
1786     return false;
1787
1788   return true;
1789 }
1790
1791 MediaStreamProvider* MediaStreamManager::GetDeviceManager(
1792     MediaStreamType stream_type) {
1793   if (IsVideoMediaType(stream_type)) {
1794     return video_capture_manager();
1795   } else if (IsAudioMediaType(stream_type)) {
1796     return audio_input_device_manager();
1797   }
1798   NOTREACHED();
1799   return NULL;
1800 }
1801
1802 void MediaStreamManager::OnDevicesChanged(
1803     base::SystemMonitor::DeviceType device_type) {
1804   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1805
1806   // NOTE: This method is only called in response to physical audio/video device
1807   // changes (from the operating system).
1808
1809   MediaStreamType stream_type;
1810   if (device_type == base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE) {
1811     stream_type = MEDIA_DEVICE_AUDIO_CAPTURE;
1812   } else if (device_type == base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE) {
1813     stream_type = MEDIA_DEVICE_VIDEO_CAPTURE;
1814   } else {
1815     return;  // Uninteresting device change.
1816   }
1817
1818   // Always do enumeration even though some enumeration is in progress,
1819   // because those enumeration commands could be sent before these devices
1820   // change.
1821   ++active_enumeration_ref_count_[stream_type];
1822   GetDeviceManager(stream_type)->EnumerateDevices(stream_type);
1823 }
1824
1825 }  // namespace content