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/stringprintf.h"
9 #include "chrome/browser/chrome_notification_types.h"
10 #include "chrome/browser/infobars/infobar.h"
11 #include "chrome/browser/infobars/infobar_service.h"
12 #include "chrome/browser/media/media_stream_infobar_delegate.h"
13 #include "chrome/browser/media/webrtc_browsertest_common.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/browser_tabstrip.h"
16 #include "chrome/browser/ui/tabs/tab_strip_model.h"
17 #include "chrome/test/base/ui_test_utils.h"
18 #include "content/public/browser/notification_service.h"
19 #include "content/public/test/browser_test_utils.h"
21 const char WebRtcTestBase::kAudioVideoCallConstraints
[] =
22 "'{audio: true, video: true}'";
23 const char WebRtcTestBase::kAudioOnlyCallConstraints
[] = "'{audio: true}'";
24 const char WebRtcTestBase::kVideoOnlyCallConstraints
[] = "'{video: true}'";
25 const char WebRtcTestBase::kFailedWithPermissionDeniedError
[] =
26 "failed-with-error-PermissionDeniedError";
30 base::LazyInstance
<bool> hit_javascript_errors_
=
31 LAZY_INSTANCE_INITIALIZER
;
33 // Intercepts all log messages. We always attach this handler but only look at
34 // the results if the test requests so. Note that this will only work if the
35 // WebrtcTestBase-inheriting test cases do not run in parallel (if they did they
36 // would race to look at the log, which is global to all tests).
37 bool JavascriptErrorDetectingLogHandler(int severity
,
41 const std::string
& str
) {
42 if (file
== NULL
|| std::string("CONSOLE") != file
)
45 bool contains_uncaught
= str
.find("\"Uncaught ") != std::string::npos
;
46 if (severity
== logging::LOG_ERROR
||
47 (severity
== logging::LOG_INFO
&& contains_uncaught
)) {
48 hit_javascript_errors_
.Get() = true;
56 WebRtcTestBase::WebRtcTestBase(): detect_errors_in_javascript_(false) {
57 // The handler gets set for each test method, but that's fine since this
58 // set operation is idempotent.
59 logging::SetLogMessageHandler(&JavascriptErrorDetectingLogHandler
);
60 hit_javascript_errors_
.Get() = false;
63 WebRtcTestBase::~WebRtcTestBase() {
64 if (detect_errors_in_javascript_
) {
65 EXPECT_FALSE(hit_javascript_errors_
.Get())
66 << "Encountered javascript errors during test execution (Search "
67 << "for Uncaught or ERROR:CONSOLE in the test output).";
71 void WebRtcTestBase::GetUserMediaAndAccept(
72 content::WebContents
* tab_contents
) const {
73 GetUserMediaWithSpecificConstraintsAndAccept(tab_contents
,
74 kAudioVideoCallConstraints
);
77 void WebRtcTestBase::GetUserMediaWithSpecificConstraintsAndAccept(
78 content::WebContents
* tab_contents
,
79 const std::string
& constraints
) const {
80 InfoBar
* infobar
= GetUserMediaAndWaitForInfoBar(tab_contents
, constraints
);
81 infobar
->delegate()->AsConfirmInfoBarDelegate()->Accept();
82 CloseInfoBarInTab(tab_contents
, infobar
);
84 // Wait for WebRTC to call the success callback.
85 const char kOkGotStream
[] = "ok-got-stream";
86 EXPECT_TRUE(PollingWaitUntil("obtainGetUserMediaResult()", kOkGotStream
,
90 void WebRtcTestBase::GetUserMediaAndDeny(content::WebContents
* tab_contents
) {
91 return GetUserMediaWithSpecificConstraintsAndDeny(tab_contents
,
92 kAudioVideoCallConstraints
);
95 void WebRtcTestBase::GetUserMediaWithSpecificConstraintsAndDeny(
96 content::WebContents
* tab_contents
,
97 const std::string
& constraints
) const {
98 InfoBar
* infobar
= GetUserMediaAndWaitForInfoBar(tab_contents
, constraints
);
99 infobar
->delegate()->AsConfirmInfoBarDelegate()->Cancel();
100 CloseInfoBarInTab(tab_contents
, infobar
);
102 // Wait for WebRTC to call the fail callback.
103 EXPECT_TRUE(PollingWaitUntil("obtainGetUserMediaResult()",
104 kFailedWithPermissionDeniedError
, tab_contents
));
107 void WebRtcTestBase::GetUserMediaAndDismiss(
108 content::WebContents
* tab_contents
) const {
110 GetUserMediaAndWaitForInfoBar(tab_contents
, kAudioVideoCallConstraints
);
111 infobar
->delegate()->InfoBarDismissed();
112 CloseInfoBarInTab(tab_contents
, infobar
);
114 // A dismiss should be treated like a deny.
115 EXPECT_TRUE(PollingWaitUntil("obtainGetUserMediaResult()",
116 kFailedWithPermissionDeniedError
, tab_contents
));
119 void WebRtcTestBase::GetUserMedia(content::WebContents
* tab_contents
,
120 const std::string
& constraints
) const {
121 // Request user media: this will launch the media stream info bar.
123 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
124 tab_contents
, "doGetUserMedia(" + constraints
+ ");", &result
));
125 EXPECT_EQ("ok-requested", result
);
128 InfoBar
* WebRtcTestBase::GetUserMediaAndWaitForInfoBar(
129 content::WebContents
* tab_contents
,
130 const std::string
& constraints
) const {
131 content::WindowedNotificationObserver
infobar_added(
132 chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED
,
133 content::NotificationService::AllSources());
135 // Request user media: this will launch the media stream info bar.
136 GetUserMedia(tab_contents
, constraints
);
138 // Wait for the bar to pop up, then return it.
139 infobar_added
.Wait();
140 content::Details
<InfoBar::AddedDetails
> details(infobar_added
.details());
141 EXPECT_TRUE(details
->delegate()->AsMediaStreamInfoBarDelegate());
142 return details
.ptr();
145 content::WebContents
* WebRtcTestBase::OpenPageAndGetUserMediaInNewTab(
146 const GURL
& url
) const {
147 chrome::AddTabAt(browser(), GURL(), -1, true);
148 ui_test_utils::NavigateToURL(browser(), url
);
149 #if defined (OS_LINUX)
150 // Load the page again on Linux to work around crbug.com/281268.
151 ui_test_utils::NavigateToURL(browser(), url
);
153 content::WebContents
* new_tab
=
154 browser()->tab_strip_model()->GetActiveWebContents();
155 GetUserMediaAndAccept(new_tab
);
159 content::WebContents
* WebRtcTestBase::OpenPageAndAcceptUserMedia(
160 const GURL
& url
) const {
161 content::WindowedNotificationObserver
infobar_added(
162 chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED
,
163 content::NotificationService::AllSources());
165 ui_test_utils::NavigateToURL(browser(), url
);
167 infobar_added
.Wait();
169 content::WebContents
* tab_contents
=
170 browser()->tab_strip_model()->GetActiveWebContents();
171 content::Details
<InfoBar::AddedDetails
> details(infobar_added
.details());
172 InfoBar
* infobar
= details
.ptr();
173 EXPECT_TRUE(infobar
);
174 infobar
->delegate()->AsMediaStreamInfoBarDelegate()->Accept();
176 CloseInfoBarInTab(tab_contents
, infobar
);
180 void WebRtcTestBase::CloseInfoBarInTab(
181 content::WebContents
* tab_contents
,
182 InfoBar
* infobar
) const {
183 content::WindowedNotificationObserver
infobar_removed(
184 chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED
,
185 content::NotificationService::AllSources());
187 InfoBarService
* infobar_service
=
188 InfoBarService::FromWebContents(tab_contents
);
189 infobar_service
->RemoveInfoBar(infobar
);
191 infobar_removed
.Wait();
194 // Convenience method which executes the provided javascript in the context
195 // of the provided web contents and returns what it evaluated to.
196 std::string
WebRtcTestBase::ExecuteJavascript(
197 const std::string
& javascript
,
198 content::WebContents
* tab_contents
) const {
200 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
201 tab_contents
, javascript
, &result
));
205 // The peer connection server lets our two tabs find each other and talk to
206 // each other (e.g. it is the application-specific "signaling solution").
207 void WebRtcTestBase::ConnectToPeerConnectionServer(
208 const std::string
& peer_name
,
209 content::WebContents
* tab_contents
) const {
210 std::string javascript
= base::StringPrintf(
211 "connect('http://localhost:%s', '%s');",
212 PeerConnectionServerRunner::kDefaultPort
, peer_name
.c_str());
213 EXPECT_EQ("ok-connected", ExecuteJavascript(javascript
, tab_contents
));
216 void WebRtcTestBase::DetectErrorsInJavaScript() {
217 detect_errors_in_javascript_
= true;