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#ifndef CHROME_BROWSER_MEDIA_MEDIA_CAPTURE_DEVICES_DISPATCHER_H_ 6#define CHROME_BROWSER_MEDIA_MEDIA_CAPTURE_DEVICES_DISPATCHER_H_ 7 8#include <deque> 9#include <list> 10#include <map> 11 12#include "base/callback.h" 13#include "base/memory/scoped_ptr.h" 14#include "base/memory/singleton.h" 15#include "base/observer_list.h" 16#include "content/public/browser/media_observer.h" 17#include "content/public/browser/notification_observer.h" 18#include "content/public/browser/notification_registrar.h" 19#include "content/public/browser/web_contents_delegate.h" 20#include "content/public/common/media_stream_request.h" 21 22class DesktopStreamsRegistry; 23class MediaStreamCaptureIndicator; 24class Profile; 25 26namespace extensions { 27class Extension; 28} 29 30namespace user_prefs { 31class PrefRegistrySyncable; 32} 33 34// This singleton is used to receive updates about media events from the content 35// layer. 36class MediaCaptureDevicesDispatcher : public content::MediaObserver, 37 public content::NotificationObserver { 38 public: 39 class Observer { 40 public: 41 // Handle an information update consisting of a up-to-date audio capture 42 // device lists. This happens when a microphone is plugged in or unplugged. 43 virtual void OnUpdateAudioDevices( 44 const content::MediaStreamDevices& devices) {} 45 46 // Handle an information update consisting of a up-to-date video capture 47 // device lists. This happens when a camera is plugged in or unplugged. 48 virtual void OnUpdateVideoDevices( 49 const content::MediaStreamDevices& devices) {} 50 51 // Handle an information update related to a media stream request. 52 virtual void OnRequestUpdate( 53 int render_process_id, 54 int render_frame_id, 55 content::MediaStreamType stream_type, 56 const content::MediaRequestState state) {} 57 58 // Handle an information update that a new stream is being created. 59 virtual void OnCreatingAudioStream(int render_process_id, 60 int render_frame_id) {} 61 62 virtual ~Observer() {} 63 }; 64 65 static MediaCaptureDevicesDispatcher* GetInstance(); 66 67 // Registers the preferences related to Media Stream default devices. 68 static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); 69 70 // Methods for observers. Called on UI thread. 71 // Observers should add themselves on construction and remove themselves 72 // on destruction. 73 void AddObserver(Observer* observer); 74 void RemoveObserver(Observer* observer); 75 const content::MediaStreamDevices& GetAudioCaptureDevices(); 76 const content::MediaStreamDevices& GetVideoCaptureDevices(); 77 78 // Method called from WebCapturerDelegate implementations to process access 79 // requests. |extension| is set to NULL if request was made from a drive-by 80 // page. 81 void ProcessMediaAccessRequest( 82 content::WebContents* web_contents, 83 const content::MediaStreamRequest& request, 84 const content::MediaResponseCallback& callback, 85 const extensions::Extension* extension); 86 87 // Checks if we have media access permission. Note that this only checks the 88 // settings and does not query the user. 89 bool CheckMediaAccessPermission(content::BrowserContext* browser_context, 90 const GURL& security_origin, 91 content::MediaStreamType type); 92 93 // Method called from WebCapturerDelegate implementations to check media 94 // access permission. Note that this does not query the user. 95 bool CheckMediaAccessPermission(content::WebContents* web_contents, 96 const GURL& security_origin, 97 content::MediaStreamType type); 98 99 // Same as above but for an |extension|, which may not be NULL. 100#if defined(ENABLE_EXTENSIONS) 101 bool CheckMediaAccessPermission(content::WebContents* web_contents, 102 const GURL& security_origin, 103 content::MediaStreamType type, 104 const extensions::Extension* extension); 105#endif 106 107 // Helper to get the default devices which can be used by the media request. 108 // Uses the first available devices if the default devices are not available. 109 // If the return list is empty, it means there is no available device on the 110 // OS. 111 // Called on the UI thread. 112 void GetDefaultDevicesForProfile(Profile* profile, 113 bool audio, 114 bool video, 115 content::MediaStreamDevices* devices); 116 117 // Helpers for picking particular requested devices, identified by raw id. 118 // If the device requested is not available it will return NULL. 119 const content::MediaStreamDevice* 120 GetRequestedAudioDevice(const std::string& requested_audio_device_id); 121 const content::MediaStreamDevice* 122 GetRequestedVideoDevice(const std::string& requested_video_device_id); 123 124 // Returns the first available audio or video device, or NULL if no devices 125 // are available. 126 const content::MediaStreamDevice* GetFirstAvailableAudioDevice(); 127 const content::MediaStreamDevice* GetFirstAvailableVideoDevice(); 128 129 // Unittests that do not require actual device enumeration should call this 130 // API on the singleton. It is safe to call this multiple times on the 131 // signleton. 132 void DisableDeviceEnumerationForTesting(); 133 134 // Overridden from content::MediaObserver: 135 virtual void OnAudioCaptureDevicesChanged() OVERRIDE; 136 virtual void OnVideoCaptureDevicesChanged() OVERRIDE; 137 virtual void OnMediaRequestStateChanged( 138 int render_process_id, 139 int render_frame_id, 140 int page_request_id, 141 const GURL& security_origin, 142 content::MediaStreamType stream_type, 143 content::MediaRequestState state) OVERRIDE; 144 virtual void OnCreatingAudioStream(int render_process_id, 145 int render_frame_id) OVERRIDE; 146 147 scoped_refptr<MediaStreamCaptureIndicator> GetMediaStreamCaptureIndicator(); 148 149 DesktopStreamsRegistry* GetDesktopStreamsRegistry(); 150 151 bool IsDesktopCaptureInProgress(); 152 153 // Only for testing. 154 void SetTestAudioCaptureDevices(const content::MediaStreamDevices& devices); 155 void SetTestVideoCaptureDevices(const content::MediaStreamDevices& devices); 156 157 private: 158 friend struct DefaultSingletonTraits<MediaCaptureDevicesDispatcher>; 159 160 struct PendingAccessRequest { 161 PendingAccessRequest(const content::MediaStreamRequest& request, 162 const content::MediaResponseCallback& callback); 163 ~PendingAccessRequest(); 164 165 // TODO(gbillock): make the MediaStreamDevicesController owned by 166 // this object when we're using bubbles. 167 content::MediaStreamRequest request; 168 content::MediaResponseCallback callback; 169 }; 170 typedef std::deque<PendingAccessRequest> RequestsQueue; 171 typedef std::map<content::WebContents*, RequestsQueue> RequestsQueues; 172 173 MediaCaptureDevicesDispatcher(); 174 virtual ~MediaCaptureDevicesDispatcher(); 175 176 // content::NotificationObserver implementation. 177 virtual void Observe(int type, 178 const content::NotificationSource& source, 179 const content::NotificationDetails& details) OVERRIDE; 180 181 // Helpers for ProcessMediaAccessRequest(). 182 void ProcessDesktopCaptureAccessRequest( 183 content::WebContents* web_contents, 184 const content::MediaStreamRequest& request, 185 const content::MediaResponseCallback& callback, 186 const extensions::Extension* extension); 187 void ProcessScreenCaptureAccessRequest( 188 content::WebContents* web_contents, 189 const content::MediaStreamRequest& request, 190 const content::MediaResponseCallback& callback, 191 const extensions::Extension* extension); 192 void ProcessTabCaptureAccessRequest( 193 content::WebContents* web_contents, 194 const content::MediaStreamRequest& request, 195 const content::MediaResponseCallback& callback, 196 const extensions::Extension* extension); 197 void ProcessMediaAccessRequestFromPlatformAppOrExtension( 198 content::WebContents* web_contents, 199 const content::MediaStreamRequest& request, 200 const content::MediaResponseCallback& callback, 201 const extensions::Extension* extension); 202 void ProcessRegularMediaAccessRequest( 203 content::WebContents* web_contents, 204 const content::MediaStreamRequest& request, 205 const content::MediaResponseCallback& callback); 206 void ProcessQueuedAccessRequest(content::WebContents* web_contents); 207 void OnAccessRequestResponse(content::WebContents* web_contents, 208 const content::MediaStreamDevices& devices, 209 content::MediaStreamRequestResult result, 210 scoped_ptr<content::MediaStreamUI> ui); 211 212 // Called by the MediaObserver() functions, executed on UI thread. 213 void NotifyAudioDevicesChangedOnUIThread(); 214 void NotifyVideoDevicesChangedOnUIThread(); 215 void UpdateMediaRequestStateOnUIThread( 216 int render_process_id, 217 int render_frame_id, 218 int page_request_id, 219 const GURL& security_origin, 220 content::MediaStreamType stream_type, 221 content::MediaRequestState state); 222 void OnCreatingAudioStreamOnUIThread(int render_process_id, 223 int render_frame_id); 224 225 // Only for testing, a list of cached audio capture devices. 226 content::MediaStreamDevices test_audio_devices_; 227 228 // Only for testing, a list of cached video capture devices. 229 content::MediaStreamDevices test_video_devices_; 230 231 // A list of observers for the device update notifications. 232 ObserverList<Observer> observers_; 233 234 // Flag used by unittests to disable device enumeration. 235 bool is_device_enumeration_disabled_; 236 237 RequestsQueues pending_requests_; 238 239 scoped_refptr<MediaStreamCaptureIndicator> media_stream_capture_indicator_; 240 241 scoped_ptr<DesktopStreamsRegistry> desktop_streams_registry_; 242 243 content::NotificationRegistrar notifications_registrar_; 244 245 // Tracks MEDIA_DESKTOP_VIDEO_CAPTURE sessions which reach the 246 // MEDIA_REQUEST_STATE_DONE state. Sessions are remove when 247 // MEDIA_REQUEST_STATE_CLOSING is encountered. 248 struct DesktopCaptureSession { 249 int render_process_id; 250 int render_frame_id; 251 int page_request_id; 252 }; 253 typedef std::list<DesktopCaptureSession> DesktopCaptureSessions; 254 DesktopCaptureSessions desktop_capture_sessions_; 255 256 DISALLOW_COPY_AND_ASSIGN(MediaCaptureDevicesDispatcher); 257}; 258 259#endif // CHROME_BROWSER_MEDIA_MEDIA_CAPTURE_DEVICES_DISPATCHER_H_ 260