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 // 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.
23 // When enumeration and open are done in separate operations,
24 // MediaStreamUIController is not involved as in steps.
26 #ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_MANAGER_H_
27 #define CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_MANAGER_H_
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 "base/threading/thread.h"
41 #include "content/browser/renderer_host/media/media_stream_provider.h"
42 #include "content/common/content_export.h"
43 #include "content/common/media/media_stream_options.h"
44 #include "content/public/browser/media_request_state.h"
45 #include "content/public/browser/resource_context.h"
53 class AudioInputDeviceManager
;
55 class FakeMediaStreamUIProxy
;
56 class MediaStreamDeviceSettings
;
57 class MediaStreamRequester
;
58 class MediaStreamUIProxy
;
59 class VideoCaptureManager
;
61 // MediaStreamManager is used to generate and close new media devices, not to
62 // start the media flow. The classes requesting new media streams are answered
63 // using MediaStreamRequester.
64 class CONTENT_EXPORT MediaStreamManager
65 : public MediaStreamProviderListener
,
66 public base::MessageLoop::DestructionObserver
,
67 public base::PowerObserver
,
68 public base::SystemMonitor::DevicesChangedObserver
{
70 // Callback to deliver the result of a media request.
71 typedef base::Callback
<void(const MediaStreamDevices
& devices
,
72 scoped_ptr
<MediaStreamUIProxy
> ui
)>
73 MediaRequestResponseCallback
;
75 explicit MediaStreamManager(media::AudioManager
* audio_manager
);
76 ~MediaStreamManager() override
;
78 // Used to access VideoCaptureManager.
79 VideoCaptureManager
* video_capture_manager();
81 // Used to access AudioInputDeviceManager.
82 AudioInputDeviceManager
* audio_input_device_manager();
84 // Creates a new media access request which is identified by a unique string
85 // that's returned to the caller. This will trigger the infobar and ask users
86 // for access to the device. |render_process_id| and |render_frame_id| are
87 // used to determine where the infobar will appear to the user. |callback| is
88 // used to send the selected device to the clients. An empty list of device
89 // will be returned if the users deny the access.
90 std::string
MakeMediaAccessRequest(
91 int render_process_id
,
94 const StreamOptions
& options
,
95 const GURL
& security_origin
,
96 const MediaRequestResponseCallback
& callback
);
98 // GenerateStream opens new media devices according to |components|. It
99 // creates a new request which is identified by a unique string that's
100 // returned to the caller. |render_process_id| and |render_frame_id| are used
101 // to determine where the infobar will appear to the user.
102 void GenerateStream(MediaStreamRequester
* requester
,
103 int render_process_id
,
105 const ResourceContext::SaltCallback
& sc
,
107 const StreamOptions
& components
,
108 const GURL
& security_origin
,
111 void CancelRequest(int render_process_id
,
113 int page_request_id
);
115 // Cancel an open request identified by |label|.
116 virtual void CancelRequest(const std::string
& label
);
118 // Cancel all requests for the given |render_process_id|.
119 void CancelAllRequests(int render_process_id
);
121 // Closes the stream device for a certain render frame. The stream must have
122 // been opened by a call to GenerateStream.
123 void StopStreamDevice(int render_process_id
,
125 const std::string
& device_id
);
127 // Gets a list of devices of |type|, which must be MEDIA_DEVICE_AUDIO_CAPTURE
128 // or MEDIA_DEVICE_VIDEO_CAPTURE.
129 // The request is identified using the string returned to the caller.
130 // When the |requester| is NULL, MediaStreamManager will enumerate both audio
131 // and video devices and also start monitoring device changes, such as
132 // plug/unplug. The new device lists will be delivered via media observer to
133 // MediaCaptureDevicesDispatcher.
134 virtual std::string
EnumerateDevices(MediaStreamRequester
* requester
,
135 int render_process_id
,
137 const ResourceContext::SaltCallback
& sc
,
139 MediaStreamType type
,
140 const GURL
& security_origin
);
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
,
148 const ResourceContext::SaltCallback
& sc
,
150 const std::string
& device_id
,
151 MediaStreamType type
,
152 const GURL
& security_origin
);
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;
164 // Called by UI to make sure the device monitor is started so that UI receive
165 // notifications about device changes.
166 void EnsureDeviceMonitorStarted();
168 // Implements MediaStreamProviderListener.
169 void Opened(MediaStreamType stream_type
, int capture_session_id
) override
;
170 void Closed(MediaStreamType stream_type
, int capture_session_id
) override
;
171 void DevicesEnumerated(MediaStreamType stream_type
,
172 const StreamDeviceInfoArray
& devices
) override
;
173 void Aborted(MediaStreamType stream_type
, int capture_session_id
) override
;
175 // Implements base::SystemMonitor::DevicesChangedObserver.
176 void OnDevicesChanged(base::SystemMonitor::DeviceType device_type
) override
;
178 // Called by the tests to specify a fake UI that should be used for next
179 // generated stream (or when using --use-fake-ui-for-media-stream).
180 void UseFakeUI(scoped_ptr
<FakeMediaStreamUIProxy
> fake_ui
);
182 // Returns all devices currently opened by a request with label |label|.
183 // If no request with |label| exist, an empty array is returned.
184 StreamDeviceInfoArray
GetDevicesOpenedByRequest(
185 const std::string
& label
) const;
187 // This object gets deleted on the UI thread after the IO thread has been
188 // destroyed. So we need to know when IO thread is being destroyed so that
189 // we can delete VideoCaptureManager and AudioInputDeviceManager. Normally
190 // this is handled by
191 // base::MessageLoop::DestructionObserver::WillDestroyCurrentMessageLoop.
192 // But for some tests which use TestBrowserThreadBundle, we need to call
193 // WillDestroyCurrentMessageLoop explicitly because the notification happens
194 // too late. (see http://crbug.com/247525#c14).
195 void WillDestroyCurrentMessageLoop() override
;
197 // Sends log messages to the render process hosts whose corresponding render
198 // processes are making device requests, to be used by the
199 // webrtcLoggingPrivate API if requested.
200 void AddLogMessageOnIOThread(const std::string
& message
);
202 // Adds |message| to native logs for outstanding device requests, for use by
203 // render processes hosts whose corresponding render processes are requesting
204 // logging from webrtcLoggingPrivate API. Safe to call from any thread.
205 static void SendMessageToNativeLog(const std::string
& message
);
207 // base::PowerObserver overrides.
208 void OnSuspend() override
;
209 void OnResume() override
;
213 MediaStreamManager();
216 // Contains all data needed to keep track of requests.
219 // Cache enumerated device list.
220 struct EnumerationCache
{
225 StreamDeviceInfoArray devices
;
228 // |DeviceRequests| is a list to ensure requests are processed in the order
229 // they arrive. The first member of the pair is the label of the
231 typedef std::list
<std::pair
<std::string
, DeviceRequest
*> > DeviceRequests
;
233 // Initializes the device managers on IO thread. Auto-starts the device
234 // thread and registers this as a listener with the device managers.
235 void InitializeDeviceManagersOnIOThread();
237 // Helper for sending up-to-date device lists to media observer when a
238 // capture device is plugged in or unplugged.
239 void NotifyDevicesChanged(MediaStreamType stream_type
,
240 const StreamDeviceInfoArray
& devices
);
242 void HandleAccessRequestResponse(const std::string
& label
,
243 const MediaStreamDevices
& devices
,
244 content::MediaStreamRequestResult result
);
245 void StopMediaStreamFromBrowser(const std::string
& label
);
247 void DoEnumerateDevices(const std::string
& label
);
249 // Enumerates audio output devices. No caching.
250 void EnumerateAudioOutputDevices(const std::string
& label
);
252 void AudioOutputDevicesEnumerated(const StreamDeviceInfoArray
& devices
);
255 // Checks if all devices that was requested in the request identififed by
256 // |label| has been opened and set the request state accordingly.
257 void HandleRequestDone(const std::string
& label
,
258 DeviceRequest
* request
);
259 // Stop the use of the device associated with |session_id| of type |type| in
260 // all |requests_|. The device is removed from the request. If a request
261 /// doesn't use any devices as a consequence, the request is deleted.
262 void StopDevice(MediaStreamType type
, int session_id
);
263 // Calls the correct capture manager and close the device with |session_id|.
264 // All requests that uses the device are updated.
265 void CloseDevice(MediaStreamType type
, int session_id
);
266 // Returns true if a request for devices has been completed and the devices
267 // has either been opened or an error has occurred.
268 bool RequestDone(const DeviceRequest
& request
) const;
269 MediaStreamProvider
* GetDeviceManager(MediaStreamType stream_type
);
270 void StartEnumeration(DeviceRequest
* request
);
271 std::string
AddRequest(DeviceRequest
* request
);
272 DeviceRequest
* FindRequest(const std::string
& label
) const;
273 void DeleteRequest(const std::string
& label
);
274 void ClearEnumerationCache(EnumerationCache
* cache
);
275 // Returns true if the |cache| is invalid, false if it's invalid or if
276 // the |stream_type| is MEDIA_NO_SERVICE.
277 // On Android, this function will always return true for
278 // MEDIA_DEVICE_AUDIO_CAPTURE since we don't have a SystemMonitor to tell
279 // us about audio device changes.
280 bool EnumerationRequired(EnumerationCache
* cache
, MediaStreamType type
);
281 // Prepare the request with label |label| by starting device enumeration if
283 void SetupRequest(const std::string
& label
);
284 // Prepare |request| of type MEDIA_DEVICE_AUDIO_CAPTURE and/or
285 // MEDIA_DEVICE_VIDEO_CAPTURE for being posted to the UI by parsing
286 // StreamOptions::Constraints for requested device IDs.
287 bool SetupDeviceCaptureRequest(DeviceRequest
* request
);
288 // Prepare |request| of type MEDIA_TAB_AUDIO_CAPTURE and/or
289 // MEDIA_TAB_VIDEO_CAPTURE for being posted to the UI by parsing
290 // StreamOptions::Constraints for requested tab capture IDs.
291 bool SetupTabCaptureRequest(DeviceRequest
* request
);
292 // Prepare |request| of type MEDIA_DESKTOP_AUDIO_CAPTURE and/or
293 // MEDIA_DESKTOP_VIDEO_CAPTURE for being posted to the UI by parsing
294 // StreamOptions::Constraints for the requested desktop ID.
295 bool SetupScreenCaptureRequest(DeviceRequest
* request
);
296 // Called when a request has been setup and devices have been enumerated if
298 void PostRequestToUI(const std::string
& label
, DeviceRequest
* request
);
299 // Returns true if a device with |device_id| has already been requested with
300 // a render procecss_id and render_frame_id and type equal to the the values
301 // in |request|. If it has been requested, |device_info| contain information
303 bool FindExistingRequestedDeviceInfo(
304 const DeviceRequest
& new_request
,
305 const MediaStreamDevice
& new_device_info
,
306 StreamDeviceInfo
* existing_device_info
,
307 MediaRequestState
* existing_request_state
) const;
309 void FinalizeGenerateStream(const std::string
& label
,
310 DeviceRequest
* request
);
311 void FinalizeRequestFailed(const std::string
& label
,
312 DeviceRequest
* request
,
313 content::MediaStreamRequestResult result
);
314 void FinalizeOpenDevice(const std::string
& label
,
315 DeviceRequest
* request
);
316 void FinalizeMediaAccessRequest(const std::string
& label
,
317 DeviceRequest
* request
,
318 const MediaStreamDevices
& devices
);
319 void FinalizeEnumerateDevices(const std::string
& label
,
320 DeviceRequest
* request
);
321 void HandleCheckMediaAccessResponse(const std::string
& label
,
324 // This method is called when an audio or video device is plugged in or
325 // removed. It make sure all MediaStreams that use a removed device is
326 // stopped and that the render process is notified. |old_devices| is the list
327 // of previously available devices. |new_devices| is the new
328 // list of currently available devices.
329 void StopRemovedDevices(const StreamDeviceInfoArray
& old_devices
,
330 const StreamDeviceInfoArray
& new_devices
);
331 // Helper method used by StopRemovedDevices to stop the use of a certain
333 void StopRemovedDevice(const MediaStreamDevice
& device
);
335 // Helpers to start and stop monitoring devices.
336 void StartMonitoring();
337 void StopMonitoring();
338 #if defined(OS_MACOSX)
339 void StartMonitoringOnUIThread();
342 // Finds the requested device id from constraints. The requested device type
343 // must be MEDIA_DEVICE_AUDIO_CAPTURE or MEDIA_DEVICE_VIDEO_CAPTURE.
344 bool GetRequestedDeviceCaptureId(const DeviceRequest
* request
,
345 MediaStreamType type
,
346 std::string
* device_id
) const;
348 void TranslateDeviceIdToSourceId(DeviceRequest
* request
,
349 MediaStreamDevice
* device
);
351 // Helper method that sends log messages to the render process hosts whose
352 // corresponding render processes are in |render_process_ids|, to be used by
353 // the webrtcLoggingPrivate API if requested.
354 void AddLogMessageOnUIThread(const std::set
<int>& render_process_ids
,
355 const std::string
& message
);
357 // Handles the callback from MediaStreamUIProxy to receive the UI window id,
358 // used for excluding the notification window in desktop capturing.
359 void OnMediaStreamUIWindowId(MediaStreamType video_type
,
360 StreamDeviceInfoArray devices
,
361 gfx::NativeViewId window_id
);
363 #if defined(OS_CHROMEOS)
364 // Ensures that we have checked for presence of a keyboard mic. This is only
365 // done once. This function should be called before posting a request on the
367 void EnsureKeyboardMicChecked();
369 // Checks if the system has a keyboard mic, and if so, inform the audio
370 // manager via SetKeyboardMicOnDeviceThread().
371 void CheckKeyboardMicOnUIThread();
373 // Tells the audio mananger that the system supports a keyboard mic.
374 void SetKeyboardMicOnDeviceThread();
377 // Task runner shared by VideoCaptureManager and AudioInputDeviceManager and
378 // used for enumerating audio output devices.
379 // Note: Enumeration tasks may take seconds to complete so must never be run
380 // on any of the BrowserThreads (UI, IO, etc). See http://crbug.com/256945.
381 scoped_refptr
<base::SingleThreadTaskRunner
> device_task_runner_
;
383 media::AudioManager
* const audio_manager_
; // not owned
384 scoped_refptr
<AudioInputDeviceManager
> audio_input_device_manager_
;
385 scoped_refptr
<VideoCaptureManager
> video_capture_manager_
;
387 base::Thread video_capture_thread_
;
390 // Indicator of device monitoring state.
391 bool monitoring_started_
;
393 #if defined(OS_CHROMEOS)
394 // Flag that's set when we have checked if the system has a keyboard mic. We
395 // only need to check it once, and not when constructing since that will
396 // affect startup time.
397 // Must be accessed on the IO thread;
398 bool has_checked_keyboard_mic_
;
401 // Stores most recently enumerated device lists. The cache is cleared when
402 // monitoring is stopped or there is no request for that type of device.
403 EnumerationCache audio_enumeration_cache_
;
404 EnumerationCache video_enumeration_cache_
;
406 // Keeps track of live enumeration commands sent to VideoCaptureManager or
407 // AudioInputDeviceManager, in order to only enumerate when necessary.
408 int active_enumeration_ref_count_
[NUM_MEDIA_TYPES
];
410 // All non-closed request. Must be accessed on IO thread.
411 DeviceRequests requests_
;
413 // Hold a pointer to the IO loop to check we delete the device thread and
414 // managers on the right thread.
415 base::MessageLoop
* io_loop_
;
418 scoped_ptr
<FakeMediaStreamUIProxy
> fake_ui_
;
420 DISALLOW_COPY_AND_ASSIGN(MediaStreamManager
);
423 } // namespace content
425 #endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_MANAGER_H_