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_frame_id,
     55         content::MediaStreamType stream_type,
     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   // Checks if we have media access permission. Note that this only checks the
     88   // settings and does not query the user.
     89   bool CheckMediaAccessPermission(content::BrowserContext* browser_context,
     90                                   const GURL& security_origin,
     91                                   content::MediaStreamType type);
     92 
     93   // Method called from WebCapturerDelegate implementations to check media
     94   // access permission. Note that this does not query the user.
     95   bool CheckMediaAccessPermission(content::WebContents* web_contents,
     96                                   const GURL& security_origin,
     97                                   content::MediaStreamType type);
     98 
     99   // Same as above but for an |extension|, which may not be NULL.
    100 #if defined(ENABLE_EXTENSIONS)
    101   bool CheckMediaAccessPermission(content::WebContents* web_contents,
    102                                   const GURL& security_origin,
    103                                   content::MediaStreamType type,
    104                                   const extensions::Extension* extension);
    105 #endif
    106 
    107   // Helper to get the default devices which can be used by the media request.
    108   // Uses the first available devices if the default devices are not available.
    109   // If the return list is empty, it means there is no available device on the
    110   // OS.
    111   // Called on the UI thread.
    112   void GetDefaultDevicesForProfile(Profile* profile,
    113                                    bool audio,
    114                                    bool video,
    115                                    content::MediaStreamDevices* devices);
    116 
    117   // Helpers for picking particular requested devices, identified by raw id.
    118   // If the device requested is not available it will return NULL.
    119   const content::MediaStreamDevice*
    120   GetRequestedAudioDevice(const std::string& requested_audio_device_id);
    121   const content::MediaStreamDevice*
    122   GetRequestedVideoDevice(const std::string& requested_video_device_id);
    123 
    124   // Returns the first available audio or video device, or NULL if no devices
    125   // are available.
    126   const content::MediaStreamDevice* GetFirstAvailableAudioDevice();
    127   const content::MediaStreamDevice* GetFirstAvailableVideoDevice();
    128 
    129   // Unittests that do not require actual device enumeration should call this
    130   // API on the singleton. It is safe to call this multiple times on the
    131   // signleton.
    132   void DisableDeviceEnumerationForTesting();
    133 
    134   // Overridden from content::MediaObserver:
    135   virtual void OnAudioCaptureDevicesChanged() OVERRIDE;
    136   virtual void OnVideoCaptureDevicesChanged() OVERRIDE;
    137   virtual void OnMediaRequestStateChanged(
    138       int render_process_id,
    139       int render_frame_id,
    140       int page_request_id,
    141       const GURL& security_origin,
    142       content::MediaStreamType stream_type,
    143       content::MediaRequestState state) OVERRIDE;
    144   virtual void OnCreatingAudioStream(int render_process_id,
    145                                      int render_frame_id) OVERRIDE;
    146 
    147   scoped_refptr<MediaStreamCaptureIndicator> GetMediaStreamCaptureIndicator();
    148 
    149   DesktopStreamsRegistry* GetDesktopStreamsRegistry();
    150 
    151   bool IsDesktopCaptureInProgress();
    152 
    153   // Only for testing.
    154   void SetTestAudioCaptureDevices(const content::MediaStreamDevices& devices);
    155   void SetTestVideoCaptureDevices(const content::MediaStreamDevices& devices);
    156 
    157  private:
    158   friend struct DefaultSingletonTraits<MediaCaptureDevicesDispatcher>;
    159 
    160   struct PendingAccessRequest {
    161     PendingAccessRequest(const content::MediaStreamRequest& request,
    162                          const content::MediaResponseCallback& callback);
    163     ~PendingAccessRequest();
    164 
    165     // TODO(gbillock): make the MediaStreamDevicesController owned by
    166     // this object when we're using bubbles.
    167     content::MediaStreamRequest request;
    168     content::MediaResponseCallback callback;
    169   };
    170   typedef std::deque<PendingAccessRequest> RequestsQueue;
    171   typedef std::map<content::WebContents*, RequestsQueue> RequestsQueues;
    172 
    173   MediaCaptureDevicesDispatcher();
    174   virtual ~MediaCaptureDevicesDispatcher();
    175 
    176   // content::NotificationObserver implementation.
    177   virtual void Observe(int type,
    178                        const content::NotificationSource& source,
    179                        const content::NotificationDetails& details) OVERRIDE;
    180 
    181   // Helpers for ProcessMediaAccessRequest().
    182   void ProcessDesktopCaptureAccessRequest(
    183       content::WebContents* web_contents,
    184       const content::MediaStreamRequest& request,
    185       const content::MediaResponseCallback& callback,
    186       const extensions::Extension* extension);
    187   void ProcessScreenCaptureAccessRequest(
    188       content::WebContents* web_contents,
    189       const content::MediaStreamRequest& request,
    190       const content::MediaResponseCallback& callback,
    191       const extensions::Extension* extension);
    192   void ProcessTabCaptureAccessRequest(
    193       content::WebContents* web_contents,
    194       const content::MediaStreamRequest& request,
    195       const content::MediaResponseCallback& callback,
    196       const extensions::Extension* extension);
    197   void ProcessMediaAccessRequestFromPlatformAppOrExtension(
    198       content::WebContents* web_contents,
    199       const content::MediaStreamRequest& request,
    200       const content::MediaResponseCallback& callback,
    201       const extensions::Extension* extension);
    202   void ProcessRegularMediaAccessRequest(
    203       content::WebContents* web_contents,
    204       const content::MediaStreamRequest& request,
    205       const content::MediaResponseCallback& callback);
    206   void ProcessQueuedAccessRequest(content::WebContents* web_contents);
    207   void OnAccessRequestResponse(content::WebContents* web_contents,
    208                                const content::MediaStreamDevices& devices,
    209                                content::MediaStreamRequestResult result,
    210                                scoped_ptr<content::MediaStreamUI> ui);
    211 
    212   // Called by the MediaObserver() functions, executed on UI thread.
    213   void NotifyAudioDevicesChangedOnUIThread();
    214   void NotifyVideoDevicesChangedOnUIThread();
    215   void UpdateMediaRequestStateOnUIThread(
    216       int render_process_id,
    217       int render_frame_id,
    218       int page_request_id,
    219       const GURL& security_origin,
    220       content::MediaStreamType stream_type,
    221       content::MediaRequestState state);
    222   void OnCreatingAudioStreamOnUIThread(int render_process_id,
    223                                        int render_frame_id);
    224 
    225   // Only for testing, a list of cached audio capture devices.
    226   content::MediaStreamDevices test_audio_devices_;
    227 
    228   // Only for testing, a list of cached video capture devices.
    229   content::MediaStreamDevices test_video_devices_;
    230 
    231   // A list of observers for the device update notifications.
    232   ObserverList<Observer> observers_;
    233 
    234   // Flag used by unittests to disable device enumeration.
    235   bool is_device_enumeration_disabled_;
    236 
    237   RequestsQueues pending_requests_;
    238 
    239   scoped_refptr<MediaStreamCaptureIndicator> media_stream_capture_indicator_;
    240 
    241   scoped_ptr<DesktopStreamsRegistry> desktop_streams_registry_;
    242 
    243   content::NotificationRegistrar notifications_registrar_;
    244 
    245   // Tracks MEDIA_DESKTOP_VIDEO_CAPTURE sessions which reach the
    246   // MEDIA_REQUEST_STATE_DONE state.  Sessions are remove when
    247   // MEDIA_REQUEST_STATE_CLOSING is encountered.
    248   struct DesktopCaptureSession {
    249     int render_process_id;
    250     int render_frame_id;
    251     int page_request_id;
    252   };
    253   typedef std::list<DesktopCaptureSession> DesktopCaptureSessions;
    254   DesktopCaptureSessions desktop_capture_sessions_;
    255 
    256   DISALLOW_COPY_AND_ASSIGN(MediaCaptureDevicesDispatcher);
    257 };
    258 
    259 #endif  // CHROME_BROWSER_MEDIA_MEDIA_CAPTURE_DEVICES_DISPATCHER_H_
    260