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