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

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: rebase 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 <memory> 7 #include <memory>
8 #include <utility> 8 #include <utility>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/lazy_instance.h" 11 #include "base/lazy_instance.h"
12 #include "base/memory/ptr_util.h" 12 #include "base/memory/ptr_util.h"
13 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/stringprintf.h" 14 #include "base/strings/stringprintf.h"
15 #include "base/task_runner_util.h" 15 #include "base/task_runner_util.h"
16 #include "chrome/browser/extensions/api/tabs/tabs_constants.h" 16 #include "chrome/browser/extensions/api/tabs/tabs_constants.h"
17 #include "chrome/browser/extensions/extension_tab_util.h" 17 #include "chrome/browser/extensions/extension_tab_util.h"
18 #include "chrome/browser/profiles/profile.h" 18 #include "chrome/browser/profiles/profile.h"
19 #include "content/public/browser/media_device_id.h" 19 #include "content/public/browser/media_device_id.h"
20 #include "content/public/browser/web_contents.h" 20 #include "content/public/browser/web_contents.h"
21 #include "extensions/browser/event_router.h" 21 #include "extensions/browser/event_router.h"
22 #include "extensions/browser/extension_registry.h" 22 #include "extensions/browser/extension_registry.h"
23 #include "extensions/common/error_utils.h" 23 #include "extensions/common/error_utils.h"
24 #include "extensions/common/permissions/permissions_data.h" 24 #include "extensions/common/permissions/permissions_data.h"
25 #include "media/audio/audio_device_description.h" 25 #include "media/audio/audio_system.h"
26 #include "url/gurl.h" 26 #include "url/gurl.h"
27 #include "url/origin.h" 27 #include "url/origin.h"
28 28
29 namespace extensions { 29 namespace extensions {
30 30
31 using content::BrowserThread; 31 using content::BrowserThread;
32 using content::RenderProcessHost;
33 using media::AudioDeviceDescriptions;
34 using media::AudioManager;
35
36 namespace wap = api::webrtc_audio_private; 32 namespace wap = api::webrtc_audio_private;
37 33
38 using api::webrtc_audio_private::RequestInfo; 34 using api::webrtc_audio_private::RequestInfo;
39 35
40 static base::LazyInstance<BrowserContextKeyedAPIFactory< 36 static base::LazyInstance<BrowserContextKeyedAPIFactory<
41 WebrtcAudioPrivateEventService>>::DestructorAtExit g_factory = 37 WebrtcAudioPrivateEventService>>::DestructorAtExit g_factory =
42 LAZY_INSTANCE_INITIALIZER; 38 LAZY_INSTANCE_INITIALIZER;
43 39
44 WebrtcAudioPrivateEventService::WebrtcAudioPrivateEventService( 40 WebrtcAudioPrivateEventService::WebrtcAudioPrivateEventService(
45 content::BrowserContext* context) 41 content::BrowserContext* context)
(...skipping 25 matching lines...) Expand all
71 return "WebrtcAudioPrivateEventService"; 67 return "WebrtcAudioPrivateEventService";
72 } 68 }
73 69
74 void WebrtcAudioPrivateEventService::OnDevicesChanged( 70 void WebrtcAudioPrivateEventService::OnDevicesChanged(
75 base::SystemMonitor::DeviceType device_type) { 71 base::SystemMonitor::DeviceType device_type) {
76 switch (device_type) { 72 switch (device_type) {
77 case base::SystemMonitor::DEVTYPE_AUDIO: 73 case base::SystemMonitor::DEVTYPE_AUDIO:
78 case base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE: 74 case base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE:
79 SignalEvent(); 75 SignalEvent();
80 break; 76 break;
81
82 default: 77 default:
83 // No action needed. 78 // No action needed.
84 break; 79 break;
85 } 80 }
86 } 81 }
87 82
88 void WebrtcAudioPrivateEventService::SignalEvent() { 83 void WebrtcAudioPrivateEventService::SignalEvent() {
89 using api::webrtc_audio_private::OnSinksChanged::kEventName; 84 using api::webrtc_audio_private::OnSinksChanged::kEventName;
90 85
91 EventRouter* router = EventRouter::Get(browser_context_); 86 EventRouter* router = EventRouter::Get(browser_context_);
92 if (!router || !router->HasEventListener(kEventName)) 87 if (!router || !router->HasEventListener(kEventName))
93 return; 88 return;
94 89
95 for (const scoped_refptr<const extensions::Extension>& extension : 90 for (const scoped_refptr<const extensions::Extension>& extension :
96 ExtensionRegistry::Get(browser_context_)->enabled_extensions()) { 91 ExtensionRegistry::Get(browser_context_)->enabled_extensions()) {
97 const std::string& extension_id = extension->id(); 92 const std::string& extension_id = extension->id();
98 if (router->ExtensionHasEventListener(extension_id, kEventName) && 93 if (router->ExtensionHasEventListener(extension_id, kEventName) &&
99 extension->permissions_data()->HasAPIPermission("webrtcAudioPrivate")) { 94 extension->permissions_data()->HasAPIPermission("webrtcAudioPrivate")) {
100 std::unique_ptr<Event> event = base::MakeUnique<Event>( 95 std::unique_ptr<Event> event = base::MakeUnique<Event>(
101 events::WEBRTC_AUDIO_PRIVATE_ON_SINKS_CHANGED, kEventName, 96 events::WEBRTC_AUDIO_PRIVATE_ON_SINKS_CHANGED, kEventName,
102 base::MakeUnique<base::ListValue>()); 97 base::MakeUnique<base::ListValue>());
103 router->DispatchEventToExtension(extension_id, std::move(event)); 98 router->DispatchEventToExtension(extension_id, std::move(event));
104 } 99 }
105 } 100 }
106 } 101 }
107 102
108 WebrtcAudioPrivateFunction::WebrtcAudioPrivateFunction() {} 103 WebrtcAudioPrivateFunction::WebrtcAudioPrivateFunction() {}
109 104
110 WebrtcAudioPrivateFunction::~WebrtcAudioPrivateFunction() { 105 WebrtcAudioPrivateFunction::~WebrtcAudioPrivateFunction() {}
111 }
112 106
113 void WebrtcAudioPrivateFunction::GetOutputDeviceDescriptions() { 107 std::string WebrtcAudioPrivateFunction::CalculateHMAC(
114 scoped_refptr<base::SingleThreadTaskRunner> audio_manager_runner =
115 AudioManager::Get()->GetTaskRunner();
116 if (!audio_manager_runner->BelongsToCurrentThread()) {
117 DCHECK_CURRENTLY_ON(BrowserThread::UI);
118 audio_manager_runner->PostTask(
119 FROM_HERE,
120 base::BindOnce(&WebrtcAudioPrivateFunction::GetOutputDeviceDescriptions,
121 this));
122 return;
123 }
124
125 std::unique_ptr<AudioDeviceDescriptions> device_descriptions =
126 base::MakeUnique<AudioDeviceDescriptions>();
127 AudioManager::Get()->GetAudioOutputDeviceDescriptions(
128 device_descriptions.get());
129
130 BrowserThread::PostTask(
131 BrowserThread::IO, FROM_HERE,
132 base::BindOnce(&WebrtcAudioPrivateFunction::OnOutputDeviceDescriptions,
133 this, base::Passed(&device_descriptions)));
134 }
135
136 void WebrtcAudioPrivateFunction::OnOutputDeviceDescriptions(
137 std::unique_ptr<AudioDeviceDescriptions> device_descriptions) {
138 NOTREACHED();
139 }
140
141 void WebrtcAudioPrivateFunction::CalculateHMAC(const std::string& raw_id) {
142 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
143 BrowserThread::PostTask(
144 BrowserThread::IO, FROM_HERE,
145 base::BindOnce(&WebrtcAudioPrivateFunction::CalculateHMAC, this,
146 raw_id));
147 return;
148 }
149
150 std::string hmac = CalculateHMACImpl(raw_id);
151 BrowserThread::PostTask(
152 BrowserThread::UI, FROM_HERE,
153 base::BindOnce(&WebrtcAudioPrivateFunction::OnHMACCalculated, this,
154 hmac));
155 }
156
157 void WebrtcAudioPrivateFunction::OnHMACCalculated(const std::string& hmac) {
158 NOTREACHED();
159 }
160
161 std::string WebrtcAudioPrivateFunction::CalculateHMACImpl(
162 const std::string& raw_id) { 108 const std::string& raw_id) {
163 DCHECK_CURRENTLY_ON(BrowserThread::IO); 109 DCHECK_CURRENTLY_ON(BrowserThread::IO);
164 110
165 // We don't hash the default device description, and we always return 111 // We don't hash the default device description, and we always return
166 // "default" for the default device. There is code in SetActiveSink 112 // "default" for the default device. There is code in SetActiveSink
167 // that transforms "default" to the empty string, and code in 113 // that transforms "default" to the empty string, and code in
168 // GetActiveSink that ensures we return "default" if we get the 114 // GetActiveSink that ensures we return "default" if we get the
169 // empty string as the current device ID. 115 // empty string as the current device ID.
170 if (media::AudioDeviceDescription::IsDefaultDevice(raw_id)) 116 if (media::AudioDeviceDescription::IsDefaultDevice(raw_id))
171 return media::AudioDeviceDescription::kDefaultDeviceId; 117 return media::AudioDeviceDescription::kDefaultDeviceId;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 error_ = base::StringPrintf( 161 error_ = base::StringPrintf(
216 "Invalid security origin. Expected=%s, actual=%s", 162 "Invalid security origin. Expected=%s, actual=%s",
217 expected_origin.spec().c_str(), security_origin.c_str()); 163 expected_origin.spec().c_str(), security_origin.c_str());
218 return nullptr; 164 return nullptr;
219 } 165 }
220 return contents->GetRenderProcessHost(); 166 return contents->GetRenderProcessHost();
221 } 167 }
222 168
223 bool WebrtcAudioPrivateGetSinksFunction::RunAsync() { 169 bool WebrtcAudioPrivateGetSinksFunction::RunAsync() {
224 DCHECK_CURRENTLY_ON(BrowserThread::UI); 170 DCHECK_CURRENTLY_ON(BrowserThread::UI);
225
226 InitDeviceIDSalt(); 171 InitDeviceIDSalt();
227 GetOutputDeviceDescriptions(); 172 BrowserThread::PostTask(
228 173 BrowserThread::IO, FROM_HERE,
174 base::BindOnce(&WebrtcAudioPrivateGetSinksFunction::
175 GetOutputDeviceDescriptionsOnIOThread,
176 this));
229 return true; 177 return true;
230 } 178 }
231 179
232 void WebrtcAudioPrivateGetSinksFunction::OnOutputDeviceDescriptions( 180 void WebrtcAudioPrivateGetSinksFunction::
233 std::unique_ptr<AudioDeviceDescriptions> raw_ids) { 181 GetOutputDeviceDescriptionsOnIOThread() {
234 DCHECK_CURRENTLY_ON(BrowserThread::IO); 182 DCHECK_CURRENTLY_ON(BrowserThread::IO);
183 media::AudioSystem::Get()->GetDeviceDescriptions(
184 base::Bind(&WebrtcAudioPrivateGetSinksFunction::
185 ReceiveOutputDeviceDescriptionsOnIOThread,
186 this),
187 false);
188 }
235 189
236 std::vector<wap::SinkInfo> results; 190 void WebrtcAudioPrivateGetSinksFunction::
237 for (const media::AudioDeviceDescription& description : *raw_ids) { 191 ReceiveOutputDeviceDescriptionsOnIOThread(
192 media::AudioDeviceDescriptions sink_devices) {
193 DCHECK_CURRENTLY_ON(BrowserThread::IO);
194 auto results = base::MakeUnique<SinkInfoVector>();
195 for (const media::AudioDeviceDescription& description : sink_devices) {
238 wap::SinkInfo info; 196 wap::SinkInfo info;
239 info.sink_id = CalculateHMACImpl(description.unique_id); 197 info.sink_id = CalculateHMAC(description.unique_id);
240 info.sink_label = description.device_name; 198 info.sink_label = description.device_name;
241 // TODO(joi): Add other parameters. 199 // TODO(joi): Add other parameters.
242 results.push_back(std::move(info)); 200 results->push_back(std::move(info));
243 } 201 }
244
245 // It's safe to directly set the results here (from a thread other
246 // than the UI thread, on which an AsyncExtensionFunction otherwise
247 // normally runs) because there is one instance of this object per
248 // function call, no actor outside of this object is modifying the
249 // results_ member, and the different method invocations on this
250 // object run strictly in sequence; first RunAsync on the UI thread,
251 // then DoQuery on the audio IO thread, then DoneOnUIThread on the
252 // UI thread.
253 results_ = wap::GetSinks::Results::Create(results);
254
255 BrowserThread::PostTask( 202 BrowserThread::PostTask(
256 BrowserThread::UI, FROM_HERE, 203 BrowserThread::UI, FROM_HERE,
257 base::BindOnce(&WebrtcAudioPrivateGetSinksFunction::DoneOnUIThread, 204 base::BindOnce(&WebrtcAudioPrivateGetSinksFunction::DoneOnUIThread, this,
258 this)); 205 base::Passed(&results)));
259 } 206 }
260 207
261 void WebrtcAudioPrivateGetSinksFunction::DoneOnUIThread() { 208 void WebrtcAudioPrivateGetSinksFunction::DoneOnUIThread(
209 std::unique_ptr<SinkInfoVector> results) {
210 DCHECK_CURRENTLY_ON(BrowserThread::UI);
211 results_ = wap::GetSinks::Results::Create(*results);
262 SendResponse(true); 212 SendResponse(true);
263 } 213 }
264 214
265 WebrtcAudioPrivateGetAssociatedSinkFunction:: 215 WebrtcAudioPrivateGetAssociatedSinkFunction::
266 WebrtcAudioPrivateGetAssociatedSinkFunction() { 216 WebrtcAudioPrivateGetAssociatedSinkFunction() {}
267 }
268 217
269 WebrtcAudioPrivateGetAssociatedSinkFunction:: 218 WebrtcAudioPrivateGetAssociatedSinkFunction::
270 ~WebrtcAudioPrivateGetAssociatedSinkFunction() { 219 ~WebrtcAudioPrivateGetAssociatedSinkFunction() {}
271 }
272 220
273 bool WebrtcAudioPrivateGetAssociatedSinkFunction::RunAsync() { 221 bool WebrtcAudioPrivateGetAssociatedSinkFunction::RunAsync() {
274 params_ = wap::GetAssociatedSink::Params::Create(*args_); 222 params_ = wap::GetAssociatedSink::Params::Create(*args_);
275 DCHECK_CURRENTLY_ON(BrowserThread::UI); 223 DCHECK_CURRENTLY_ON(BrowserThread::UI);
276 EXTENSION_FUNCTION_VALIDATE(params_.get()); 224 EXTENSION_FUNCTION_VALIDATE(params_.get());
277
278 InitDeviceIDSalt(); 225 InitDeviceIDSalt();
279 226
280 AudioManager::Get()->GetTaskRunner()->PostTask( 227 BrowserThread::PostTask(
281 FROM_HERE, base::BindOnce(&WebrtcAudioPrivateGetAssociatedSinkFunction:: 228 BrowserThread::IO, FROM_HERE,
282 GetDevicesOnDeviceThread, 229 base::BindOnce(&WebrtcAudioPrivateGetAssociatedSinkFunction::
283 this)); 230 GetInputDeviceDescriptionsOnIOThread,
231 this));
284 232
285 return true; 233 return true;
286 } 234 }
287 235
288 void WebrtcAudioPrivateGetAssociatedSinkFunction::GetDevicesOnDeviceThread() { 236 void WebrtcAudioPrivateGetAssociatedSinkFunction::
289 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 237 GetInputDeviceDescriptionsOnIOThread() {
290 AudioManager::Get()->GetAudioInputDeviceDescriptions(&source_devices_); 238 DCHECK_CURRENTLY_ON(BrowserThread::IO);
291 239 media::AudioSystem::Get()->GetDeviceDescriptions(
292 BrowserThread::PostTask( 240 base::Bind(&WebrtcAudioPrivateGetAssociatedSinkFunction::
293 BrowserThread::IO, FROM_HERE, 241 ReceiveInputDeviceDescriptionsOnIOThread,
294 base::BindOnce(&WebrtcAudioPrivateGetAssociatedSinkFunction:: 242 this),
295 GetRawSourceIDOnIOThread, 243 true);
296 this));
297 } 244 }
298 245
299 void 246 void WebrtcAudioPrivateGetAssociatedSinkFunction::
300 WebrtcAudioPrivateGetAssociatedSinkFunction::GetRawSourceIDOnIOThread() { 247 ReceiveInputDeviceDescriptionsOnIOThread(
248 media::AudioDeviceDescriptions source_devices) {
301 DCHECK_CURRENTLY_ON(BrowserThread::IO); 249 DCHECK_CURRENTLY_ON(BrowserThread::IO);
302
303 url::Origin security_origin(GURL(params_->security_origin)); 250 url::Origin security_origin(GURL(params_->security_origin));
304 std::string source_id_in_origin(params_->source_id_in_origin); 251 std::string source_id_in_origin(params_->source_id_in_origin);
305 252
306 // Find the raw source ID for source_id_in_origin. 253 // Find the raw source ID for source_id_in_origin.
307 std::string raw_source_id; 254 std::string raw_source_id;
308 for (AudioDeviceDescriptions::const_iterator it = source_devices_.begin(); 255 for (const auto& device : source_devices) {
309 it != source_devices_.end(); ++it) {
310 const std::string& id = it->unique_id;
311 if (content::DoesMediaDeviceIDMatchHMAC(device_id_salt(), security_origin, 256 if (content::DoesMediaDeviceIDMatchHMAC(device_id_salt(), security_origin,
312 source_id_in_origin, id)) { 257 source_id_in_origin,
313 raw_source_id = id; 258 device.unique_id)) {
259 raw_source_id = device.unique_id;
314 DVLOG(2) << "Found raw ID " << raw_source_id 260 DVLOG(2) << "Found raw ID " << raw_source_id
315 << " for source ID in origin " << source_id_in_origin; 261 << " for source ID in origin " << source_id_in_origin;
316 break; 262 break;
317 } 263 }
318 } 264 }
319 265 if (raw_source_id.empty()) {
320 AudioManager::Get()->GetTaskRunner()->PostTask( 266 CalculateHMACOnIOThread(std::string());
321 FROM_HERE, base::BindOnce(&WebrtcAudioPrivateGetAssociatedSinkFunction:: 267 return;
322 GetAssociatedSinkOnDeviceThread, 268 }
323 this, raw_source_id)); 269 media::AudioSystem::Get()->GetAssociatedOutputDeviceID(
270 raw_source_id,
271 base::Bind(
272 &WebrtcAudioPrivateGetAssociatedSinkFunction::CalculateHMACOnIOThread,
273 this));
324 } 274 }
325 275
326 void 276 void WebrtcAudioPrivateGetAssociatedSinkFunction::CalculateHMACOnIOThread(
327 WebrtcAudioPrivateGetAssociatedSinkFunction::GetAssociatedSinkOnDeviceThread( 277 const std::string& raw_sink_id) {
328 const std::string& raw_source_id) { 278 DCHECK_CURRENTLY_ON(BrowserThread::IO);
329 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 279 BrowserThread::PostTask(
330 280 BrowserThread::UI, FROM_HERE,
331 // We return an empty string if there is no associated output device. 281 base::BindOnce(
332 std::string raw_sink_id; 282 &WebrtcAudioPrivateGetAssociatedSinkFunction::ReceiveHMACOnUIThread,
333 if (!raw_source_id.empty()) { 283 this, CalculateHMAC(raw_sink_id)));
334 raw_sink_id =
335 AudioManager::Get()->GetAssociatedOutputDeviceID(raw_source_id);
336 }
337
338 CalculateHMAC(raw_sink_id);
339 } 284 }
340 285
341 void WebrtcAudioPrivateGetAssociatedSinkFunction::OnHMACCalculated( 286 void WebrtcAudioPrivateGetAssociatedSinkFunction::ReceiveHMACOnUIThread(
342 const std::string& associated_sink_id) { 287 const std::string& associated_sink_id) {
343 DCHECK_CURRENTLY_ON(BrowserThread::UI); 288 DCHECK_CURRENTLY_ON(BrowserThread::UI);
344
345 if (associated_sink_id == media::AudioDeviceDescription::kDefaultDeviceId) { 289 if (associated_sink_id == media::AudioDeviceDescription::kDefaultDeviceId) {
346 DVLOG(2) << "Got default ID, replacing with empty ID."; 290 DVLOG(2) << "Got default ID, replacing with empty ID.";
347 results_ = wap::GetAssociatedSink::Results::Create(""); 291 results_ = wap::GetAssociatedSink::Results::Create("");
348 } else { 292 } else {
349 results_ = wap::GetAssociatedSink::Results::Create(associated_sink_id); 293 results_ = wap::GetAssociatedSink::Results::Create(associated_sink_id);
350 } 294 }
351
352 SendResponse(true); 295 SendResponse(true);
353 } 296 }
354 297
355 WebrtcAudioPrivateSetAudioExperimentsFunction:: 298 WebrtcAudioPrivateSetAudioExperimentsFunction::
356 WebrtcAudioPrivateSetAudioExperimentsFunction() {} 299 WebrtcAudioPrivateSetAudioExperimentsFunction() {}
357 300
358 WebrtcAudioPrivateSetAudioExperimentsFunction:: 301 WebrtcAudioPrivateSetAudioExperimentsFunction::
359 ~WebrtcAudioPrivateSetAudioExperimentsFunction() {} 302 ~WebrtcAudioPrivateSetAudioExperimentsFunction() {}
360 303
361 bool WebrtcAudioPrivateSetAudioExperimentsFunction::RunAsync() { 304 bool WebrtcAudioPrivateSetAudioExperimentsFunction::RunAsync() {
(...skipping 11 matching lines...) Expand all
373 } 316 }
374 317
375 host->SetEchoCanceller3(*params->audio_experiments.enable_aec3); 318 host->SetEchoCanceller3(*params->audio_experiments.enable_aec3);
376 } 319 }
377 320
378 SendResponse(true); 321 SendResponse(true);
379 return true; 322 return true;
380 } 323 }
381 324
382 } // namespace extensions 325 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698