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 #ifndef CHROME_BROWSER_MEDIA_MEDIA_CAPTURE_DEVICES_DISPATCHER_H_
      6 #define CHROME_BROWSER_MEDIA_MEDIA_CAPTURE_DEVICES_DISPATCHER_H_
      7 
      8 #include <deque>
      9 #include <list>
     10 #include <map>
     11 
     12 #include "base/callback.h"
     13 #include "base/memory/scoped_ptr.h"
     14 #include "base/memory/singleton.h"
     15 #include "base/observer_list.h"
     16 #include "content/public/browser/media_observer.h"
     17 #include "content/public/browser/notification_observer.h"
     18 #include "content/public/browser/notification_registrar.h"
     19 #include "content/public/browser/web_contents_delegate.h"
     20 #include "content/public/common/media_stream_request.h"
     21 
     22 class DesktopStreamsRegistry;
     23 class MediaStreamCaptureIndicator;
     24 class Profile;
     25 
     26 namespace extensions {
     27 class Extension;
     28 }
     29 
     30 namespace user_prefs {
     31 class PrefRegistrySyncable;
     32 }
     33 
     34 // This singleton is used to receive updates about media events from the content
     35 // layer.
     36 class MediaCaptureDevicesDispatcher : public content::MediaObserver,
     37                                       public content::NotificationObserver {
     38  public:
     39   class Observer {
     40    public:
     41     // Handle an information update consisting of a up-to-date audio capture
     42     // device lists. This happens when a microphone is plugged in or unplugged.
     43     virtual void OnUpdateAudioDevices(
     44         const content::MediaStreamDevices& devices) {}
     45 
     46     // Handle an information update consisting of a up-to-date video capture
     47     // device lists. This happens when a camera is plugged in or unplugged.
     48     virtual void OnUpdateVideoDevices(
     49         const content::MediaStreamDevices& devices) {}
     50 
     51     // Handle an information update related to a media stream request.
     52     virtual void OnRequestUpdate(
     53         int render_process_id,
     54         int render_view_id,
     55         const content::MediaStreamDevice& device,
     56         const content::MediaRequestState state) {}
     57 
     58     // Handle an information update that a new stream is being created.
     59     virtual void OnCreatingAudioStream(int render_process_id,
     60                                        int render_frame_id) {}
     61 
     62     virtual ~Observer() {}
     63   };
     64 
     65   static MediaCaptureDevicesDispatcher* GetInstance();
     66 
     67   // Registers the preferences related to Media Stream default devices.
     68   static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
     69 
     70   // Methods for observers. Called on UI thread.
     71   // Observers should add themselves on construction and remove themselves
     72   // on destruction.
     73   void AddObserver(Observer* observer);
     74   void RemoveObserver(Observer* observer);
     75   const content::MediaStreamDevices& GetAudioCaptureDevices();
     76   const content::MediaStreamDevices& GetVideoCaptureDevices();
     77 
     78   // Method called from WebCapturerDelegate implementations to process access
     79   // requests. |extension| is set to NULL if request was made from a drive-by
     80   // page.
     81   void ProcessMediaAccessRequest(
     82       content::WebContents* web_contents,
     83       const content::MediaStreamRequest& request,
     84       const content::MediaResponseCallback& callback,
     85       const extensions::Extension* extension);
     86 
     87   // Helper to get the default devices which can be used by the media request.
     88   // Uses the first available devices if the default devices are not available.
     89   // If the return list is empty, it means there is no available device on the
     90   // OS.
     91   // Called on the UI thread.
     92   void GetDefaultDevicesForProfile(Profile* profile,
     93                                    bool audio,
     94                                    bool video,
     95                                    content::MediaStreamDevices* devices);
     96 
     97   // Helpers for picking particular requested devices, identified by raw id.
     98   // If the device requested is not available it will return NULL.
     99   const content::MediaStreamDevice*
    100   GetRequestedAudioDevice(const std::string& requested_audio_device_id);
    101   const content::MediaStreamDevice*
    102   GetRequestedVideoDevice(const std::string& requested_video_device_id);
    103 
    104   // Returns the first available audio or video device, or NULL if no devices
    105   // are available.
    106   const content::MediaStreamDevice* GetFirstAvailableAudioDevice();
    107   const content::MediaStreamDevice* GetFirstAvailableVideoDevice();
    108 
    109   // Unittests that do not require actual device enumeration should call this
    110   // API on the singleton. It is safe to call this multiple times on the
    111   // signleton.
    112   void DisableDeviceEnumerationForTesting();
    113 
    114   // Overridden from content::MediaObserver:
    115   virtual void OnAudioCaptureDevicesChanged() OVERRIDE;
    116   virtual void OnVideoCaptureDevicesChanged() OVERRIDE;
    117   virtual void OnMediaRequestStateChanged(
    118       int render_process_id,
    119       int render_view_id,
    120       int page_request_id,
    121       const GURL& security_origin,
    122       const content::MediaStreamDevice& device,
    123       content::MediaRequestState state) OVERRIDE;
    124   virtual void OnCreatingAudioStream(int render_process_id,
    125                                      int render_frame_id) OVERRIDE;
    126   virtual void OnAudioStreamPlaying(
    127       int render_process_id,
    128       int render_frame_id,
    129       int stream_id,
    130       const ReadPowerAndClipCallback& power_read_callback) OVERRIDE;
    131   virtual void OnAudioStreamStopped(
    132       int render_process_id,
    133       int render_frame_id,
    134       int stream_id) OVERRIDE;
    135 
    136   scoped_refptr<MediaStreamCaptureIndicator> GetMediaStreamCaptureIndicator();
    137 
    138   DesktopStreamsRegistry* GetDesktopStreamsRegistry();
    139 
    140   bool IsDesktopCaptureInProgress();
    141 
    142   // Only for testing.
    143   void SetTestAudioCaptureDevices(const content::MediaStreamDevices& devices);
    144   void SetTestVideoCaptureDevices(const content::MediaStreamDevices& devices);
    145 
    146  private:
    147   friend struct DefaultSingletonTraits<MediaCaptureDevicesDispatcher>;
    148 
    149   struct PendingAccessRequest {
    150     PendingAccessRequest(const content::MediaStreamRequest& request,
    151                          const content::MediaResponseCallback& callback);
    152     ~PendingAccessRequest();
    153 
    154     // TODO(gbillock): make the MediaStreamDevicesController owned by
    155     // this object when we're using bubbles.
    156     content::MediaStreamRequest request;
    157     content::MediaResponseCallback callback;
    158   };
    159   typedef std::deque<PendingAccessRequest> RequestsQueue;
    160   typedef std::map<content::WebContents*, RequestsQueue> RequestsQueues;
    161 
    162   MediaCaptureDevicesDispatcher();
    163   virtual ~MediaCaptureDevicesDispatcher();
    164 
    165   // content::NotificationObserver implementation.
    166   virtual void Observe(int type,
    167                        const content::NotificationSource& source,
    168                        const content::NotificationDetails& details) OVERRIDE;
    169 
    170   // Helpers for ProcessMediaAccessRequest().
    171   void ProcessDesktopCaptureAccessRequest(
    172       content::WebContents* web_contents,
    173       const content::MediaStreamRequest& request,
    174       const content::MediaResponseCallback& callback,
    175       const extensions::Extension* extension);
    176   void ProcessScreenCaptureAccessRequest(
    177       content::WebContents* web_contents,
    178       const content::MediaStreamRequest& request,
    179       const content::MediaResponseCallback& callback,
    180       const extensions::Extension* extension);
    181   void ProcessTabCaptureAccessRequest(
    182       content::WebContents* web_contents,
    183       const content::MediaStreamRequest& request,
    184       const content::MediaResponseCallback& callback,
    185       const extensions::Extension* extension);
    186   void ProcessMediaAccessRequestFromPlatformAppOrExtension(
    187       content::WebContents* web_contents,
    188       const content::MediaStreamRequest& request,
    189       const content::MediaResponseCallback& callback,
    190       const extensions::Extension* extension);
    191   void ProcessRegularMediaAccessRequest(
    192       content::WebContents* web_contents,
    193       const content::MediaStreamRequest& request,
    194       const content::MediaResponseCallback& callback);
    195   void ProcessQueuedAccessRequest(content::WebContents* web_contents);
    196   void OnAccessRequestResponse(content::WebContents* web_contents,
    197                                const content::MediaStreamDevices& devices,
    198                                content::MediaStreamRequestResult result,
    199                                scoped_ptr<content::MediaStreamUI> ui);
    200 
    201   // Called by the MediaObserver() functions, executed on UI thread.
    202   void NotifyAudioDevicesChangedOnUIThread();
    203   void NotifyVideoDevicesChangedOnUIThread();
    204   void UpdateMediaRequestStateOnUIThread(
    205       int render_process_id,
    206       int render_view_id,
    207       int page_request_id,
    208       const GURL& security_origin,
    209       const content::MediaStreamDevice& device,
    210       content::MediaRequestState state);
    211   void OnCreatingAudioStreamOnUIThread(int render_process_id,
    212                                        int render_frame_id);
    213 
    214   // Only for testing, a list of cached audio capture devices.
    215   content::MediaStreamDevices test_audio_devices_;
    216 
    217   // Only for testing, a list of cached video capture devices.
    218   content::MediaStreamDevices test_video_devices_;
    219 
    220   // A list of observers for the device update notifications.
    221   ObserverList<Observer> observers_;
    222 
    223   // Flag used by unittests to disable device enumeration.
    224   bool is_device_enumeration_disabled_;
    225 
    226   RequestsQueues pending_requests_;
    227 
    228   scoped_refptr<MediaStreamCaptureIndicator> media_stream_capture_indicator_;
    229 
    230   scoped_ptr<DesktopStreamsRegistry> desktop_streams_registry_;
    231 
    232   content::NotificationRegistrar notifications_registrar_;
    233 
    234   // Tracks MEDIA_DESKTOP_VIDEO_CAPTURE sessions which reach the
    235   // MEDIA_REQUEST_STATE_DONE state.  Sessions are remove when
    236   // MEDIA_REQUEST_STATE_CLOSING is encountered.
    237   struct DesktopCaptureSession {
    238     int render_process_id;
    239     int render_view_id;
    240     int page_request_id;
    241   };
    242   typedef std::list<DesktopCaptureSession> DesktopCaptureSessions;
    243   DesktopCaptureSessions desktop_capture_sessions_;
    244 
    245   DISALLOW_COPY_AND_ASSIGN(MediaCaptureDevicesDispatcher);
    246 };
    247 
    248 #endif  // CHROME_BROWSER_MEDIA_MEDIA_CAPTURE_DEVICES_DISPATCHER_H_
    249