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 AudioWaitingExtensionTest::SetUp(); |
| 313 } |
| 314 }; |
| 315 |
| 316 IN_PROC_BROWSER_TEST_F(HangoutServicesBrowserTest, |
| 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 |