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 "chrome/browser/media/webrtc/webrtc_browsertest_base.h"
6
7 #include <stddef.h>
8
9 #include <limits>
10
11 #include "base/json/json_reader.h"
12 #include "base/lazy_instance.h"
13 #include "base/logging.h"
14 #include "base/macros.h"
15 #include "base/path_service.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/string_split.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/stringprintf.h"
20 #include "base/values.h"
21 #include "build/build_config.h"
22 #include "chrome/browser/extensions/chrome_test_extension_loader.h"
23 #include "chrome/browser/media/webrtc/webrtc_browsertest_common.h"
24 #include "chrome/browser/profiles/profile.h"
25 #include "chrome/browser/ui/browser.h"
26 #include "chrome/browser/ui/browser_tabstrip.h"
27 #include "chrome/browser/ui/tabs/tab_strip_model.h"
28 #include "chrome/common/chrome_paths.h"
29 #include "chrome/test/base/ui_test_utils.h"
30 #include "components/permissions/permission_request_manager.h"
31 #include "components/permissions/test/permission_request_observer.h"
32 #include "content/public/test/browser_test_utils.h"
33 #include "extensions/browser/extension_registry.h"
34 #include "net/test/embedded_test_server/embedded_test_server.h"
35
36 #if defined(OS_WIN)
37 // For fine-grained suppression.
38 #include "base/win/windows_version.h"
39 #endif
40
41 const char WebRtcTestBase::kAudioVideoCallConstraints[] =
42 "{audio: true, video: true}";
43 const char WebRtcTestBase::kVideoCallConstraintsQVGA[] =
44 "{video: {mandatory: {minWidth: 320, maxWidth: 320, "
45 " minHeight: 240, maxHeight: 240}}}";
46 const char WebRtcTestBase::kVideoCallConstraints360p[] =
47 "{video: {mandatory: {minWidth: 640, maxWidth: 640, "
48 " minHeight: 360, maxHeight: 360}}}";
49 const char WebRtcTestBase::kVideoCallConstraintsVGA[] =
50 "{video: {mandatory: {minWidth: 640, maxWidth: 640, "
51 " minHeight: 480, maxHeight: 480}}}";
52 const char WebRtcTestBase::kVideoCallConstraints720p[] =
53 "{video: {mandatory: {minWidth: 1280, maxWidth: 1280, "
54 " minHeight: 720, maxHeight: 720}}}";
55 const char WebRtcTestBase::kVideoCallConstraints1080p[] =
56 "{video: {mandatory: {minWidth: 1920, maxWidth: 1920, "
57 " minHeight: 1080, maxHeight: 1080}}}";
58 const char WebRtcTestBase::kAudioOnlyCallConstraints[] = "{audio: true}";
59 const char WebRtcTestBase::kVideoOnlyCallConstraints[] = "{video: true}";
60 const char WebRtcTestBase::kOkGotStream[] = "ok-got-stream";
61 const char WebRtcTestBase::kFailedWithNotAllowedError[] =
62 "failed-with-error-NotAllowedError";
63 const char WebRtcTestBase::kAudioVideoCallConstraints360p[] =
64 "{audio: true, video: {mandatory: {minWidth: 640, maxWidth: 640, "
65 " minHeight: 360, maxHeight: 360}}}";
66 const char WebRtcTestBase::kAudioVideoCallConstraints720p[] =
67 "{audio: true, video: {mandatory: {minWidth: 1280, maxWidth: 1280, "
68 " minHeight: 720, maxHeight: 720}}}";
69 const char WebRtcTestBase::kUseDefaultCertKeygen[] = "null";
70 const char WebRtcTestBase::kUseDefaultAudioCodec[] = "";
71 const char WebRtcTestBase::kUseDefaultVideoCodec[] = "";
72 const char WebRtcTestBase::kVP9Profile0Specifier[] = "profile-id=0";
73 const char WebRtcTestBase::kVP9Profile2Specifier[] = "profile-id=2";
74 const char WebRtcTestBase::kUndefined[] = "undefined";
75
76 namespace {
77
78 base::LazyInstance<bool>::DestructorAtExit hit_javascript_errors_ =
79 LAZY_INSTANCE_INITIALIZER;
80
81 // Intercepts all log messages. We always attach this handler but only look at
82 // the results if the test requests so. Note that this will only work if the
83 // WebrtcTestBase-inheriting test cases do not run in parallel (if they did they
84 // would race to look at the log, which is global to all tests).
JavascriptErrorDetectingLogHandler(int severity,const char * file,int line,size_t message_start,const std::string & str)85 bool JavascriptErrorDetectingLogHandler(int severity,
86 const char* file,
87 int line,
88 size_t message_start,
89 const std::string& str) {
90 if (file == NULL || std::string("CONSOLE") != file)
91 return false;
92
93 // TODO(crbug.com/918871): Fix AppRTC and stop ignoring this error.
94 if (str.find("Synchronous XHR in page dismissal") != std::string::npos)
95 return false;
96
97 bool contains_uncaught = str.find("\"Uncaught ") != std::string::npos;
98 if (severity == logging::LOG_ERROR ||
99 (severity == logging::LOG_INFO && contains_uncaught)) {
100 hit_javascript_errors_.Get() = true;
101 }
102
103 return false;
104 }
105
JsonArrayToVectorOfStrings(const std::string & json_array)106 std::vector<std::string> JsonArrayToVectorOfStrings(
107 const std::string& json_array) {
108 std::unique_ptr<base::Value> value =
109 base::JSONReader::ReadDeprecated(json_array);
110 EXPECT_TRUE(value);
111 EXPECT_TRUE(value->is_list());
112 std::unique_ptr<base::ListValue> list =
113 base::ListValue::From(std::move(value));
114 std::vector<std::string> vector;
115 vector.reserve(list->GetSize());
116 for (size_t i = 0; i < list->GetSize(); ++i) {
117 base::Value* item;
118 EXPECT_TRUE(list->Get(i, &item));
119 EXPECT_TRUE(item->is_string());
120 std::string item_str;
121 EXPECT_TRUE(item->GetAsString(&item_str));
122 vector.push_back(std::move(item_str));
123 }
124 return vector;
125 }
126
127 } // namespace
128
WebRtcTestBase()129 WebRtcTestBase::WebRtcTestBase(): detect_errors_in_javascript_(false) {
130 // The handler gets set for each test method, but that's fine since this
131 // set operation is idempotent.
132 logging::SetLogMessageHandler(&JavascriptErrorDetectingLogHandler);
133 hit_javascript_errors_.Get() = false;
134
135 EnablePixelOutput();
136 }
137
~WebRtcTestBase()138 WebRtcTestBase::~WebRtcTestBase() {
139 if (detect_errors_in_javascript_) {
140 EXPECT_FALSE(hit_javascript_errors_.Get())
141 << "Encountered javascript errors during test execution (Search "
142 << "for Uncaught or ERROR:CONSOLE in the test output).";
143 }
144 }
145
GetUserMediaAndAccept(content::WebContents * tab_contents) const146 bool WebRtcTestBase::GetUserMediaAndAccept(
147 content::WebContents* tab_contents) const {
148 return GetUserMediaWithSpecificConstraintsAndAccept(
149 tab_contents, kAudioVideoCallConstraints);
150 }
151
GetUserMediaWithSpecificConstraintsAndAccept(content::WebContents * tab_contents,const std::string & constraints) const152 bool WebRtcTestBase::GetUserMediaWithSpecificConstraintsAndAccept(
153 content::WebContents* tab_contents,
154 const std::string& constraints) const {
155 std::string result;
156 permissions::PermissionRequestManager::FromWebContents(tab_contents)
157 ->set_auto_response_for_test(
158 permissions::PermissionRequestManager::ACCEPT_ALL);
159 permissions::PermissionRequestObserver observer(tab_contents);
160 GetUserMedia(tab_contents, constraints);
161 EXPECT_TRUE(observer.request_shown());
162 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
163 tab_contents->GetMainFrame(), "obtainGetUserMediaResult();", &result));
164 return kOkGotStream == result;
165 }
166
GetUserMediaWithSpecificConstraintsAndAcceptIfPrompted(content::WebContents * tab_contents,const std::string & constraints) const167 bool WebRtcTestBase::GetUserMediaWithSpecificConstraintsAndAcceptIfPrompted(
168 content::WebContents* tab_contents,
169 const std::string& constraints) const {
170 std::string result;
171 permissions::PermissionRequestManager::FromWebContents(tab_contents)
172 ->set_auto_response_for_test(
173 permissions::PermissionRequestManager::ACCEPT_ALL);
174 GetUserMedia(tab_contents, constraints);
175 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
176 tab_contents->GetMainFrame(), "obtainGetUserMediaResult();", &result));
177 return kOkGotStream == result;
178 }
179
GetUserMediaAndDeny(content::WebContents * tab_contents)180 void WebRtcTestBase::GetUserMediaAndDeny(content::WebContents* tab_contents) {
181 return GetUserMediaWithSpecificConstraintsAndDeny(tab_contents,
182 kAudioVideoCallConstraints);
183 }
184
GetUserMediaWithSpecificConstraintsAndDeny(content::WebContents * tab_contents,const std::string & constraints) const185 void WebRtcTestBase::GetUserMediaWithSpecificConstraintsAndDeny(
186 content::WebContents* tab_contents,
187 const std::string& constraints) const {
188 std::string result;
189 permissions::PermissionRequestManager::FromWebContents(tab_contents)
190 ->set_auto_response_for_test(
191 permissions::PermissionRequestManager::DENY_ALL);
192 permissions::PermissionRequestObserver observer(tab_contents);
193 GetUserMedia(tab_contents, constraints);
194 EXPECT_TRUE(observer.request_shown());
195 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
196 tab_contents->GetMainFrame(), "obtainGetUserMediaResult();", &result));
197 EXPECT_EQ(kFailedWithNotAllowedError, result);
198 }
199
GetUserMediaAndDismiss(content::WebContents * tab_contents) const200 void WebRtcTestBase::GetUserMediaAndDismiss(
201 content::WebContents* tab_contents) const {
202 std::string result;
203 permissions::PermissionRequestManager::FromWebContents(tab_contents)
204 ->set_auto_response_for_test(
205 permissions::PermissionRequestManager::DISMISS);
206 permissions::PermissionRequestObserver observer(tab_contents);
207 GetUserMedia(tab_contents, kAudioVideoCallConstraints);
208 EXPECT_TRUE(observer.request_shown());
209 // A dismiss should be treated like a deny.
210 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
211 tab_contents->GetMainFrame(), "obtainGetUserMediaResult();", &result));
212 EXPECT_EQ(kFailedWithNotAllowedError, result);
213 }
214
GetUserMediaAndExpectAutoAcceptWithoutPrompt(content::WebContents * tab_contents) const215 void WebRtcTestBase::GetUserMediaAndExpectAutoAcceptWithoutPrompt(
216 content::WebContents* tab_contents) const {
217 std::string result;
218 // We issue a GetUserMedia() request. We expect that the origin already has a
219 // sticky "accept" permission (e.g. because the caller previously called
220 // GetUserMediaAndAccept()), and therefore the GetUserMedia() request
221 // automatically succeeds without a prompt.
222 // If the caller made a mistake, a prompt may show up instead. For this case,
223 // we set an auto-response to avoid leaving the prompt hanging. The choice of
224 // DENY_ALL makes sure that the response to the prompt doesn't accidentally
225 // result in a newly granted media stream permission.
226 permissions::PermissionRequestManager::FromWebContents(tab_contents)
227 ->set_auto_response_for_test(
228 permissions::PermissionRequestManager::DENY_ALL);
229 permissions::PermissionRequestObserver observer(tab_contents);
230 GetUserMedia(tab_contents, kAudioVideoCallConstraints);
231 EXPECT_FALSE(observer.request_shown());
232 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
233 tab_contents->GetMainFrame(), "obtainGetUserMediaResult();", &result));
234 EXPECT_EQ(kOkGotStream, result);
235 }
236
GetUserMediaAndExpectAutoDenyWithoutPrompt(content::WebContents * tab_contents) const237 void WebRtcTestBase::GetUserMediaAndExpectAutoDenyWithoutPrompt(
238 content::WebContents* tab_contents) const {
239 std::string result;
240 // We issue a GetUserMedia() request. We expect that the origin already has a
241 // sticky "deny" permission (e.g. because the caller previously called
242 // GetUserMediaAndDeny()), and therefore the GetUserMedia() request
243 // automatically succeeds without a prompt.
244 // If the caller made a mistake, a prompt may show up instead. For this case,
245 // we set an auto-response to avoid leaving the prompt hanging. The choice of
246 // ACCEPT_ALL makes sure that the response to the prompt doesn't accidentally
247 // result in a newly granted media stream permission.
248 permissions::PermissionRequestManager::FromWebContents(tab_contents)
249 ->set_auto_response_for_test(
250 permissions::PermissionRequestManager::ACCEPT_ALL);
251 permissions::PermissionRequestObserver observer(tab_contents);
252 GetUserMedia(tab_contents, kAudioVideoCallConstraints);
253 EXPECT_FALSE(observer.request_shown());
254 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
255 tab_contents->GetMainFrame(), "obtainGetUserMediaResult();", &result));
256 EXPECT_EQ(kFailedWithNotAllowedError, result);
257 }
258
GetUserMedia(content::WebContents * tab_contents,const std::string & constraints) const259 void WebRtcTestBase::GetUserMedia(content::WebContents* tab_contents,
260 const std::string& constraints) const {
261 // Request user media: this will launch the media stream info bar or bubble.
262 std::string result;
263 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
264 tab_contents, "doGetUserMedia(" + constraints + ");", &result));
265 EXPECT_TRUE(result == "request-callback-denied" ||
266 result == "request-callback-granted");
267 }
268
OpenPageAndGetUserMediaInNewTab(const GURL & url) const269 content::WebContents* WebRtcTestBase::OpenPageAndGetUserMediaInNewTab(
270 const GURL& url) const {
271 return OpenPageAndGetUserMediaInNewTabWithConstraints(
272 url, kAudioVideoCallConstraints);
273 }
274
275 content::WebContents*
OpenPageAndGetUserMediaInNewTabWithConstraints(const GURL & url,const std::string & constraints) const276 WebRtcTestBase::OpenPageAndGetUserMediaInNewTabWithConstraints(
277 const GURL& url,
278 const std::string& constraints) const {
279 chrome::AddTabAt(browser(), GURL(url::kAboutBlankURL), -1, true);
280 ui_test_utils::NavigateToURL(browser(), url);
281 content::WebContents* new_tab =
282 browser()->tab_strip_model()->GetActiveWebContents();
283 // Accept if necessary, but don't expect a prompt (because auto-accept is also
284 // okay).
285 permissions::PermissionRequestManager::FromWebContents(new_tab)
286 ->set_auto_response_for_test(
287 permissions::PermissionRequestManager::ACCEPT_ALL);
288 GetUserMedia(new_tab, constraints);
289 std::string result;
290 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
291 new_tab->GetMainFrame(), "obtainGetUserMediaResult();", &result));
292 EXPECT_EQ(kOkGotStream, result);
293 return new_tab;
294 }
295
OpenTestPageAndGetUserMediaInNewTab(const std::string & test_page) const296 content::WebContents* WebRtcTestBase::OpenTestPageAndGetUserMediaInNewTab(
297 const std::string& test_page) const {
298 return OpenPageAndGetUserMediaInNewTab(
299 embedded_test_server()->GetURL(test_page));
300 }
301
OpenTestPageInNewTab(const std::string & test_page) const302 content::WebContents* WebRtcTestBase::OpenTestPageInNewTab(
303 const std::string& test_page) const {
304 chrome::AddTabAt(browser(), GURL(url::kAboutBlankURL), -1, true);
305 GURL url = embedded_test_server()->GetURL(test_page);
306 ui_test_utils::NavigateToURL(browser(), url);
307 content::WebContents* new_tab =
308 browser()->tab_strip_model()->GetActiveWebContents();
309 // Accept if necessary, but don't expect a prompt (because auto-accept is also
310 // okay).
311 permissions::PermissionRequestManager::FromWebContents(new_tab)
312 ->set_auto_response_for_test(
313 permissions::PermissionRequestManager::ACCEPT_ALL);
314 return new_tab;
315 }
316
CloseLastLocalStream(content::WebContents * tab_contents) const317 void WebRtcTestBase::CloseLastLocalStream(
318 content::WebContents* tab_contents) const {
319 EXPECT_EQ("ok-stopped",
320 ExecuteJavascript("stopLocalStream();", tab_contents));
321 }
322
323 // Convenience method which executes the provided javascript in the context
324 // of the provided web contents and returns what it evaluated to.
ExecuteJavascript(const std::string & javascript,content::WebContents * tab_contents) const325 std::string WebRtcTestBase::ExecuteJavascript(
326 const std::string& javascript,
327 content::WebContents* tab_contents) const {
328 std::string result;
329 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
330 tab_contents, javascript, &result));
331 return result;
332 }
333
ChangeToLegacyGetStats(content::WebContents * tab) const334 void WebRtcTestBase::ChangeToLegacyGetStats(content::WebContents* tab) const {
335 content::ExecuteScriptAsync(tab, "changeToLegacyGetStats()");
336 }
337
SetupPeerconnectionWithLocalStream(content::WebContents * tab,const std::string & certificate_keygen_algorithm) const338 void WebRtcTestBase::SetupPeerconnectionWithLocalStream(
339 content::WebContents* tab,
340 const std::string& certificate_keygen_algorithm) const {
341 SetupPeerconnectionWithoutLocalStream(tab, certificate_keygen_algorithm);
342 EXPECT_EQ("ok-added", ExecuteJavascript("addLocalStream()", tab));
343 }
344
SetupPeerconnectionWithoutLocalStream(content::WebContents * tab,const std::string & certificate_keygen_algorithm) const345 void WebRtcTestBase::SetupPeerconnectionWithoutLocalStream(
346 content::WebContents* tab,
347 const std::string& certificate_keygen_algorithm) const {
348 std::string javascript = base::StringPrintf(
349 "preparePeerConnection(%s)", certificate_keygen_algorithm.c_str());
350 EXPECT_EQ("ok-peerconnection-created", ExecuteJavascript(javascript, tab));
351 }
352
SetupPeerconnectionWithCertificateAndLocalStream(content::WebContents * tab,const std::string & certificate) const353 void WebRtcTestBase::SetupPeerconnectionWithCertificateAndLocalStream(
354 content::WebContents* tab,
355 const std::string& certificate) const {
356 SetupPeerconnectionWithCertificateWithoutLocalStream(tab, certificate);
357 EXPECT_EQ("ok-added", ExecuteJavascript("addLocalStream()", tab));
358 }
359
SetupPeerconnectionWithCertificateWithoutLocalStream(content::WebContents * tab,const std::string & certificate) const360 void WebRtcTestBase::SetupPeerconnectionWithCertificateWithoutLocalStream(
361 content::WebContents* tab,
362 const std::string& certificate) const {
363 std::string javascript = base::StringPrintf(
364 "preparePeerConnectionWithCertificate(%s)", certificate.c_str());
365 EXPECT_EQ("ok-peerconnection-created", ExecuteJavascript(javascript, tab));
366 }
367
SetupPeerconnectionWithConstraintsAndLocalStream(content::WebContents * tab,const std::string & constraints,const std::string & certificate_keygen_algorithm) const368 void WebRtcTestBase::SetupPeerconnectionWithConstraintsAndLocalStream(
369 content::WebContents* tab,
370 const std::string& constraints,
371 const std::string& certificate_keygen_algorithm) const {
372 std::string javascript = base::StringPrintf(
373 "preparePeerConnection(%s, %s)", certificate_keygen_algorithm.c_str(),
374 constraints.c_str());
375 EXPECT_EQ("ok-peerconnection-created", ExecuteJavascript(javascript, tab));
376 EXPECT_EQ("ok-added", ExecuteJavascript("addLocalStream()", tab));
377 }
378
CreateLocalOffer(content::WebContents * from_tab) const379 std::string WebRtcTestBase::CreateLocalOffer(
380 content::WebContents* from_tab) const {
381 std::string response = ExecuteJavascript("createLocalOffer({})", from_tab);
382 EXPECT_EQ("ok-", response.substr(0, 3)) << "Failed to create local offer: "
383 << response;
384
385 std::string local_offer = response.substr(3);
386 return local_offer;
387 }
388
CreateAnswer(std::string local_offer,content::WebContents * to_tab) const389 std::string WebRtcTestBase::CreateAnswer(std::string local_offer,
390 content::WebContents* to_tab) const {
391 std::string javascript =
392 base::StringPrintf("receiveOfferFromPeer('%s', {})", local_offer.c_str());
393 std::string response = ExecuteJavascript(javascript, to_tab);
394 EXPECT_EQ("ok-", response.substr(0, 3))
395 << "Receiving peer failed to receive offer and create answer: "
396 << response;
397
398 std::string answer = response.substr(3);
399 response = ExecuteJavascript(
400 base::StringPrintf("verifyDefaultCodecs('%s')", answer.c_str()),
401 to_tab);
402 EXPECT_EQ("ok-", response.substr(0, 3))
403 << "Receiving peer failed to verify default codec: " << response;
404 return answer;
405 }
406
ReceiveAnswer(const std::string & answer,content::WebContents * from_tab) const407 void WebRtcTestBase::ReceiveAnswer(const std::string& answer,
408 content::WebContents* from_tab) const {
409 ASSERT_EQ(
410 "ok-accepted-answer",
411 ExecuteJavascript(
412 base::StringPrintf("receiveAnswerFromPeer('%s')", answer.c_str()),
413 from_tab));
414 }
415
GatherAndSendIceCandidates(content::WebContents * from_tab,content::WebContents * to_tab) const416 void WebRtcTestBase::GatherAndSendIceCandidates(
417 content::WebContents* from_tab,
418 content::WebContents* to_tab) const {
419 std::string ice_candidates =
420 ExecuteJavascript("getAllIceCandidates()", from_tab);
421
422 EXPECT_EQ("ok-received-candidates", ExecuteJavascript(
423 base::StringPrintf("receiveIceCandidates('%s')", ice_candidates.c_str()),
424 to_tab));
425 }
426
CreateDataChannel(content::WebContents * tab,const std::string & label)427 void WebRtcTestBase::CreateDataChannel(content::WebContents* tab,
428 const std::string& label) {
429 EXPECT_EQ("ok-created",
430 ExecuteJavascript("createDataChannel('" + label + "')", tab));
431 }
432
NegotiateCall(content::WebContents * from_tab,content::WebContents * to_tab) const433 void WebRtcTestBase::NegotiateCall(content::WebContents* from_tab,
434 content::WebContents* to_tab) const {
435 std::string local_offer = CreateLocalOffer(from_tab);
436 std::string answer = CreateAnswer(local_offer, to_tab);
437 ReceiveAnswer(answer, from_tab);
438
439 // Send all ICE candidates (wait for gathering to finish if necessary).
440 GatherAndSendIceCandidates(to_tab, from_tab);
441 GatherAndSendIceCandidates(from_tab, to_tab);
442 }
443
VerifyLocalDescriptionContainsCertificate(content::WebContents * tab,const std::string & certificate) const444 void WebRtcTestBase::VerifyLocalDescriptionContainsCertificate(
445 content::WebContents* tab,
446 const std::string& certificate) const {
447 std::string javascript = base::StringPrintf(
448 "verifyLocalDescriptionContainsCertificate(%s)", certificate.c_str());
449 EXPECT_EQ("ok-verified", ExecuteJavascript(javascript, tab));
450 }
451
HangUp(content::WebContents * from_tab) const452 void WebRtcTestBase::HangUp(content::WebContents* from_tab) const {
453 EXPECT_EQ("ok-call-hung-up", ExecuteJavascript("hangUp()", from_tab));
454 }
455
DetectErrorsInJavaScript()456 void WebRtcTestBase::DetectErrorsInJavaScript() {
457 detect_errors_in_javascript_ = true;
458 }
459
StartDetectingVideo(content::WebContents * tab_contents,const std::string & video_element) const460 void WebRtcTestBase::StartDetectingVideo(
461 content::WebContents* tab_contents,
462 const std::string& video_element) const {
463 std::string javascript = base::StringPrintf(
464 "startDetection('%s', 320, 240)", video_element.c_str());
465 EXPECT_EQ("ok-started", ExecuteJavascript(javascript, tab_contents));
466 }
467
WaitForVideoToPlay(content::WebContents * tab_contents) const468 bool WebRtcTestBase::WaitForVideoToPlay(
469 content::WebContents* tab_contents) const {
470 bool is_video_playing = test::PollingWaitUntil(
471 "isVideoPlaying()", "video-playing", tab_contents);
472 EXPECT_TRUE(is_video_playing);
473 return is_video_playing;
474 }
475
WaitForVideoToStop(content::WebContents * tab_contents) const476 bool WebRtcTestBase::WaitForVideoToStop(
477 content::WebContents* tab_contents) const {
478 bool is_video_stopped =
479 test::PollingWaitUntil("isVideoStopped()", "video-stopped", tab_contents);
480 EXPECT_TRUE(is_video_stopped);
481 return is_video_stopped;
482 }
483
GetStreamSize(content::WebContents * tab_contents,const std::string & video_element) const484 std::string WebRtcTestBase::GetStreamSize(
485 content::WebContents* tab_contents,
486 const std::string& video_element) const {
487 std::string javascript =
488 base::StringPrintf("getStreamSize('%s')", video_element.c_str());
489 std::string result = ExecuteJavascript(javascript, tab_contents);
490 EXPECT_TRUE(base::StartsWith(result, "ok-", base::CompareCase::SENSITIVE));
491 return result.substr(3);
492 }
493
OnWin8OrHigher() const494 bool WebRtcTestBase::OnWin8OrHigher() const {
495 #if defined(OS_WIN)
496 return base::win::GetVersion() >= base::win::Version::WIN8;
497 #else
498 return false;
499 #endif
500 }
501
OpenDatabase(content::WebContents * tab) const502 void WebRtcTestBase::OpenDatabase(content::WebContents* tab) const {
503 EXPECT_EQ("ok-database-opened", ExecuteJavascript("openDatabase()", tab));
504 }
505
CloseDatabase(content::WebContents * tab) const506 void WebRtcTestBase::CloseDatabase(content::WebContents* tab) const {
507 EXPECT_EQ("ok-database-closed", ExecuteJavascript("closeDatabase()", tab));
508 }
509
DeleteDatabase(content::WebContents * tab) const510 void WebRtcTestBase::DeleteDatabase(content::WebContents* tab) const {
511 EXPECT_EQ("ok-database-deleted", ExecuteJavascript("deleteDatabase()", tab));
512 }
513
GenerateAndCloneCertificate(content::WebContents * tab,const std::string & keygen_algorithm) const514 void WebRtcTestBase::GenerateAndCloneCertificate(
515 content::WebContents* tab, const std::string& keygen_algorithm) const {
516 std::string javascript = base::StringPrintf(
517 "generateAndCloneCertificate(%s)", keygen_algorithm.c_str());
518 EXPECT_EQ("ok-generated-and-cloned", ExecuteJavascript(javascript, tab));
519 }
520
VerifyStatsGeneratedCallback(content::WebContents * tab) const521 void WebRtcTestBase::VerifyStatsGeneratedCallback(
522 content::WebContents* tab) const {
523 EXPECT_EQ("ok-got-stats",
524 ExecuteJavascript("verifyLegacyStatsGenerated()", tab));
525 }
526
VerifyStatsGeneratedPromise(content::WebContents * tab) const527 std::vector<std::string> WebRtcTestBase::VerifyStatsGeneratedPromise(
528 content::WebContents* tab) const {
529 std::string result = ExecuteJavascript("verifyStatsGeneratedPromise()", tab);
530 EXPECT_TRUE(base::StartsWith(result, "ok-", base::CompareCase::SENSITIVE));
531 return JsonArrayToVectorOfStrings(result.substr(3));
532 }
533
MeasureGetStatsCallbackPerformance(content::WebContents * tab) const534 double WebRtcTestBase::MeasureGetStatsCallbackPerformance(
535 content::WebContents* tab) const {
536 std::string result = ExecuteJavascript(
537 "measureGetStatsCallbackPerformance()", tab);
538 EXPECT_TRUE(base::StartsWith(result, "ok-", base::CompareCase::SENSITIVE));
539 double ms;
540 if (!base::StringToDouble(result.substr(3), &ms))
541 return std::numeric_limits<double>::infinity();
542 return ms;
543 }
544
545 scoped_refptr<content::TestStatsReportDictionary>
GetStatsReportDictionary(content::WebContents * tab) const546 WebRtcTestBase::GetStatsReportDictionary(content::WebContents* tab) const {
547 std::string result = ExecuteJavascript("getStatsReportDictionary()", tab);
548 EXPECT_TRUE(base::StartsWith(result, "ok-", base::CompareCase::SENSITIVE));
549 std::unique_ptr<base::Value> parsed_json =
550 base::JSONReader::ReadDeprecated(result.substr(3));
551 base::DictionaryValue* dictionary;
552 CHECK(parsed_json);
553 CHECK(parsed_json->GetAsDictionary(&dictionary));
554 ignore_result(parsed_json.release());
555 return scoped_refptr<content::TestStatsReportDictionary>(
556 new content::TestStatsReportDictionary(
557 std::unique_ptr<base::DictionaryValue>(dictionary)));
558 }
559
MeasureGetStatsPerformance(content::WebContents * tab) const560 double WebRtcTestBase::MeasureGetStatsPerformance(
561 content::WebContents* tab) const {
562 std::string result = ExecuteJavascript("measureGetStatsPerformance()", tab);
563 EXPECT_TRUE(base::StartsWith(result, "ok-", base::CompareCase::SENSITIVE));
564 double ms;
565 if (!base::StringToDouble(result.substr(3), &ms))
566 return std::numeric_limits<double>::infinity();
567 return ms;
568 }
569
GetMandatoryStatsTypes(content::WebContents * tab) const570 std::vector<std::string> WebRtcTestBase::GetMandatoryStatsTypes(
571 content::WebContents* tab) const {
572 return JsonArrayToVectorOfStrings(
573 ExecuteJavascript("getMandatoryStatsTypes()", tab));
574 }
575
SetDefaultAudioCodec(content::WebContents * tab,const std::string & audio_codec) const576 void WebRtcTestBase::SetDefaultAudioCodec(
577 content::WebContents* tab,
578 const std::string& audio_codec) const {
579 EXPECT_EQ("ok", ExecuteJavascript(
580 "setDefaultAudioCodec('" + audio_codec + "')", tab));
581 }
582
SetDefaultVideoCodec(content::WebContents * tab,const std::string & video_codec,bool prefer_hw_codec,const std::string & profile) const583 void WebRtcTestBase::SetDefaultVideoCodec(content::WebContents* tab,
584 const std::string& video_codec,
585 bool prefer_hw_codec,
586 const std::string& profile) const {
587 std::string codec_profile = profile;
588 // When no |profile| is given, we default VP9 to Profile 0.
589 if (video_codec.compare("VP9") == 0 && codec_profile.empty())
590 codec_profile = kVP9Profile0Specifier;
591
592 EXPECT_EQ("ok", ExecuteJavascript(
593 "setDefaultVideoCodec('" + video_codec + "'," +
594 (prefer_hw_codec ? "true" : "false") + "," +
595 (codec_profile.empty() ? "null"
596 : "'" + codec_profile + "'") +
597 ")",
598 tab));
599 }
600
EnableOpusDtx(content::WebContents * tab) const601 void WebRtcTestBase::EnableOpusDtx(content::WebContents* tab) const {
602 EXPECT_EQ("ok-forced", ExecuteJavascript("forceOpusDtx()", tab));
603 }
604
GetDesktopMediaStream(content::WebContents * tab)605 std::string WebRtcTestBase::GetDesktopMediaStream(content::WebContents* tab) {
606 DCHECK(static_cast<bool>(LoadDesktopCaptureExtension()));
607
608 // Post a task to the extension, opening a desktop media stream.
609 return ExecuteJavascript("openDesktopMediaStream()", tab);
610 }
611
LoadDesktopCaptureExtension()612 base::Optional<std::string> WebRtcTestBase::LoadDesktopCaptureExtension() {
613 base::Optional<std::string> extension_id;
614 if (!desktop_capture_extension_.get()) {
615 extensions::ChromeTestExtensionLoader loader(browser()->profile());
616 base::FilePath extension_path;
617 EXPECT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &extension_path));
618 extension_path = extension_path.AppendASCII("extensions/desktop_capture");
619 desktop_capture_extension_ = loader.LoadExtension(extension_path);
620 LOG(INFO) << "Loaded desktop capture extension, id = "
621 << desktop_capture_extension_->id();
622
623 extensions::ExtensionRegistry* registry =
624 extensions::ExtensionRegistry::Get(browser()->profile());
625
626 EXPECT_TRUE(registry->enabled_extensions().GetByID(
627 desktop_capture_extension_->id()));
628 }
629 if (desktop_capture_extension_)
630 extension_id.emplace(desktop_capture_extension_->id());
631 return extension_id;
632 }
633