• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_browsertest_base.h"
6 
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"
20 
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";
27 
28 namespace {
29 
30 base::LazyInstance<bool> hit_javascript_errors_ =
31       LAZY_INSTANCE_INITIALIZER;
32 
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).
JavascriptErrorDetectingLogHandler(int severity,const char * file,int line,size_t message_start,const std::string & str)37 bool JavascriptErrorDetectingLogHandler(int severity,
38                                         const char* file,
39                                         int line,
40                                         size_t message_start,
41                                         const std::string& str) {
42   if (file == NULL || std::string("CONSOLE") != file)
43     return false;
44 
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;
49   }
50 
51   return false;
52 }
53 
54 }  // namespace
55 
WebRtcTestBase()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;
61 }
62 
~WebRtcTestBase()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).";
68   }
69 }
70 
GetUserMediaAndAccept(content::WebContents * tab_contents) const71 void WebRtcTestBase::GetUserMediaAndAccept(
72     content::WebContents* tab_contents) const {
73   GetUserMediaWithSpecificConstraintsAndAccept(tab_contents,
74                                                kAudioVideoCallConstraints);
75 }
76 
GetUserMediaWithSpecificConstraintsAndAccept(content::WebContents * tab_contents,const std::string & constraints) const77 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);
83 
84   // Wait for WebRTC to call the success callback.
85   const char kOkGotStream[] = "ok-got-stream";
86   EXPECT_TRUE(PollingWaitUntil("obtainGetUserMediaResult()", kOkGotStream,
87                                tab_contents));
88 }
89 
GetUserMediaAndDeny(content::WebContents * tab_contents)90 void WebRtcTestBase::GetUserMediaAndDeny(content::WebContents* tab_contents) {
91   return GetUserMediaWithSpecificConstraintsAndDeny(tab_contents,
92                                                     kAudioVideoCallConstraints);
93 }
94 
GetUserMediaWithSpecificConstraintsAndDeny(content::WebContents * tab_contents,const std::string & constraints) const95 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);
101 
102   // Wait for WebRTC to call the fail callback.
103   EXPECT_TRUE(PollingWaitUntil("obtainGetUserMediaResult()",
104                                kFailedWithPermissionDeniedError, tab_contents));
105 }
106 
GetUserMediaAndDismiss(content::WebContents * tab_contents) const107 void WebRtcTestBase::GetUserMediaAndDismiss(
108     content::WebContents* tab_contents) const {
109   InfoBar* infobar =
110       GetUserMediaAndWaitForInfoBar(tab_contents, kAudioVideoCallConstraints);
111   infobar->delegate()->InfoBarDismissed();
112   CloseInfoBarInTab(tab_contents, infobar);
113 
114   // A dismiss should be treated like a deny.
115   EXPECT_TRUE(PollingWaitUntil("obtainGetUserMediaResult()",
116                                kFailedWithPermissionDeniedError, tab_contents));
117 }
118 
GetUserMedia(content::WebContents * tab_contents,const std::string & constraints) const119 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.
122   std::string result;
123   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
124       tab_contents, "doGetUserMedia(" + constraints + ");", &result));
125   EXPECT_EQ("ok-requested", result);
126 }
127 
GetUserMediaAndWaitForInfoBar(content::WebContents * tab_contents,const std::string & constraints) const128 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());
134 
135   // Request user media: this will launch the media stream info bar.
136   GetUserMedia(tab_contents, constraints);
137 
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();
143 }
144 
OpenPageAndGetUserMediaInNewTab(const GURL & url) const145 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);
152 #endif
153   content::WebContents* new_tab =
154       browser()->tab_strip_model()->GetActiveWebContents();
155   GetUserMediaAndAccept(new_tab);
156   return new_tab;
157 }
158 
OpenPageAndAcceptUserMedia(const GURL & url) const159 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());
164 
165   ui_test_utils::NavigateToURL(browser(), url);
166 
167   infobar_added.Wait();
168 
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();
175 
176   CloseInfoBarInTab(tab_contents, infobar);
177   return tab_contents;
178 }
179 
CloseInfoBarInTab(content::WebContents * tab_contents,InfoBar * infobar) const180 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());
186 
187   InfoBarService* infobar_service =
188       InfoBarService::FromWebContents(tab_contents);
189   infobar_service->RemoveInfoBar(infobar);
190 
191   infobar_removed.Wait();
192 }
193 
194 // Convenience method which executes the provided javascript in the context
195 // of the provided web contents and returns what it evaluated to.
ExecuteJavascript(const std::string & javascript,content::WebContents * tab_contents) const196 std::string WebRtcTestBase::ExecuteJavascript(
197     const std::string& javascript,
198     content::WebContents* tab_contents) const {
199   std::string result;
200   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
201       tab_contents, javascript, &result));
202   return result;
203 }
204 
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").
ConnectToPeerConnectionServer(const std::string & peer_name,content::WebContents * tab_contents) const207 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));
214 }
215 
DetectErrorsInJavaScript()216 void WebRtcTestBase::DetectErrorsInJavaScript() {
217   detect_errors_in_javascript_ = true;
218 }
219