1 // Copyright 2014 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/signin/signin_promo.h"
6 #include "chrome/browser/signin/signin_tracker_factory.h"
7 #include "chrome/browser/ui/browser.h"
8 #include "chrome/browser/ui/tabs/tab_strip_model.h"
9 #include "chrome/browser/ui/webui/signin/inline_login_ui.h"
10 #include "chrome/test/base/ui_test_utils.h"
11 #include "content/public/browser/notification_service.h"
12 #include "content/public/browser/notification_types.h"
13 #include "content/public/browser/web_contents.h"
14 #include "content/public/test/browser_test_utils.h"
16 using content::MessageLoopRunner
;
18 // anonymous namespace for signin with UI helper functions.
21 // The SignInObserver observes the signin manager and blocks until a
22 // GoogleSigninSucceeded or a GoogleSigninFailed notification is fired.
23 class SignInObserver
: public SigninTracker::Observer
{
30 virtual ~SignInObserver() {}
32 // Returns whether a GoogleSigninSucceeded event has happened.
37 // Blocks and waits until the user signs in. Wait() does not block if a
38 // GoogleSigninSucceeded or a GoogleSigninFailed has already occurred.
44 message_loop_runner_
= new MessageLoopRunner
;
45 message_loop_runner_
->Run();
49 void SigninFailed(const GoogleServiceAuthError
& error
) override
{
50 DVLOG(1) << "Google signin failed.";
54 message_loop_runner_
->Quit();
58 void AccountAddedToCookie(const GoogleServiceAuthError
& error
) override
{}
60 void SigninSuccess() override
{
61 DVLOG(1) << "Google signin succeeded.";
66 message_loop_runner_
->Quit();
71 // Bool to mark an observed event as seen prior to calling Wait(), used to
72 // prevent the observer from blocking.
74 // True is the message loop runner is running.
76 // True if a GoogleSigninSucceeded event has been observed.
78 scoped_refptr
<MessageLoopRunner
> message_loop_runner_
;
81 } // anonymous namespace
84 namespace login_ui_test_utils
{
86 void WaitUntilUIReady(Browser
* browser
) {
88 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
89 browser
->tab_strip_model()->GetActiveWebContents(),
90 "if (!inline.login.getAuthExtHost())"
91 " inline.login.initialize();"
92 "var handler = function() {"
93 " window.domAutomationController.send('ready');"
95 "if (inline.login.isAuthReady())"
98 " inline.login.getAuthExtHost().addEventListener('ready', handler);",
100 ASSERT_EQ("ready", message
);
103 void WaitUntilElementExistsInSigninFrame(Browser
* browser
,
104 const std::string
& element_id
) {
107 "function WaitForElementById(elementId) {"
108 " var retries = 10; /* 10 seconds. */"
109 " function CheckelementExists() {"
110 " if (document.getElementById(elementId) != null) {"
111 " window.domAutomationController.send('found');"
112 " } else if (retries > 0) { "
114 " window.setTimeout(CheckelementExists, 1000);"
116 " window.domAutomationController.send('failed');"
119 " CheckelementExists();"
121 "WaitForElementById('" + element_id
+ "');";
122 content::WebContents
* web_contents
=
123 browser
->tab_strip_model()->GetActiveWebContents();
124 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
125 InlineLoginUI::GetAuthFrame(web_contents
, GURL(), "signin-frame"),
128 ASSERT_EQ("found", message
) <<
129 "Failed to find element with id " << element_id
;
132 bool ElementExistsInSigninFrame(Browser
* browser
,
133 const std::string
& element_id
) {
134 content::WebContents
* web_contents
=
135 browser
->tab_strip_model()->GetActiveWebContents();
137 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
138 InlineLoginUI::GetAuthFrame(web_contents
, GURL(), "signin-frame"),
139 "window.domAutomationController.send("
140 " document.getElementById('" + element_id
+ "') != null);",
145 void SigninInNewGaiaFlow(Browser
* browser
,
146 const std::string
& email
,
147 const std::string
& password
) {
148 std::string js
= "document.getElementById('Email').value = '" + email
+ "';"
149 "document.getElementById('next').click();";
151 content::WebContents
* web_contents
=
152 browser
->tab_strip_model()->GetActiveWebContents();
153 ASSERT_TRUE(content::ExecuteScript(InlineLoginUI::GetAuthFrame(
154 web_contents
, GURL(), "signin-frame"), js
));
156 WaitUntilElementExistsInSigninFrame(browser
, "Passwd");
157 js
= "document.getElementById('Passwd').value = '" + password
+ "';"
158 "document.getElementById('signIn').click();";
160 ASSERT_TRUE(content::ExecuteScript(InlineLoginUI::GetAuthFrame(
161 web_contents
, GURL(), "signin-frame"), js
));
164 void SigninInOldGaiaFlow(Browser
* browser
,
165 const std::string
& email
,
166 const std::string
& password
) {
168 "document.getElementById('Email').value = '" + email
+ "';"
169 "document.getElementById('Passwd').value = '" + password
+ "';"
170 "document.getElementById('signIn').click();";
172 content::WebContents
* web_contents
=
173 browser
->tab_strip_model()->GetActiveWebContents();
174 ASSERT_TRUE(content::ExecuteScript(InlineLoginUI::GetAuthFrame(
175 web_contents
, GURL(), "signin-frame"), js
));
178 void ExecuteJsToSigninInSigninFrame(Browser
* browser
,
179 const std::string
& email
,
180 const std::string
& password
) {
181 WaitUntilElementExistsInSigninFrame(browser
, "Email");
182 if (ElementExistsInSigninFrame(browser
, "next"))
183 SigninInNewGaiaFlow(browser
, email
, password
);
185 SigninInOldGaiaFlow(browser
, email
, password
);
188 bool SignInWithUI(Browser
* browser
,
189 const std::string
& username
,
190 const std::string
& password
) {
192 SignInObserver signin_observer
;
193 scoped_ptr
<SigninTracker
> tracker
=
194 SigninTrackerFactory::CreateForProfile(browser
->profile(),
197 GURL signin_url
= signin::GetPromoURL(
198 signin_metrics::SOURCE_START_PAGE
, false);
199 DVLOG(1) << "Navigating to " << signin_url
;
200 // For some tests, the window is not shown yet and this might be the first tab
201 // navigation, so GetActiveWebContents() for CURRENT_TAB is NULL. That's why
202 // we use NEW_FOREGROUND_TAB rather than the CURRENT_TAB used by default in
203 // ui_test_utils::NavigateToURL().
204 ui_test_utils::NavigateToURLWithDisposition(
208 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION
);
210 DVLOG(1) << "Wait for login UI to be ready.";
211 WaitUntilUIReady(browser
);
212 DVLOG(1) << "Sign in user: " << username
;
213 ExecuteJsToSigninInSigninFrame(browser
, username
, password
);
214 signin_observer
.Wait();
215 return signin_observer
.DidSignIn();
218 } // namespace login_ui_test_utils