1 // Copyright 2013 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_EXTENSIONS_API_WEBRTC_AUDIO_PRIVATE_WEBRTC_AUDIO_PRIVATE_API_H_ 6 #define CHROME_BROWSER_EXTENSIONS_API_WEBRTC_AUDIO_PRIVATE_WEBRTC_AUDIO_PRIVATE_API_H_ 7 8 #include "base/memory/ref_counted.h" 9 #include "base/system_monitor/system_monitor.h" 10 #include "chrome/browser/extensions/chrome_extension_function.h" 11 #include "chrome/common/extensions/api/webrtc_audio_private.h" 12 #include "content/public/browser/render_view_host.h" 13 #include "extensions/browser/browser_context_keyed_api_factory.h" 14 #include "media/audio/audio_device_name.h" 15 #include "url/gurl.h" 16 17 namespace content { 18 class ResourceContext; 19 } 20 21 namespace extensions { 22 23 // Listens for device changes and forwards as an extension event. 24 class WebrtcAudioPrivateEventService 25 : public BrowserContextKeyedAPI, 26 public base::SystemMonitor::DevicesChangedObserver { 27 public: 28 explicit WebrtcAudioPrivateEventService(content::BrowserContext* context); 29 virtual ~WebrtcAudioPrivateEventService(); 30 31 // BrowserContextKeyedAPI implementation. 32 virtual void Shutdown() OVERRIDE; 33 static BrowserContextKeyedAPIFactory<WebrtcAudioPrivateEventService>* 34 GetFactoryInstance(); 35 static const char* service_name(); 36 37 // base::SystemMonitor::DevicesChangedObserver implementation. 38 virtual void OnDevicesChanged( 39 base::SystemMonitor::DeviceType device_type) OVERRIDE; 40 41 private: 42 friend class BrowserContextKeyedAPIFactory<WebrtcAudioPrivateEventService>; 43 44 void SignalEvent(); 45 46 content::BrowserContext* browser_context_; 47 }; 48 49 // Common base for WebrtcAudioPrivate functions, that provides a 50 // couple of optionally-used common implementations. 51 class WebrtcAudioPrivateFunction : public ChromeAsyncExtensionFunction { 52 protected: 53 WebrtcAudioPrivateFunction(); 54 virtual ~WebrtcAudioPrivateFunction(); 55 56 protected: 57 // Retrieves the list of output device names on the appropriate 58 // thread. Call from UI thread, callback will occur on IO thread. 59 void GetOutputDeviceNames(); 60 61 // Must override this if you call GetOutputDeviceNames. Called on IO thread. 62 virtual void OnOutputDeviceNames( 63 scoped_ptr<media::AudioDeviceNames> device_names); 64 65 // Retrieve the list of AudioOutputController objects. Calls back 66 // via OnControllerList. 67 // 68 // Returns false on error, in which case it has set |error_| and the 69 // entire function should fail. 70 // 71 // Call from any thread. Callback will occur on originating thread. 72 bool GetControllerList(int tab_id); 73 74 // Must override this if you call GetControllerList. 75 virtual void OnControllerList( 76 const content::RenderViewHost::AudioOutputControllerList& list); 77 78 // Calculates a single HMAC. Call from any thread. Calls back via 79 // OnHMACCalculated on UI thread. 80 // 81 // This function, and device ID HMACs in this API in general use the 82 // calling extension's ID as the security origin. The only exception 83 // to this rule is when calculating the input device ID HMAC in 84 // getAssociatedSink, where we use the provided |securityOrigin|. 85 void CalculateHMAC(const std::string& raw_id); 86 87 // Must override this if you call CalculateHMAC. 88 virtual void OnHMACCalculated(const std::string& hmac); 89 90 // Calculates a single HMAC, using the extension ID as the security origin. 91 // 92 // Call only on IO thread. 93 std::string CalculateHMACImpl(const std::string& raw_id); 94 95 // Initializes |resource_context_|. Must be called on the UI thread, 96 // before any calls to |resource_context()|. 97 void InitResourceContext(); 98 99 // Callable from any thread. Must previously have called 100 // |InitResourceContext()|. 101 content::ResourceContext* resource_context() const; 102 103 private: 104 content::ResourceContext* resource_context_; 105 106 DISALLOW_COPY_AND_ASSIGN(WebrtcAudioPrivateFunction); 107 }; 108 109 class WebrtcAudioPrivateGetSinksFunction : public WebrtcAudioPrivateFunction { 110 protected: 111 virtual ~WebrtcAudioPrivateGetSinksFunction() {} 112 113 private: 114 DECLARE_EXTENSION_FUNCTION("webrtcAudioPrivate.getSinks", 115 WEBRTC_AUDIO_PRIVATE_GET_SINKS); 116 117 // Sequence of events is that we query the list of sinks on the 118 // AudioManager's thread, then calculate HMACs on the IO thread, 119 // then finish on the UI thread. 120 virtual bool RunAsync() OVERRIDE; 121 void DoQuery(); 122 virtual void OnOutputDeviceNames( 123 scoped_ptr<media::AudioDeviceNames> raw_ids) OVERRIDE; 124 void DoneOnUIThread(); 125 }; 126 127 class WebrtcAudioPrivateGetActiveSinkFunction 128 : public WebrtcAudioPrivateFunction { 129 protected: 130 virtual ~WebrtcAudioPrivateGetActiveSinkFunction() {} 131 132 private: 133 DECLARE_EXTENSION_FUNCTION("webrtcAudioPrivate.getActiveSink", 134 WEBRTC_AUDIO_PRIVATE_GET_ACTIVE_SINK); 135 136 virtual bool RunAsync() OVERRIDE; 137 virtual void OnControllerList( 138 const content::RenderViewHost::AudioOutputControllerList& 139 controllers) OVERRIDE; 140 virtual void OnHMACCalculated(const std::string& hmac) OVERRIDE; 141 }; 142 143 class WebrtcAudioPrivateSetActiveSinkFunction 144 : public WebrtcAudioPrivateFunction { 145 public: 146 WebrtcAudioPrivateSetActiveSinkFunction(); 147 148 protected: 149 virtual ~WebrtcAudioPrivateSetActiveSinkFunction(); 150 151 private: 152 DECLARE_EXTENSION_FUNCTION("webrtcAudioPrivate.setActiveSink", 153 WEBRTC_AUDIO_PRIVATE_SET_ACTIVE_SINK); 154 155 virtual bool RunAsync() OVERRIDE; 156 virtual void OnControllerList( 157 const content::RenderViewHost::AudioOutputControllerList& 158 controllers) OVERRIDE; 159 virtual void OnOutputDeviceNames( 160 scoped_ptr<media::AudioDeviceNames> device_names) OVERRIDE; 161 void SwitchDone(); 162 void DoneOnUIThread(); 163 164 int tab_id_; 165 std::string sink_id_; 166 167 // Filled in by OnControllerList. 168 content::RenderViewHost::AudioOutputControllerList controllers_; 169 170 // Number of sink IDs we are still waiting for. Can become greater 171 // than 0 in OnControllerList, decreases on every OnSinkId call. 172 size_t num_remaining_sink_ids_; 173 }; 174 175 class WebrtcAudioPrivateGetAssociatedSinkFunction 176 : public WebrtcAudioPrivateFunction { 177 public: 178 WebrtcAudioPrivateGetAssociatedSinkFunction(); 179 180 protected: 181 virtual ~WebrtcAudioPrivateGetAssociatedSinkFunction(); 182 183 private: 184 DECLARE_EXTENSION_FUNCTION("webrtcAudioPrivate.getAssociatedSink", 185 WEBRTC_AUDIO_PRIVATE_GET_ASSOCIATED_SINK); 186 187 virtual bool RunAsync() OVERRIDE; 188 189 // This implementation is slightly complicated because of different 190 // thread requirements for the various functions we need to invoke. 191 // 192 // Each worker function will post a task to the appropriate thread 193 // for the next one. 194 // 195 // The sequence of events is: 196 // 1. Get the list of source devices on the device thread. 197 // 2. Given a source ID for an origin and that security origin, find 198 // the raw source ID. This needs to happen on the IO thread since 199 // we will be using the ResourceContext. 200 // 3. Given a raw source ID, get the raw associated sink ID on the 201 // device thread. 202 // 4. Given the raw associated sink ID, get its HMAC on the IO thread. 203 // 5. Respond with the HMAC of the associated sink ID on the UI thread. 204 205 // Fills in |source_devices_|. Note that these are input devices, 206 // not output devices, so don't use 207 // |WebrtcAudioPrivateFunction::GetOutputDeviceNames|. 208 void GetDevicesOnDeviceThread(); 209 210 // Takes the parameters of the function, retrieves the raw source 211 // device ID, or the empty string if none. 212 void GetRawSourceIDOnIOThread(); 213 214 // Gets the raw sink ID for a raw source ID. Sends it to |CalculateHMAC|. 215 void GetAssociatedSinkOnDeviceThread(const std::string& raw_source_id); 216 217 // Receives the associated sink ID after its HMAC is calculated. 218 virtual void OnHMACCalculated(const std::string& hmac) OVERRIDE; 219 220 // Accessed from UI thread and device thread, but only on one at a 221 // time, no locking needed. 222 scoped_ptr<api::webrtc_audio_private::GetAssociatedSink::Params> params_; 223 224 // Audio sources (input devices). Filled in by DoWorkOnDeviceThread. 225 media::AudioDeviceNames source_devices_; 226 }; 227 228 } // namespace extensions 229 230 #endif // CHROME_BROWSER_EXTENSIONS_API_WEBRTC_AUDIO_PRIVATE_WEBRTC_AUDIO_PRIVATE_API_H_ 231