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 // MediaStreamManager is used to open/enumerate media capture devices (video
      6 // supported now). Call flow:
      7 // 1. GenerateStream is called when a render process wants to use a capture
      8 //    device.
      9 // 2. MediaStreamManager will ask MediaStreamUIController for permission to
     10 //    use devices and for which device to use.
     11 // 3. MediaStreamManager will request the corresponding media device manager(s)
     12 //    to enumerate available devices. The result will be given to
     13 //    MediaStreamUIController.
     14 // 4. MediaStreamUIController will, by posting the request to UI, let the
     15 //    users to select which devices to use and send callback to
     16 //    MediaStreamManager with the result.
     17 // 5. MediaStreamManager will call the proper media device manager to open the
     18 //    device and let the MediaStreamRequester know it has been done.
     19 
     20 // If either user or test harness selects --use-fake-device-for-media-stream,
     21 // a fake video device or devices are used instead of real ones.
     22 
     23 // When enumeration and open are done in separate operations,
     24 // MediaStreamUIController is not involved as in steps.
     25 
     26 #ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_MANAGER_H_
     27 #define CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_MANAGER_H_
     28 
     29 #include <list>
     30 #include <set>
     31 #include <string>
     32 #include <utility>
     33 
     34 #include "base/basictypes.h"
     35 #include "base/memory/ref_counted.h"
     36 #include "base/memory/scoped_ptr.h"
     37 #include "base/message_loop/message_loop.h"
     38 #include "base/power_monitor/power_observer.h"
     39 #include "base/system_monitor/system_monitor.h"
     40 #include "content/browser/renderer_host/media/media_stream_provider.h"
     41 #include "content/common/content_export.h"
     42 #include "content/common/media/media_stream_options.h"
     43 #include "content/public/browser/media_request_state.h"
     44 #include "content/public/browser/resource_context.h"
     45 
     46 namespace media {
     47 class AudioManager;
     48 }
     49 
     50 namespace content {
     51 
     52 class AudioInputDeviceManager;
     53 class BrowserContext;
     54 class FakeMediaStreamUIProxy;
     55 class MediaStreamDeviceSettings;
     56 class MediaStreamRequester;
     57 class MediaStreamUIProxy;
     58 class VideoCaptureManager;
     59 
     60 // MediaStreamManager is used to generate and close new media devices, not to
     61 // start the media flow. The classes requesting new media streams are answered
     62 // using MediaStreamRequester.
     63 class CONTENT_EXPORT MediaStreamManager
     64     : public MediaStreamProviderListener,
     65       public base::MessageLoop::DestructionObserver,
     66       public base::PowerObserver,
     67       public base::SystemMonitor::DevicesChangedObserver {
     68  public:
     69   // Callback to deliver the result of a media request.
     70   typedef base::Callback<void(const MediaStreamDevices& devices,
     71                               scoped_ptr<MediaStreamUIProxy> ui)>
     72       MediaRequestResponseCallback;
     73 
     74   explicit MediaStreamManager(media::AudioManager* audio_manager);
     75   virtual ~MediaStreamManager();
     76 
     77   // Used to access VideoCaptureManager.
     78   VideoCaptureManager* video_capture_manager();
     79 
     80   // Used to access AudioInputDeviceManager.
     81   AudioInputDeviceManager* audio_input_device_manager();
     82 
     83   // Creates a new media access request which is identified by a unique string
     84   // that's returned to the caller. This will trigger the infobar and ask users
     85   // for access to the device. |render_process_id| and |render_frame_id| are
     86   // used to determine where the infobar will appear to the user. |callback| is
     87   // used to send the selected device to the clients. An empty list of device
     88   // will be returned if the users deny the access.
     89   std::string MakeMediaAccessRequest(
     90       int render_process_id,
     91       int render_frame_id,
     92       int page_request_id,
     93       const StreamOptions& options,
     94       const GURL& security_origin,
     95       const MediaRequestResponseCallback& callback);
     96 
     97   // GenerateStream opens new media devices according to |components|.  It
     98   // creates a new request which is identified by a unique string that's
     99   // returned to the caller.  |render_process_id| and |render_frame_id| are used
    100   // to determine where the infobar will appear to the user.
    101   void GenerateStream(MediaStreamRequester* requester,
    102                       int render_process_id,
    103                       int render_frame_id,
    104                       const ResourceContext::SaltCallback& sc,
    105                       int page_request_id,
    106                       const StreamOptions& components,
    107                       const GURL& security_origin,
    108                       bool user_gesture);
    109 
    110   void CancelRequest(int render_process_id,
    111                      int render_frame_id,
    112                      int page_request_id);
    113 
    114   // Cancel an open request identified by |label|.
    115   virtual void CancelRequest(const std::string& label);
    116 
    117   // Cancel all requests for the given |render_process_id|.
    118   void CancelAllRequests(int render_process_id);
    119 
    120   // Closes the stream device for a certain render frame. The stream must have
    121   // been opened by a call to GenerateStream.
    122   void StopStreamDevice(int render_process_id,
    123                         int render_frame_id,
    124                         const std::string& device_id);
    125 
    126   // Gets a list of devices of |type|, which must be MEDIA_DEVICE_AUDIO_CAPTURE
    127   // or MEDIA_DEVICE_VIDEO_CAPTURE.
    128   // The request is identified using the string returned to the caller.
    129   // When the |requester| is NULL, MediaStreamManager will enumerate both audio
    130   // and video devices and also start monitoring device changes, such as
    131   // plug/unplug. The new device lists will be delivered via media observer to
    132   // MediaCaptureDevicesDispatcher.
    133   virtual std::string EnumerateDevices(MediaStreamRequester* requester,
    134                                        int render_process_id,
    135                                        int render_frame_id,
    136                                        const ResourceContext::SaltCallback& sc,
    137                                        int page_request_id,
    138                                        MediaStreamType type,
    139                                        const GURL& security_origin);
    140 
    141   // Open a device identified by |device_id|.  |type| must be either
    142   // MEDIA_DEVICE_AUDIO_CAPTURE or MEDIA_DEVICE_VIDEO_CAPTURE.
    143   // The request is identified using string returned to the caller.
    144   void OpenDevice(MediaStreamRequester* requester,
    145                   int render_process_id,
    146                   int render_frame_id,
    147                   const ResourceContext::SaltCallback& sc,
    148                   int page_request_id,
    149                   const std::string& device_id,
    150                   MediaStreamType type,
    151                   const GURL& security_origin);
    152 
    153   // Finds and returns the device id corresponding to the given
    154   // |source_id|. Returns true if there was a raw device id that matched the
    155   // given |source_id|, false if nothing matched it.
    156   bool TranslateSourceIdToDeviceId(
    157       MediaStreamType stream_type,
    158       const ResourceContext::SaltCallback& rc,
    159       const GURL& security_origin,
    160       const std::string& source_id,
    161       std::string* device_id) const;
    162 
    163   // Called by UI to make sure the device monitor is started so that UI receive
    164   // notifications about device changes.
    165   void EnsureDeviceMonitorStarted();
    166 
    167   // Implements MediaStreamProviderListener.
    168   virtual void Opened(MediaStreamType stream_type,
    169                       int capture_session_id) OVERRIDE;
    170   virtual void Closed(MediaStreamType stream_type,
    171                       int capture_session_id) OVERRIDE;
    172   virtual void DevicesEnumerated(MediaStreamType stream_type,
    173                                  const StreamDeviceInfoArray& devices) OVERRIDE;
    174   virtual void Aborted(MediaStreamType stream_type,
    175                        int capture_session_id) OVERRIDE;
    176 
    177   // Implements base::SystemMonitor::DevicesChangedObserver.
    178   virtual void OnDevicesChanged(
    179       base::SystemMonitor::DeviceType device_type) OVERRIDE;
    180 
    181   // Called by the tests to specify a fake UI that should be used for next
    182   // generated stream (or when using --use-fake-ui-for-media-stream).
    183   void UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy> fake_ui);
    184 
    185   // Returns all devices currently opened by a request with label |label|.
    186   // If no request with |label| exist, an empty array is returned.
    187   StreamDeviceInfoArray GetDevicesOpenedByRequest(
    188       const std::string& label) const;
    189 
    190   // This object gets deleted on the UI thread after the IO thread has been
    191   // destroyed. So we need to know when IO thread is being destroyed so that
    192   // we can delete VideoCaptureManager and AudioInputDeviceManager. Normally
    193   // this is handled by
    194   // base::MessageLoop::DestructionObserver::WillDestroyCurrentMessageLoop.
    195   // But for some tests which use TestBrowserThreadBundle, we need to call
    196   // WillDestroyCurrentMessageLoop explicitly because the notification happens
    197   // too late. (see http://crbug.com/247525#c14).
    198   virtual void WillDestroyCurrentMessageLoop() OVERRIDE;
    199 
    200   // Sends log messages to the render process hosts whose corresponding render
    201   // processes are making device requests, to be used by the
    202   // webrtcLoggingPrivate API if requested.
    203   void AddLogMessageOnIOThread(const std::string& message);
    204 
    205   // Adds |message| to native logs for outstanding device requests, for use by
    206   // render processes hosts whose corresponding render processes are requesting
    207   // logging from webrtcLoggingPrivate API. Safe to call from any thread.
    208   static void SendMessageToNativeLog(const std::string& message);
    209 
    210   // base::PowerObserver overrides.
    211   virtual void OnSuspend() OVERRIDE;
    212   virtual void OnResume() OVERRIDE;
    213 
    214  protected:
    215   // Used for testing.
    216   MediaStreamManager();
    217 
    218  private:
    219   // Contains all data needed to keep track of requests.
    220   class DeviceRequest;
    221 
    222   // Cache enumerated device list.
    223   struct EnumerationCache {
    224     EnumerationCache();
    225     ~EnumerationCache();
    226 
    227     bool valid;
    228     StreamDeviceInfoArray devices;
    229   };
    230 
    231   // |DeviceRequests| is a list to ensure requests are processed in the order
    232   // they arrive. The first member of the pair is the label of the
    233   // |DeviceRequest|.
    234   typedef std::list<std::pair<std::string, DeviceRequest*> > DeviceRequests;
    235 
    236   // Initializes the device managers on IO thread.  Auto-starts the device
    237   // thread and registers this as a listener with the device managers.
    238   void InitializeDeviceManagersOnIOThread();
    239 
    240   // Helper for sending up-to-date device lists to media observer when a
    241   // capture device is plugged in or unplugged.
    242   void NotifyDevicesChanged(MediaStreamType stream_type,
    243                             const StreamDeviceInfoArray& devices);
    244 
    245   void HandleAccessRequestResponse(const std::string& label,
    246                                    const MediaStreamDevices& devices,
    247                                    content::MediaStreamRequestResult result);
    248   void StopMediaStreamFromBrowser(const std::string& label);
    249 
    250   void DoEnumerateDevices(const std::string& label);
    251 
    252   // Enumerates audio output devices. No caching.
    253   void EnumerateAudioOutputDevices(const std::string& label);
    254 
    255   void AudioOutputDevicesEnumerated(const StreamDeviceInfoArray& devices);
    256 
    257   // Helpers.
    258   // Checks if all devices that was requested in the request identififed by
    259   // |label| has been opened and set the request state accordingly.
    260   void HandleRequestDone(const std::string& label,
    261                          DeviceRequest* request);
    262   // Stop the use of the device associated with |session_id| of type |type| in
    263   // all |requests_|. The device is removed from the request. If a request
    264   /// doesn't use any devices as a consequence, the request is deleted.
    265   void StopDevice(MediaStreamType type, int session_id);
    266   // Calls the correct capture manager and close the device with |session_id|.
    267   // All requests that uses the device are updated.
    268   void CloseDevice(MediaStreamType type, int session_id);
    269   // Returns true if a request for devices has been completed and the devices
    270   // has either been opened or an error has occurred.
    271   bool RequestDone(const DeviceRequest& request) const;
    272   MediaStreamProvider* GetDeviceManager(MediaStreamType stream_type);
    273   void StartEnumeration(DeviceRequest* request);
    274   std::string AddRequest(DeviceRequest* request);
    275   DeviceRequest* FindRequest(const std::string& label) const;
    276   void DeleteRequest(const std::string& label);
    277   void ClearEnumerationCache(EnumerationCache* cache);
    278   // Returns true if the |cache| is invalid, false if it's invalid or if
    279   // the |stream_type| is MEDIA_NO_SERVICE.
    280   // On Android, this function will always return true for
    281   // MEDIA_DEVICE_AUDIO_CAPTURE since we don't have a SystemMonitor to tell
    282   // us about audio device changes.
    283   bool EnumerationRequired(EnumerationCache* cache, MediaStreamType type);
    284   // Prepare the request with label |label| by starting device enumeration if
    285   // needed.
    286   void SetupRequest(const std::string& label);
    287   // Prepare |request| of type MEDIA_DEVICE_AUDIO_CAPTURE and/or
    288   // MEDIA_DEVICE_VIDEO_CAPTURE for being posted to the UI by parsing
    289   // StreamOptions::Constraints for requested device IDs.
    290   bool SetupDeviceCaptureRequest(DeviceRequest* request);
    291   // Prepare |request| of type MEDIA_TAB_AUDIO_CAPTURE and/or
    292   // MEDIA_TAB_VIDEO_CAPTURE for being posted to the UI by parsing
    293   // StreamOptions::Constraints for requested tab capture IDs.
    294   bool SetupTabCaptureRequest(DeviceRequest* request);
    295   // Prepare |request| of type MEDIA_LOOPBACK_AUDIO_CAPTURE and/or
    296   // MEDIA_DESKTOP_VIDEO_CAPTURE for being posted to the UI by parsing
    297   // StreamOptions::Constraints for the requested desktop ID.
    298   bool SetupScreenCaptureRequest(DeviceRequest* request);
    299   // Called when a request has been setup and devices have been enumerated if
    300   // needed.
    301   void PostRequestToUI(const std::string& label, DeviceRequest* request);
    302   // Returns true if a device with |device_id| has already been requested with
    303   // a render procecss_id and render_frame_id and type equal to the the values
    304   // in |request|. If it has been requested, |device_info| contain information
    305   // about the device.
    306   bool FindExistingRequestedDeviceInfo(
    307       const DeviceRequest& new_request,
    308       const MediaStreamDevice& new_device_info,
    309       StreamDeviceInfo* existing_device_info,
    310       MediaRequestState* existing_request_state) const;
    311 
    312   void FinalizeGenerateStream(const std::string& label,
    313                               DeviceRequest* request);
    314   void FinalizeRequestFailed(const std::string& label,
    315                              DeviceRequest* request,
    316                              content::MediaStreamRequestResult result);
    317   void FinalizeOpenDevice(const std::string& label,
    318                           DeviceRequest* request);
    319   void FinalizeMediaAccessRequest(const std::string& label,
    320                                   DeviceRequest* request,
    321                                   const MediaStreamDevices& devices);
    322   void FinalizeEnumerateDevices(const std::string& label,
    323                                 DeviceRequest* request);
    324   void HandleCheckMediaAccessResponse(const std::string& label,
    325                                       bool have_access);
    326 
    327   // This method is called when an audio or video device is plugged in or
    328   // removed. It make sure all MediaStreams that use a removed device is
    329   // stopped and that the render process is notified. |old_devices| is the list
    330   // of previously available devices. |new_devices| is the new
    331   // list of currently available devices.
    332   void StopRemovedDevices(const StreamDeviceInfoArray& old_devices,
    333                           const StreamDeviceInfoArray& new_devices);
    334   // Helper method used by StopRemovedDevices to stop the use of a certain
    335   // device.
    336   void StopRemovedDevice(const MediaStreamDevice& device);
    337 
    338   // Helpers to start and stop monitoring devices.
    339   void StartMonitoring();
    340   void StopMonitoring();
    341 #if defined(OS_MACOSX)
    342   void StartMonitoringOnUIThread();
    343 #endif
    344 
    345   // Finds the requested device id from constraints. The requested device type
    346   // must be MEDIA_DEVICE_AUDIO_CAPTURE or MEDIA_DEVICE_VIDEO_CAPTURE.
    347   bool GetRequestedDeviceCaptureId(const DeviceRequest* request,
    348                                    MediaStreamType type,
    349                                    std::string* device_id) const;
    350 
    351   void TranslateDeviceIdToSourceId(DeviceRequest* request,
    352                                    MediaStreamDevice* device);
    353 
    354   // Helper method that sends log messages to the render process hosts whose
    355   // corresponding render processes are in |render_process_ids|, to be used by
    356   // the webrtcLoggingPrivate API if requested.
    357   void AddLogMessageOnUIThread(const std::set<int>& render_process_ids,
    358                                const std::string& message);
    359 
    360   // Handles the callback from MediaStreamUIProxy to receive the UI window id,
    361   // used for excluding the notification window in desktop capturing.
    362   void OnMediaStreamUIWindowId(MediaStreamType video_type,
    363                                StreamDeviceInfoArray devices,
    364                                gfx::NativeViewId window_id);
    365 
    366 #if defined(OS_CHROMEOS)
    367   // Ensures that we have checked for presence of a keyboard mic. This is only
    368   // done once. This function should be called before posting a request on the
    369   // UI thread.
    370   void EnsureKeyboardMicChecked();
    371 
    372   // Checks if the system has a keyboard mic, and if so, inform the audio
    373   // manager via SetKeyboardMicOnDeviceThread().
    374   void CheckKeyboardMicOnUIThread();
    375 
    376   // Tells the audio mananger that the system supports a keyboard mic.
    377   void SetKeyboardMicOnDeviceThread();
    378 #endif
    379 
    380   // Task runner shared by VideoCaptureManager and AudioInputDeviceManager and
    381   // used for enumerating audio output devices.
    382   // Note: Enumeration tasks may take seconds to complete so must never be run
    383   // on any of the BrowserThreads (UI, IO, etc).  See http://crbug.com/256945.
    384   scoped_refptr<base::SingleThreadTaskRunner> device_task_runner_;
    385 
    386   media::AudioManager* const audio_manager_;  // not owned
    387   scoped_refptr<AudioInputDeviceManager> audio_input_device_manager_;
    388   scoped_refptr<VideoCaptureManager> video_capture_manager_;
    389 
    390   // Indicator of device monitoring state.
    391   bool monitoring_started_;
    392 
    393 #if defined(OS_CHROMEOS)
    394   // Flag that's set when we have checked if the system has a keyboard mic. We
    395   // only need to check it once, and not when constructing since that will
    396   // affect startup time.
    397   // Must be accessed on the IO thread;
    398   bool has_checked_keyboard_mic_;
    399 #endif
    400 
    401   // Stores most recently enumerated device lists. The cache is cleared when
    402   // monitoring is stopped or there is no request for that type of device.
    403   EnumerationCache audio_enumeration_cache_;
    404   EnumerationCache video_enumeration_cache_;
    405 
    406   // Keeps track of live enumeration commands sent to VideoCaptureManager or
    407   // AudioInputDeviceManager, in order to only enumerate when necessary.
    408   int active_enumeration_ref_count_[NUM_MEDIA_TYPES];
    409 
    410   // All non-closed request. Must be accessed on IO thread.
    411   DeviceRequests requests_;
    412 
    413   // Hold a pointer to the IO loop to check we delete the device thread and
    414   // managers on the right thread.
    415   base::MessageLoop* io_loop_;
    416 
    417   bool use_fake_ui_;
    418   scoped_ptr<FakeMediaStreamUIProxy> fake_ui_;
    419 
    420   DISALLOW_COPY_AND_ASSIGN(MediaStreamManager);
    421 };
    422 
    423 }  // namespace content
    424 
    425 #endif  // CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_MANAGER_H_
    426