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 "base/json/json_writer.h" 6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/strings/string_util.h" 71e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/strings/stringprintf.h" 8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/strings/utf_string_conversions.h" 91e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/synchronization/waitable_event.h" 101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/threading/platform_thread.h" 111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/time/time.h" 12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/browser_process.h" 131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.h" 14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/extensions/component_loader.h" 151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/extensions/extension_apitest.h" 161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/extensions/extension_function_test_utils.h" 171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/extensions/extension_tab_util.h" 18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/media/webrtc_log_uploader.h" 191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/ui/browser.h" 201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h" 211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/test/base/in_process_browser_test.h" 221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/test/base/ui_test_utils.h" 23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "content/public/browser/media_device_id.h" 251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "content/public/browser/web_contents.h" 26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "content/public/test/browser_test_utils.h" 271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "extensions/common/permissions/permission_set.h" 28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/permissions/permissions_data.h" 291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "media/audio/audio_manager.h" 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/audio/audio_manager_base.h" 311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "net/test/embedded_test_server/embedded_test_server.h" 321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using base::JSONWriter; 351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using content::RenderViewHost; 361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using content::WebContents; 371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using media::AudioDeviceNames; 381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using media::AudioManager; 391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)namespace extensions { 411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using extension_function_test_utils::RunFunctionAndReturnError; 431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using extension_function_test_utils::RunFunctionAndReturnSingleResult; 441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class AudioWaitingExtensionTest : public ExtensionApiTest { 46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) protected: 47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) void WaitUntilAudioIsPlaying(WebContents* tab) { 48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Wait for audio to start playing. We gate this on there being one 49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // or more AudioOutputController objects for our tab. 50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool audio_playing = false; 51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (size_t remaining_tries = 50; remaining_tries > 0; --remaining_tries) { 52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) tab->GetRenderViewHost()->GetAudioOutputControllers( 53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Bind(OnAudioControllers, &audio_playing)); 54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (audio_playing) 56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) break; 57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); 59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!audio_playing) 62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) FAIL() << "Audio did not start playing within ~5 seconds."; 63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Used by the test above to wait until audio is playing. 66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) static void OnAudioControllers( 67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool* audio_playing, 68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const RenderViewHost::AudioOutputControllerList& list) { 69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!list.empty()) 70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) *audio_playing = true; 71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}; 73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class WebrtcAudioPrivateTest : public AudioWaitingExtensionTest { 751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) public: 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebrtcAudioPrivateTest() 7723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) : enumeration_event_(false, false) { 7823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 7923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 8023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) virtual void SetUpOnMainThread() OVERRIDE { 8123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) AudioWaitingExtensionTest::SetUpOnMainThread(); 8223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // Needs to happen after chrome's schemes are added. 8323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) source_url_ = GURL("chrome-extension://fakeid012345678/fakepage.html"); 841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) protected: 871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::string InvokeGetActiveSink(int tab_id) { 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::ListValue parameters; 891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) parameters.AppendInteger(tab_id); 901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::string parameter_string; 911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) JSONWriter::Write(¶meters, ¶meter_string); 921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_refptr<WebrtcAudioPrivateGetActiveSinkFunction> function = 941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) new WebrtcAudioPrivateGetActiveSinkFunction(); 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) function->set_source_url(source_url_); 961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<base::Value> result( 971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) RunFunctionAndReturnSingleResult(function.get(), 981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) parameter_string, 991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) browser())); 1001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::string device_id; 1011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) result->GetAsString(&device_id); 1021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return device_id; 1031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::Value> InvokeGetSinks(base::ListValue** sink_list) { 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<WebrtcAudioPrivateGetSinksFunction> function = 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new WebrtcAudioPrivateGetSinksFunction(); 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) function->set_source_url(source_url_); 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::Value> result( 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunFunctionAndReturnSingleResult(function.get(), "[]", browser())); 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->GetAsList(sink_list); 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return result.Pass(); 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Synchronously (from the calling thread's point of view) runs the 1171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // given enumeration function on the device thread. On return, 1181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // |device_names| has been filled with the device names resulting 1191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // from that call. 1201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) void GetAudioDeviceNames( 1211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) void (AudioManager::*EnumerationFunc)(AudioDeviceNames*), 1221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) AudioDeviceNames* device_names) { 1231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) AudioManager* audio_manager = AudioManager::Get(); 1241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 125116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!audio_manager->GetWorkerTaskRunner()->BelongsToCurrentThread()) { 126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch audio_manager->GetWorkerTaskRunner()->PostTask( 1271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) FROM_HERE, 1281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::Bind(&WebrtcAudioPrivateTest::GetAudioDeviceNames, this, 1291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EnumerationFunc, device_names)); 1301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) enumeration_event_.Wait(); 1311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } else { 1321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) (audio_manager->*EnumerationFunc)(device_names); 1331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) enumeration_event_.Signal(); 1341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Synchronously (from the calling thread's point of view) retrieve the 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // device id in the |origin| on the IO thread. On return, 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // |id_in_origin| contains the id |raw_device_id| is known by in 140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // the origin. 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void GetIDInOrigin(content::ResourceContext* resource_context, 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL origin, 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& raw_device_id, 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string* id_in_origin) { 145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)) { 146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) content::BrowserThread::PostTask( 147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) content::BrowserThread::IO, FROM_HERE, 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&WebrtcAudioPrivateTest::GetIDInOrigin, 149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) this, resource_context, origin, raw_device_id, 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) id_in_origin)); 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) enumeration_event_.Wait(); 152a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *id_in_origin = content::GetHMACForMediaDeviceID( 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) resource_context->GetMediaDeviceIDSalt(), 155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) origin, 156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) raw_device_id); 157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) enumeration_event_.Signal(); 158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Event used to signal completion of enumeration. 1621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::WaitableEvent enumeration_event_; 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL source_url_; 1651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}; 1661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if !defined(OS_MACOSX) 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// http://crbug.com/334579 1691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, GetSinks) { 1701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) AudioDeviceNames devices; 1711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) GetAudioDeviceNames(&AudioManager::GetAudioOutputDeviceNames, &devices); 1721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::ListValue* sink_list = NULL; 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::Value> result = InvokeGetSinks(&sink_list); 1751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::string result_string; 1771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) JSONWriter::Write(result.get(), &result_string); 1781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) VLOG(2) << result_string; 1791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ(devices.size(), sink_list->GetSize()); 1811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Iterate through both lists in lockstep and compare. The order 1831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // should be identical. 1841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) size_t ix = 0; 1851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) AudioDeviceNames::const_iterator it = devices.begin(); 1861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) for (; ix < sink_list->GetSize() && it != devices.end(); 1871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ++ix, ++it) { 1881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::DictionaryValue* dict = NULL; 1891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) sink_list->GetDictionary(ix, &dict); 1901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::string sink_id; 1911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) dict->GetString("sinkId", &sink_id); 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string expected_id; 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (it->unique_id.empty() || 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it->unique_id == media::AudioManagerBase::kDefaultDeviceId) { 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) expected_id = media::AudioManagerBase::kDefaultDeviceId; 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetIDInOrigin(profile()->GetResourceContext(), 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) source_url_.GetOrigin(), 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it->unique_id, 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &expected_id); 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(expected_id, sink_id); 2051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::string sink_label; 2061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) dict->GetString("sinkLabel", &sink_label); 2071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ(it->device_name, sink_label); 2081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // TODO(joi): Verify the contents of these once we start actually 2101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // filling them in. 2111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_TRUE(dict->HasKey("isDefault")); 2121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_TRUE(dict->HasKey("isReady")); 2131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_TRUE(dict->HasKey("sampleRate")); 2141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 2151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif // OS_MACOSX 2171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// This exercises the case where you have a tab with no active media 2191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// stream and try to retrieve the currently active audio sink. 2201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, GetActiveSinkNoMediaStream) { 2211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); 2221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) int tab_id = ExtensionTabUtil::GetTabId(tab); 2231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::ListValue parameters; 2241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) parameters.AppendInteger(tab_id); 2251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::string parameter_string; 2261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) JSONWriter::Write(¶meters, ¶meter_string); 2271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_refptr<WebrtcAudioPrivateGetActiveSinkFunction> function = 2291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) new WebrtcAudioPrivateGetActiveSinkFunction(); 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) function->set_source_url(source_url_); 2311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<base::Value> result( 2321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) RunFunctionAndReturnSingleResult(function.get(), 2331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) parameter_string, 2341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) browser())); 2351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::string result_string; 2371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) JSONWriter::Write(result.get(), &result_string); 2381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ("\"\"", result_string); 2391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 2401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// This exercises the case where you have a tab with no active media 2421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// stream and try to set the audio sink. 2431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, SetActiveSinkNoMediaStream) { 2441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); 2451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) int tab_id = ExtensionTabUtil::GetTabId(tab); 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::ListValue parameters; 2471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) parameters.AppendInteger(tab_id); 2481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) parameters.AppendString("no such id"); 2491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::string parameter_string; 2501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) JSONWriter::Write(¶meters, ¶meter_string); 2511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_refptr<WebrtcAudioPrivateSetActiveSinkFunction> function = 2531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) new WebrtcAudioPrivateSetActiveSinkFunction(); 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) function->set_source_url(source_url_); 2551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::string error(RunFunctionAndReturnError(function.get(), 2561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) parameter_string, 2571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) browser())); 2581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ(base::StringPrintf("No active stream for tab with id: %d.", tab_id), 2591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) error); 2601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 2611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, GetAndSetWithMediaStream) { 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // First retrieve the list of all sinks, so that we can run a test 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // where we set the active sink to each of the different available 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // sinks in turn. 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::ListValue* sink_list = NULL; 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::Value> result = InvokeGetSinks(&sink_list); 2681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ASSERT_TRUE(StartEmbeddedTestServer()); 2701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Open a normal page that uses an audio sink. 2721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ui_test_utils::NavigateToURL( 2731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) browser(), 2741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) GURL(embedded_test_server()->GetURL("/extensions/loop_audio.html"))); 2751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); 2771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) int tab_id = ExtensionTabUtil::GetTabId(tab); 2781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 279f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) WaitUntilAudioIsPlaying(tab); 2801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::string current_device = InvokeGetActiveSink(tab_id); 2821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) VLOG(2) << "Before setting, current device: " << current_device; 2831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_NE("", current_device); 2841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Set to each of the other devices in turn. 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (size_t ix = 0; ix < sink_list->GetSize(); ++ix) { 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* dict = NULL; 2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sink_list->GetDictionary(ix, &dict); 2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string target_device; 2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dict->GetString("sinkId", &target_device); 2911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::ListValue parameters; 2931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) parameters.AppendInteger(tab_id); 2941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) parameters.AppendString(target_device); 2951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::string parameter_string; 2961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) JSONWriter::Write(¶meters, ¶meter_string); 2971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_refptr<WebrtcAudioPrivateSetActiveSinkFunction> function = 2991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) new WebrtcAudioPrivateSetActiveSinkFunction(); 3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) function->set_source_url(source_url_); 3011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<base::Value> result(RunFunctionAndReturnSingleResult( 3021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) function.get(), parameter_string, browser())); 3031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // The function was successful if the above invocation doesn't 3041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // fail. Just for kicks, also check that it returns no result. 3051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ(NULL, result.get()); 3061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) current_device = InvokeGetActiveSink(tab_id); 3081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) VLOG(2) << "After setting to " << target_device 3091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) << ", current device is " << current_device; 3101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ(target_device, current_device); 3111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 3121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 3131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, GetAssociatedSink) { 3151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Get the list of input devices. We can cheat in the unit test and 3161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // run this on the main thread since nobody else will be running at 3171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // the same time. 3181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) AudioDeviceNames devices; 3191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) GetAudioDeviceNames(&AudioManager::GetAudioInputDeviceNames, &devices); 3201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Try to get an associated sink for each source. 3221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) for (AudioDeviceNames::const_iterator device = devices.begin(); 3231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) device != devices.end(); 3241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ++device) { 325a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_refptr<WebrtcAudioPrivateGetAssociatedSinkFunction> function = 326a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) new WebrtcAudioPrivateGetAssociatedSinkFunction(); 3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) function->set_source_url(source_url_); 328a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 329a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string raw_device_id = device->unique_id; 330a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) VLOG(2) << "Trying to find associated sink for device " << raw_device_id; 331a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string source_id_in_origin; 3321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) GURL origin(GURL("http://www.google.com/").GetOrigin()); 3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetIDInOrigin(profile()->GetResourceContext(), 3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) origin, 3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) raw_device_id, 3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &source_id_in_origin); 3371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::ListValue parameters; 3391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) parameters.AppendString(origin.spec()); 3401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) parameters.AppendString(source_id_in_origin); 3411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::string parameter_string; 3421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) JSONWriter::Write(¶meters, ¶meter_string); 3431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<base::Value> result( 3451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) RunFunctionAndReturnSingleResult(function.get(), 3461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) parameter_string, 3471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) browser())); 3481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::string result_string; 3491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) JSONWriter::Write(result.get(), &result_string); 3501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) VLOG(2) << "Results: " << result_string; 3511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 3521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 3531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, TriggerEvent) { 3551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) WebrtcAudioPrivateEventService* service = 356a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) WebrtcAudioPrivateEventService::GetFactoryInstance()->Get(profile()); 3571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Just trigger, without any extension listening. 3591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) service->OnDevicesChanged(base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE); 3601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Now load our test extension and do it again. 3621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const extensions::Extension* extension = LoadExtension( 3631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) test_data_dir_.AppendASCII("webrtc_audio_private_event_listener")); 3641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) service->OnDevicesChanged(base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE); 3651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Check that the extension got the notification. 3671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::string result = ExecuteScriptInBackgroundPage(extension->id(), 3681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) "reportIfGot()"); 3691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ("true", result); 3701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 3711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 372f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class HangoutServicesBrowserTest : public AudioWaitingExtensionTest { 373f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public: 374f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) virtual void SetUp() OVERRIDE { 375f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Make sure the Hangout Services component extension gets loaded. 376f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ComponentLoader::EnableBackgroundExtensionsForTesting(); 377f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) AudioWaitingExtensionTest::SetUp(); 378f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 379f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}; 380f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(GOOGLE_CHROME_BUILD) || defined(ENABLE_HANGOUT_SERVICES_EXTENSION) 382f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(HangoutServicesBrowserTest, 383f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) RunComponentExtensionTest) { 384f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // This runs the end-to-end JavaScript test for the Hangout Services 385f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // component extension, which uses the webrtcAudioPrivate API among 386f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // others. 387f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ASSERT_TRUE(StartEmbeddedTestServer()); 388f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) GURL url(embedded_test_server()->GetURL( 389f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) "/extensions/hangout_services_test.html")); 390f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // The "externally connectable" extension permission doesn't seem to 391f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // like when we use 127.0.0.1 as the host, but using localhost works. 392f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string url_spec = url.spec(); 393f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ReplaceFirstSubstringAfterOffset(&url_spec, 0, "127.0.0.1", "localhost"); 394f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) GURL localhost_url(url_spec); 395f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ui_test_utils::NavigateToURL(browser(), localhost_url); 396f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 397f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); 398f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) WaitUntilAudioIsPlaying(tab); 399f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 400f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Override, i.e. disable, uploading. We don't want to try sending data to 401f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // servers when running the test. We don't bother about the contents of the 402f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // buffer |dummy|, that's tested in other tests. 403f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string dummy; 404f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) g_browser_process->webrtc_log_uploader()-> 405f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) OverrideUploadWithBufferForTesting(&dummy); 406f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 407f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ASSERT_TRUE(content::ExecuteScript(tab, "browsertestRunAllTests();")); 408f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::TitleWatcher title_watcher(tab, base::ASCIIToUTF16("success")); 4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("failure")); 411a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 result = title_watcher.WaitAndGetTitle(); 4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(base::ASCIIToUTF16("success"), result); 413effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 414effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch g_browser_process->webrtc_log_uploader()->OverrideUploadWithBufferForTesting( 415effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NULL); 416f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif // defined(GOOGLE_CHROME_BUILD) || defined(ENABLE_HANGOUT_SERVICES_EXTENSION) 418f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 4191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} // namespace extensions 420