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
52namespace content {
53
54// Forward declaration of DeviceMonitorMac and its only useable method.
55class DeviceMonitorMac {
56 public:
57  void StartMonitoring(
58    const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner);
59};
60
61namespace {
62// Creates a random label used to identify requests.
63std::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
81void 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.
128void 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.
141void 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|.
161std::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.
177std::string ReturnEmptySalt() {
178  return std::string();
179}
180
181// Clears the MediaStreamDevice.name from all devices in |devices|.
182static 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.
199class 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
355MediaStreamManager::EnumerationCache::EnumerationCache()
356    : valid(false) {
357}
358
359MediaStreamManager::EnumerationCache::~EnumerationCache() {
360}
361
362MediaStreamManager::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
371MediaStreamManager::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
401MediaStreamManager::~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
413VideoCaptureManager* MediaStreamManager::video_capture_manager() {
414  DCHECK_CURRENTLY_ON(BrowserThread::IO);
415  DCHECK(video_capture_manager_.get());
416  return video_capture_manager_.get();
417}
418
419AudioInputDeviceManager* 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
425std::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
461void 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
499void 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
515void 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
553void 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
567void 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
596void 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
635void 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
656std::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
697void 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
742void 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
764void 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
792void 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
838bool 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
870void MediaStreamManager::EnsureDeviceMonitorStarted() {
871  DCHECK_CURRENTLY_ON(BrowserThread::IO);
872  StartMonitoring();
873}
874
875void 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
900void 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
936void 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)
963void 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
973void 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
983bool 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
1036void 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
1049void MediaStreamManager::ClearEnumerationCache(EnumerationCache* cache) {
1050  DCHECK_EQ(base::MessageLoop::current(), io_loop_);
1051  cache->valid = false;
1052}
1053
1054bool 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
1079void 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
1100std::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
1114MediaStreamManager::DeviceRequest*
1115MediaStreamManager::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
1124void 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
1137void 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
1185void 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
1261bool 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
1287bool 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
1330bool 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
1373StreamDeviceInfoArray 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
1381bool 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
1419void 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
1444void 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
1462void 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
1470void 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
1514void 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
1565void 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
1576void 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
1602void 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
1652void 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
1683void MediaStreamManager::Closed(MediaStreamType stream_type,
1684                                int capture_session_id) {
1685  DCHECK_CURRENTLY_ON(BrowserThread::IO);
1686}
1687
1688void 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
1772void 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
1781void MediaStreamManager::SendMessageToNativeLog(const std::string& message) {
1782  BrowserThread::PostTask(
1783      BrowserThread::UI, FROM_HERE,
1784      base::Bind(DoAddLogMessage, message));
1785}
1786
1787void MediaStreamManager::OnSuspend() {
1788  SendMessageToNativeLog("Power state suspended.");
1789}
1790
1791void MediaStreamManager::OnResume() {
1792  SendMessageToNativeLog("Power state resumed.");
1793}
1794
1795void 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
1821void 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
1841void 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
1945void 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
1965void 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
1971void 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
1987void 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
2016bool 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
2039MediaStreamProvider* 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
2050void 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
2073void 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)
2095void 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
2106void 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
2120void MediaStreamManager::SetKeyboardMicOnDeviceThread() {
2121  DCHECK(device_task_runner_->BelongsToCurrentThread());
2122  audio_manager_->SetHasKeyboardMic();
2123}
2124#endif
2125
2126}  // namespace content
2127