Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 "base/json/json_writer.h" | 5 #include "base/json/json_writer.h" |
| 6 #include "base/message_loop/message_loop.h" | 6 #include "base/message_loop/message_loop.h" |
| 7 #include "base/strings/string_util.h" | |
| 7 #include "base/strings/stringprintf.h" | 8 #include "base/strings/stringprintf.h" |
| 9 #include "base/strings/utf_string_conversions.h" | |
| 8 #include "base/synchronization/waitable_event.h" | 10 #include "base/synchronization/waitable_event.h" |
| 9 #include "base/threading/platform_thread.h" | 11 #include "base/threading/platform_thread.h" |
| 10 #include "base/time/time.h" | 12 #include "base/time/time.h" |
| 11 #include "chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_privat e_api.h" | 13 #include "chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_privat e_api.h" |
| 14 #include "chrome/browser/extensions/component_loader.h" | |
| 12 #include "chrome/browser/extensions/extension_apitest.h" | 15 #include "chrome/browser/extensions/extension_apitest.h" |
| 13 #include "chrome/browser/extensions/extension_function_test_utils.h" | 16 #include "chrome/browser/extensions/extension_function_test_utils.h" |
| 14 #include "chrome/browser/extensions/extension_tab_util.h" | 17 #include "chrome/browser/extensions/extension_tab_util.h" |
| 15 #include "chrome/browser/ui/browser.h" | 18 #include "chrome/browser/ui/browser.h" |
| 16 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 19 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 17 #include "chrome/common/extensions/permissions/permissions_data.h" | 20 #include "chrome/common/extensions/permissions/permissions_data.h" |
| 18 #include "chrome/test/base/in_process_browser_test.h" | 21 #include "chrome/test/base/in_process_browser_test.h" |
| 19 #include "chrome/test/base/ui_test_utils.h" | 22 #include "chrome/test/base/ui_test_utils.h" |
| 20 #include "content/public/browser/media_device_id.h" | 23 #include "content/public/browser/media_device_id.h" |
| 21 #include "content/public/browser/web_contents.h" | 24 #include "content/public/browser/web_contents.h" |
| 25 #include "content/public/test/browser_test_utils.h" | |
| 22 #include "extensions/common/permissions/permission_set.h" | 26 #include "extensions/common/permissions/permission_set.h" |
| 23 #include "media/audio/audio_manager.h" | 27 #include "media/audio/audio_manager.h" |
| 24 #include "net/test/embedded_test_server/embedded_test_server.h" | 28 #include "net/test/embedded_test_server/embedded_test_server.h" |
| 25 #include "testing/gtest/include/gtest/gtest.h" | 29 #include "testing/gtest/include/gtest/gtest.h" |
| 26 | 30 |
| 27 using base::JSONWriter; | 31 using base::JSONWriter; |
| 28 using content::RenderViewHost; | 32 using content::RenderViewHost; |
| 29 using content::WebContents; | 33 using content::WebContents; |
| 30 using media::AudioDeviceNames; | 34 using media::AudioDeviceNames; |
| 31 using media::AudioManager; | 35 using media::AudioManager; |
| 32 | 36 |
| 33 namespace extensions { | 37 namespace extensions { |
| 34 | 38 |
| 35 using extension_function_test_utils::RunFunctionAndReturnError; | 39 using extension_function_test_utils::RunFunctionAndReturnError; |
| 36 using extension_function_test_utils::RunFunctionAndReturnSingleResult; | 40 using extension_function_test_utils::RunFunctionAndReturnSingleResult; |
| 37 | 41 |
| 38 class WebrtcAudioPrivateTest : public ExtensionApiTest { | 42 class AudioWaitingExtensionTest : public ExtensionApiTest { |
| 43 protected: | |
| 44 void WaitUntilAudioIsPlaying(WebContents* tab) { | |
| 45 // Wait for audio to start playing. We gate this on there being one | |
| 46 // or more AudioOutputController objects for our tab. | |
| 47 bool audio_playing = false; | |
| 48 for (size_t remaining_tries = 50; remaining_tries > 0; --remaining_tries) { | |
| 49 tab->GetRenderViewHost()->GetAudioOutputControllers( | |
| 50 base::Bind(OnAudioControllers, &audio_playing)); | |
| 51 base::MessageLoop::current()->RunUntilIdle(); | |
| 52 if (audio_playing) | |
| 53 break; | |
| 54 | |
| 55 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); | |
| 56 } | |
| 57 | |
| 58 if (!audio_playing) | |
| 59 FAIL() << "Audio did not start playing within ~5 seconds."; | |
| 60 } | |
| 61 | |
| 62 // Used by the test above to wait until audio is playing. | |
| 63 static void OnAudioControllers( | |
| 64 bool* audio_playing, | |
| 65 const RenderViewHost::AudioOutputControllerList& list) { | |
| 66 if (!list.empty()) | |
| 67 *audio_playing = true; | |
| 68 } | |
| 69 }; | |
| 70 | |
| 71 class WebrtcAudioPrivateTest : public AudioWaitingExtensionTest { | |
| 39 public: | 72 public: |
| 40 WebrtcAudioPrivateTest() : enumeration_event_(false, false) { | 73 WebrtcAudioPrivateTest() : enumeration_event_(false, false) { |
| 41 } | 74 } |
| 42 | 75 |
| 43 protected: | 76 protected: |
| 44 std::string InvokeGetActiveSink(int tab_id) { | 77 std::string InvokeGetActiveSink(int tab_id) { |
| 45 ListValue parameters; | 78 ListValue parameters; |
| 46 parameters.AppendInteger(tab_id); | 79 parameters.AppendInteger(tab_id); |
| 47 std::string parameter_string; | 80 std::string parameter_string; |
| 48 JSONWriter::Write(¶meters, ¶meter_string); | 81 JSONWriter::Write(¶meters, ¶meter_string); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 158 | 191 |
| 159 scoped_refptr<WebrtcAudioPrivateSetActiveSinkFunction> function = | 192 scoped_refptr<WebrtcAudioPrivateSetActiveSinkFunction> function = |
| 160 new WebrtcAudioPrivateSetActiveSinkFunction(); | 193 new WebrtcAudioPrivateSetActiveSinkFunction(); |
| 161 std::string error(RunFunctionAndReturnError(function.get(), | 194 std::string error(RunFunctionAndReturnError(function.get(), |
| 162 parameter_string, | 195 parameter_string, |
| 163 browser())); | 196 browser())); |
| 164 EXPECT_EQ(base::StringPrintf("No active stream for tab with id: %d.", tab_id), | 197 EXPECT_EQ(base::StringPrintf("No active stream for tab with id: %d.", tab_id), |
| 165 error); | 198 error); |
| 166 } | 199 } |
| 167 | 200 |
| 168 // Used by the test below to wait until audio is playing. | |
| 169 static void OnAudioControllers( | |
| 170 bool* audio_playing, | |
| 171 const RenderViewHost::AudioOutputControllerList& list) { | |
| 172 if (!list.empty()) | |
| 173 *audio_playing = true; | |
| 174 } | |
| 175 | |
| 176 IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, GetAndSetWithMediaStream) { | 201 IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, GetAndSetWithMediaStream) { |
| 177 // First get the list of output devices, so that we can (if | 202 // First get the list of output devices, so that we can (if |
| 178 // available) set the active device to a device other than the one | 203 // available) set the active device to a device other than the one |
| 179 // it starts as. This function is not threadsafe and is normally | 204 // it starts as. This function is not threadsafe and is normally |
| 180 // called only from the audio IO thread, but we know no other code | 205 // called only from the audio IO thread, but we know no other code |
| 181 // is currently running so we call it directly. | 206 // is currently running so we call it directly. |
| 182 AudioDeviceNames devices; | 207 AudioDeviceNames devices; |
| 183 GetAudioDeviceNames(&AudioManager::GetAudioOutputDeviceNames, &devices); | 208 GetAudioDeviceNames(&AudioManager::GetAudioOutputDeviceNames, &devices); |
| 184 | 209 |
| 185 ASSERT_TRUE(StartEmbeddedTestServer()); | 210 ASSERT_TRUE(StartEmbeddedTestServer()); |
| 186 | 211 |
| 187 // Open a normal page that uses an audio sink. | 212 // Open a normal page that uses an audio sink. |
| 188 ui_test_utils::NavigateToURL( | 213 ui_test_utils::NavigateToURL( |
| 189 browser(), | 214 browser(), |
| 190 GURL(embedded_test_server()->GetURL("/extensions/loop_audio.html"))); | 215 GURL(embedded_test_server()->GetURL("/extensions/loop_audio.html"))); |
| 191 | 216 |
| 192 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); | 217 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); |
| 193 int tab_id = ExtensionTabUtil::GetTabId(tab); | 218 int tab_id = ExtensionTabUtil::GetTabId(tab); |
| 194 | 219 |
| 195 // Wait for audio to start playing. We gate this on there being one | 220 WaitUntilAudioIsPlaying(tab); |
| 196 // or more AudioOutputController objects for our tab. | |
| 197 bool audio_playing = false; | |
| 198 for (size_t remaining_tries = 50; remaining_tries > 0; --remaining_tries) { | |
| 199 tab->GetRenderViewHost()->GetAudioOutputControllers( | |
| 200 base::Bind(OnAudioControllers, &audio_playing)); | |
| 201 base::MessageLoop::current()->RunUntilIdle(); | |
| 202 if (audio_playing) | |
| 203 break; | |
| 204 | |
| 205 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); | |
| 206 } | |
| 207 | |
| 208 if (!audio_playing) | |
| 209 FAIL() << "Audio did not start playing within ~5 seconds."; | |
| 210 | 221 |
| 211 std::string current_device = InvokeGetActiveSink(tab_id); | 222 std::string current_device = InvokeGetActiveSink(tab_id); |
| 212 VLOG(2) << "Before setting, current device: " << current_device; | 223 VLOG(2) << "Before setting, current device: " << current_device; |
| 213 EXPECT_NE("", current_device); | 224 EXPECT_NE("", current_device); |
| 214 | 225 |
| 215 // Set to each of the other devices in turn. | 226 // Set to each of the other devices in turn. |
| 216 for (AudioDeviceNames::const_iterator it = devices.begin(); | 227 for (AudioDeviceNames::const_iterator it = devices.begin(); |
| 217 it != devices.end(); | 228 it != devices.end(); |
| 218 ++it) { | 229 ++it) { |
| 219 std::string target_device(it->unique_id); | 230 std::string target_device(it->unique_id); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 286 const extensions::Extension* extension = LoadExtension( | 297 const extensions::Extension* extension = LoadExtension( |
| 287 test_data_dir_.AppendASCII("webrtc_audio_private_event_listener")); | 298 test_data_dir_.AppendASCII("webrtc_audio_private_event_listener")); |
| 288 service->OnDevicesChanged(base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE); | 299 service->OnDevicesChanged(base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE); |
| 289 | 300 |
| 290 // Check that the extension got the notification. | 301 // Check that the extension got the notification. |
| 291 std::string result = ExecuteScriptInBackgroundPage(extension->id(), | 302 std::string result = ExecuteScriptInBackgroundPage(extension->id(), |
| 292 "reportIfGot()"); | 303 "reportIfGot()"); |
| 293 EXPECT_EQ("true", result); | 304 EXPECT_EQ("true", result); |
| 294 } | 305 } |
| 295 | 306 |
| 307 class HangoutServicesBrowserTest : public AudioWaitingExtensionTest { | |
| 308 public: | |
| 309 virtual void SetUp() OVERRIDE { | |
| 310 // Make sure the Hangout Services component extension gets loaded. | |
| 311 ComponentLoader::EnableBackgroundExtensionsForTesting(); | |
| 312 ExtensionBrowserTest::SetUp(); | |
|
Henrik Grunell
2013/11/06 08:49:01
Just checking: should it be ExtensionApiTest::SetU
Jói
2013/11/06 11:19:29
Good catch, it should be <superclass>::SetUp(), so
| |
| 313 } | |
| 314 }; | |
| 315 | |
| 316 IN_PROC_BROWSER_TEST_F(HangoutServicesBrowserTest, | |
|
Henrik Grunell
2013/11/06 08:49:01
If the services test runs other than audio tests,
Jói
2013/11/06 11:19:29
I thought about that, but it doesn't really belong
Henrik Grunell
2013/11/06 11:43:30
I'm fine with that.
| |
| 317 RunComponentExtensionTest) { | |
| 318 // This runs the end-to-end JavaScript test for the Hangout Services | |
| 319 // component extension, which uses the webrtcAudioPrivate API among | |
| 320 // others. | |
| 321 ASSERT_TRUE(StartEmbeddedTestServer()); | |
| 322 GURL url(embedded_test_server()->GetURL( | |
| 323 "/extensions/hangout_services_test.html")); | |
| 324 // The "externally connectable" extension permission doesn't seem to | |
| 325 // like when we use 127.0.0.1 as the host, but using localhost works. | |
| 326 std::string url_spec = url.spec(); | |
| 327 ReplaceFirstSubstringAfterOffset(&url_spec, 0, "127.0.0.1", "localhost"); | |
| 328 GURL localhost_url(url_spec); | |
| 329 ui_test_utils::NavigateToURL(browser(), localhost_url); | |
| 330 | |
| 331 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); | |
| 332 WaitUntilAudioIsPlaying(tab); | |
| 333 | |
| 334 ASSERT_TRUE(content::ExecuteScript(tab, "browsertestRunAllTests();")); | |
| 335 | |
| 336 content::TitleWatcher title_watcher(tab, ASCIIToUTF16("success")); | |
| 337 title_watcher.AlsoWaitForTitle(ASCIIToUTF16("failure")); | |
| 338 string16 result = title_watcher.WaitAndGetTitle(); | |
| 339 EXPECT_EQ(ASCIIToUTF16("success"), result); | |
| 340 } | |
| 341 | |
| 296 } // namespace extensions | 342 } // namespace extensions |
| OLD | NEW |