| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // MediaStreamManager is used to open media capture devices (video supported |
| // now). Call flow: |
| // 1. GenerateStream is called when a render process wants to use a capture |
| // device. |
| // 2. MediaStreamManager will ask MediaStreamUIController for permission to |
| // use devices and for which device to use. |
| // 3. MediaStreamManager will request the corresponding media device manager(s) |
| // to enumerate available devices. The result will be given to |
| // MediaStreamUIController. |
| // 4. MediaStreamUIController will, by posting the request to UI, let the |
| // users to select which devices to use and send callback to |
| // MediaStreamManager with the result. |
| // 5. MediaStreamManager will call the proper media device manager to open the |
| // device and let the MediaStreamRequester know it has been done. |
| |
| // If either user or test harness selects --use-fake-device-for-media-stream, |
| // a fake video device or devices are used instead of real ones. |
| |
| // When enumeration and open are done in separate operations, |
| // MediaStreamUIController is not involved as in steps. |
| |
| #ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_MANAGER_H_ |
| #define CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_MANAGER_H_ |
| |
| #include <list> |
| #include <map> |
| #include <memory> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/macros.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/power_monitor/power_observer.h" |
| #include "base/threading/thread.h" |
| #include "build/build_config.h" |
| #include "content/browser/renderer_host/media/media_devices_manager.h" |
| #include "content/browser/renderer_host/media/media_stream_provider.h" |
| #include "content/common/content_export.h" |
| #include "content/common/media/media_devices.h" |
| #include "content/common/media/media_stream_options.h" |
| #include "content/public/browser/media_request_state.h" |
| |
| namespace media { |
| class AudioManager; |
| } |
| |
| namespace url { |
| class Origin; |
| } |
| |
| namespace content { |
| |
| class AudioInputDeviceManager; |
| class FakeMediaStreamUIProxy; |
| class MediaStreamRequester; |
| class MediaStreamUIProxy; |
| class VideoCaptureManager; |
| |
| // MediaStreamManager is used to generate and close new media devices, not to |
| // start the media flow. The classes requesting new media streams are answered |
| // using MediaStreamRequester. |
| class CONTENT_EXPORT MediaStreamManager |
| : public MediaStreamProviderListener, |
| public base::MessageLoop::DestructionObserver, |
| public base::PowerObserver { |
| public: |
| // Callback to deliver the result of a media request. |
| typedef base::Callback<void(const MediaStreamDevices& devices, |
| std::unique_ptr<MediaStreamUIProxy> ui)> |
| MediaRequestResponseCallback; |
| |
| // Callback for testing. |
| typedef base::Callback<bool(const StreamControls&)> |
| GenerateStreamTestCallback; |
| |
| // Adds |message| to native logs for outstanding device requests, for use by |
| // render processes hosts whose corresponding render processes are requesting |
| // logging from webrtcLoggingPrivate API. Safe to call from any thread. |
| static void SendMessageToNativeLog(const std::string& message); |
| |
| explicit MediaStreamManager(media::AudioManager* audio_manager); |
| |
| ~MediaStreamManager() override; |
| |
| // Used to access VideoCaptureManager. |
| VideoCaptureManager* video_capture_manager(); |
| |
| // Used to access AudioInputDeviceManager. |
| AudioInputDeviceManager* audio_input_device_manager(); |
| |
| // Used to access MediaDevicesManager. |
| MediaDevicesManager* media_devices_manager(); |
| |
| // Creates a new media access request which is identified by a unique string |
| // that's returned to the caller. This will trigger the infobar and ask users |
| // for access to the device. |render_process_id| and |render_frame_id| are |
| // used to determine where the infobar will appear to the user. |callback| is |
| // used to send the selected device to the clients. An empty list of device |
| // will be returned if the users deny the access. |
| std::string MakeMediaAccessRequest( |
| int render_process_id, |
| int render_frame_id, |
| int page_request_id, |
| const StreamControls& controls, |
| const url::Origin& security_origin, |
| const MediaRequestResponseCallback& callback); |
| |
| // GenerateStream opens new media devices according to |components|. It |
| // creates a new request which is identified by a unique string that's |
| // returned to the caller. |render_process_id| and |render_frame_id| are used |
| // to determine where the infobar will appear to the user. |
| void GenerateStream(MediaStreamRequester* requester, |
| int render_process_id, |
| int render_frame_id, |
| const std::string& salt, |
| int page_request_id, |
| const StreamControls& controls, |
| const url::Origin& security_origin, |
| bool user_gesture); |
| |
| void CancelRequest(int render_process_id, |
| int render_frame_id, |
| int page_request_id); |
| |
| // Cancel an open request identified by |label|. |
| virtual void CancelRequest(const std::string& label); |
| |
| // Cancel all requests for the given |render_process_id|. |
| void CancelAllRequests(int render_process_id); |
| |
| // Closes the stream device for a certain render frame. The stream must have |
| // been opened by a call to GenerateStream. |
| void StopStreamDevice(int render_process_id, |
| int render_frame_id, |
| const std::string& device_id); |
| |
| // Open a device identified by |device_id|. |type| must be either |
| // MEDIA_DEVICE_AUDIO_CAPTURE or MEDIA_DEVICE_VIDEO_CAPTURE. |
| // The request is identified using string returned to the caller. |
| void OpenDevice(MediaStreamRequester* requester, |
| int render_process_id, |
| int render_frame_id, |
| const std::string& salt, |
| int page_request_id, |
| const std::string& device_id, |
| MediaStreamType type, |
| const url::Origin& security_origin); |
| |
| // Finds and returns the device id corresponding to the given |
| // |source_id|. Returns true if there was a raw device id that matched the |
| // given |source_id|, false if nothing matched it. |
| // TODO(guidou): Update to provide a callback-based interface. |
| // See http://crbug.com/648155. |
| bool TranslateSourceIdToDeviceId(MediaStreamType stream_type, |
| const std::string& salt, |
| const url::Origin& security_origin, |
| const std::string& source_id, |
| std::string* device_id) const; |
| |
| // Find |device_id| in the list of |requests_|, and returns its session id, |
| // or StreamDeviceInfo::kNoId if not found. |
| int VideoDeviceIdToSessionId(const std::string& device_id) const; |
| |
| // Called by UI to make sure the device monitor is started so that UI receive |
| // notifications about device changes. |
| void EnsureDeviceMonitorStarted(); |
| |
| // Implements MediaStreamProviderListener. |
| void Opened(MediaStreamType stream_type, int capture_session_id) override; |
| void Closed(MediaStreamType stream_type, int capture_session_id) override; |
| void Aborted(MediaStreamType stream_type, int capture_session_id) override; |
| |
| // Returns all devices currently opened by a request with label |label|. |
| // If no request with |label| exist, an empty array is returned. |
| StreamDeviceInfoArray GetDevicesOpenedByRequest( |
| const std::string& label) const; |
| |
| // This object gets deleted on the UI thread after the IO thread has been |
| // destroyed. So we need to know when IO thread is being destroyed so that |
| // we can delete VideoCaptureManager and AudioInputDeviceManager. Normally |
| // this is handled by |
| // base::MessageLoop::DestructionObserver::WillDestroyCurrentMessageLoop. |
| // But for some tests which use TestBrowserThreadBundle, we need to call |
| // WillDestroyCurrentMessageLoop explicitly because the notification happens |
| // too late. (see http://crbug.com/247525#c14). |
| void WillDestroyCurrentMessageLoop() override; |
| |
| // Sends log messages to the render process hosts whose corresponding render |
| // processes are making device requests, to be used by the |
| // webrtcLoggingPrivate API if requested. |
| void AddLogMessageOnIOThread(const std::string& message); |
| |
| // base::PowerObserver overrides. |
| void OnSuspend() override; |
| void OnResume() override; |
| |
| // Called by the tests to specify a fake UI that should be used for next |
| // generated stream (or when using --use-fake-ui-for-media-stream). |
| void UseFakeUIForTests(std::unique_ptr<FakeMediaStreamUIProxy> fake_ui); |
| |
| // Register and unregister a new callback for receiving native log entries. |
| // The registered callback will be invoked on the IO thread. |
| // The registration and unregistration will be done asynchronously so it is |
| // not guaranteed that when the call returns the operation has completed. |
| void RegisterNativeLogCallback(int renderer_host_id, |
| const base::Callback<void(const std::string&)>& callback); |
| void UnregisterNativeLogCallback(int renderer_host_id); |
| |
| // Generates a hash of a device's unique ID usable by one |
| // particular security origin. |
| static std::string GetHMACForMediaDeviceID(const std::string& salt, |
| const url::Origin& security_origin, |
| const std::string& raw_unique_id); |
| |
| // Convenience method to check if |device_guid| is an HMAC of |
| // |raw_device_id| for |security_origin|. |
| static bool DoesMediaDeviceIDMatchHMAC(const std::string& salt, |
| const url::Origin& security_origin, |
| const std::string& device_guid, |
| const std::string& raw_unique_id); |
| |
| // Returns true if the renderer process identified with |render_process_id| |
| // is allowed to access |origin|. |
| static bool IsOriginAllowed(int render_process_id, const url::Origin& origin); |
| |
| // Set whether the capturing is secure for the capturing session with given |
| // |session_id|, |render_process_id|, and the MediaStreamType |type|. |
| void SetCapturingLinkSecured(int render_process_id, |
| int session_id, |
| content::MediaStreamType type, |
| bool is_secure); |
| |
| // Helper for sending up-to-date device lists to media observer when a |
| // capture device is plugged in or unplugged. |
| void NotifyDevicesChanged(MediaDeviceType stream_type, |
| const MediaDeviceInfoArray& devices); |
| |
| // This method is called when an audio or video device is removed. It makes |
| // sure all MediaStreams that use a removed device are stopped and that the |
| // render process is notified. |
| void StopRemovedDevice(MediaDeviceType type, const MediaDeviceInfo& device); |
| |
| void SetGenerateStreamCallbackForTesting( |
| GenerateStreamTestCallback test_callback); |
| |
| #if defined(OS_WIN) |
| void FlushVideoCaptureThreadForTesting(); |
| #endif |
| |
| private: |
| // Contains all data needed to keep track of requests. |
| class DeviceRequest; |
| |
| // |DeviceRequests| is a list to ensure requests are processed in the order |
| // they arrive. The first member of the pair is the label of the |
| // |DeviceRequest|. |
| using LabeledDeviceRequest = std::pair<std::string, DeviceRequest*>; |
| using DeviceRequests = std::list<LabeledDeviceRequest>; |
| |
| // Initializes the device managers on IO thread. Auto-starts the device |
| // thread and registers this as a listener with the device managers. |
| void InitializeDeviceManagersOnIOThread(); |
| |
| // |output_parameters| contains real values only if the request requires it. |
| void HandleAccessRequestResponse( |
| const std::string& label, |
| const media::AudioParameters& output_parameters, |
| const MediaStreamDevices& devices, |
| content::MediaStreamRequestResult result); |
| void StopMediaStreamFromBrowser(const std::string& label); |
| |
| // Helpers. |
| // Checks if all devices that was requested in the request identififed by |
| // |label| has been opened and set the request state accordingly. |
| void HandleRequestDone(const std::string& label, |
| DeviceRequest* request); |
| // Stop the use of the device associated with |session_id| of type |type| in |
| // all |requests_|. The device is removed from the request. If a request |
| /// doesn't use any devices as a consequence, the request is deleted. |
| void StopDevice(MediaStreamType type, int session_id); |
| // Calls the correct capture manager and close the device with |session_id|. |
| // All requests that uses the device are updated. |
| void CloseDevice(MediaStreamType type, int session_id); |
| // Returns true if a request for devices has been completed and the devices |
| // has either been opened or an error has occurred. |
| bool RequestDone(const DeviceRequest& request) const; |
| MediaStreamProvider* GetDeviceManager(MediaStreamType stream_type); |
| void StartEnumeration(DeviceRequest* request, const std::string& label); |
| std::string AddRequest(DeviceRequest* request); |
| DeviceRequest* FindRequest(const std::string& label) const; |
| void DeleteRequest(const std::string& label); |
| // Prepare the request with label |label| by starting device enumeration if |
| // needed. |
| void SetupRequest(const std::string& label); |
| // Prepare |request| of type MEDIA_DEVICE_AUDIO_CAPTURE and/or |
| // MEDIA_DEVICE_VIDEO_CAPTURE for being posted to the UI by parsing |
| // StreamControls for requested device IDs. |
| bool SetupDeviceCaptureRequest(DeviceRequest* request, |
| const MediaDeviceEnumeration& enumeration); |
| // Prepare |request| of type MEDIA_TAB_AUDIO_CAPTURE and/or |
| // MEDIA_TAB_VIDEO_CAPTURE for being posted to the UI by parsing |
| // StreamControls for requested tab capture IDs. |
| bool SetupTabCaptureRequest(DeviceRequest* request); |
| // Prepare |request| of type MEDIA_DESKTOP_AUDIO_CAPTURE and/or |
| // MEDIA_DESKTOP_VIDEO_CAPTURE for being posted to the UI by parsing |
| // StreamControls for the requested desktop ID. |
| bool SetupScreenCaptureRequest(DeviceRequest* request); |
| // Called when a request has been setup and devices have been enumerated if |
| // needed. |
| void ReadOutputParamsAndPostRequestToUI( |
| const std::string& label, |
| DeviceRequest* request, |
| const MediaDeviceEnumeration& enumeration); |
| // Called when audio output parameters have been read if needed. |
| void PostRequestToUI(const std::string& label, |
| DeviceRequest* request, |
| const MediaDeviceEnumeration& enumeration, |
| const media::AudioParameters& output_parameters); |
| // Returns true if a device with |device_id| has already been requested with |
| // a render procecss_id and render_frame_id and type equal to the the values |
| // in |request|. If it has been requested, |device_info| contain information |
| // about the device. |
| bool FindExistingRequestedDeviceInfo( |
| const DeviceRequest& new_request, |
| const MediaStreamDevice& new_device_info, |
| StreamDeviceInfo* existing_device_info, |
| MediaRequestState* existing_request_state) const; |
| |
| void FinalizeGenerateStream(const std::string& label, DeviceRequest* request); |
| void FinalizeRequestFailed(const std::string& label, |
| DeviceRequest* request, |
| content::MediaStreamRequestResult result); |
| void FinalizeOpenDevice(const std::string& label, DeviceRequest* request); |
| void FinalizeMediaAccessRequest(const std::string& label, |
| DeviceRequest* request, |
| const MediaStreamDevices& devices); |
| void HandleCheckMediaAccessResponse(const std::string& label, |
| bool have_access); |
| |
| // Picks a device ID from a list of required and alternate device IDs, |
| // presented as part of a TrackControls structure. |
| // Either the required device ID is picked (if present), or the first |
| // valid alternate device ID. |
| // Returns false if the required device ID is present and invalid. |
| // Otherwise, if no valid device is found, device_id is unchanged. |
| bool PickDeviceId(const std::string& salt, |
| const url::Origin& security_origin, |
| const TrackControls& controls, |
| const MediaDeviceInfoArray& devices, |
| std::string* device_id) const; |
| |
| // Finds the requested device id from request. The requested device type |
| // must be MEDIA_DEVICE_AUDIO_CAPTURE or MEDIA_DEVICE_VIDEO_CAPTURE. |
| bool GetRequestedDeviceCaptureId(const DeviceRequest* request, |
| MediaStreamType type, |
| const MediaDeviceInfoArray& devices, |
| std::string* device_id) const; |
| |
| void TranslateDeviceIdToSourceId(DeviceRequest* request, |
| MediaStreamDevice* device); |
| |
| // Handles the callback from MediaStreamUIProxy to receive the UI window id, |
| // used for excluding the notification window in desktop capturing. |
| void OnMediaStreamUIWindowId(MediaStreamType video_type, |
| StreamDeviceInfoArray devices, |
| gfx::NativeViewId window_id); |
| |
| // Runs on the IO thread and does the actual [un]registration of callbacks. |
| void DoNativeLogCallbackRegistration(int renderer_host_id, |
| const base::Callback<void(const std::string&)>& callback); |
| void DoNativeLogCallbackUnregistration(int renderer_host_id); |
| |
| // Callback to handle the reply to a low-level enumeration request. |
| void DevicesEnumerated(bool requested_audio_input, |
| bool requested_video_input, |
| const std::string& label, |
| const MediaDeviceEnumeration& enumeration); |
| |
| // Creates MediaStreamDevices for |devices_infos| of |stream_type|. For video |
| // capture device it also uses cached content from |video_capture_manager_| to |
| // set the MediaStreamDevice fields. |
| MediaStreamDevices ConvertToMediaStreamDevices( |
| MediaStreamType stream_type, |
| const MediaDeviceInfoArray& device_infos); |
| |
| // Task runner shared by VideoCaptureManager and AudioInputDeviceManager and |
| // used for enumerating audio output devices. |
| // Note: Enumeration tasks may take seconds to complete so must never be run |
| // on any of the BrowserThreads (UI, IO, etc). See http://crbug.com/256945. |
| scoped_refptr<base::SingleThreadTaskRunner> device_task_runner_; |
| |
| media::AudioManager* const audio_manager_; // not owned |
| scoped_refptr<AudioInputDeviceManager> audio_input_device_manager_; |
| scoped_refptr<VideoCaptureManager> video_capture_manager_; |
| #if defined(OS_WIN) |
| base::Thread video_capture_thread_; |
| #endif |
| |
| std::unique_ptr<MediaDevicesManager> media_devices_manager_; |
| |
| // All non-closed request. Must be accessed on IO thread. |
| DeviceRequests requests_; |
| |
| bool use_fake_ui_; |
| std::unique_ptr<FakeMediaStreamUIProxy> fake_ui_; |
| |
| // Maps render process hosts to log callbacks. Used on the IO thread. |
| std::map<int, base::Callback<void(const std::string&)>> log_callbacks_; |
| |
| GenerateStreamTestCallback generate_stream_test_callback_; |
| |
| DISALLOW_COPY_AND_ASSIGN(MediaStreamManager); |
| }; |
| |
| } // namespace content |
| |
| #endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_MANAGER_H_ |