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