11e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 21e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 31e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// found in the LICENSE file. 41e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 51e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.h" 61e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 71e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/lazy_instance.h" 81e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 91e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/task_runner_util.h" 101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/extensions/api/tabs/tabs_constants.h" 111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/extensions/extension_tab_util.h" 13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "content/public/browser/media_device_id.h" 15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/public/browser/resource_context.h" 161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "content/public/browser/web_contents.h" 17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/event_router.h" 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h" 191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "extensions/common/error_utils.h" 2046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/common/permissions/permissions_data.h" 211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "media/audio/audio_manager_base.h" 221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "media/audio/audio_output_controller.h" 231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)namespace extensions { 251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using content::BrowserThread; 271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using content::RenderViewHost; 281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using media::AudioDeviceNames; 291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using media::AudioManager; 301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)namespace wap = api::webrtc_audio_private; 321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)static base::LazyInstance< 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) BrowserContextKeyedAPIFactory<WebrtcAudioPrivateEventService> > g_factory = 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LAZY_INSTANCE_INITIALIZER; 361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)WebrtcAudioPrivateEventService::WebrtcAudioPrivateEventService( 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) content::BrowserContext* context) 39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : browser_context_(context) { 401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // In unit tests, the SystemMonitor may not be created. 411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::SystemMonitor* system_monitor = base::SystemMonitor::Get(); 421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (system_monitor) 431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) system_monitor->AddDevicesChangedObserver(this); 441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)WebrtcAudioPrivateEventService::~WebrtcAudioPrivateEventService() { 471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void WebrtcAudioPrivateEventService::Shutdown() { 501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // In unit tests, the SystemMonitor may not be created. 511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::SystemMonitor* system_monitor = base::SystemMonitor::Get(); 521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (system_monitor) 531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) system_monitor->RemoveDevicesChangedObserver(this); 541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// static 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BrowserContextKeyedAPIFactory<WebrtcAudioPrivateEventService>* 581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)WebrtcAudioPrivateEventService::GetFactoryInstance() { 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return g_factory.Pointer(); 601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// static 631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const char* WebrtcAudioPrivateEventService::service_name() { 641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return "WebrtcAudioPrivateEventService"; 651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void WebrtcAudioPrivateEventService::OnDevicesChanged( 681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::SystemMonitor::DeviceType device_type) { 691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) switch (device_type) { 701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) case base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE: 711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) case base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE: 721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SignalEvent(); 731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) break; 741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) default: 761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // No action needed. 771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) break; 781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void WebrtcAudioPrivateEventService::SignalEvent() { 821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) using api::webrtc_audio_private::OnSinksChanged::kEventName; 831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EventRouter* router = EventRouter::Get(browser_context_); 851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (!router || !router->HasEventListener(kEventName)) 861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return; 871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ExtensionService* extension_service = 88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ExtensionSystem::Get(browser_context_)->extension_service(); 891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const ExtensionSet* extensions = extension_service->extensions(); 901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) for (ExtensionSet::const_iterator it = extensions->begin(); 911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) it != extensions->end(); ++it) { 921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const std::string& extension_id = (*it)->id(); 931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (router->ExtensionHasEventListener(extension_id, kEventName) && 9446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) (*it)->permissions_data()->HasAPIPermission("webrtcAudioPrivate")) { 951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<Event> event( 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new Event(kEventName, make_scoped_ptr(new base::ListValue()).Pass())); 971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) router->DispatchEventToExtension(extension_id, event.Pass()); 981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 1011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)WebrtcAudioPrivateFunction::WebrtcAudioPrivateFunction() 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : resource_context_(NULL) { 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)WebrtcAudioPrivateFunction::~WebrtcAudioPrivateFunction() { 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebrtcAudioPrivateFunction::GetOutputDeviceNames() { 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> audio_manager_runner = 111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch AudioManager::Get()->GetWorkerTaskRunner(); 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!audio_manager_runner->BelongsToCurrentThread()) { 113effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) audio_manager_runner->PostTask( 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&WebrtcAudioPrivateFunction::GetOutputDeviceNames, this)); 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<AudioDeviceNames> device_names(new AudioDeviceNames); 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AudioManager::Get()->GetAudioOutputDeviceNames(device_names.get()); 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BrowserThread::PostTask( 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BrowserThread::IO, 1251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) FROM_HERE, 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&WebrtcAudioPrivateFunction::OnOutputDeviceNames, 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) this, 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Passed(&device_names))); 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebrtcAudioPrivateFunction::OnOutputDeviceNames( 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<AudioDeviceNames> device_names) { 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOTREACHED(); 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool WebrtcAudioPrivateFunction::GetControllerList(int tab_id) { 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::WebContents* contents = NULL; 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!ExtensionTabUtil::GetTabById( 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) tab_id, GetProfile(), true, NULL, NULL, &contents, NULL)) { 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) error_ = extensions::ErrorUtils::FormatErrorMessage( 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extensions::tabs_constants::kTabNotFoundError, 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::IntToString(tab_id)); 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RenderViewHost* rvh = contents->GetRenderViewHost(); 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!rvh) 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) rvh->GetAudioOutputControllers(base::Bind( 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &WebrtcAudioPrivateFunction::OnControllerList, this)); 1521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return true; 1531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 1541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebrtcAudioPrivateFunction::OnControllerList( 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const content::RenderViewHost::AudioOutputControllerList& list) { 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOTREACHED(); 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebrtcAudioPrivateFunction::CalculateHMAC(const std::string& raw_id) { 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BrowserThread::PostTask( 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BrowserThread::IO, 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&WebrtcAudioPrivateFunction::CalculateHMAC, this, raw_id)); 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string hmac = CalculateHMACImpl(raw_id); 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BrowserThread::PostTask( 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BrowserThread::UI, 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&WebrtcAudioPrivateFunction::OnHMACCalculated, this, hmac)); 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebrtcAudioPrivateFunction::OnHMACCalculated(const std::string& hmac) { 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOTREACHED(); 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string WebrtcAudioPrivateFunction::CalculateHMACImpl( 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& raw_id) { 182effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // We don't hash the default device name, and we always return 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // "default" for the default device. There is code in SetActiveSink 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // that transforms "default" to the empty string, and code in 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // GetActiveSink that ensures we return "default" if we get the 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // empty string as the current device ID. 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (raw_id.empty() || raw_id == media::AudioManagerBase::kDefaultDeviceId) 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return media::AudioManagerBase::kDefaultDeviceId; 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL security_origin(source_url().GetOrigin()); 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return content::GetHMACForMediaDeviceID( 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) resource_context()->GetMediaDeviceIDSalt(), 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) security_origin, 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) raw_id); 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebrtcAudioPrivateFunction::InitResourceContext() { 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) resource_context_ = GetProfile()->GetResourceContext(); 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)content::ResourceContext* WebrtcAudioPrivateFunction::resource_context() const { 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(resource_context_); // Did you forget to InitResourceContext()? 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return resource_context_; 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 208010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool WebrtcAudioPrivateGetSinksFunction::RunAsync() { 209effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) InitResourceContext(); 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetOutputDeviceNames(); 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebrtcAudioPrivateGetSinksFunction::OnOutputDeviceNames( 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<AudioDeviceNames> raw_ids) { 219effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 2201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::vector<linked_ptr<wap::SinkInfo> > results; 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (AudioDeviceNames::const_iterator it = raw_ids->begin(); 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != raw_ids->end(); 2241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ++it) { 2251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) linked_ptr<wap::SinkInfo> info(new wap::SinkInfo); 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) info->sink_id = CalculateHMACImpl(it->unique_id); 2271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) info->sink_label = it->device_name; 2281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // TODO(joi): Add other parameters. 2291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) results.push_back(info); 2301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 2311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // It's safe to directly set the results here (from a thread other 2331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // than the UI thread, on which an AsyncExtensionFunction otherwise 2341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // normally runs) because there is one instance of this object per 2351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // function call, no actor outside of this object is modifying the 2361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // results_ member, and the different method invocations on this 237010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // object run strictly in sequence; first RunAsync on the UI thread, 2381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // then DoQuery on the audio IO thread, then DoneOnUIThread on the 2391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // UI thread. 2401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) results_.reset(wap::GetSinks::Results::Create(results).release()); 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BrowserThread::PostTask( 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BrowserThread::UI, 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&WebrtcAudioPrivateGetSinksFunction::DoneOnUIThread, this)); 2461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 2471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void WebrtcAudioPrivateGetSinksFunction::DoneOnUIThread() { 2491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SendResponse(true); 2501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 2511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 252010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool WebrtcAudioPrivateGetActiveSinkFunction::RunAsync() { 253effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) InitResourceContext(); 2551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<wap::GetActiveSink::Params> params( 2571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) wap::GetActiveSink::Params::Create(*args_)); 2581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXTENSION_FUNCTION_VALIDATE(params.get()); 2591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return GetControllerList(params->tab_id); 2611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 2621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void WebrtcAudioPrivateGetActiveSinkFunction::OnControllerList( 2641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const RenderViewHost::AudioOutputControllerList& controllers) { 265effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (controllers.empty()) { 2681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // If there is no current audio stream for the rvh, we return an 2691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // empty string as the sink ID. 2701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DVLOG(2) << "chrome.webrtcAudioPrivate.getActiveSink: No controllers."; 2711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) results_.reset( 2721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) wap::GetActiveSink::Results::Create(std::string()).release()); 2731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SendResponse(true); 2741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } else { 2751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DVLOG(2) << "chrome.webrtcAudioPrivate.getActiveSink: " 2761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) << controllers.size() << " controllers."; 2771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // TODO(joi): Debug-only, DCHECK that all items have the same ID. 2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Send the raw ID through CalculateHMAC, and send the result in 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // OnHMACCalculated. 2811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) (*controllers.begin())->GetOutputDeviceId( 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&WebrtcAudioPrivateGetActiveSinkFunction::CalculateHMAC, 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) this)); 2841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 2851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 2861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebrtcAudioPrivateGetActiveSinkFunction::OnHMACCalculated( 2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& hmac_id) { 289effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string result = hmac_id; 2921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (result.empty()) { 2931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DVLOG(2) << "Received empty ID, replacing with default ID."; 2941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) result = media::AudioManagerBase::kDefaultDeviceId; 2951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 2961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) results_.reset(wap::GetActiveSink::Results::Create(result).release()); 2971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SendResponse(true); 2981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 2991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)WebrtcAudioPrivateSetActiveSinkFunction:: 3011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)WebrtcAudioPrivateSetActiveSinkFunction() 3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : tab_id_(0), 3031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) num_remaining_sink_ids_(0) { 3041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 3051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)WebrtcAudioPrivateSetActiveSinkFunction:: 3071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)~WebrtcAudioPrivateSetActiveSinkFunction() { 3081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 3091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 310010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool WebrtcAudioPrivateSetActiveSinkFunction::RunAsync() { 311effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 3121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<wap::SetActiveSink::Params> params( 3131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) wap::SetActiveSink::Params::Create(*args_)); 3141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXTENSION_FUNCTION_VALIDATE(params.get()); 3151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) InitResourceContext(); 3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) tab_id_ = params->tab_id; 3191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) sink_id_ = params->sink_id; 3201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return GetControllerList(tab_id_); 3221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 3231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void WebrtcAudioPrivateSetActiveSinkFunction::OnControllerList( 3251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const RenderViewHost::AudioOutputControllerList& controllers) { 326effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controllers_ = controllers; 3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) num_remaining_sink_ids_ = controllers_.size(); 3301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (num_remaining_sink_ids_ == 0) { 3311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) error_ = extensions::ErrorUtils::FormatErrorMessage( 3321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) "No active stream for tab with id: *.", 3331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::IntToString(tab_id_)); 3341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SendResponse(false); 3351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } else { 3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // We need to get the output device names, and calculate the HMAC 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // for each, to find the raw ID for the ID provided to this API 3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // function call. 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetOutputDeviceNames(); 3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebrtcAudioPrivateSetActiveSinkFunction::OnOutputDeviceNames( 3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<AudioDeviceNames> device_names) { 345effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string raw_sink_id; 3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (sink_id_ == media::AudioManagerBase::kDefaultDeviceId) { 3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(2) << "Received default ID, replacing with empty ID."; 3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) raw_sink_id = ""; 3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (AudioDeviceNames::const_iterator it = device_names->begin(); 3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != device_names->end(); 3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++it) { 3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (sink_id_ == CalculateHMACImpl(it->unique_id)) { 3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) raw_sink_id = it->unique_id; 3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (raw_sink_id.empty()) 3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(2) << "Found no matching raw sink ID for HMAC " << sink_id_; 3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RenderViewHost::AudioOutputControllerList::const_iterator it = 3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controllers_.begin(); 3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (; it != controllers_.end(); ++it) { 3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (*it)->SwitchOutputDevice(raw_sink_id, base::Bind( 3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &WebrtcAudioPrivateSetActiveSinkFunction::SwitchDone, this)); 3701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 3711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 3721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void WebrtcAudioPrivateSetActiveSinkFunction::SwitchDone() { 3741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (--num_remaining_sink_ids_ == 0) { 3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BrowserThread::PostTask( 3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BrowserThread::UI, 3771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) FROM_HERE, 3781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::Bind(&WebrtcAudioPrivateSetActiveSinkFunction::DoneOnUIThread, 3791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) this)); 3801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 3811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 3821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void WebrtcAudioPrivateSetActiveSinkFunction::DoneOnUIThread() { 3841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SendResponse(true); 3851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 3861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)WebrtcAudioPrivateGetAssociatedSinkFunction:: 388a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)WebrtcAudioPrivateGetAssociatedSinkFunction() { 389a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 390a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 391a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)WebrtcAudioPrivateGetAssociatedSinkFunction:: 3921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)~WebrtcAudioPrivateGetAssociatedSinkFunction() { 3931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 3941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 395010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool WebrtcAudioPrivateGetAssociatedSinkFunction::RunAsync() { 396a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) params_ = wap::GetAssociatedSink::Params::Create(*args_); 397effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 398a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXTENSION_FUNCTION_VALIDATE(params_.get()); 3991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) InitResourceContext(); 4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 402116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch AudioManager::Get()->GetWorkerTaskRunner()->PostTask( 4031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) FROM_HERE, 404a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(&WebrtcAudioPrivateGetAssociatedSinkFunction:: 4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetDevicesOnDeviceThread, this)); 4061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 4071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return true; 4081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 4091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 410a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void WebrtcAudioPrivateGetAssociatedSinkFunction::GetDevicesOnDeviceThread() { 411116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(AudioManager::Get()->GetWorkerTaskRunner()->BelongsToCurrentThread()); 412a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) AudioManager::Get()->GetAudioInputDeviceNames(&source_devices_); 413a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BrowserThread::PostTask( 415a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) BrowserThread::IO, 416a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) FROM_HERE, 417a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(&WebrtcAudioPrivateGetAssociatedSinkFunction:: 418a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) GetRawSourceIDOnIOThread, 4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) this)); 4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void 4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)WebrtcAudioPrivateGetAssociatedSinkFunction::GetRawSourceIDOnIOThread() { 424effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 4251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL security_origin(params_->security_origin); 4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string source_id_in_origin(params_->source_id_in_origin); 4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Find the raw source ID for source_id_in_origin. 4301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::string raw_source_id; 431a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for (AudioDeviceNames::const_iterator it = source_devices_.begin(); 432a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) it != source_devices_.end(); 4331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ++it) { 4341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const std::string& id = it->unique_id; 4351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (content::DoesMediaDeviceIDMatchHMAC( 4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) resource_context()->GetMediaDeviceIDSalt(), 437a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) security_origin, 438a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) source_id_in_origin, 439a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) id)) { 4401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) raw_source_id = id; 4411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DVLOG(2) << "Found raw ID " << raw_source_id 4421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) << " for source ID in origin " << source_id_in_origin; 4431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) break; 4441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 4451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 4461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 447116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch AudioManager::Get()->GetWorkerTaskRunner()->PostTask( 448a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) FROM_HERE, 449a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(&WebrtcAudioPrivateGetAssociatedSinkFunction:: 450a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) GetAssociatedSinkOnDeviceThread, 451a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) this, 4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) raw_source_id)); 453a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 454a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void 456a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)WebrtcAudioPrivateGetAssociatedSinkFunction::GetAssociatedSinkOnDeviceThread( 457a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& raw_source_id) { 458116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(AudioManager::Get()->GetWorkerTaskRunner()->BelongsToCurrentThread()); 459a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 4601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // We return an empty string if there is no associated output device. 4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string raw_sink_id; 4621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (!raw_source_id.empty()) { 4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) raw_sink_id = 4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AudioManager::Get()->GetAssociatedOutputDeviceID(raw_source_id); 4651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 4661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CalculateHMAC(raw_sink_id); 4681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 4691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebrtcAudioPrivateGetAssociatedSinkFunction::OnHMACCalculated( 4711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const std::string& associated_sink_id) { 472effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 4731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (associated_sink_id == media::AudioManagerBase::kDefaultDeviceId) { 4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(2) << "Got default ID, replacing with empty ID."; 4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) results_.reset(wap::GetAssociatedSink::Results::Create("").release()); 4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 4785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) results_.reset( 4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) wap::GetAssociatedSink::Results::Create(associated_sink_id).release()); 4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SendResponse(true); 4831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 4841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 4851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} // namespace extensions 486