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