Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Side by Side Diff: chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc

Issue 2791203002: Switching WebRtc private API from AudioManager to AudioSystem (Closed)
Patch Set: Review comments addressed Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_privat e_api.h" 5 #include "chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_privat e_api.h"
6 6
7 #include <utility> 7 #include <utility>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/lazy_instance.h" 10 #include "base/lazy_instance.h"
11 #include "base/memory/ptr_util.h" 11 #include "base/memory/ptr_util.h"
12 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_number_conversions.h"
13 #include "base/task_runner_util.h" 13 #include "base/task_runner_util.h"
14 #include "chrome/browser/extensions/api/tabs/tabs_constants.h" 14 #include "chrome/browser/extensions/api/tabs/tabs_constants.h"
15 #include "chrome/browser/extensions/extension_tab_util.h" 15 #include "chrome/browser/extensions/extension_tab_util.h"
16 #include "chrome/browser/profiles/profile.h" 16 #include "chrome/browser/profiles/profile.h"
17 #include "content/public/browser/media_device_id.h" 17 #include "content/public/browser/media_device_id.h"
18 #include "content/public/browser/web_contents.h" 18 #include "content/public/browser/web_contents.h"
19 #include "extensions/browser/event_router.h" 19 #include "extensions/browser/event_router.h"
20 #include "extensions/browser/extension_registry.h" 20 #include "extensions/browser/extension_registry.h"
21 #include "extensions/common/error_utils.h" 21 #include "extensions/common/error_utils.h"
22 #include "extensions/common/permissions/permissions_data.h" 22 #include "extensions/common/permissions/permissions_data.h"
23 #include "media/audio/audio_device_description.h" 23 #include "media/audio/audio_system.h"
24 #include "url/gurl.h" 24 #include "url/gurl.h"
25 #include "url/origin.h" 25 #include "url/origin.h"
26 26
27 namespace extensions { 27 namespace extensions {
28 28
29 using content::BrowserThread; 29 using content::BrowserThread;
30 using content::RenderProcessHost;
31 using media::AudioDeviceDescriptions;
32 using media::AudioManager;
33
34 namespace wap = api::webrtc_audio_private; 30 namespace wap = api::webrtc_audio_private;
35 31
36 static base::LazyInstance<BrowserContextKeyedAPIFactory< 32 static base::LazyInstance<BrowserContextKeyedAPIFactory<
37 WebrtcAudioPrivateEventService>>::DestructorAtExit g_factory = 33 WebrtcAudioPrivateEventService>>::DestructorAtExit g_factory =
38 LAZY_INSTANCE_INITIALIZER; 34 LAZY_INSTANCE_INITIALIZER;
39 35
40 WebrtcAudioPrivateEventService::WebrtcAudioPrivateEventService( 36 WebrtcAudioPrivateEventService::WebrtcAudioPrivateEventService(
41 content::BrowserContext* context) 37 content::BrowserContext* context)
42 : browser_context_(context) { 38 : browser_context_(context) {
43 // In unit tests, the SystemMonitor may not be created. 39 // In unit tests, the SystemMonitor may not be created.
(...skipping 23 matching lines...) Expand all
67 return "WebrtcAudioPrivateEventService"; 63 return "WebrtcAudioPrivateEventService";
68 } 64 }
69 65
70 void WebrtcAudioPrivateEventService::OnDevicesChanged( 66 void WebrtcAudioPrivateEventService::OnDevicesChanged(
71 base::SystemMonitor::DeviceType device_type) { 67 base::SystemMonitor::DeviceType device_type) {
72 switch (device_type) { 68 switch (device_type) {
73 case base::SystemMonitor::DEVTYPE_AUDIO: 69 case base::SystemMonitor::DEVTYPE_AUDIO:
74 case base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE: 70 case base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE:
75 SignalEvent(); 71 SignalEvent();
76 break; 72 break;
77
78 default: 73 default:
79 // No action needed. 74 // No action needed.
80 break; 75 break;
81 } 76 }
82 } 77 }
83 78
84 void WebrtcAudioPrivateEventService::SignalEvent() { 79 void WebrtcAudioPrivateEventService::SignalEvent() {
85 using api::webrtc_audio_private::OnSinksChanged::kEventName; 80 using api::webrtc_audio_private::OnSinksChanged::kEventName;
86 81
87 EventRouter* router = EventRouter::Get(browser_context_); 82 EventRouter* router = EventRouter::Get(browser_context_);
88 if (!router || !router->HasEventListener(kEventName)) 83 if (!router || !router->HasEventListener(kEventName))
89 return; 84 return;
90 85
91 for (const scoped_refptr<const extensions::Extension>& extension : 86 for (const scoped_refptr<const extensions::Extension>& extension :
92 ExtensionRegistry::Get(browser_context_)->enabled_extensions()) { 87 ExtensionRegistry::Get(browser_context_)->enabled_extensions()) {
93 const std::string& extension_id = extension->id(); 88 const std::string& extension_id = extension->id();
94 if (router->ExtensionHasEventListener(extension_id, kEventName) && 89 if (router->ExtensionHasEventListener(extension_id, kEventName) &&
95 extension->permissions_data()->HasAPIPermission("webrtcAudioPrivate")) { 90 extension->permissions_data()->HasAPIPermission("webrtcAudioPrivate")) {
96 std::unique_ptr<Event> event = base::MakeUnique<Event>( 91 std::unique_ptr<Event> event = base::MakeUnique<Event>(
97 events::WEBRTC_AUDIO_PRIVATE_ON_SINKS_CHANGED, kEventName, 92 events::WEBRTC_AUDIO_PRIVATE_ON_SINKS_CHANGED, kEventName,
98 base::MakeUnique<base::ListValue>()); 93 base::MakeUnique<base::ListValue>());
99 router->DispatchEventToExtension(extension_id, std::move(event)); 94 router->DispatchEventToExtension(extension_id, std::move(event));
100 } 95 }
101 } 96 }
102 } 97 }
103 98
104 WebrtcAudioPrivateFunction::WebrtcAudioPrivateFunction() {} 99 WebrtcAudioPrivateFunction::WebrtcAudioPrivateFunction() {}
105 100
106 WebrtcAudioPrivateFunction::~WebrtcAudioPrivateFunction() { 101 WebrtcAudioPrivateFunction::~WebrtcAudioPrivateFunction() {}
107 }
108 102
109 void WebrtcAudioPrivateFunction::GetOutputDeviceDescriptions() { 103 std::string WebrtcAudioPrivateFunction::CalculateHMAC(
110 scoped_refptr<base::SingleThreadTaskRunner> audio_manager_runner =
111 AudioManager::Get()->GetTaskRunner();
112 if (!audio_manager_runner->BelongsToCurrentThread()) {
113 DCHECK_CURRENTLY_ON(BrowserThread::UI);
114 audio_manager_runner->PostTask(
115 FROM_HERE,
116 base::Bind(&WebrtcAudioPrivateFunction::GetOutputDeviceDescriptions,
117 this));
118 return;
119 }
120
121 std::unique_ptr<AudioDeviceDescriptions> device_descriptions =
122 base::MakeUnique<AudioDeviceDescriptions>();
123 AudioManager::Get()->GetAudioOutputDeviceDescriptions(
124 device_descriptions.get());
125
126 BrowserThread::PostTask(
127 BrowserThread::IO, FROM_HERE,
128 base::Bind(&WebrtcAudioPrivateFunction::OnOutputDeviceDescriptions, this,
129 base::Passed(&device_descriptions)));
130 }
131
132 void WebrtcAudioPrivateFunction::OnOutputDeviceDescriptions(
133 std::unique_ptr<AudioDeviceDescriptions> device_descriptions) {
134 NOTREACHED();
135 }
136
137 void WebrtcAudioPrivateFunction::CalculateHMAC(const std::string& raw_id) {
138 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
139 BrowserThread::PostTask(
140 BrowserThread::IO,
141 FROM_HERE,
142 base::Bind(&WebrtcAudioPrivateFunction::CalculateHMAC, this, raw_id));
143 return;
144 }
145
146 std::string hmac = CalculateHMACImpl(raw_id);
147 BrowserThread::PostTask(
148 BrowserThread::UI,
149 FROM_HERE,
150 base::Bind(&WebrtcAudioPrivateFunction::OnHMACCalculated, this, hmac));
151 }
152
153 void WebrtcAudioPrivateFunction::OnHMACCalculated(const std::string& hmac) {
154 NOTREACHED();
155 }
156
157 std::string WebrtcAudioPrivateFunction::CalculateHMACImpl(
158 const std::string& raw_id) { 104 const std::string& raw_id) {
159 DCHECK_CURRENTLY_ON(BrowserThread::IO); 105 DCHECK_CURRENTLY_ON(BrowserThread::IO);
160 106
161 // We don't hash the default device description, and we always return 107 // We don't hash the default device description, and we always return
162 // "default" for the default device. There is code in SetActiveSink 108 // "default" for the default device. There is code in SetActiveSink
163 // that transforms "default" to the empty string, and code in 109 // that transforms "default" to the empty string, and code in
164 // GetActiveSink that ensures we return "default" if we get the 110 // GetActiveSink that ensures we return "default" if we get the
165 // empty string as the current device ID. 111 // empty string as the current device ID.
166 if (media::AudioDeviceDescription::IsDefaultDevice(raw_id)) 112 if (media::AudioDeviceDescription::IsDefaultDevice(raw_id))
167 return media::AudioDeviceDescription::kDefaultDeviceId; 113 return media::AudioDeviceDescription::kDefaultDeviceId;
168 114
169 url::Origin security_origin(source_url().GetOrigin()); 115 url::Origin security_origin(source_url().GetOrigin());
170 return content::GetHMACForMediaDeviceID(device_id_salt(), security_origin, 116 return content::GetHMACForMediaDeviceID(device_id_salt(), security_origin,
171 raw_id); 117 raw_id);
172 } 118 }
173 119
174 void WebrtcAudioPrivateFunction::InitDeviceIDSalt() { 120 void WebrtcAudioPrivateFunction::InitDeviceIDSalt() {
175 device_id_salt_ = GetProfile()->GetResourceContext()->GetMediaDeviceIDSalt(); 121 device_id_salt_ = GetProfile()->GetResourceContext()->GetMediaDeviceIDSalt();
176 } 122 }
177 123
178 std::string WebrtcAudioPrivateFunction::device_id_salt() const { 124 std::string WebrtcAudioPrivateFunction::device_id_salt() const {
179 return device_id_salt_; 125 return device_id_salt_;
180 } 126 }
181 127
182 bool WebrtcAudioPrivateGetSinksFunction::RunAsync() { 128 bool WebrtcAudioPrivateGetSinksFunction::RunAsync() {
183 DCHECK_CURRENTLY_ON(BrowserThread::UI); 129 DCHECK_CURRENTLY_ON(BrowserThread::UI);
184
185 InitDeviceIDSalt(); 130 InitDeviceIDSalt();
186 GetOutputDeviceDescriptions(); 131 BrowserThread::PostTask(
187 132 BrowserThread::IO, FROM_HERE,
133 base::Bind(
134 &WebrtcAudioPrivateGetSinksFunction::GetOutputDeviceDescriptions,
135 this));
188 return true; 136 return true;
189 } 137 }
190 138
139 void WebrtcAudioPrivateGetSinksFunction::GetOutputDeviceDescriptions() {
140 DCHECK_CURRENTLY_ON(BrowserThread::IO);
141 media::AudioSystem::Get()->GetDeviceDescriptions(
142 base::Bind(
143 &WebrtcAudioPrivateGetSinksFunction::OnOutputDeviceDescriptions,
144 this),
145 false);
146 }
147
191 void WebrtcAudioPrivateGetSinksFunction::OnOutputDeviceDescriptions( 148 void WebrtcAudioPrivateGetSinksFunction::OnOutputDeviceDescriptions(
192 std::unique_ptr<AudioDeviceDescriptions> raw_ids) { 149 media::AudioDeviceDescriptions sink_devices) {
193 DCHECK_CURRENTLY_ON(BrowserThread::IO); 150 DCHECK_CURRENTLY_ON(BrowserThread::IO);
194 151 auto results = base::MakeUnique<SinkInfoVector>();
195 std::vector<wap::SinkInfo> results; 152 for (const media::AudioDeviceDescription& description : sink_devices) {
196 for (const media::AudioDeviceDescription& description : *raw_ids) {
197 wap::SinkInfo info; 153 wap::SinkInfo info;
198 info.sink_id = CalculateHMACImpl(description.unique_id); 154 info.sink_id = CalculateHMAC(description.unique_id);
199 info.sink_label = description.device_name; 155 info.sink_label = description.device_name;
200 // TODO(joi): Add other parameters. 156 // TODO(joi): Add other parameters.
201 results.push_back(std::move(info)); 157 results->push_back(std::move(info));
202 } 158 }
203
204 // It's safe to directly set the results here (from a thread other
205 // than the UI thread, on which an AsyncExtensionFunction otherwise
206 // normally runs) because there is one instance of this object per
207 // function call, no actor outside of this object is modifying the
208 // results_ member, and the different method invocations on this
209 // object run strictly in sequence; first RunAsync on the UI thread,
210 // then DoQuery on the audio IO thread, then DoneOnUIThread on the
211 // UI thread.
212 results_ = wap::GetSinks::Results::Create(results);
213
214 BrowserThread::PostTask( 159 BrowserThread::PostTask(
215 BrowserThread::UI, 160 BrowserThread::UI, FROM_HERE,
216 FROM_HERE, 161 base::Bind(&WebrtcAudioPrivateGetSinksFunction::DoneOnUIThread, this,
217 base::Bind(&WebrtcAudioPrivateGetSinksFunction::DoneOnUIThread, this)); 162 base::Passed(&results)));
218 } 163 }
219 164
220 void WebrtcAudioPrivateGetSinksFunction::DoneOnUIThread() { 165 void WebrtcAudioPrivateGetSinksFunction::DoneOnUIThread(
166 std::unique_ptr<SinkInfoVector> results) {
167 DCHECK_CURRENTLY_ON(BrowserThread::UI);
168 results_ = wap::GetSinks::Results::Create(*results);
221 SendResponse(true); 169 SendResponse(true);
222 } 170 }
223 171
224 WebrtcAudioPrivateGetAssociatedSinkFunction:: 172 WebrtcAudioPrivateGetAssociatedSinkFunction::
225 WebrtcAudioPrivateGetAssociatedSinkFunction() { 173 WebrtcAudioPrivateGetAssociatedSinkFunction() {}
226 }
227 174
228 WebrtcAudioPrivateGetAssociatedSinkFunction:: 175 WebrtcAudioPrivateGetAssociatedSinkFunction::
229 ~WebrtcAudioPrivateGetAssociatedSinkFunction() { 176 ~WebrtcAudioPrivateGetAssociatedSinkFunction() {}
230 }
231 177
232 bool WebrtcAudioPrivateGetAssociatedSinkFunction::RunAsync() { 178 bool WebrtcAudioPrivateGetAssociatedSinkFunction::RunAsync() {
233 params_ = wap::GetAssociatedSink::Params::Create(*args_); 179 params_ = wap::GetAssociatedSink::Params::Create(*args_);
234 DCHECK_CURRENTLY_ON(BrowserThread::UI); 180 DCHECK_CURRENTLY_ON(BrowserThread::UI);
235 EXTENSION_FUNCTION_VALIDATE(params_.get()); 181 EXTENSION_FUNCTION_VALIDATE(params_.get());
236
237 InitDeviceIDSalt(); 182 InitDeviceIDSalt();
238 183
239 AudioManager::Get()->GetTaskRunner()->PostTask( 184 BrowserThread::PostTask(
240 FROM_HERE, 185 BrowserThread::IO, FROM_HERE,
241 base::Bind(&WebrtcAudioPrivateGetAssociatedSinkFunction:: 186 base::Bind(&WebrtcAudioPrivateGetAssociatedSinkFunction::
242 GetDevicesOnDeviceThread, this)); 187 GetInputDeviceDescriptions,
188 this));
243 189
244 return true; 190 return true;
245 } 191 }
246 192
247 void WebrtcAudioPrivateGetAssociatedSinkFunction::GetDevicesOnDeviceThread() { 193 void WebrtcAudioPrivateGetAssociatedSinkFunction::GetInputDeviceDescriptions() {
248 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 194 DCHECK_CURRENTLY_ON(BrowserThread::IO);
249 AudioManager::Get()->GetAudioInputDeviceDescriptions(&source_devices_); 195 media::AudioSystem::Get()->GetDeviceDescriptions(
250
251 BrowserThread::PostTask(
252 BrowserThread::IO,
253 FROM_HERE,
254 base::Bind(&WebrtcAudioPrivateGetAssociatedSinkFunction:: 196 base::Bind(&WebrtcAudioPrivateGetAssociatedSinkFunction::
255 GetRawSourceIDOnIOThread, 197 OnInputDeviceDescriptions,
256 this)); 198 this),
199 true);
257 } 200 }
258 201
259 void 202 void WebrtcAudioPrivateGetAssociatedSinkFunction::OnInputDeviceDescriptions(
260 WebrtcAudioPrivateGetAssociatedSinkFunction::GetRawSourceIDOnIOThread() { 203 media::AudioDeviceDescriptions source_devices) {
261 DCHECK_CURRENTLY_ON(BrowserThread::IO); 204 DCHECK_CURRENTLY_ON(BrowserThread::IO);
262
263 url::Origin security_origin(GURL(params_->security_origin)); 205 url::Origin security_origin(GURL(params_->security_origin));
264 std::string source_id_in_origin(params_->source_id_in_origin); 206 std::string source_id_in_origin(params_->source_id_in_origin);
265 207
266 // Find the raw source ID for source_id_in_origin. 208 // Find the raw source ID for source_id_in_origin.
267 std::string raw_source_id; 209 std::string raw_source_id;
268 for (AudioDeviceDescriptions::const_iterator it = source_devices_.begin(); 210 for (const auto& device : source_devices) {
269 it != source_devices_.end(); ++it) {
270 const std::string& id = it->unique_id;
271 if (content::DoesMediaDeviceIDMatchHMAC(device_id_salt(), security_origin, 211 if (content::DoesMediaDeviceIDMatchHMAC(device_id_salt(), security_origin,
272 source_id_in_origin, id)) { 212 source_id_in_origin,
273 raw_source_id = id; 213 device.unique_id)) {
214 raw_source_id = device.unique_id;
274 DVLOG(2) << "Found raw ID " << raw_source_id 215 DVLOG(2) << "Found raw ID " << raw_source_id
275 << " for source ID in origin " << source_id_in_origin; 216 << " for source ID in origin " << source_id_in_origin;
276 break; 217 break;
277 } 218 }
278 } 219 }
279 220 if (raw_source_id.empty()) {
280 AudioManager::Get()->GetTaskRunner()->PostTask( 221 CalculateHMACAndReplyOnUIThread(std::string());
281 FROM_HERE, 222 return;
282 base::Bind(&WebrtcAudioPrivateGetAssociatedSinkFunction:: 223 }
283 GetAssociatedSinkOnDeviceThread, 224 media::AudioSystem::Get()->GetAssociatedOutputDeviceID(
284 this, 225 raw_source_id, base::Bind(&WebrtcAudioPrivateGetAssociatedSinkFunction::
285 raw_source_id)); 226 CalculateHMACAndReplyOnUIThread,
227 this));
286 } 228 }
287 229
288 void 230 void WebrtcAudioPrivateGetAssociatedSinkFunction::
289 WebrtcAudioPrivateGetAssociatedSinkFunction::GetAssociatedSinkOnDeviceThread( 231 CalculateHMACAndReplyOnUIThread(const std::string& raw_sink_id) {
Guido Urdaneta 2017/04/06 13:52:42 Normally the OnXXThread prefix is used to indicate
290 const std::string& raw_source_id) { 232 DCHECK_CURRENTLY_ON(BrowserThread::IO);
291 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 233 BrowserThread::PostTask(
292 234 BrowserThread::UI, FROM_HERE,
293 // We return an empty string if there is no associated output device. 235 base::Bind(&WebrtcAudioPrivateGetAssociatedSinkFunction::OnHMACCalculated,
294 std::string raw_sink_id; 236 this, CalculateHMAC(raw_sink_id)));
295 if (!raw_source_id.empty()) {
296 raw_sink_id =
297 AudioManager::Get()->GetAssociatedOutputDeviceID(raw_source_id);
298 }
299
300 CalculateHMAC(raw_sink_id);
301 } 237 }
302 238
303 void WebrtcAudioPrivateGetAssociatedSinkFunction::OnHMACCalculated( 239 void WebrtcAudioPrivateGetAssociatedSinkFunction::OnHMACCalculated(
304 const std::string& associated_sink_id) { 240 const std::string& associated_sink_id) {
305 DCHECK_CURRENTLY_ON(BrowserThread::UI); 241 DCHECK_CURRENTLY_ON(BrowserThread::UI);
306
307 if (associated_sink_id == media::AudioDeviceDescription::kDefaultDeviceId) { 242 if (associated_sink_id == media::AudioDeviceDescription::kDefaultDeviceId) {
308 DVLOG(2) << "Got default ID, replacing with empty ID."; 243 DVLOG(2) << "Got default ID, replacing with empty ID.";
309 results_ = wap::GetAssociatedSink::Results::Create(""); 244 results_ = wap::GetAssociatedSink::Results::Create("");
310 } else { 245 } else {
311 results_ = wap::GetAssociatedSink::Results::Create(associated_sink_id); 246 results_ = wap::GetAssociatedSink::Results::Create(associated_sink_id);
312 } 247 }
313
314 SendResponse(true); 248 SendResponse(true);
315 } 249 }
316 250
317 } // namespace extensions 251 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698