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
3 // found in the LICENSE file.
4
5 #include "base/command_line.h"
6 #include "base/deferred_sequenced_task_runner.h"
7 #include "base/test/bind.h"
8 #include "build/build_config.h"
9 #include "chrome/browser/media/webrtc/webrtc_browsertest_base.h"
10 #include "chrome/browser/media/webrtc/webrtc_browsertest_common.h"
11 #include "chrome/browser/ui/browser.h"
12 #include "chrome/browser/ui/browser_tabstrip.h"
13 #include "chrome/browser/ui/tabs/tab_strip_model.h"
14 #include "chrome/common/chrome_switches.h"
15 #include "chrome/test/base/in_process_browser_test.h"
16 #include "chrome/test/base/ui_test_utils.h"
17 #include "content/public/browser/network_service_instance.h"
18 #include "content/public/common/content_switches.h"
19 #include "content/public/common/network_service_util.h"
20 #include "content/public/test/browser_test.h"
21 #include "content/public/test/browser_test_utils.h"
22 #include "media/base/media_switches.h"
23 #include "mojo/public/cpp/bindings/remote.h"
24 #include "net/nqe/network_quality_estimator.h"
25 #include "net/test/embedded_test_server/embedded_test_server.h"
26 #include "services/network/network_service.h"
27 #include "services/network/public/cpp/features.h"
28 #include "services/network/public/mojom/network_service_test.mojom.h"
29 #include "third_party/blink/public/common/features.h"
30
31 #if defined(OS_MAC)
32 #include "base/mac/mac_util.h"
33 #endif
34
35 static const char kMainWebrtcTestHtmlPage[] =
36 "/webrtc/webrtc_jsep01_test.html";
37
38 static const char kKeygenAlgorithmRsa[] =
39 "{ name: \"RSASSA-PKCS1-v1_5\", modulusLength: 2048, publicExponent: "
40 "new Uint8Array([1, 0, 1]), hash: \"SHA-256\" }";
41 static const char kKeygenAlgorithmEcdsa[] =
42 "{ name: \"ECDSA\", namedCurve: \"P-256\" }";
43
44 // Top-level integration test for WebRTC. It always uses fake devices; see
45 // WebRtcWebcamBrowserTest for a test that acquires any real webcam on the
46 // system.
47 class WebRtcBrowserTest : public WebRtcTestBase {
48 public:
WebRtcBrowserTest()49 WebRtcBrowserTest() : left_tab_(nullptr), right_tab_(nullptr) {}
50
SetUpInProcessBrowserTestFixture()51 void SetUpInProcessBrowserTestFixture() override {
52 DetectErrorsInJavaScript(); // Look for errors in our rather complex js.
53 }
54
SetUpCommandLine(base::CommandLine * command_line)55 void SetUpCommandLine(base::CommandLine* command_line) override {
56 // Ensure the infobar is enabled, since we expect that in this test.
57 EXPECT_FALSE(command_line->HasSwitch(switches::kUseFakeUIForMediaStream));
58
59 // Flag used by TestWebAudioMediaStream to force garbage collection.
60 command_line->AppendSwitchASCII(switches::kJavaScriptFlags, "--expose-gc");
61 }
62
RunsAudioVideoWebRTCCallInTwoTabs(const std::string & video_codec=WebRtcTestBase::kUseDefaultVideoCodec,bool prefer_hw_video_codec=false,const std::string & offer_cert_keygen_alg=WebRtcTestBase::kUseDefaultCertKeygen,const std::string & answer_cert_keygen_alg=WebRtcTestBase::kUseDefaultCertKeygen)63 void RunsAudioVideoWebRTCCallInTwoTabs(
64 const std::string& video_codec = WebRtcTestBase::kUseDefaultVideoCodec,
65 bool prefer_hw_video_codec = false,
66 const std::string& offer_cert_keygen_alg =
67 WebRtcTestBase::kUseDefaultCertKeygen,
68 const std::string& answer_cert_keygen_alg =
69 WebRtcTestBase::kUseDefaultCertKeygen) {
70 StartServerAndOpenTabs();
71
72 SetupPeerconnectionWithLocalStream(left_tab_, offer_cert_keygen_alg);
73 SetupPeerconnectionWithLocalStream(right_tab_, answer_cert_keygen_alg);
74
75 if (!video_codec.empty()) {
76 SetDefaultVideoCodec(left_tab_, video_codec, prefer_hw_video_codec);
77 SetDefaultVideoCodec(right_tab_, video_codec, prefer_hw_video_codec);
78 }
79 NegotiateCall(left_tab_, right_tab_);
80
81 DetectVideoAndHangUp();
82 }
83
RunsAudioVideoWebRTCCallInTwoTabsWithClonedCertificate(const std::string & cert_keygen_alg=WebRtcTestBase::kUseDefaultCertKeygen)84 void RunsAudioVideoWebRTCCallInTwoTabsWithClonedCertificate(
85 const std::string& cert_keygen_alg =
86 WebRtcTestBase::kUseDefaultCertKeygen) {
87 StartServerAndOpenTabs();
88
89 // Generate and clone a certificate, resulting in JavaScript variable
90 // |gCertificateClone| being set to the resulting clone.
91 DeleteDatabase(left_tab_);
92 OpenDatabase(left_tab_);
93 GenerateAndCloneCertificate(left_tab_, cert_keygen_alg);
94 CloseDatabase(left_tab_);
95 DeleteDatabase(left_tab_);
96
97 SetupPeerconnectionWithCertificateAndLocalStream(
98 left_tab_, "gCertificateClone");
99 SetupPeerconnectionWithLocalStream(right_tab_, cert_keygen_alg);
100
101 NegotiateCall(left_tab_, right_tab_);
102 VerifyLocalDescriptionContainsCertificate(left_tab_, "gCertificate");
103
104 DetectVideoAndHangUp();
105 }
106
GetPeerToPeerConnectionsCountChangeFromNetworkService()107 uint32_t GetPeerToPeerConnectionsCountChangeFromNetworkService() {
108 uint32_t connection_count = 0u;
109 if (content::IsInProcessNetworkService()) {
110 base::RunLoop run_loop;
111 content::GetNetworkTaskRunner()->PostTask(
112 FROM_HERE, base::BindLambdaForTesting([&connection_count, &run_loop] {
113 connection_count =
114 network::NetworkService::GetNetworkServiceForTesting()
115 ->network_quality_estimator()
116 ->GetPeerToPeerConnectionsCountChange();
117 run_loop.Quit();
118 }));
119 run_loop.Run();
120 return connection_count;
121 }
122
123 mojo::Remote<network::mojom::NetworkServiceTest> network_service_test;
124 content::GetNetworkService()->BindTestInterface(
125 network_service_test.BindNewPipeAndPassReceiver());
126 // TODO(crbug.com/901026): Make sure the network process is started to avoid
127 // a deadlock on Android.
128 network_service_test.FlushForTesting();
129
130 mojo::ScopedAllowSyncCallForTesting allow_sync_call;
131
132 bool available = network_service_test->GetPeerToPeerConnectionsCountChange(
133 &connection_count);
134 EXPECT_TRUE(available);
135
136 return connection_count;
137 }
138
139 protected:
StartServerAndOpenTabs()140 void StartServerAndOpenTabs() {
141 ASSERT_TRUE(embedded_test_server()->Start());
142 left_tab_ = OpenTestPageAndGetUserMediaInNewTab(kMainWebrtcTestHtmlPage);
143 right_tab_ = OpenTestPageAndGetUserMediaInNewTab(kMainWebrtcTestHtmlPage);
144 }
145
DetectVideoAndHangUp()146 void DetectVideoAndHangUp() {
147 StartDetectingVideo(left_tab_, "remote-view");
148 StartDetectingVideo(right_tab_, "remote-view");
149 #if !defined(OS_MAC)
150 // Video is choppy on Mac OS X. http://crbug.com/443542.
151 WaitForVideoToPlay(left_tab_);
152 WaitForVideoToPlay(right_tab_);
153 #endif
154 HangUp(left_tab_);
155 HangUp(right_tab_);
156 }
157
158 content::WebContents* left_tab_;
159 content::WebContents* right_tab_;
160 };
161
162 // TODO(898546): many of these tests are failing on ASan builds.
163 // They are also flaky crashers on Linux.
164 #if defined(ADDRESS_SANITIZER) || defined(OS_LINUX) || defined(OS_CHROMEOS)
165 #define MAYBE_WebRtcBrowserTest DISABLED_WebRtcBrowserTest
166 class DISABLED_WebRtcBrowserTest : public WebRtcBrowserTest {};
167 #else
168 #define MAYBE_WebRtcBrowserTest WebRtcBrowserTest
169 #endif
170
IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,RunsAudioVideoWebRTCCallInTwoTabsVP8)171 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
172 RunsAudioVideoWebRTCCallInTwoTabsVP8) {
173 RunsAudioVideoWebRTCCallInTwoTabs("VP8");
174 }
175
IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,RunsAudioVideoWebRTCCallInTwoTabsVP9)176 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
177 RunsAudioVideoWebRTCCallInTwoTabsVP9) {
178 RunsAudioVideoWebRTCCallInTwoTabs("VP9");
179 }
180
181 #if BUILDFLAG(RTC_USE_H264)
182
IN_PROC_BROWSER_TEST_F(WebRtcBrowserTest,RunsAudioVideoWebRTCCallInTwoTabsH264)183 IN_PROC_BROWSER_TEST_F(WebRtcBrowserTest,
184 RunsAudioVideoWebRTCCallInTwoTabsH264) {
185 // Only run test if run-time feature corresponding to |rtc_use_h264| is on.
186 if (!base::FeatureList::IsEnabled(
187 blink::features::kWebRtcH264WithOpenH264FFmpeg)) {
188 LOG(WARNING) << "Run-time feature WebRTC-H264WithOpenH264FFmpeg disabled. "
189 "Skipping WebRtcBrowserTest.RunsAudioVideoWebRTCCallInTwoTabsH264 "
190 "(test \"OK\")";
191 return;
192 }
193
194 #if defined(OS_MAC)
195 // TODO(jam): this test only on 10.12.
196 if (base::mac::IsOS10_12())
197 return;
198 #endif
199
200 RunsAudioVideoWebRTCCallInTwoTabs("H264", true /* prefer_hw_video_codec */);
201 }
202
203 #endif // BUILDFLAG(RTC_USE_H264)
204
IN_PROC_BROWSER_TEST_F(WebRtcBrowserTest,TestWebAudioMediaStream)205 IN_PROC_BROWSER_TEST_F(WebRtcBrowserTest, TestWebAudioMediaStream) {
206 // This tests against crash regressions for the WebAudio-MediaStream
207 // integration.
208 ASSERT_TRUE(embedded_test_server()->Start());
209 GURL url(embedded_test_server()->GetURL("/webrtc/webaudio_crash.html"));
210 ui_test_utils::NavigateToURL(browser(), url);
211 content::WebContents* tab =
212 browser()->tab_strip_model()->GetActiveWebContents();
213
214 // A sleep is necessary to be able to detect the crash.
215 test::SleepInJavascript(tab, 1000);
216
217 ASSERT_FALSE(tab->IsCrashed());
218 }
219
IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,RunsAudioVideoWebRTCCallInTwoTabsOfferRsaAnswerRsa)220 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
221 RunsAudioVideoWebRTCCallInTwoTabsOfferRsaAnswerRsa) {
222 RunsAudioVideoWebRTCCallInTwoTabs(WebRtcTestBase::kUseDefaultVideoCodec,
223 false /* prefer_hw_video_codec */,
224 kKeygenAlgorithmRsa, kKeygenAlgorithmRsa);
225 }
226
IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,RunsAudioVideoWebRTCCallInTwoTabsOfferEcdsaAnswerEcdsa)227 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
228 RunsAudioVideoWebRTCCallInTwoTabsOfferEcdsaAnswerEcdsa) {
229 RunsAudioVideoWebRTCCallInTwoTabs(
230 WebRtcTestBase::kUseDefaultVideoCodec, false /* prefer_hw_video_codec */,
231 kKeygenAlgorithmEcdsa, kKeygenAlgorithmEcdsa);
232 }
233
IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,RunsAudioVideoWebRTCCallInTwoTabsWithClonedCertificateRsa)234 IN_PROC_BROWSER_TEST_F(
235 MAYBE_WebRtcBrowserTest,
236 RunsAudioVideoWebRTCCallInTwoTabsWithClonedCertificateRsa) {
237 RunsAudioVideoWebRTCCallInTwoTabsWithClonedCertificate(kKeygenAlgorithmRsa);
238 }
239
IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,RunsAudioVideoWebRTCCallInTwoTabsWithClonedCertificateEcdsa)240 IN_PROC_BROWSER_TEST_F(
241 MAYBE_WebRtcBrowserTest,
242 RunsAudioVideoWebRTCCallInTwoTabsWithClonedCertificateEcdsa) {
243 RunsAudioVideoWebRTCCallInTwoTabsWithClonedCertificate(kKeygenAlgorithmEcdsa);
244 }
245
IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,RunsAudioVideoWebRTCCallInTwoTabsOfferRsaAnswerEcdsa)246 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
247 RunsAudioVideoWebRTCCallInTwoTabsOfferRsaAnswerEcdsa) {
248 RunsAudioVideoWebRTCCallInTwoTabs(WebRtcTestBase::kUseDefaultVideoCodec,
249 false /* prefer_hw_video_codec */,
250 kKeygenAlgorithmRsa, kKeygenAlgorithmEcdsa);
251 }
252
IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,RunsAudioVideoWebRTCCallInTwoTabsOfferEcdsaAnswerRsa)253 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
254 RunsAudioVideoWebRTCCallInTwoTabsOfferEcdsaAnswerRsa) {
255 RunsAudioVideoWebRTCCallInTwoTabs(WebRtcTestBase::kUseDefaultVideoCodec,
256 false /* prefer_hw_video_codec */,
257 kKeygenAlgorithmEcdsa, kKeygenAlgorithmRsa);
258 }
259
IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,RunsAudioVideoWebRTCCallInTwoTabsGetStatsCallback)260 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
261 RunsAudioVideoWebRTCCallInTwoTabsGetStatsCallback) {
262 StartServerAndOpenTabs();
263 SetupPeerconnectionWithLocalStream(left_tab_);
264 SetupPeerconnectionWithLocalStream(right_tab_);
265 NegotiateCall(left_tab_, right_tab_);
266
267 VerifyStatsGeneratedCallback(left_tab_);
268
269 DetectVideoAndHangUp();
270 }
271
IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,GetPeerToPeerConnectionsCountChangeFromNetworkService)272 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
273 GetPeerToPeerConnectionsCountChangeFromNetworkService) {
274 EXPECT_EQ(0u, GetPeerToPeerConnectionsCountChangeFromNetworkService());
275
276 StartServerAndOpenTabs();
277 SetupPeerconnectionWithLocalStream(left_tab_);
278
279 SetupPeerconnectionWithLocalStream(right_tab_);
280 NegotiateCall(left_tab_, right_tab_);
281
282 VerifyStatsGeneratedCallback(left_tab_);
283 EXPECT_EQ(2u, GetPeerToPeerConnectionsCountChangeFromNetworkService());
284
285 DetectVideoAndHangUp();
286 EXPECT_EQ(0u, GetPeerToPeerConnectionsCountChangeFromNetworkService());
287 }
288
IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,RunsAudioVideoWebRTCCallInTwoTabsGetStatsPromise)289 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
290 RunsAudioVideoWebRTCCallInTwoTabsGetStatsPromise) {
291 StartServerAndOpenTabs();
292 SetupPeerconnectionWithLocalStream(left_tab_);
293 SetupPeerconnectionWithLocalStream(right_tab_);
294 CreateDataChannel(left_tab_, "data");
295 CreateDataChannel(right_tab_, "data");
296 NegotiateCall(left_tab_, right_tab_);
297
298 std::set<std::string> missing_expected_stats;
299 for (const std::string& type : GetMandatoryStatsTypes(left_tab_)) {
300 missing_expected_stats.insert(type);
301 }
302 for (const std::string& type : VerifyStatsGeneratedPromise(left_tab_)) {
303 missing_expected_stats.erase(type);
304 }
305 for (const std::string& type : missing_expected_stats) {
306 EXPECT_TRUE(false) << "Expected stats dictionary is missing: " << type;
307 }
308
309 DetectVideoAndHangUp();
310 }
311
IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,RunsAudioVideoWebRTCCallInTwoTabsEmitsGatheringStateChange)312 IN_PROC_BROWSER_TEST_F(
313 MAYBE_WebRtcBrowserTest,
314 RunsAudioVideoWebRTCCallInTwoTabsEmitsGatheringStateChange) {
315 StartServerAndOpenTabs();
316 SetupPeerconnectionWithLocalStream(left_tab_);
317 SetupPeerconnectionWithLocalStream(right_tab_);
318 NegotiateCall(left_tab_, right_tab_);
319
320 std::string ice_gatheringstate =
321 ExecuteJavascript("getLastGatheringState()", left_tab_);
322
323 EXPECT_EQ("complete", ice_gatheringstate);
324 DetectVideoAndHangUp();
325 }
326
IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,RunsAudioVideoWebRTCCallInTwoTabsEmitsGatheringStateChange_ConnectionCount)327 IN_PROC_BROWSER_TEST_F(
328 MAYBE_WebRtcBrowserTest,
329 RunsAudioVideoWebRTCCallInTwoTabsEmitsGatheringStateChange_ConnectionCount) {
330 EXPECT_EQ(0u, GetPeerToPeerConnectionsCountChangeFromNetworkService());
331 StartServerAndOpenTabs();
332 SetupPeerconnectionWithLocalStream(left_tab_);
333 SetupPeerconnectionWithLocalStream(right_tab_);
334 NegotiateCall(left_tab_, right_tab_);
335 EXPECT_EQ(2u, GetPeerToPeerConnectionsCountChangeFromNetworkService());
336
337 std::string ice_gatheringstate =
338 ExecuteJavascript("getLastGatheringState()", left_tab_);
339
340 EXPECT_EQ("complete", ice_gatheringstate);
341 DetectVideoAndHangUp();
342 EXPECT_EQ(0u, GetPeerToPeerConnectionsCountChangeFromNetworkService());
343 }
344