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.
5 #include "chrome/browser/media/webrtc_browsertest_base.h"
7 #include "base/lazy_instance.h"
8 #include "base/strings/string_util.h"
9 #include "base/strings/stringprintf.h"
10 #include "chrome/browser/media/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/browser/ui/website_settings/permission_bubble_manager.h"
15 #include "chrome/test/base/ui_test_utils.h"
16 #include "content/public/test/browser_test_utils.h"
17 #include "net/test/embedded_test_server/embedded_test_server.h"
20 // For fine-grained suppression.
21 #include "base/win/windows_version.h"
24 const char WebRtcTestBase::kAudioVideoCallConstraints
[] =
25 "{audio: true, video: true}";
26 const char WebRtcTestBase::kVideoCallConstraintsQVGA
[] =
27 "{video: {mandatory: {minWidth: 320, maxWidth: 320, "
28 " minHeight: 240, maxHeight: 240}}}";
29 const char WebRtcTestBase::kVideoCallConstraints360p
[] =
30 "{video: {mandatory: {minWidth: 640, maxWidth: 640, "
31 " minHeight: 360, maxHeight: 360}}}";
32 const char WebRtcTestBase::kVideoCallConstraintsVGA
[] =
33 "{video: {mandatory: {minWidth: 640, maxWidth: 640, "
34 " minHeight: 480, maxHeight: 480}}}";
35 const char WebRtcTestBase::kVideoCallConstraints720p
[] =
36 "{video: {mandatory: {minWidth: 1280, maxWidth: 1280, "
37 " minHeight: 720, maxHeight: 720}}}";
38 const char WebRtcTestBase::kVideoCallConstraints1080p
[] =
39 "{video: {mandatory: {minWidth: 1920, maxWidth: 1920, "
40 " minHeight: 1080, maxHeight: 1080}}}";
41 const char WebRtcTestBase::kAudioOnlyCallConstraints
[] = "{audio: true}";
42 const char WebRtcTestBase::kVideoOnlyCallConstraints
[] = "{video: true}";
43 const char WebRtcTestBase::kOkGotStream
[] = "ok-got-stream";
44 const char WebRtcTestBase::kFailedWithPermissionDeniedError
[] =
45 "failed-with-error-PermissionDeniedError";
46 const char WebRtcTestBase::kFailedWithPermissionDismissedError
[] =
47 "failed-with-error-PermissionDismissedError";
48 const char WebRtcTestBase::kAudioVideoCallConstraints360p
[] =
49 "{audio: true, video: {mandatory: {minWidth: 640, maxWidth: 640, "
50 " minHeight: 360, maxHeight: 360}}}";
51 const char WebRtcTestBase::kAudioVideoCallConstraints720p
[] =
52 "{audio: true, video: {mandatory: {minWidth: 1280, maxWidth: 1280, "
53 " minHeight: 720, maxHeight: 720}}}";
57 base::LazyInstance
<bool> hit_javascript_errors_
=
58 LAZY_INSTANCE_INITIALIZER
;
60 // Intercepts all log messages. We always attach this handler but only look at
61 // the results if the test requests so. Note that this will only work if the
62 // WebrtcTestBase-inheriting test cases do not run in parallel (if they did they
63 // would race to look at the log, which is global to all tests).
64 bool JavascriptErrorDetectingLogHandler(int severity
,
68 const std::string
& str
) {
69 if (file
== NULL
|| std::string("CONSOLE") != file
)
72 bool contains_uncaught
= str
.find("\"Uncaught ") != std::string::npos
;
73 if (severity
== logging::LOG_ERROR
||
74 (severity
== logging::LOG_INFO
&& contains_uncaught
)) {
75 hit_javascript_errors_
.Get() = true;
83 WebRtcTestBase::WebRtcTestBase(): detect_errors_in_javascript_(false) {
84 // The handler gets set for each test method, but that's fine since this
85 // set operation is idempotent.
86 logging::SetLogMessageHandler(&JavascriptErrorDetectingLogHandler
);
87 hit_javascript_errors_
.Get() = false;
92 WebRtcTestBase::~WebRtcTestBase() {
93 if (detect_errors_in_javascript_
) {
94 EXPECT_FALSE(hit_javascript_errors_
.Get())
95 << "Encountered javascript errors during test execution (Search "
96 << "for Uncaught or ERROR:CONSOLE in the test output).";
100 bool WebRtcTestBase::GetUserMediaAndAccept(
101 content::WebContents
* tab_contents
) const {
102 return GetUserMediaWithSpecificConstraintsAndAccept(
103 tab_contents
, kAudioVideoCallConstraints
);
106 bool WebRtcTestBase::GetUserMediaWithSpecificConstraintsAndAccept(
107 content::WebContents
* tab_contents
,
108 const std::string
& constraints
) const {
110 PermissionBubbleManager::FromWebContents(tab_contents
)
111 ->set_auto_response_for_test(PermissionBubbleManager::ACCEPT_ALL
);
112 GetUserMedia(tab_contents
, constraints
);
113 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
114 tab_contents
->GetMainFrame(), "obtainGetUserMediaResult();", &result
));
115 return kOkGotStream
== result
;
118 void WebRtcTestBase::GetUserMediaAndDeny(content::WebContents
* tab_contents
) {
119 return GetUserMediaWithSpecificConstraintsAndDeny(tab_contents
,
120 kAudioVideoCallConstraints
);
123 void WebRtcTestBase::GetUserMediaWithSpecificConstraintsAndDeny(
124 content::WebContents
* tab_contents
,
125 const std::string
& constraints
) const {
127 PermissionBubbleManager::FromWebContents(tab_contents
)
128 ->set_auto_response_for_test(PermissionBubbleManager::DENY_ALL
);
129 GetUserMedia(tab_contents
, constraints
);
130 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
131 tab_contents
->GetMainFrame(), "obtainGetUserMediaResult();", &result
));
132 EXPECT_EQ(kFailedWithPermissionDeniedError
, result
);
135 void WebRtcTestBase::GetUserMediaAndDismiss(
136 content::WebContents
* tab_contents
) const {
138 PermissionBubbleManager::FromWebContents(tab_contents
)
139 ->set_auto_response_for_test(PermissionBubbleManager::DISMISS
);
140 GetUserMedia(tab_contents
, kAudioVideoCallConstraints
);
141 // A dismiss should be treated like a deny.
142 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
143 tab_contents
->GetMainFrame(), "obtainGetUserMediaResult();", &result
));
144 EXPECT_EQ(kFailedWithPermissionDismissedError
, result
);
147 void WebRtcTestBase::GetUserMedia(content::WebContents
* tab_contents
,
148 const std::string
& constraints
) const {
149 // Request user media: this will launch the media stream info bar or bubble.
151 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
152 tab_contents
, "doGetUserMedia(" + constraints
+ ");", &result
));
153 EXPECT_TRUE(result
== "request-callback-denied" ||
154 result
== "request-callback-granted");
157 content::WebContents
* WebRtcTestBase::OpenPageAndGetUserMediaInNewTab(
158 const GURL
& url
) const {
159 return OpenPageAndGetUserMediaInNewTabWithConstraints(
160 url
, kAudioVideoCallConstraints
);
163 content::WebContents
*
164 WebRtcTestBase::OpenPageAndGetUserMediaInNewTabWithConstraints(
166 const std::string
& constraints
) const {
167 chrome::AddTabAt(browser(), GURL(), -1, true);
168 ui_test_utils::NavigateToURL(browser(), url
);
169 content::WebContents
* new_tab
=
170 browser()->tab_strip_model()->GetActiveWebContents();
171 EXPECT_TRUE(GetUserMediaWithSpecificConstraintsAndAccept(
172 new_tab
, constraints
));
176 content::WebContents
* WebRtcTestBase::OpenTestPageAndGetUserMediaInNewTab(
177 const std::string
& test_page
) const {
178 return OpenPageAndGetUserMediaInNewTab(
179 embedded_test_server()->GetURL(test_page
));
182 void WebRtcTestBase::CloseLastLocalStream(
183 content::WebContents
* tab_contents
) const {
184 EXPECT_EQ("ok-stopped",
185 ExecuteJavascript("stopLocalStream();", tab_contents
));
188 // Convenience method which executes the provided javascript in the context
189 // of the provided web contents and returns what it evaluated to.
190 std::string
WebRtcTestBase::ExecuteJavascript(
191 const std::string
& javascript
,
192 content::WebContents
* tab_contents
) const {
194 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
195 tab_contents
, javascript
, &result
));
199 void WebRtcTestBase::SetupPeerconnectionWithLocalStream(
200 content::WebContents
* tab
) const {
201 SetupPeerconnectionWithoutLocalStream(tab
);
202 EXPECT_EQ("ok-added", ExecuteJavascript("addLocalStream()", tab
));
205 void WebRtcTestBase::SetupPeerconnectionWithoutLocalStream(
206 content::WebContents
* tab
) const {
207 EXPECT_EQ("ok-peerconnection-created",
208 ExecuteJavascript("preparePeerConnection()", tab
));
211 std::string
WebRtcTestBase::CreateLocalOffer(
212 content::WebContents
* from_tab
) const {
213 std::string response
= ExecuteJavascript("createLocalOffer({})", from_tab
);
214 EXPECT_EQ("ok-", response
.substr(0, 3)) << "Failed to create local offer: "
217 std::string local_offer
= response
.substr(3);
221 std::string
WebRtcTestBase::CreateAnswer(std::string local_offer
,
222 content::WebContents
* to_tab
) const {
223 std::string javascript
=
224 base::StringPrintf("receiveOfferFromPeer('%s', {})", local_offer
.c_str());
225 std::string response
= ExecuteJavascript(javascript
, to_tab
);
226 EXPECT_EQ("ok-", response
.substr(0, 3))
227 << "Receiving peer failed to receive offer and create answer: "
230 std::string answer
= response
.substr(3);
234 void WebRtcTestBase::ReceiveAnswer(std::string answer
,
235 content::WebContents
* from_tab
) const {
237 "ok-accepted-answer",
239 base::StringPrintf("receiveAnswerFromPeer('%s')", answer
.c_str()),
243 void WebRtcTestBase::GatherAndSendIceCandidates(
244 content::WebContents
* from_tab
,
245 content::WebContents
* to_tab
) const {
246 std::string ice_candidates
=
247 ExecuteJavascript("getAllIceCandidates()", from_tab
);
249 EXPECT_EQ("ok-received-candidates", ExecuteJavascript(
250 base::StringPrintf("receiveIceCandidates('%s')", ice_candidates
.c_str()),
254 void WebRtcTestBase::NegotiateCall(content::WebContents
* from_tab
,
255 content::WebContents
* to_tab
) const {
256 std::string local_offer
= CreateLocalOffer(from_tab
);
257 std::string answer
= CreateAnswer(local_offer
, to_tab
);
258 ReceiveAnswer(answer
, from_tab
);
260 // Send all ICE candidates (wait for gathering to finish if necessary).
261 GatherAndSendIceCandidates(to_tab
, from_tab
);
262 GatherAndSendIceCandidates(from_tab
, to_tab
);
265 void WebRtcTestBase::HangUp(content::WebContents
* from_tab
) const {
266 EXPECT_EQ("ok-call-hung-up", ExecuteJavascript("hangUp()", from_tab
));
269 void WebRtcTestBase::DetectErrorsInJavaScript() {
270 detect_errors_in_javascript_
= true;
273 void WebRtcTestBase::StartDetectingVideo(
274 content::WebContents
* tab_contents
,
275 const std::string
& video_element
) const {
276 std::string javascript
= base::StringPrintf(
277 "startDetection('%s', 320, 240)", video_element
.c_str());
278 EXPECT_EQ("ok-started", ExecuteJavascript(javascript
, tab_contents
));
281 bool WebRtcTestBase::WaitForVideoToPlay(
282 content::WebContents
* tab_contents
) const {
283 bool is_video_playing
= test::PollingWaitUntil(
284 "isVideoPlaying()", "video-playing", tab_contents
);
285 EXPECT_TRUE(is_video_playing
);
286 return is_video_playing
;
289 std::string
WebRtcTestBase::GetStreamSize(
290 content::WebContents
* tab_contents
,
291 const std::string
& video_element
) const {
292 std::string javascript
=
293 base::StringPrintf("getStreamSize('%s')", video_element
.c_str());
294 std::string result
= ExecuteJavascript(javascript
, tab_contents
);
295 EXPECT_TRUE(base::StartsWithASCII(result
, "ok-", true));
296 return result
.substr(3);
299 bool WebRtcTestBase::HasWebcamAvailableOnSystem(
300 content::WebContents
* tab_contents
) const {
302 ExecuteJavascript("hasVideoInputDeviceOnSystem();", tab_contents
);
303 return result
== "has-video-input-device";
306 bool WebRtcTestBase::OnWinXp() const {
308 return base::win::GetVersion() <= base::win::VERSION_XP
;
314 bool WebRtcTestBase::OnWin8() const {
316 return base::win::GetVersion() > base::win::VERSION_WIN7
;