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