1 // Copyright (c) 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 "base/message_loop/message_loop.h"
6 #include "base/prefs/pref_service.h"
7 #include "base/strings/stringprintf.h"
8 #include "base/synchronization/waitable_event.h"
9 #include "chrome/browser/browser_process.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/chromeos/login/oauth2_login_manager.h"
12 #include "chrome/browser/chromeos/login/oauth2_login_manager_factory.h"
13 #include "chrome/browser/chromeos/login/oobe_base_test.h"
14 #include "chrome/browser/chromeos/login/user_manager.h"
15 #include "chrome/browser/chromeos/login/wizard_controller.h"
16 #include "chrome/browser/extensions/extension_test_message_listener.h"
17 #include "chrome/browser/profiles/profile_manager.h"
18 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
19 #include "chrome/browser/ui/app_modal_dialogs/javascript_app_modal_dialog.h"
20 #include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h"
21 #include "chrome/browser/ui/browser.h"
22 #include "chrome/browser/ui/browser_tabstrip.h"
23 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
24 #include "chrome/browser/ui/tabs/tab_strip_model.h"
25 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
26 #include "chrome/test/base/ui_test_utils.h"
27 #include "components/signin/core/browser/profile_oauth2_token_service.h"
28 #include "content/public/browser/notification_service.h"
29 #include "content/public/test/browser_test_utils.h"
30 #include "extensions/browser/process_manager.h"
31 #include "google_apis/gaia/gaia_constants.h"
32 #include "google_apis/gaia/gaia_urls.h"
33 #include "net/cookies/canonical_cookie.h"
34 #include "net/cookies/cookie_monster.h"
35 #include "net/cookies/cookie_store.h"
36 #include "net/test/embedded_test_server/http_request.h"
37 #include "net/test/embedded_test_server/http_response.h"
38 #include "net/url_request/url_request_context.h"
39 #include "net/url_request/url_request_context_getter.h"
41 using net::test_server::BasicHttpResponse
;
42 using net::test_server::HttpRequest
;
43 using net::test_server::HttpResponse
;
49 // Email of owner account for test.
50 const char kTestAccountId
[] = "username@gmail.com";
51 const char kTestRawAccountId
[] = "User.Name";
52 const char kTestAccountPassword
[] = "fake-password";
53 const char kTestAuthCode
[] = "fake-auth-code";
54 const char kTestGaiaUberToken
[] = "fake-uber-token";
55 const char kTestAuthLoginAccessToken
[] = "fake-access-token";
56 const char kTestRefreshToken
[] = "fake-refresh-token";
57 const char kTestAuthSIDCookie
[] = "fake-auth-SID-cookie";
58 const char kTestAuthLSIDCookie
[] = "fake-auth-LSID-cookie";
59 const char kTestSessionSIDCookie
[] = "fake-session-SID-cookie";
60 const char kTestSessionLSIDCookie
[] = "fake-session-LSID-cookie";
61 const char kTestSession2SIDCookie
[] = "fake-session2-SID-cookie";
62 const char kTestSession2LSIDCookie
[] = "fake-session2-LSID-cookie";
63 const char kTestUserinfoToken
[] = "fake-userinfo-token";
64 const char kTestLoginToken
[] = "fake-login-token";
65 const char kTestSyncToken
[] = "fake-sync-token";
66 const char kTestAuthLoginToken
[] = "fake-oauthlogin-token";
68 class OAuth2LoginManagerStateWaiter
: public OAuth2LoginManager::Observer
{
70 explicit OAuth2LoginManagerStateWaiter(Profile
* profile
)
72 waiting_for_state_(false),
73 final_state_(OAuth2LoginManager::SESSION_RESTORE_NOT_STARTED
) {
77 const std::set
<OAuth2LoginManager::SessionRestoreState
>& states
) {
78 DCHECK(!waiting_for_state_
);
79 OAuth2LoginManager
* login_manager
=
80 OAuth2LoginManagerFactory::GetInstance()->GetForProfile(profile_
);
82 if (states_
.find(login_manager
->state()) != states_
.end()) {
83 final_state_
= login_manager
->state();
87 waiting_for_state_
= true;
88 login_manager
->AddObserver(this);
89 runner_
= new content::MessageLoopRunner
;
91 login_manager
->RemoveObserver(this);
94 OAuth2LoginManager::SessionRestoreState
final_state() { return final_state_
; }
97 // OAuth2LoginManager::Observer overrides.
98 virtual void OnSessionRestoreStateChanged(
99 Profile
* user_profile
,
100 OAuth2LoginManager::SessionRestoreState state
) OVERRIDE
{
101 if (!waiting_for_state_
)
104 if (states_
.find(state
) == states_
.end())
107 final_state_
= state
;
108 waiting_for_state_
= false;
113 std::set
<OAuth2LoginManager::SessionRestoreState
> states_
;
114 bool waiting_for_state_
;
115 OAuth2LoginManager::SessionRestoreState final_state_
;
116 scoped_refptr
<content::MessageLoopRunner
> runner_
;
118 DISALLOW_COPY_AND_ASSIGN(OAuth2LoginManagerStateWaiter
);
123 class OAuth2Test
: public OobeBaseTest
{
127 void SetupGaiaServerForNewAccount() {
128 FakeGaia::MergeSessionParams params
;
129 params
.auth_sid_cookie
= kTestAuthSIDCookie
;
130 params
.auth_lsid_cookie
= kTestAuthLSIDCookie
;
131 params
.auth_code
= kTestAuthCode
;
132 params
.refresh_token
= kTestRefreshToken
;
133 params
.access_token
= kTestAuthLoginAccessToken
;
134 params
.gaia_uber_token
= kTestGaiaUberToken
;
135 params
.session_sid_cookie
= kTestSessionSIDCookie
;
136 params
.session_lsid_cookie
= kTestSessionLSIDCookie
;
137 fake_gaia_
->SetMergeSessionParams(params
);
138 SetupGaiaServerWithAccessTokens();
141 void SetupGaiaServerForUnexpiredAccount() {
142 FakeGaia::MergeSessionParams params
;
143 params
.email
= kTestAccountId
;
144 fake_gaia_
->SetMergeSessionParams(params
);
145 SetupGaiaServerWithAccessTokens();
148 void SetupGaiaServerForExpiredAccount() {
149 FakeGaia::MergeSessionParams params
;
150 params
.gaia_uber_token
= kTestGaiaUberToken
;
151 params
.session_sid_cookie
= kTestSession2SIDCookie
;
152 params
.session_lsid_cookie
= kTestSession2LSIDCookie
;
153 fake_gaia_
->SetMergeSessionParams(params
);
154 SetupGaiaServerWithAccessTokens();
157 void LoginAsExistingUser() {
158 content::WindowedNotificationObserver(
159 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
,
160 content::NotificationService::AllSources()).Wait();
162 JsExpect("!!document.querySelector('#account-picker')");
163 JsExpect("!!document.querySelector('#pod-row')");
165 EXPECT_EQ(GetOAuthStatusFromLocalState(kTestAccountId
),
166 User::OAUTH2_TOKEN_STATUS_VALID
);
168 EXPECT_TRUE(TryToLogin(kTestAccountId
, kTestAccountPassword
));
169 Profile
* profile
= ProfileManager::GetPrimaryUserProfile();
171 // Wait for the session merge to finish.
172 WaitForMergeSessionCompletion(OAuth2LoginManager::SESSION_RESTORE_DONE
);
174 // Check for existance of refresh token.
175 ProfileOAuth2TokenService
* token_service
=
176 ProfileOAuth2TokenServiceFactory::GetForProfile(profile
);
177 EXPECT_TRUE(token_service
->RefreshTokenIsAvailable(kTestAccountId
));
179 EXPECT_EQ(GetOAuthStatusFromLocalState(kTestAccountId
),
180 User::OAUTH2_TOKEN_STATUS_VALID
);
183 bool TryToLogin(const std::string
& username
,
184 const std::string
& password
) {
185 if (!AddUserToSession(username
, password
))
188 if (const User
* active_user
= UserManager::Get()->GetActiveUser())
189 return active_user
->email() == username
;
194 User::OAuthTokenStatus
GetOAuthStatusFromLocalState(
195 const std::string
& user_id
) const {
196 PrefService
* local_state
= g_browser_process
->local_state();
197 const base::DictionaryValue
* prefs_oauth_status
=
198 local_state
->GetDictionary("OAuthTokenStatus");
199 int oauth_token_status
= User::OAUTH_TOKEN_STATUS_UNKNOWN
;
200 if (prefs_oauth_status
&&
201 prefs_oauth_status
->GetIntegerWithoutPathExpansion(
202 user_id
, &oauth_token_status
)) {
203 User::OAuthTokenStatus result
=
204 static_cast<User::OAuthTokenStatus
>(oauth_token_status
);
207 return User::OAUTH_TOKEN_STATUS_UNKNOWN
;
211 // OobeBaseTest overrides.
212 virtual Profile
* profile() OVERRIDE
{
213 if (UserManager::Get()->GetActiveUser())
214 return ProfileManager::GetPrimaryUserProfile();
216 return OobeBaseTest::profile();
219 bool AddUserToSession(const std::string
& username
,
220 const std::string
& password
) {
221 ExistingUserController
* controller
=
222 ExistingUserController::current_controller();
228 controller
->Login(UserContext(username
, password
, std::string()));
229 content::WindowedNotificationObserver(
230 chrome::NOTIFICATION_SESSION_STARTED
,
231 content::NotificationService::AllSources()).Wait();
232 const UserList
& logged_users
= UserManager::Get()->GetLoggedInUsers();
233 for (UserList::const_iterator it
= logged_users
.begin();
234 it
!= logged_users
.end(); ++it
) {
235 if ((*it
)->email() == username
)
241 void SetupGaiaServerWithAccessTokens() {
242 // Configure OAuth authentication.
243 GaiaUrls
* gaia_urls
= GaiaUrls::GetInstance();
245 // This token satisfies the userinfo.email request from
246 // DeviceOAuth2TokenService used in token validation.
247 FakeGaia::AccessTokenInfo userinfo_token_info
;
248 userinfo_token_info
.token
= kTestUserinfoToken
;
249 userinfo_token_info
.scopes
.insert(
250 "https://www.googleapis.com/auth/userinfo.email");
251 userinfo_token_info
.audience
= gaia_urls
->oauth2_chrome_client_id();
252 userinfo_token_info
.email
= kTestAccountId
;
253 fake_gaia_
->IssueOAuthToken(kTestRefreshToken
, userinfo_token_info
);
255 FakeGaia::AccessTokenInfo userinfo_profile_token_info
;
256 userinfo_profile_token_info
.token
= kTestUserinfoToken
;
257 userinfo_profile_token_info
.scopes
.insert(
258 "https://www.googleapis.com/auth/userinfo.profile");
259 userinfo_profile_token_info
.audience
= gaia_urls
->oauth2_chrome_client_id();
260 userinfo_profile_token_info
.email
= kTestAccountId
;
261 fake_gaia_
->IssueOAuthToken(kTestRefreshToken
, userinfo_profile_token_info
);
263 // The any-api access token for accessing the token minting endpoint.
264 FakeGaia::AccessTokenInfo login_token_info
;
265 login_token_info
.token
= kTestLoginToken
;
266 login_token_info
.scopes
.insert(GaiaConstants::kAnyApiOAuth2Scope
);
267 login_token_info
.audience
= gaia_urls
->oauth2_chrome_client_id();
268 fake_gaia_
->IssueOAuthToken(kTestRefreshToken
, login_token_info
);
270 // The /auth/chromesync access token for accessing sync endpoint.
271 FakeGaia::AccessTokenInfo sync_token_info
;
272 sync_token_info
.token
= kTestSyncToken
;
273 sync_token_info
.scopes
.insert(GaiaConstants::kChromeSyncOAuth2Scope
);
274 sync_token_info
.audience
= gaia_urls
->oauth2_chrome_client_id();
275 fake_gaia_
->IssueOAuthToken(kTestRefreshToken
, sync_token_info
);
277 FakeGaia::AccessTokenInfo auth_login_token_info
;
278 auth_login_token_info
.token
= kTestAuthLoginToken
;
279 auth_login_token_info
.scopes
.insert(GaiaConstants::kOAuth1LoginScope
);
280 auth_login_token_info
.audience
= gaia_urls
->oauth2_chrome_client_id();
281 fake_gaia_
->IssueOAuthToken(kTestRefreshToken
, auth_login_token_info
);
284 void CheckSessionState(OAuth2LoginManager::SessionRestoreState state
) {
285 OAuth2LoginManager
* login_manager
=
286 OAuth2LoginManagerFactory::GetInstance()->GetForProfile(
288 ASSERT_EQ(state
, login_manager
->state());
291 void WaitForMergeSessionCompletion(
292 OAuth2LoginManager::SessionRestoreState final_state
) {
293 // Wait for the session merge to finish.
294 std::set
<OAuth2LoginManager::SessionRestoreState
> states
;
295 states
.insert(OAuth2LoginManager::SESSION_RESTORE_DONE
);
296 states
.insert(OAuth2LoginManager::SESSION_RESTORE_FAILED
);
297 states
.insert(OAuth2LoginManager::SESSION_RESTORE_CONNECTION_FAILED
);
298 OAuth2LoginManagerStateWaiter
merge_session_waiter(profile());
299 merge_session_waiter
.WaitForStates(states
);
300 EXPECT_EQ(merge_session_waiter
.final_state(), final_state
);
303 void StartNewUserSession(bool wait_for_merge
) {
304 SetupGaiaServerForNewAccount();
305 SimulateNetworkOnline();
306 chromeos::WizardController::SkipPostLoginScreensForTesting();
307 chromeos::WizardController
* wizard_controller
=
308 chromeos::WizardController::default_controller();
309 wizard_controller
->SkipToLoginForTesting(LoginScreenContext());
311 content::WindowedNotificationObserver(
312 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
,
313 content::NotificationService::AllSources()).Wait();
315 // Use capitalized and dotted user name on purpose to make sure
316 // our email normalization kicks in.
317 GetLoginDisplay()->ShowSigninScreenForCreds(kTestRawAccountId
,
318 kTestAccountPassword
);
320 content::WindowedNotificationObserver(
321 chrome::NOTIFICATION_SESSION_STARTED
,
322 content::NotificationService::AllSources()).Wait();
324 if (wait_for_merge
) {
325 // Wait for the session merge to finish.
326 WaitForMergeSessionCompletion(OAuth2LoginManager::SESSION_RESTORE_DONE
);
330 DISALLOW_COPY_AND_ASSIGN(OAuth2Test
);
333 class CookieReader
: public base::RefCountedThreadSafe
<CookieReader
> {
338 void ReadCookies(Profile
* profile
) {
339 context_
= profile
->GetRequestContext();
340 content::BrowserThread::PostTask(
341 content::BrowserThread::IO
, FROM_HERE
,
342 base::Bind(&CookieReader::ReadCookiesOnIOThread
,
344 runner_
= new content::MessageLoopRunner
;
348 std::string
GetCookieValue(const std::string
& name
) {
349 for (std::vector
<net::CanonicalCookie
>::const_iterator iter
=
350 cookie_list_
.begin();
351 iter
!= cookie_list_
.end();
353 if (iter
->Name() == name
) {
354 return iter
->Value();
357 return std::string();
361 friend class base::RefCountedThreadSafe
<CookieReader
>;
363 virtual ~CookieReader() {
366 void ReadCookiesOnIOThread() {
367 context_
->GetURLRequestContext()->cookie_store()->GetCookieMonster()->
368 GetAllCookiesAsync(base::Bind(
369 &CookieReader::OnGetAllCookiesOnUIThread
,
373 void OnGetAllCookiesOnUIThread(const net::CookieList
& cookies
) {
374 cookie_list_
= cookies
;
375 content::BrowserThread::PostTask(
376 content::BrowserThread::UI
, FROM_HERE
,
377 base::Bind(&CookieReader::OnCookiesReadyOnUIThread
,
381 void OnCookiesReadyOnUIThread() {
385 scoped_refptr
<net::URLRequestContextGetter
> context_
;
386 net::CookieList cookie_list_
;
387 scoped_refptr
<content::MessageLoopRunner
> runner_
;
389 DISALLOW_COPY_AND_ASSIGN(CookieReader
);
392 // PRE_MergeSession is testing merge session for a new profile.
393 IN_PROC_BROWSER_TEST_F(OAuth2Test
, PRE_PRE_PRE_MergeSession
) {
394 StartNewUserSession(true);
395 // Check for existance of refresh token.
396 ProfileOAuth2TokenService
* token_service
=
397 ProfileOAuth2TokenServiceFactory::GetForProfile(
399 EXPECT_TRUE(token_service
->RefreshTokenIsAvailable(kTestAccountId
));
401 EXPECT_EQ(GetOAuthStatusFromLocalState(kTestAccountId
),
402 User::OAUTH2_TOKEN_STATUS_VALID
);
404 scoped_refptr
<CookieReader
> cookie_reader(new CookieReader());
405 cookie_reader
->ReadCookies(profile());
406 EXPECT_EQ(cookie_reader
->GetCookieValue("SID"), kTestSessionSIDCookie
);
407 EXPECT_EQ(cookie_reader
->GetCookieValue("LSID"), kTestSessionLSIDCookie
);
410 // MergeSession test is running merge session process for an existing profile
411 // that was generated in PRE_PRE_PRE_MergeSession test. In this test, we
412 // are not running /MergeSession process since the /ListAccounts call confirms
413 // that the session is not stale.
414 IN_PROC_BROWSER_TEST_F(OAuth2Test
, PRE_PRE_MergeSession
) {
415 SetupGaiaServerForUnexpiredAccount();
416 SimulateNetworkOnline();
417 LoginAsExistingUser();
418 scoped_refptr
<CookieReader
> cookie_reader(new CookieReader());
419 cookie_reader
->ReadCookies(profile());
420 // These are still cookie values form the initial session since
422 EXPECT_EQ(cookie_reader
->GetCookieValue("SID"), kTestSessionSIDCookie
);
423 EXPECT_EQ(cookie_reader
->GetCookieValue("LSID"), kTestSessionLSIDCookie
);
426 // MergeSession test is running merge session process for an existing profile
427 // that was generated in PRE_PRE_MergeSession test.
428 IN_PROC_BROWSER_TEST_F(OAuth2Test
, PRE_MergeSession
) {
429 SetupGaiaServerForExpiredAccount();
430 SimulateNetworkOnline();
431 LoginAsExistingUser();
432 scoped_refptr
<CookieReader
> cookie_reader(new CookieReader());
433 cookie_reader
->ReadCookies(profile());
434 // These should be cookie values that we generated by calling /MergeSession,
435 // since /ListAccounts should have tell us that the initial session cookies
437 EXPECT_EQ(cookie_reader
->GetCookieValue("SID"), kTestSession2SIDCookie
);
438 EXPECT_EQ(cookie_reader
->GetCookieValue("LSID"), kTestSession2LSIDCookie
);
441 // MergeSession test is attempting to merge session for an existing profile
442 // that was generated in PRE_PRE_MergeSession test. This attempt should fail
443 // since FakeGaia instance isn't configured to return relevant tokens/cookies.
444 IN_PROC_BROWSER_TEST_F(OAuth2Test
, MergeSession
) {
445 SimulateNetworkOnline();
447 content::WindowedNotificationObserver(
448 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
,
449 content::NotificationService::AllSources()).Wait();
451 JsExpect("!!document.querySelector('#account-picker')");
452 JsExpect("!!document.querySelector('#pod-row')");
454 EXPECT_EQ(GetOAuthStatusFromLocalState(kTestAccountId
),
455 User::OAUTH2_TOKEN_STATUS_VALID
);
457 EXPECT_TRUE(TryToLogin(kTestAccountId
, kTestAccountPassword
));
459 // Wait for the session merge to finish.
460 WaitForMergeSessionCompletion(OAuth2LoginManager::SESSION_RESTORE_FAILED
);
462 EXPECT_EQ(GetOAuthStatusFromLocalState(kTestAccountId
),
463 User::OAUTH2_TOKEN_STATUS_INVALID
);
467 const char kGooglePageContent
[] =
468 "<html><title>Hello!</title><script>alert('hello');</script>"
469 "<body>Hello Google!</body></html>";
470 const char kRandomPageContent
[] =
471 "<html><title>SomthingElse</title><body>I am SomethingElse</body></html>";
472 const char kHelloPagePath
[] = "/hello_google";
473 const char kRandomPagePath
[] = "/non_google_page";
476 // FakeGoogle serves content of http://www.google.com/hello_google page for
477 // merge session tests.
480 FakeGoogle() : start_event_(true, false) {
485 scoped_ptr
<HttpResponse
> HandleRequest(const HttpRequest
& request
) {
486 // The scheme and host of the URL is actually not important but required to
487 // get a valid GURL in order to parse |request.relative_url|.
488 GURL request_url
= GURL("http://localhost").Resolve(request
.relative_url
);
489 LOG(WARNING
) << "Requesting page " << request
.relative_url
;
490 std::string request_path
= request_url
.path();
491 scoped_ptr
<BasicHttpResponse
> http_response(new BasicHttpResponse());
492 if (request_path
== kHelloPagePath
) { // Serving "google" page.
493 start_event_
.Signal();
494 content::BrowserThread::PostTask(
495 content::BrowserThread::UI
, FROM_HERE
,
496 base::Bind(&FakeGoogle::QuitRunnerOnUIThread
,
497 base::Unretained(this)));
499 http_response
->set_code(net::HTTP_OK
);
500 http_response
->set_content_type("text/html");
501 http_response
->set_content(kGooglePageContent
);
502 } else if (request_path
== kRandomPagePath
) { // Serving "non-google" page.
503 http_response
->set_code(net::HTTP_OK
);
504 http_response
->set_content_type("text/html");
505 http_response
->set_content(kRandomPageContent
);
507 return scoped_ptr
<HttpResponse
>(); // Request not understood.
510 return http_response
.PassAs
<HttpResponse
>();
513 // True if we have already served the test page.
514 bool IsPageRequested () {
515 return start_event_
.IsSignaled();
518 // Waits until we receive a request to serve the test page.
519 void WaitForPageRequest() {
520 // If we have already served the request, bail out.
521 if (start_event_
.IsSignaled())
524 runner_
= new content::MessageLoopRunner
;
529 void QuitRunnerOnUIThread() {
533 // This event will tell us when we actually see HTTP request on the server
534 // side. It should be signalled only after the page/XHR throttle had been
535 // removed (after merge session completes).
536 base::WaitableEvent start_event_
;
537 scoped_refptr
<content::MessageLoopRunner
> runner_
;
539 DISALLOW_COPY_AND_ASSIGN(FakeGoogle
);
542 // FakeGaia specialization that can delay /MergeSession handler until
543 // we explicitly call DelayedFakeGaia::UnblockMergeSession().
544 class DelayedFakeGaia
: public FakeGaia
{
547 : blocking_event_(true, false),
548 start_event_(true, false) {
551 void UnblockMergeSession() {
552 blocking_event_
.Signal();
555 void WaitForMergeSessionToStart() {
556 // If we have already served the request, bail out.
557 if (start_event_
.IsSignaled())
560 runner_
= new content::MessageLoopRunner
;
565 // FakeGaia overrides.
566 virtual void HandleMergeSession(const HttpRequest
& request
,
567 BasicHttpResponse
* http_response
) OVERRIDE
{
568 start_event_
.Signal();
569 content::BrowserThread::PostTask(
570 content::BrowserThread::UI
, FROM_HERE
,
571 base::Bind(&DelayedFakeGaia::QuitRunnerOnUIThread
,
572 base::Unretained(this)));
573 blocking_event_
.Wait();
574 FakeGaia::HandleMergeSession(request
, http_response
);
577 void QuitRunnerOnUIThread() {
582 base::WaitableEvent blocking_event_
;
583 base::WaitableEvent start_event_
;
584 scoped_refptr
<content::MessageLoopRunner
> runner_
;
586 DISALLOW_COPY_AND_ASSIGN(DelayedFakeGaia
);
589 class MergeSessionTest
: public OAuth2Test
{
591 MergeSessionTest() : delayed_fake_gaia_(new DelayedFakeGaia()) {
592 fake_gaia_
.reset(delayed_fake_gaia_
);
595 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
596 OAuth2Test::SetUpCommandLine(command_line
);
598 // Get fake URL for fake google.com.
599 const GURL
& server_url
= embedded_test_server()->base_url();
600 std::string
google_host("www.google.com");
601 GURL::Replacements replace_google_host
;
602 replace_google_host
.SetHostStr(google_host
);
603 GURL google_url
= server_url
.ReplaceComponents(replace_google_host
);
604 fake_google_page_url_
= google_url
.Resolve(kHelloPagePath
);
606 std::string
non_google_host("www.somethingelse.org");
607 GURL::Replacements replace_non_google_host
;
608 replace_non_google_host
.SetHostStr(non_google_host
);
609 GURL non_google_url
= server_url
.ReplaceComponents(replace_non_google_host
);
610 non_google_page_url_
= non_google_url
.Resolve(kRandomPagePath
);
613 virtual void SetUp() OVERRIDE
{
614 embedded_test_server()->RegisterRequestHandler(
615 base::Bind(&FakeGoogle::HandleRequest
,
616 base::Unretained(&fake_google_
)));
621 void UnblockMergeSession() {
622 delayed_fake_gaia_
->UnblockMergeSession();
625 void WaitForMergeSessionToStart() {
626 delayed_fake_gaia_
->WaitForMergeSessionToStart();
629 void JsExpect(content::WebContents
* contents
,
630 const std::string
& expression
) {
632 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
634 "window.domAutomationController.send(!!(" + expression
+ "));",
636 ASSERT_TRUE(result
) << expression
;
639 const GURL
& GetBackGroundPageUrl(const std::string
& extension_id
) {
640 extensions::ProcessManager
* manager
=
641 extensions::ExtensionSystem::Get(profile())->process_manager();
642 extensions::ExtensionHost
* host
=
643 manager
->GetBackgroundHostForExtension(extension_id
);
644 return host
->host_contents()->GetURL();
647 void JsExpectOnBackgroundPage(const std::string
& extension_id
,
648 const std::string
& expression
) {
649 extensions::ProcessManager
* manager
=
650 extensions::ExtensionSystem::Get(profile())->process_manager();
651 extensions::ExtensionHost
* host
=
652 manager
->GetBackgroundHostForExtension(extension_id
);
654 ADD_FAILURE() << "Extension " << extension_id
655 << " has no background page.";
659 JsExpect(host
->host_contents(), expression
);
662 FakeGoogle fake_google_
;
663 DelayedFakeGaia
* delayed_fake_gaia_
;
664 GURL fake_google_page_url_
;
665 GURL non_google_page_url_
;
668 DISALLOW_COPY_AND_ASSIGN(MergeSessionTest
);
671 Browser
* FindOrCreateVisibleBrowser(Profile
* profile
) {
672 chrome::ScopedTabbedBrowserDisplayer
displayer(
673 profile
, chrome::GetActiveDesktop());
674 Browser
* browser
= displayer
.browser();
675 if (browser
->tab_strip_model()->count() == 0)
676 chrome::AddTabAt(browser
, GURL(), -1, true);
680 IN_PROC_BROWSER_TEST_F(MergeSessionTest
, PageThrottle
) {
681 StartNewUserSession(false);
683 // Try to open a page from google.com.
685 FindOrCreateVisibleBrowser(profile());
686 ui_test_utils::NavigateToURLWithDisposition(
688 fake_google_page_url_
,
689 CURRENT_TAB
, ui_test_utils::BROWSER_TEST_NONE
);
691 // Wait until we get send merge session request.
692 WaitForMergeSessionToStart();
694 // Make sure the page is blocked by the throttle.
695 EXPECT_FALSE(fake_google_
.IsPageRequested());
697 // Check that throttle page is displayed instead.
698 base::string16 title
;
699 ui_test_utils::GetCurrentTabTitle(browser
, &title
);
700 DVLOG(1) << "Loaded page at the start : " << title
;
702 // Unblock GAIA request.
703 UnblockMergeSession();
705 // Wait for the session merge to finish.
706 WaitForMergeSessionCompletion(OAuth2LoginManager::SESSION_RESTORE_DONE
);
708 // Make sure the test page is served.
709 fake_google_
.WaitForPageRequest();
711 // Check that real page is no longer blocked by the throttle and that the
712 // real page pops up JS dialog.
713 AppModalDialog
* dialog
= ui_test_utils::WaitForAppModalDialog();
714 ASSERT_TRUE(dialog
->IsJavaScriptModalDialog());
715 JavaScriptAppModalDialog
* js_dialog
=
716 static_cast<JavaScriptAppModalDialog
*>(dialog
);
717 js_dialog
->native_dialog()->AcceptAppModalDialog();
719 ui_test_utils::GetCurrentTabTitle(browser
, &title
);
720 DVLOG(1) << "Loaded page at the end : " << title
;
723 IN_PROC_BROWSER_TEST_F(MergeSessionTest
, XHRThrottle
) {
724 StartNewUserSession(false);
726 // Wait until we get send merge session request.
727 WaitForMergeSessionToStart();
729 // Reset ExtensionBrowserTest::observer_ to the right browser object.
730 Browser
* browser
= FindOrCreateVisibleBrowser(profile());
731 observer_
.reset(new ExtensionTestNotificationObserver(browser
));
733 // Run background page tests. The tests will just wait for XHR request
735 ResultCatcher catcher
;
737 scoped_ptr
<ExtensionTestMessageListener
> non_google_xhr_listener(
738 new ExtensionTestMessageListener("non-google-xhr-received", false));
740 // Load extension with a background page. The background page will
741 // attempt to load |fake_google_page_url_| via XHR.
742 const extensions::Extension
* ext
= LoadExtension(
743 test_data_dir_
.AppendASCII("merge_session"));
746 // Kick off XHR request from the extension.
747 JsExpectOnBackgroundPage(
749 base::StringPrintf("startThrottledTests('%s', '%s')",
750 fake_google_page_url_
.spec().c_str(),
751 non_google_page_url_
.spec().c_str()));
753 // Verify that we've sent XHR request form the extension side...
754 JsExpectOnBackgroundPage(ext
->id(),
755 "googleRequestSent && !googleResponseReceived");
757 // ...but didn't see it on the server side yet.
758 EXPECT_FALSE(fake_google_
.IsPageRequested());
760 // Unblock GAIA request.
761 UnblockMergeSession();
763 // Wait for the session merge to finish.
764 WaitForMergeSessionCompletion(OAuth2LoginManager::SESSION_RESTORE_DONE
);
766 // Wait until non-google XHR content to load first.
767 ASSERT_TRUE(non_google_xhr_listener
->WaitUntilSatisfied());
769 if (!catcher
.GetNextResult()) {
770 std::string message
= catcher
.message();
771 ADD_FAILURE() << "Tests failed: " << message
;
774 EXPECT_TRUE(fake_google_
.IsPageRequested());
777 } // namespace chromeos