1 // Copyright (c) 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/process/process_handle.h"
6 #include "base/strings/string_number_conversions.h"
7 #include "base/strings/stringprintf.h"
8 #include "content/browser/media/webrtc_internals.h"
9 #include "content/browser/web_contents/web_contents_impl.h"
10 #include "content/public/test/browser_test_utils.h"
11 #include "content/public/test/content_browser_test_utils.h"
12 #include "content/shell/browser/shell.h"
13 #include "content/test/webrtc_content_browsertest_base.h"
14 #include "media/audio/audio_manager.h"
15 #include "net/test/embedded_test_server/embedded_test_server.h"
19 const int kExpectedConsumerId
= 0;
21 // Get the ID for the render process host when there should only be one.
22 bool GetRenderProcessHostId(base::ProcessId
* id
) {
23 content::RenderProcessHost::iterator
it(
24 content::RenderProcessHost::AllHostsIterator());
25 *id
= base::GetProcId(it
.GetCurrentValue()->GetHandle());
26 EXPECT_NE(base::kNullProcessId
, *id
);
27 if (*id
== base::kNullProcessId
)
30 EXPECT_TRUE(it
.IsAtEnd());
38 class WebRtcAecDumpBrowserTest
: public WebRtcContentBrowserTest
{
40 WebRtcAecDumpBrowserTest() {}
41 ~WebRtcAecDumpBrowserTest() override
{}
45 #define IntToStringType base::IntToString16
47 #define IntToStringType base::IntToString
50 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
51 // Timing out on ARM linux bot: http://crbug.com/238490
52 #define MAYBE_CallWithAecDump DISABLED_CallWithAecDump
53 #elif defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)
54 // Renderer crashes under Android ASAN: https://crbug.com/408496.
55 #define MAYBE_CallWithAecDump DISABLED_CallWithAecDump
57 #define MAYBE_CallWithAecDump CallWithAecDump
60 // This tests will make a complete PeerConnection-based call, verify that
61 // video is playing for the call, and verify that a non-empty AEC dump file
62 // exists. The AEC dump is enabled through webrtc-internals. The HTML and
63 // Javascript is bypassed since it would trigger a file picker dialog. Instead,
64 // the dialog callback FileSelected() is invoked directly. In fact, there's
65 // never a webrtc-internals page opened at all since that's not needed.
66 IN_PROC_BROWSER_TEST_F(WebRtcAecDumpBrowserTest
, MAYBE_CallWithAecDump
) {
67 if (!media::AudioManager::Get()->HasAudioOutputDevices()) {
68 LOG(INFO
) << "Missing output devices: skipping test...";
72 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
74 // We must navigate somewhere first so that the render process is created.
75 NavigateToURL(shell(), GURL(""));
77 base::FilePath dump_file
;
78 ASSERT_TRUE(CreateTemporaryFile(&dump_file
));
79 base::DeleteFile(dump_file
, false);
81 // This fakes the behavior of another open tab with webrtc-internals, and
82 // enabling AEC dump in that tab.
83 WebRTCInternals::GetInstance()->FileSelected(dump_file
, -1, NULL
);
85 GURL
url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
86 NavigateToURL(shell(), url
);
87 DisableOpusIfOnAndroid();
88 ExecuteJavascriptAndWaitForOk("call({video: true, audio: true});");
90 EXPECT_FALSE(base::PathExists(dump_file
));
92 // Add file extensions that we expect to be added. The dump name will be
93 // <temporary path>.<render process id>.<consumer id>, for example
94 // "/tmp/.com.google.Chrome.Z6UC3P.12345.0".
95 base::ProcessId render_process_id
= base::kNullProcessId
;
96 EXPECT_TRUE(GetRenderProcessHostId(&render_process_id
));
97 dump_file
= dump_file
.AddExtension(IntToStringType(render_process_id
))
98 .AddExtension(IntToStringType(kExpectedConsumerId
));
100 EXPECT_TRUE(base::PathExists(dump_file
));
102 EXPECT_TRUE(base::GetFileSize(dump_file
, &file_size
));
103 EXPECT_GT(file_size
, 0);
105 base::DeleteFile(dump_file
, false);
108 // TODO(grunell): Add test for multiple dumps when re-use of
109 // MediaStreamAudioProcessor in AudioCapturer has been removed.
111 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
112 // Timing out on ARM linux bot: http://crbug.com/238490
113 #define MAYBE_CallWithAecDumpEnabledThenDisabled DISABLED_CallWithAecDumpEnabledThenDisabled
114 #elif defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)
115 // Renderer crashes under Android ASAN: https://crbug.com/408496.
116 #define MAYBE_CallWithAecDumpEnabledThenDisabled DISABLED_CallWithAecDumpEnabledThenDisabled
118 #define MAYBE_CallWithAecDumpEnabledThenDisabled CallWithAecDumpEnabledThenDisabled
121 // As above, but enable and disable dump before starting a call. The file should
122 // be created, but should be empty.
123 IN_PROC_BROWSER_TEST_F(WebRtcAecDumpBrowserTest
,
124 MAYBE_CallWithAecDumpEnabledThenDisabled
) {
125 if (!media::AudioManager::Get()->HasAudioOutputDevices()) {
126 LOG(INFO
) << "Missing output devices: skipping test...";
130 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
132 // We must navigate somewhere first so that the render process is created.
133 NavigateToURL(shell(), GURL(""));
135 base::FilePath dump_file
;
136 ASSERT_TRUE(CreateTemporaryFile(&dump_file
));
137 base::DeleteFile(dump_file
, false);
139 // This fakes the behavior of another open tab with webrtc-internals, and
140 // enabling AEC dump in that tab, then disabling it.
141 WebRTCInternals::GetInstance()->FileSelected(dump_file
, -1, NULL
);
142 WebRTCInternals::GetInstance()->DisableAecDump();
144 GURL
url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
145 NavigateToURL(shell(), url
);
146 DisableOpusIfOnAndroid();
147 ExecuteJavascriptAndWaitForOk("call({video: true, audio: true});");
149 // Add file extensions that we expect to be added.
150 base::ProcessId render_process_id
= base::kNullProcessId
;
151 EXPECT_TRUE(GetRenderProcessHostId(&render_process_id
));
152 dump_file
= dump_file
.AddExtension(IntToStringType(render_process_id
))
153 .AddExtension(IntToStringType(kExpectedConsumerId
));
155 EXPECT_FALSE(base::PathExists(dump_file
));
157 base::DeleteFile(dump_file
, false);
160 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
161 // Timing out on ARM linux bot: http://crbug.com/238490
162 #define MAYBE_TwoCallsWithAecDump DISABLED_TwoCallsWithAecDump
163 #elif defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)
164 // Renderer crashes under Android ASAN: https://crbug.com/408496.
165 #define MAYBE_TwoCallsWithAecDump DISABLED_TwoCallsWithAecDump
167 #define MAYBE_TwoCallsWithAecDump TwoCallsWithAecDump
170 IN_PROC_BROWSER_TEST_F(WebRtcAecDumpBrowserTest
, MAYBE_TwoCallsWithAecDump
) {
172 // http://crbug.com/425034.
173 LOG(INFO
) << "Disabled on Win XP: skipping test...";
176 if (!media::AudioManager::Get()->HasAudioOutputDevices()) {
177 LOG(INFO
) << "Missing output devices: skipping test...";
181 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
183 // We must navigate somewhere first so that the render process is created.
184 NavigateToURL(shell(), GURL(""));
186 // Create a second window.
187 Shell
* shell2
= CreateBrowser();
188 NavigateToURL(shell2
, GURL(""));
190 base::FilePath dump_file
;
191 ASSERT_TRUE(CreateTemporaryFile(&dump_file
));
192 base::DeleteFile(dump_file
, false);
194 // This fakes the behavior of another open tab with webrtc-internals, and
195 // enabling AEC dump in that tab.
196 WebRTCInternals::GetInstance()->FileSelected(dump_file
, -1, NULL
);
198 GURL
url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
200 NavigateToURL(shell(), url
);
201 NavigateToURL(shell2
, url
);
202 ExecuteJavascriptAndWaitForOk("call({video: true, audio: true});");
204 EXPECT_TRUE(ExecuteScriptAndExtractString(
205 shell2
->web_contents(),
206 "call({video: true, audio: true});",
208 ASSERT_STREQ("OK", result
.c_str());
210 EXPECT_FALSE(base::PathExists(dump_file
));
212 RenderProcessHost::iterator it
=
213 content::RenderProcessHost::AllHostsIterator();
214 for (; !it
.IsAtEnd(); it
.Advance()) {
215 base::ProcessId render_process_id
=
216 base::GetProcId(it
.GetCurrentValue()->GetHandle());
217 EXPECT_NE(base::kNullProcessId
, render_process_id
);
219 // Add file extensions that we expect to be added.
220 base::FilePath unique_dump_file
=
221 dump_file
.AddExtension(IntToStringType(render_process_id
))
222 .AddExtension(IntToStringType(kExpectedConsumerId
));
224 EXPECT_TRUE(base::PathExists(unique_dump_file
));
226 EXPECT_TRUE(base::GetFileSize(unique_dump_file
, &file_size
));
227 EXPECT_GT(file_size
, 0);
229 base::DeleteFile(unique_dump_file
, false);
233 } // namespace content