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
22class DesktopStreamsRegistry;
23class MediaStreamCaptureIndicator;
24class Profile;
25
26namespace extensions {
27class Extension;
28}
29
30namespace user_prefs {
31class PrefRegistrySyncable;
32}
33
34// This singleton is used to receive updates about media events from the content
35// layer.
36class 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