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