Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <string> | 5 #include <string> |
| 6 #include <utility> | 6 #include <utility> |
| 7 | 7 |
| 8 #include "base/macros.h" | 8 #include "base/macros.h" |
| 9 #include "base/memory/ptr_util.h" | |
| 9 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
| 10 #include "base/strings/stringprintf.h" | 11 #include "base/strings/stringprintf.h" |
| 11 #include "base/synchronization/waitable_event.h" | 12 #include "base/synchronization/waitable_event.h" |
| 12 #include "chrome/browser/browser_process.h" | 13 #include "chrome/browser/browser_process.h" |
| 13 #include "chrome/browser/chrome_notification_types.h" | 14 #include "chrome/browser/chrome_notification_types.h" |
| 14 #include "chrome/browser/chromeos/login/signin/oauth2_login_manager.h" | 15 #include "chrome/browser/chromeos/login/signin/oauth2_login_manager.h" |
| 15 #include "chrome/browser/chromeos/login/signin/oauth2_login_manager_factory.h" | 16 #include "chrome/browser/chromeos/login/signin/oauth2_login_manager_factory.h" |
| 16 #include "chrome/browser/chromeos/login/signin_specifics.h" | 17 #include "chrome/browser/chromeos/login/signin_specifics.h" |
| 17 #include "chrome/browser/chromeos/login/startup_utils.h" | 18 #include "chrome/browser/chromeos/login/startup_utils.h" |
| 18 #include "chrome/browser/chromeos/login/test/oobe_base_test.h" | 19 #include "chrome/browser/chromeos/login/test/oobe_base_test.h" |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 31 #include "chromeos/login/auth/user_context.h" | 32 #include "chromeos/login/auth/user_context.h" |
| 32 #include "components/app_modal/javascript_app_modal_dialog.h" | 33 #include "components/app_modal/javascript_app_modal_dialog.h" |
| 33 #include "components/app_modal/native_app_modal_dialog.h" | 34 #include "components/app_modal/native_app_modal_dialog.h" |
| 34 #include "components/browser_sync/browser_sync_switches.h" | 35 #include "components/browser_sync/browser_sync_switches.h" |
| 35 #include "components/prefs/pref_service.h" | 36 #include "components/prefs/pref_service.h" |
| 36 #include "components/signin/core/account_id/account_id.h" | 37 #include "components/signin/core/account_id/account_id.h" |
| 37 #include "components/signin/core/browser/account_tracker_service.h" | 38 #include "components/signin/core/browser/account_tracker_service.h" |
| 38 #include "components/signin/core/browser/profile_oauth2_token_service.h" | 39 #include "components/signin/core/browser/profile_oauth2_token_service.h" |
| 39 #include "components/user_manager/user.h" | 40 #include "components/user_manager/user.h" |
| 40 #include "components/user_manager/user_manager.h" | 41 #include "components/user_manager/user_manager.h" |
| 42 #include "content/public/browser/browser_thread.h" | |
| 41 #include "content/public/browser/notification_service.h" | 43 #include "content/public/browser/notification_service.h" |
| 42 #include "content/public/test/browser_test_utils.h" | 44 #include "content/public/test/browser_test_utils.h" |
| 43 #include "extensions/browser/process_manager.h" | 45 #include "extensions/browser/process_manager.h" |
| 44 #include "extensions/test/extension_test_message_listener.h" | 46 #include "extensions/test/extension_test_message_listener.h" |
| 45 #include "extensions/test/result_catcher.h" | 47 #include "extensions/test/result_catcher.h" |
| 46 #include "google_apis/gaia/gaia_constants.h" | 48 #include "google_apis/gaia/gaia_constants.h" |
| 47 #include "google_apis/gaia/gaia_urls.h" | 49 #include "google_apis/gaia/gaia_urls.h" |
| 48 #include "net/cookies/canonical_cookie.h" | 50 #include "net/cookies/canonical_cookie.h" |
| 49 #include "net/cookies/cookie_store.h" | 51 #include "net/cookies/cookie_store.h" |
| 50 #include "net/test/embedded_test_server/http_request.h" | 52 #include "net/test/embedded_test_server/http_request.h" |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 135 | 137 |
| 136 Profile* profile_; | 138 Profile* profile_; |
| 137 std::set<OAuth2LoginManager::SessionRestoreState> states_; | 139 std::set<OAuth2LoginManager::SessionRestoreState> states_; |
| 138 bool waiting_for_state_; | 140 bool waiting_for_state_; |
| 139 OAuth2LoginManager::SessionRestoreState final_state_; | 141 OAuth2LoginManager::SessionRestoreState final_state_; |
| 140 scoped_refptr<content::MessageLoopRunner> runner_; | 142 scoped_refptr<content::MessageLoopRunner> runner_; |
| 141 | 143 |
| 142 DISALLOW_COPY_AND_ASSIGN(OAuth2LoginManagerStateWaiter); | 144 DISALLOW_COPY_AND_ASSIGN(OAuth2LoginManagerStateWaiter); |
| 143 }; | 145 }; |
| 144 | 146 |
| 147 // Blocks a BrowserThread on construction and unblocks it on destruction. | |
|
achuithb
2017/02/02 00:37:10
This seems like a generally useful class - I'm sur
xiyuan
2017/02/02 18:43:59
I am surprised that I could not find similar class
| |
| 148 class BrowserThreadBlocker { | |
| 149 public: | |
| 150 explicit BrowserThreadBlocker(content::BrowserThread::ID identifier) | |
| 151 : unblock_event_(new base::WaitableEvent( | |
| 152 base::WaitableEvent::ResetPolicy::MANUAL, | |
| 153 base::WaitableEvent::InitialState::NOT_SIGNALED)) { | |
| 154 content::BrowserThread::PostTask( | |
| 155 identifier, FROM_HERE, | |
| 156 base::Bind(&BlockThreadOnThread, base::Owned(unblock_event_))); | |
| 157 } | |
| 158 ~BrowserThreadBlocker() { unblock_event_->Signal(); } | |
|
achuithb
2017/02/02 00:37:10
Wonder if it's safer to use an explicit Release me
xiyuan
2017/02/02 18:43:59
Dtor should be safe as long as we don't have deriv
| |
| 159 | |
| 160 private: | |
| 161 // Blocks the target thread until |event| is signaled. | |
| 162 static void BlockThreadOnThread(base::WaitableEvent* event) { event->Wait(); } | |
| 163 | |
| 164 // Owned by the BlockThreadOnThread callback. | |
|
achuithb
2017/02/02 00:37:10
Maybe it's more accurate to say that this shared s
xiyuan
2017/02/02 18:43:59
Updated the comment to:
// |unblock_event_| is d
| |
| 165 base::WaitableEvent* const unblock_event_; | |
| 166 DISALLOW_COPY_AND_ASSIGN(BrowserThreadBlocker); | |
|
achuithb
2017/02/02 00:37:10
I'd add a newline before this line
xiyuan
2017/02/02 18:43:59
Done.
| |
| 167 }; | |
| 168 | |
| 145 } // namespace | 169 } // namespace |
| 146 | 170 |
| 147 class OAuth2Test : public OobeBaseTest { | 171 class OAuth2Test : public OobeBaseTest { |
| 148 protected: | 172 protected: |
| 149 OAuth2Test() {} | 173 OAuth2Test() {} |
| 150 | 174 |
| 151 void SetUpCommandLine(base::CommandLine* command_line) override { | 175 void SetUpCommandLine(base::CommandLine* command_line) override { |
| 152 OobeBaseTest::SetUpCommandLine(command_line); | 176 OobeBaseTest::SetUpCommandLine(command_line); |
| 153 | 177 |
| 154 // Disable sync sinc we don't really need this for these tests and it also | 178 // Disable sync sinc we don't really need this for these tests and it also |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 357 // Use capitalized and dotted user name on purpose to make sure | 381 // Use capitalized and dotted user name on purpose to make sure |
| 358 // our email normalization kicks in. | 382 // our email normalization kicks in. |
| 359 GetLoginDisplay()->ShowSigninScreenForCreds(kTestRawEmail, | 383 GetLoginDisplay()->ShowSigninScreenForCreds(kTestRawEmail, |
| 360 kTestAccountPassword); | 384 kTestAccountPassword); |
| 361 session_start_waiter.Wait(); | 385 session_start_waiter.Wait(); |
| 362 | 386 |
| 363 if (wait_for_merge) { | 387 if (wait_for_merge) { |
| 364 // Wait for the session merge to finish. | 388 // Wait for the session merge to finish. |
| 365 WaitForMergeSessionCompletion(OAuth2LoginManager::SESSION_RESTORE_DONE); | 389 WaitForMergeSessionCompletion(OAuth2LoginManager::SESSION_RESTORE_DONE); |
| 366 } | 390 } |
| 367 } | 391 } |
| 368 | 392 |
| 393 OAuth2LoginManager::SessionRestoreStrategy GetSessionRestoreStrategy() { | |
| 394 OAuth2LoginManager* login_manager = | |
| 395 OAuth2LoginManagerFactory::GetInstance()->GetForProfile(profile()); | |
| 396 return login_manager->restore_strategy_; | |
| 397 } | |
| 398 | |
| 399 private: | |
| 369 DISALLOW_COPY_AND_ASSIGN(OAuth2Test); | 400 DISALLOW_COPY_AND_ASSIGN(OAuth2Test); |
| 370 }; | 401 }; |
| 371 | 402 |
| 372 class CookieReader : public base::RefCountedThreadSafe<CookieReader> { | 403 class CookieReader : public base::RefCountedThreadSafe<CookieReader> { |
| 373 public: | 404 public: |
| 374 CookieReader() { | 405 CookieReader() { |
| 375 } | 406 } |
| 376 | 407 |
| 377 void ReadCookies(Profile* profile) { | 408 void ReadCookies(Profile* profile) { |
| 378 context_ = profile->GetRequestContext(); | 409 context_ = profile->GetRequestContext(); |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 498 TryToLogin(AccountId::FromUserEmailGaiaId(kTestEmail, kTestGaiaId), | 529 TryToLogin(AccountId::FromUserEmailGaiaId(kTestEmail, kTestGaiaId), |
| 499 kTestAccountPassword)); | 530 kTestAccountPassword)); |
| 500 | 531 |
| 501 // Wait for the session merge to finish. | 532 // Wait for the session merge to finish. |
| 502 WaitForMergeSessionCompletion(OAuth2LoginManager::SESSION_RESTORE_FAILED); | 533 WaitForMergeSessionCompletion(OAuth2LoginManager::SESSION_RESTORE_FAILED); |
| 503 | 534 |
| 504 EXPECT_EQ(GetOAuthStatusFromLocalState(account_id), | 535 EXPECT_EQ(GetOAuthStatusFromLocalState(account_id), |
| 505 user_manager::User::OAUTH2_TOKEN_STATUS_INVALID); | 536 user_manager::User::OAUTH2_TOKEN_STATUS_INVALID); |
| 506 } | 537 } |
| 507 | 538 |
| 539 // Sets up a new user with stored refresh token. | |
| 540 IN_PROC_BROWSER_TEST_F(OAuth2Test, PRE_OverlappingContinueSessionRestore) { | |
| 541 StartNewUserSession(true); | |
| 542 } | |
| 543 | |
| 544 // Tests that ContinueSessionRestore could be called multiple times. | |
|
achuithb
2017/02/02 00:37:10
Impressive test.
| |
| 545 IN_PROC_BROWSER_TEST_F(OAuth2Test, OverlappingContinueSessionRestore) { | |
| 546 SetupGaiaServerForUnexpiredAccount(); | |
| 547 SimulateNetworkOnline(); | |
| 548 | |
| 549 // Waits for login screen to be ready. | |
| 550 content::WindowedNotificationObserver( | |
| 551 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, | |
| 552 content::NotificationService::AllSources()) | |
| 553 .Wait(); | |
| 554 | |
| 555 // Blocks DB thread to control TokenService::LoadCredentials timing. | |
| 556 std::unique_ptr<BrowserThreadBlocker> db_blocker = | |
| 557 base::MakeUnique<BrowserThreadBlocker>(content::BrowserThread::DB); | |
| 558 | |
| 559 // Signs in as the existing user created in pre test. | |
| 560 EXPECT_TRUE( | |
| 561 TryToLogin(AccountId::FromUserEmailGaiaId(kTestEmail, kTestGaiaId), | |
| 562 kTestAccountPassword)); | |
| 563 | |
| 564 // Session restore should be using the saved tokens. | |
| 565 EXPECT_EQ(OAuth2LoginManager::RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN, | |
| 566 GetSessionRestoreStrategy()); | |
| 567 | |
| 568 // Checks that refresh token is not yet loaded. | |
| 569 ProfileOAuth2TokenService* token_service = | |
| 570 ProfileOAuth2TokenServiceFactory::GetForProfile(profile()); | |
| 571 const std::string account_id = | |
| 572 PickAccountId(profile(), kTestGaiaId, kTestEmail); | |
| 573 EXPECT_FALSE(token_service->RefreshTokenIsAvailable(account_id)); | |
| 574 | |
| 575 // Invokes ContinueSessionRestore multiple times and there should be | |
| 576 // no DCHECK failures. | |
| 577 OAuth2LoginManager* login_manager = | |
| 578 OAuth2LoginManagerFactory::GetInstance()->GetForProfile(profile()); | |
| 579 login_manager->ContinueSessionRestore(); | |
| 580 login_manager->ContinueSessionRestore(); | |
| 581 | |
| 582 // Let go DB thread to finish TokenService::LoadCredentials. | |
| 583 db_blocker.reset(); | |
| 584 | |
| 585 // Session restore can finish normally and token is loaded. | |
| 586 WaitForMergeSessionCompletion(OAuth2LoginManager::SESSION_RESTORE_DONE); | |
| 587 EXPECT_TRUE(token_service->RefreshTokenIsAvailable(account_id)); | |
| 588 } | |
| 508 | 589 |
| 509 const char kGooglePageContent[] = | 590 const char kGooglePageContent[] = |
| 510 "<html><title>Hello!</title><script>alert('hello');</script>" | 591 "<html><title>Hello!</title><script>alert('hello');</script>" |
| 511 "<body>Hello Google!</body></html>"; | 592 "<body>Hello Google!</body></html>"; |
| 512 const char kRandomPageContent[] = | 593 const char kRandomPageContent[] = |
| 513 "<html><title>SomthingElse</title><body>I am SomethingElse</body></html>"; | 594 "<html><title>SomthingElse</title><body>I am SomethingElse</body></html>"; |
| 514 const char kHelloPagePath[] = "/hello_google"; | 595 const char kHelloPagePath[] = "/hello_google"; |
| 515 const char kRandomPagePath[] = "/non_google_page"; | 596 const char kRandomPagePath[] = "/non_google_page"; |
| 516 | 597 |
| 517 | 598 |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 641 const GURL& server_url = embedded_test_server()->base_url(); | 722 const GURL& server_url = embedded_test_server()->base_url(); |
| 642 GURL::Replacements replace_google_host; | 723 GURL::Replacements replace_google_host; |
| 643 replace_google_host.SetHostStr("www.google.com"); | 724 replace_google_host.SetHostStr("www.google.com"); |
| 644 GURL google_url = server_url.ReplaceComponents(replace_google_host); | 725 GURL google_url = server_url.ReplaceComponents(replace_google_host); |
| 645 fake_google_page_url_ = google_url.Resolve(kHelloPagePath); | 726 fake_google_page_url_ = google_url.Resolve(kHelloPagePath); |
| 646 | 727 |
| 647 GURL::Replacements replace_non_google_host; | 728 GURL::Replacements replace_non_google_host; |
| 648 replace_non_google_host.SetHostStr("www.somethingelse.org"); | 729 replace_non_google_host.SetHostStr("www.somethingelse.org"); |
| 649 GURL non_google_url = server_url.ReplaceComponents(replace_non_google_host); | 730 GURL non_google_url = server_url.ReplaceComponents(replace_non_google_host); |
| 650 non_google_page_url_ = non_google_url.Resolve(kRandomPagePath); | 731 non_google_page_url_ = non_google_url.Resolve(kRandomPagePath); |
| 651 } | 732 } |
| 652 | 733 |
| 653 void SetUp() override { | 734 void SetUp() override { |
| 654 embedded_test_server()->RegisterRequestHandler( | 735 embedded_test_server()->RegisterRequestHandler(base::Bind( |
| 655 base::Bind(&FakeGoogle::HandleRequest, | 736 &FakeGoogle::HandleRequest, base::Unretained(&fake_google_))); |
| 656 base::Unretained(&fake_google_))); | |
| 657 OAuth2Test::SetUp(); | 737 OAuth2Test::SetUp(); |
| 658 } | 738 } |
| 659 | 739 |
| 660 protected: | 740 protected: |
| 661 void UnblockMergeSession() { | 741 void UnblockMergeSession() { |
| 662 delayed_fake_gaia_->UnblockMergeSession(); | 742 delayed_fake_gaia_->UnblockMergeSession(); |
| 663 } | 743 } |
| 664 | 744 |
| 665 void WaitForMergeSessionToStart() { | 745 void WaitForMergeSessionToStart() { |
| 666 delayed_fake_gaia_->WaitForMergeSessionToStart(); | 746 delayed_fake_gaia_->WaitForMergeSessionToStart(); |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 807 | 887 |
| 808 if (!catcher.GetNextResult()) { | 888 if (!catcher.GetNextResult()) { |
| 809 std::string message = catcher.message(); | 889 std::string message = catcher.message(); |
| 810 ADD_FAILURE() << "Tests failed: " << message; | 890 ADD_FAILURE() << "Tests failed: " << message; |
| 811 } | 891 } |
| 812 | 892 |
| 813 EXPECT_TRUE(fake_google_.IsPageRequested()); | 893 EXPECT_TRUE(fake_google_.IsPageRequested()); |
| 814 } | 894 } |
| 815 | 895 |
| 816 } // namespace chromeos | 896 } // namespace chromeos |
| OLD | NEW |