Refactor WebsiteSettings to operate on a SecurityInfo
[chromium-blink-merge.git] / chrome / browser / media / webrtc_browsertest_base.cc
blob55cf90613e6f99094bd13525027102c7c69a8926
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"
19 #if defined(OS_WIN)
20 // For fine-grained suppression.
21 #include "base/win/windows_version.h"
22 #endif
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}}}";
55 namespace {
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,
65 const char* file,
66 int line,
67 size_t message_start,
68 const std::string& str) {
69 if (file == NULL || std::string("CONSOLE") != file)
70 return false;
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;
78 return false;
81 // PermissionRequestObserver ---------------------------------------------------
83 // Used to observe the creation of permission prompt without responding.
84 class PermissionRequestObserver : public PermissionBubbleManager::Observer {
85 public:
86 explicit PermissionRequestObserver(content::WebContents* web_contents)
87 : bubble_manager_(PermissionBubbleManager::FromWebContents(web_contents)),
88 request_shown_(false),
89 message_loop_runner_(new content::MessageLoopRunner) {
90 bubble_manager_->AddObserver(this);
92 ~PermissionRequestObserver() override {
93 // Safe to remove twice if it happens.
94 bubble_manager_->RemoveObserver(this);
97 void Wait() { message_loop_runner_->Run(); }
99 bool request_shown() const { return request_shown_; }
101 private:
102 // PermissionBubbleManager::Observer
103 void OnBubbleAdded() override {
104 request_shown_ = true;
105 bubble_manager_->RemoveObserver(this);
106 message_loop_runner_->Quit();
109 PermissionBubbleManager* bubble_manager_;
110 bool request_shown_;
111 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
113 DISALLOW_COPY_AND_ASSIGN(PermissionRequestObserver);
116 } // namespace
118 WebRtcTestBase::WebRtcTestBase(): detect_errors_in_javascript_(false) {
119 // The handler gets set for each test method, but that's fine since this
120 // set operation is idempotent.
121 logging::SetLogMessageHandler(&JavascriptErrorDetectingLogHandler);
122 hit_javascript_errors_.Get() = false;
124 EnablePixelOutput();
127 WebRtcTestBase::~WebRtcTestBase() {
128 if (detect_errors_in_javascript_) {
129 EXPECT_FALSE(hit_javascript_errors_.Get())
130 << "Encountered javascript errors during test execution (Search "
131 << "for Uncaught or ERROR:CONSOLE in the test output).";
135 bool WebRtcTestBase::GetUserMediaAndAccept(
136 content::WebContents* tab_contents) const {
137 return GetUserMediaWithSpecificConstraintsAndAccept(
138 tab_contents, kAudioVideoCallConstraints);
141 bool WebRtcTestBase::GetUserMediaWithSpecificConstraintsAndAccept(
142 content::WebContents* tab_contents,
143 const std::string& constraints) const {
144 std::string result;
145 PermissionBubbleManager::FromWebContents(tab_contents)
146 ->set_auto_response_for_test(PermissionBubbleManager::ACCEPT_ALL);
147 PermissionRequestObserver permissionRequestObserver(tab_contents);
148 GetUserMedia(tab_contents, constraints);
149 EXPECT_TRUE(permissionRequestObserver.request_shown());
150 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
151 tab_contents->GetMainFrame(), "obtainGetUserMediaResult();", &result));
152 return kOkGotStream == result;
155 bool WebRtcTestBase::GetUserMediaWithSpecificConstraintsAndAcceptIfPrompted(
156 content::WebContents* tab_contents,
157 const std::string& constraints) const {
158 std::string result;
159 PermissionBubbleManager::FromWebContents(tab_contents)
160 ->set_auto_response_for_test(PermissionBubbleManager::ACCEPT_ALL);
161 GetUserMedia(tab_contents, constraints);
162 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
163 tab_contents->GetMainFrame(), "obtainGetUserMediaResult();", &result));
164 return kOkGotStream == result;
167 void WebRtcTestBase::GetUserMediaAndDeny(content::WebContents* tab_contents) {
168 return GetUserMediaWithSpecificConstraintsAndDeny(tab_contents,
169 kAudioVideoCallConstraints);
172 void WebRtcTestBase::GetUserMediaWithSpecificConstraintsAndDeny(
173 content::WebContents* tab_contents,
174 const std::string& constraints) const {
175 std::string result;
176 PermissionBubbleManager::FromWebContents(tab_contents)
177 ->set_auto_response_for_test(PermissionBubbleManager::DENY_ALL);
178 PermissionRequestObserver permissionRequestObserver(tab_contents);
179 GetUserMedia(tab_contents, constraints);
180 EXPECT_TRUE(permissionRequestObserver.request_shown());
181 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
182 tab_contents->GetMainFrame(), "obtainGetUserMediaResult();", &result));
183 EXPECT_EQ(kFailedWithPermissionDeniedError, result);
186 void WebRtcTestBase::GetUserMediaAndDismiss(
187 content::WebContents* tab_contents) const {
188 std::string result;
189 PermissionBubbleManager::FromWebContents(tab_contents)
190 ->set_auto_response_for_test(PermissionBubbleManager::DISMISS);
191 PermissionRequestObserver permissionRequestObserver(tab_contents);
192 GetUserMedia(tab_contents, kAudioVideoCallConstraints);
193 EXPECT_TRUE(permissionRequestObserver.request_shown());
194 // A dismiss should be treated like a deny.
195 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
196 tab_contents->GetMainFrame(), "obtainGetUserMediaResult();", &result));
197 EXPECT_EQ(kFailedWithPermissionDismissedError, result);
200 void WebRtcTestBase::GetUserMediaAndExpectAutoAcceptWithoutPrompt(
201 content::WebContents* tab_contents) const {
202 std::string result;
203 // We issue a GetUserMedia() request. We expect that the origin already has a
204 // sticky "accept" permission (e.g. because the caller previously called
205 // GetUserMediaAndAccept()), and therefore the GetUserMedia() request
206 // automatically succeeds without a prompt.
207 // If the caller made a mistake, a prompt may show up instead. For this case,
208 // we set an auto-response to avoid leaving the prompt hanging. The choice of
209 // DENY_ALL makes sure that the response to the prompt doesn't accidentally
210 // result in a newly granted media stream permission.
211 PermissionBubbleManager::FromWebContents(tab_contents)
212 ->set_auto_response_for_test(PermissionBubbleManager::DENY_ALL);
213 PermissionRequestObserver permissionRequestObserver(tab_contents);
214 GetUserMedia(tab_contents, kAudioVideoCallConstraints);
215 EXPECT_FALSE(permissionRequestObserver.request_shown());
216 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
217 tab_contents->GetMainFrame(), "obtainGetUserMediaResult();", &result));
218 EXPECT_EQ(kOkGotStream, result);
221 void WebRtcTestBase::GetUserMediaAndExpectAutoDenyWithoutPrompt(
222 content::WebContents* tab_contents) const {
223 std::string result;
224 // We issue a GetUserMedia() request. We expect that the origin already has a
225 // sticky "deny" permission (e.g. because the caller previously called
226 // GetUserMediaAndDeny()), and therefore the GetUserMedia() request
227 // automatically succeeds without a prompt.
228 // If the caller made a mistake, a prompt may show up instead. For this case,
229 // we set an auto-response to avoid leaving the prompt hanging. The choice of
230 // ACCEPT_ALL makes sure that the response to the prompt doesn't accidentally
231 // result in a newly granted media stream permission.
232 PermissionBubbleManager::FromWebContents(tab_contents)
233 ->set_auto_response_for_test(PermissionBubbleManager::ACCEPT_ALL);
234 PermissionRequestObserver permissionRequestObserver(tab_contents);
235 GetUserMedia(tab_contents, kAudioVideoCallConstraints);
236 EXPECT_FALSE(permissionRequestObserver.request_shown());
237 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
238 tab_contents->GetMainFrame(), "obtainGetUserMediaResult();", &result));
239 EXPECT_EQ(kFailedWithPermissionDeniedError, result);
242 void WebRtcTestBase::GetUserMedia(content::WebContents* tab_contents,
243 const std::string& constraints) const {
244 // Request user media: this will launch the media stream info bar or bubble.
245 std::string result;
246 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
247 tab_contents, "doGetUserMedia(" + constraints + ");", &result));
248 EXPECT_TRUE(result == "request-callback-denied" ||
249 result == "request-callback-granted");
252 content::WebContents* WebRtcTestBase::OpenPageAndGetUserMediaInNewTab(
253 const GURL& url) const {
254 return OpenPageAndGetUserMediaInNewTabWithConstraints(
255 url, kAudioVideoCallConstraints);
258 content::WebContents*
259 WebRtcTestBase::OpenPageAndGetUserMediaInNewTabWithConstraints(
260 const GURL& url,
261 const std::string& constraints) const {
262 chrome::AddTabAt(browser(), GURL(), -1, true);
263 ui_test_utils::NavigateToURL(browser(), url);
264 content::WebContents* new_tab =
265 browser()->tab_strip_model()->GetActiveWebContents();
266 // Accept if necessary, but don't expect a prompt (because auto-accept is also
267 // okay).
268 PermissionBubbleManager::FromWebContents(new_tab)
269 ->set_auto_response_for_test(PermissionBubbleManager::ACCEPT_ALL);
270 GetUserMedia(new_tab, constraints);
271 std::string result;
272 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
273 new_tab->GetMainFrame(), "obtainGetUserMediaResult();", &result));
274 EXPECT_EQ(kOkGotStream, result);
275 return new_tab;
278 content::WebContents* WebRtcTestBase::OpenTestPageAndGetUserMediaInNewTab(
279 const std::string& test_page) const {
280 return OpenPageAndGetUserMediaInNewTab(
281 embedded_test_server()->GetURL(test_page));
284 void WebRtcTestBase::CloseLastLocalStream(
285 content::WebContents* tab_contents) const {
286 EXPECT_EQ("ok-stopped",
287 ExecuteJavascript("stopLocalStream();", tab_contents));
290 // Convenience method which executes the provided javascript in the context
291 // of the provided web contents and returns what it evaluated to.
292 std::string WebRtcTestBase::ExecuteJavascript(
293 const std::string& javascript,
294 content::WebContents* tab_contents) const {
295 std::string result;
296 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
297 tab_contents, javascript, &result));
298 return result;
301 void WebRtcTestBase::SetupPeerconnectionWithLocalStream(
302 content::WebContents* tab) const {
303 SetupPeerconnectionWithoutLocalStream(tab);
304 EXPECT_EQ("ok-added", ExecuteJavascript("addLocalStream()", tab));
307 void WebRtcTestBase::SetupPeerconnectionWithoutLocalStream(
308 content::WebContents* tab) const {
309 EXPECT_EQ("ok-peerconnection-created",
310 ExecuteJavascript("preparePeerConnection()", tab));
313 std::string WebRtcTestBase::CreateLocalOffer(
314 content::WebContents* from_tab) const {
315 std::string response = ExecuteJavascript("createLocalOffer({})", from_tab);
316 EXPECT_EQ("ok-", response.substr(0, 3)) << "Failed to create local offer: "
317 << response;
319 std::string local_offer = response.substr(3);
320 return local_offer;
323 std::string WebRtcTestBase::CreateAnswer(std::string local_offer,
324 content::WebContents* to_tab) const {
325 std::string javascript =
326 base::StringPrintf("receiveOfferFromPeer('%s', {})", local_offer.c_str());
327 std::string response = ExecuteJavascript(javascript, to_tab);
328 EXPECT_EQ("ok-", response.substr(0, 3))
329 << "Receiving peer failed to receive offer and create answer: "
330 << response;
332 std::string answer = response.substr(3);
333 return answer;
336 void WebRtcTestBase::ReceiveAnswer(std::string answer,
337 content::WebContents* from_tab) const {
338 ASSERT_EQ(
339 "ok-accepted-answer",
340 ExecuteJavascript(
341 base::StringPrintf("receiveAnswerFromPeer('%s')", answer.c_str()),
342 from_tab));
345 void WebRtcTestBase::GatherAndSendIceCandidates(
346 content::WebContents* from_tab,
347 content::WebContents* to_tab) const {
348 std::string ice_candidates =
349 ExecuteJavascript("getAllIceCandidates()", from_tab);
351 EXPECT_EQ("ok-received-candidates", ExecuteJavascript(
352 base::StringPrintf("receiveIceCandidates('%s')", ice_candidates.c_str()),
353 to_tab));
356 void WebRtcTestBase::NegotiateCall(content::WebContents* from_tab,
357 content::WebContents* to_tab) const {
358 std::string local_offer = CreateLocalOffer(from_tab);
359 std::string answer = CreateAnswer(local_offer, to_tab);
360 ReceiveAnswer(answer, from_tab);
362 // Send all ICE candidates (wait for gathering to finish if necessary).
363 GatherAndSendIceCandidates(to_tab, from_tab);
364 GatherAndSendIceCandidates(from_tab, to_tab);
367 void WebRtcTestBase::HangUp(content::WebContents* from_tab) const {
368 EXPECT_EQ("ok-call-hung-up", ExecuteJavascript("hangUp()", from_tab));
371 void WebRtcTestBase::DetectErrorsInJavaScript() {
372 detect_errors_in_javascript_ = true;
375 void WebRtcTestBase::StartDetectingVideo(
376 content::WebContents* tab_contents,
377 const std::string& video_element) const {
378 std::string javascript = base::StringPrintf(
379 "startDetection('%s', 320, 240)", video_element.c_str());
380 EXPECT_EQ("ok-started", ExecuteJavascript(javascript, tab_contents));
383 bool WebRtcTestBase::WaitForVideoToPlay(
384 content::WebContents* tab_contents) const {
385 bool is_video_playing = test::PollingWaitUntil(
386 "isVideoPlaying()", "video-playing", tab_contents);
387 EXPECT_TRUE(is_video_playing);
388 return is_video_playing;
391 std::string WebRtcTestBase::GetStreamSize(
392 content::WebContents* tab_contents,
393 const std::string& video_element) const {
394 std::string javascript =
395 base::StringPrintf("getStreamSize('%s')", video_element.c_str());
396 std::string result = ExecuteJavascript(javascript, tab_contents);
397 EXPECT_TRUE(base::StartsWith(result, "ok-", base::CompareCase::SENSITIVE));
398 return result.substr(3);
401 bool WebRtcTestBase::HasWebcamAvailableOnSystem(
402 content::WebContents* tab_contents) const {
403 std::string result =
404 ExecuteJavascript("hasVideoInputDeviceOnSystem();", tab_contents);
405 return result == "has-video-input-device";
408 bool WebRtcTestBase::OnWinXp() const {
409 #if defined(OS_WIN)
410 return base::win::GetVersion() <= base::win::VERSION_XP;
411 #else
412 return false;
413 #endif
416 bool WebRtcTestBase::OnWin8() const {
417 #if defined(OS_WIN)
418 return base::win::GetVersion() > base::win::VERSION_WIN7;
419 #else
420 return false;
421 #endif