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 <stddef.h> | 5 #include <stddef.h> |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/json/json_writer.h" | 10 #include "base/json/json_writer.h" |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 using media::AudioManager; | 50 using media::AudioManager; |
51 | 51 |
52 namespace extensions { | 52 namespace extensions { |
53 | 53 |
54 using extension_function_test_utils::RunFunctionAndReturnError; | 54 using extension_function_test_utils::RunFunctionAndReturnError; |
55 using extension_function_test_utils::RunFunctionAndReturnSingleResult; | 55 using extension_function_test_utils::RunFunctionAndReturnSingleResult; |
56 | 56 |
57 class AudioWaitingExtensionTest : public ExtensionApiTest { | 57 class AudioWaitingExtensionTest : public ExtensionApiTest { |
58 protected: | 58 protected: |
59 void WaitUntilAudioIsPlaying(WebContents* tab) { | 59 void WaitUntilAudioIsPlaying(WebContents* tab) { |
60 // Wait for audio to start playing. We gate this on there being one | 60 // Wait for audio to start playing. |
61 // or more AudioOutputController objects for our tab. | |
62 bool audio_playing = false; | 61 bool audio_playing = false; |
63 for (size_t remaining_tries = 50; remaining_tries > 0; --remaining_tries) { | 62 for (size_t remaining_tries = 50; remaining_tries > 0; --remaining_tries) { |
64 tab->GetRenderProcessHost()->GetAudioOutputControllers( | 63 audio_playing = tab->WasRecentlyAudible(); |
65 base::Bind(OnAudioControllers, &audio_playing)); | |
66 base::RunLoop().RunUntilIdle(); | 64 base::RunLoop().RunUntilIdle(); |
67 if (audio_playing) | 65 if (audio_playing) |
68 break; | 66 break; |
69 | 67 |
70 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); | 68 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); |
71 } | 69 } |
72 | 70 |
73 if (!audio_playing) | 71 if (!audio_playing) |
74 FAIL() << "Audio did not start playing within ~5 seconds."; | 72 FAIL() << "Audio did not start playing within ~5 seconds."; |
75 } | 73 } |
76 | |
77 // Used by the test above to wait until audio is playing. | |
78 static void OnAudioControllers( | |
79 bool* audio_playing, | |
80 const RenderProcessHost::AudioOutputControllerList& list) { | |
81 if (!list.empty()) | |
82 *audio_playing = true; | |
83 } | |
84 }; | 74 }; |
85 | 75 |
86 class WebrtcAudioPrivateTest : public AudioWaitingExtensionTest { | 76 class WebrtcAudioPrivateTest : public AudioWaitingExtensionTest { |
87 public: | 77 public: |
88 WebrtcAudioPrivateTest() | 78 WebrtcAudioPrivateTest() |
89 : enumeration_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC, | 79 : enumeration_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC, |
90 base::WaitableEvent::InitialState::NOT_SIGNALED) {} | 80 base::WaitableEvent::InitialState::NOT_SIGNALED) {} |
91 | 81 |
92 void SetUpOnMainThread() override { | 82 void SetUpOnMainThread() override { |
93 AudioWaitingExtensionTest::SetUpOnMainThread(); | 83 AudioWaitingExtensionTest::SetUpOnMainThread(); |
94 // Needs to happen after chrome's schemes are added. | 84 // Needs to happen after chrome's schemes are added. |
95 source_url_ = GURL("chrome-extension://fakeid012345678/fakepage.html"); | 85 source_url_ = GURL("chrome-extension://fakeid012345678/fakepage.html"); |
96 } | 86 } |
97 | 87 |
98 protected: | 88 protected: |
99 void AppendTabIdToRequestInfo(base::ListValue* params, int tab_id) { | 89 void AppendTabIdToRequestInfo(base::ListValue* params, int tab_id) { |
100 std::unique_ptr<base::DictionaryValue> request_info( | 90 std::unique_ptr<base::DictionaryValue> request_info( |
101 new base::DictionaryValue()); | 91 new base::DictionaryValue()); |
102 request_info->SetInteger("tabId", tab_id); | 92 request_info->SetInteger("tabId", tab_id); |
103 params->Append(std::move(request_info)); | 93 params->Append(std::move(request_info)); |
104 } | 94 } |
105 | 95 |
106 std::string InvokeGetActiveSink(int tab_id) { | |
107 base::ListValue parameters; | |
108 AppendTabIdToRequestInfo(¶meters, tab_id); | |
109 std::string parameter_string; | |
110 JSONWriter::Write(parameters, ¶meter_string); | |
111 | |
112 scoped_refptr<WebrtcAudioPrivateGetActiveSinkFunction> function = | |
113 new WebrtcAudioPrivateGetActiveSinkFunction(); | |
114 function->set_source_url(source_url_); | |
115 std::unique_ptr<base::Value> result(RunFunctionAndReturnSingleResult( | |
116 function.get(), parameter_string, browser())); | |
117 std::string device_id; | |
118 result->GetAsString(&device_id); | |
119 return device_id; | |
120 } | |
121 | |
122 std::unique_ptr<base::Value> InvokeGetSinks(base::ListValue** sink_list) { | 96 std::unique_ptr<base::Value> InvokeGetSinks(base::ListValue** sink_list) { |
123 scoped_refptr<WebrtcAudioPrivateGetSinksFunction> function = | 97 scoped_refptr<WebrtcAudioPrivateGetSinksFunction> function = |
124 new WebrtcAudioPrivateGetSinksFunction(); | 98 new WebrtcAudioPrivateGetSinksFunction(); |
125 function->set_source_url(source_url_); | 99 function->set_source_url(source_url_); |
126 | 100 |
127 std::unique_ptr<base::Value> result( | 101 std::unique_ptr<base::Value> result( |
128 RunFunctionAndReturnSingleResult(function.get(), "[]", browser())); | 102 RunFunctionAndReturnSingleResult(function.get(), "[]", browser())); |
129 result->GetAsList(sink_list); | 103 result->GetAsList(sink_list); |
130 return result; | 104 return result; |
131 } | 105 } |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 | 199 |
226 // TODO(joi): Verify the contents of these once we start actually | 200 // TODO(joi): Verify the contents of these once we start actually |
227 // filling them in. | 201 // filling them in. |
228 EXPECT_TRUE(dict->HasKey("isDefault")); | 202 EXPECT_TRUE(dict->HasKey("isDefault")); |
229 EXPECT_TRUE(dict->HasKey("isReady")); | 203 EXPECT_TRUE(dict->HasKey("isReady")); |
230 EXPECT_TRUE(dict->HasKey("sampleRate")); | 204 EXPECT_TRUE(dict->HasKey("sampleRate")); |
231 } | 205 } |
232 } | 206 } |
233 #endif // OS_MACOSX | 207 #endif // OS_MACOSX |
234 | 208 |
235 // This exercises the case where you have a tab with no active media | |
236 // stream and try to retrieve the currently active audio sink. | |
237 IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, GetActiveSinkNoMediaStream) { | |
238 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); | |
239 int tab_id = ExtensionTabUtil::GetTabId(tab); | |
240 base::ListValue parameters; | |
241 AppendTabIdToRequestInfo(¶meters, tab_id); | |
242 std::string parameter_string; | |
243 JSONWriter::Write(parameters, ¶meter_string); | |
244 | |
245 scoped_refptr<WebrtcAudioPrivateGetActiveSinkFunction> function = | |
246 new WebrtcAudioPrivateGetActiveSinkFunction(); | |
247 function->set_source_url(source_url_); | |
248 std::unique_ptr<base::Value> result(RunFunctionAndReturnSingleResult( | |
249 function.get(), parameter_string, browser())); | |
250 | |
251 std::string result_string; | |
252 JSONWriter::Write(*result, &result_string); | |
253 EXPECT_EQ("\"\"", result_string); | |
254 } | |
255 | |
256 // This exercises the case where you have a tab with no active media | |
257 // stream and try to set the audio sink. | |
258 IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, SetActiveSinkNoMediaStream) { | |
259 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); | |
260 int tab_id = ExtensionTabUtil::GetTabId(tab); | |
261 base::ListValue parameters; | |
262 AppendTabIdToRequestInfo(¶meters, tab_id); | |
263 parameters.AppendString("no such id"); | |
264 std::string parameter_string; | |
265 JSONWriter::Write(parameters, ¶meter_string); | |
266 | |
267 scoped_refptr<WebrtcAudioPrivateSetActiveSinkFunction> function = | |
268 new WebrtcAudioPrivateSetActiveSinkFunction(); | |
269 function->set_source_url(source_url_); | |
270 std::string error(RunFunctionAndReturnError(function.get(), | |
271 parameter_string, | |
272 browser())); | |
273 EXPECT_EQ(base::StringPrintf("No active stream for tabId %d", tab_id), | |
274 error); | |
275 } | |
276 | |
277 IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, GetAndSetWithMediaStream) { | |
278 // Disabled on Win 7. https://crbug.com/500432. | |
279 #if defined(OS_WIN) | |
280 if (base::win::GetVersion() == base::win::VERSION_WIN7) | |
281 return; | |
282 #endif | |
283 | |
284 // First retrieve the list of all sinks, so that we can run a test | |
285 // where we set the active sink to each of the different available | |
286 // sinks in turn. | |
287 base::ListValue* sink_list = NULL; | |
288 std::unique_ptr<base::Value> result = InvokeGetSinks(&sink_list); | |
289 | |
290 ASSERT_TRUE(StartEmbeddedTestServer()); | |
291 | |
292 // Open a normal page that uses an audio sink. | |
293 ui_test_utils::NavigateToURL( | |
294 browser(), | |
295 GURL(embedded_test_server()->GetURL("/extensions/loop_audio.html"))); | |
296 | |
297 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); | |
298 int tab_id = ExtensionTabUtil::GetTabId(tab); | |
299 | |
300 WaitUntilAudioIsPlaying(tab); | |
301 | |
302 std::string current_device = InvokeGetActiveSink(tab_id); | |
303 VLOG(2) << "Before setting, current device: " << current_device; | |
304 EXPECT_NE("", current_device); | |
305 | |
306 // Set to each of the other devices in turn. | |
307 for (size_t ix = 0; ix < sink_list->GetSize(); ++ix) { | |
308 base::DictionaryValue* dict = NULL; | |
309 sink_list->GetDictionary(ix, &dict); | |
310 std::string target_device; | |
311 dict->GetString("sinkId", &target_device); | |
312 | |
313 base::ListValue parameters; | |
314 AppendTabIdToRequestInfo(¶meters, tab_id); | |
315 parameters.AppendString(target_device); | |
316 std::string parameter_string; | |
317 JSONWriter::Write(parameters, ¶meter_string); | |
318 | |
319 scoped_refptr<WebrtcAudioPrivateSetActiveSinkFunction> function = | |
320 new WebrtcAudioPrivateSetActiveSinkFunction(); | |
321 function->set_source_url(source_url_); | |
322 std::unique_ptr<base::Value> result(RunFunctionAndReturnSingleResult( | |
323 function.get(), parameter_string, browser())); | |
324 // The function was successful if the above invocation doesn't | |
325 // fail. Just for kicks, also check that it returns no result. | |
326 EXPECT_EQ(NULL, result.get()); | |
327 | |
328 current_device = InvokeGetActiveSink(tab_id); | |
329 VLOG(2) << "After setting to " << target_device | |
330 << ", current device is " << current_device; | |
331 EXPECT_EQ(target_device, current_device); | |
332 } | |
333 } | |
334 | |
335 IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, GetAssociatedSink) { | 209 IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, GetAssociatedSink) { |
336 // Get the list of input devices. We can cheat in the unit test and | 210 // Get the list of input devices. We can cheat in the unit test and |
337 // run this on the main thread since nobody else will be running at | 211 // run this on the main thread since nobody else will be running at |
338 // the same time. | 212 // the same time. |
339 AudioDeviceDescriptions devices; | 213 AudioDeviceDescriptions devices; |
340 GetAudioDeviceDescriptions(&AudioManager::GetAudioInputDeviceDescriptions, | 214 GetAudioDeviceDescriptions(&AudioManager::GetAudioInputDeviceDescriptions, |
341 &devices); | 215 &devices); |
342 | 216 |
343 // Try to get an associated sink for each source. | 217 // Try to get an associated sink for each source. |
344 for (const auto& device : devices) { | 218 for (const auto& device : devices) { |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("failure")); | 303 title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("failure")); |
430 base::string16 result = title_watcher.WaitAndGetTitle(); | 304 base::string16 result = title_watcher.WaitAndGetTitle(); |
431 EXPECT_EQ(base::ASCIIToUTF16("success"), result); | 305 EXPECT_EQ(base::ASCIIToUTF16("success"), result); |
432 | 306 |
433 g_browser_process->webrtc_log_uploader()->OverrideUploadWithBufferForTesting( | 307 g_browser_process->webrtc_log_uploader()->OverrideUploadWithBufferForTesting( |
434 NULL); | 308 NULL); |
435 } | 309 } |
436 #endif // BUILDFLAG(ENABLE_HANGOUT_SERVICES_EXTENSION) | 310 #endif // BUILDFLAG(ENABLE_HANGOUT_SERVICES_EXTENSION) |
437 | 311 |
438 } // namespace extensions | 312 } // namespace extensions |
OLD | NEW |