Home | History | Annotate | Download | only in media
      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
   2127