Index: chrome/browser/chromeos/login/oauth2_browsertest.cc |
diff --git a/chrome/browser/chromeos/login/oauth2_browsertest.cc b/chrome/browser/chromeos/login/oauth2_browsertest.cc |
index bbbed3e9bc248d9434002f00f00b4ce5503585ce..953d21cbdc7b292f2e9f9f68ac2b219c7684542f 100644 |
--- a/chrome/browser/chromeos/login/oauth2_browsertest.cc |
+++ b/chrome/browser/chromeos/login/oauth2_browsertest.cc |
@@ -3,16 +3,26 @@ |
// found in the LICENSE file. |
#include "base/message_loop/message_loop.h" |
+#include "base/prefs/pref_service.h" |
+#include "chrome/browser/browser_process.h" |
#include "chrome/browser/chrome_notification_types.h" |
#include "chrome/browser/chromeos/login/oauth2_login_manager.h" |
#include "chrome/browser/chromeos/login/oauth2_login_manager_factory.h" |
#include "chrome/browser/chromeos/login/oobe_base_test.h" |
+#include "chrome/browser/chromeos/login/user_manager.h" |
#include "chrome/browser/chromeos/login/wizard_controller.h" |
#include "chrome/browser/profiles/profile_manager.h" |
+#include "chrome/browser/signin/profile_oauth2_token_service.h" |
+#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" |
#include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h" |
#include "content/public/browser/notification_service.h" |
#include "google_apis/gaia/gaia_constants.h" |
#include "google_apis/gaia/gaia_urls.h" |
+#include "net/cookies/canonical_cookie.h" |
+#include "net/cookies/cookie_monster.h" |
+#include "net/cookies/cookie_store.h" |
+#include "net/url_request/url_request_context.h" |
+#include "net/url_request/url_request_context_getter.h" |
namespace chromeos { |
@@ -20,13 +30,18 @@ namespace { |
// Email of owner account for test. |
const char kTestAccountId[] = "username@gmail.com"; |
- |
+const char kTestRawAccountId[] = "User.Name"; |
+const char kTestAccountPassword[] = "fake-password"; |
const char kTestAuthCode[] = "fake-auth-code"; |
const char kTestGaiaUberToken[] = "fake-uber-token"; |
const char kTestAuthLoginAccessToken[] = "fake-access-token"; |
const char kTestRefreshToken[] = "fake-refresh-token"; |
+const char kTestAuthSIDCookie[] = "fake-auth-SID-cookie"; |
+const char kTestAuthLSIDCookie[] = "fake-auth-LSID-cookie"; |
const char kTestSessionSIDCookie[] = "fake-session-SID-cookie"; |
const char kTestSessionLSIDCookie[] = "fake-session-LSID-cookie"; |
+const char kTestSession2SIDCookie[] = "fake-session2-SID-cookie"; |
+const char kTestSession2LSIDCookie[] = "fake-session2-LSID-cookie"; |
const char kTestUserinfoToken[] = "fake-userinfo-token"; |
const char kTestLoginToken[] = "fake-login-token"; |
const char kTestSyncToken[] = "fake-sync-token"; |
@@ -40,16 +55,85 @@ class OAuth2Test : public OobeBaseTest { |
virtual void SetUpOnMainThread() OVERRIDE { |
OobeBaseTest::SetUpOnMainThread(); |
+ } |
+ |
+ void SetupGaiaServerForNewAccount() { |
+ FakeGaia::MergeSessionParams params; |
+ params.auth_sid_cookie = kTestAuthSIDCookie; |
+ params.auth_lsid_cookie = kTestAuthLSIDCookie; |
+ params.auth_code = kTestAuthCode; |
+ params.refresh_token = kTestRefreshToken; |
+ params.access_token = kTestAuthLoginAccessToken; |
+ params.gaia_uber_token = kTestGaiaUberToken; |
+ params.session_sid_cookie = kTestSessionSIDCookie; |
+ params.session_lsid_cookie = kTestSessionLSIDCookie; |
+ fake_gaia_.SetMergeSessionParams(params); |
+ SetupGaiaServerWithAccessTokens(); |
+ } |
+ |
+ void SetupGaiaServerForExistingAccount() { |
+ FakeGaia::MergeSessionParams params; |
+ params.gaia_uber_token = kTestGaiaUberToken; |
+ params.session_sid_cookie = kTestSession2SIDCookie; |
+ params.session_lsid_cookie = kTestSession2LSIDCookie; |
+ fake_gaia_.SetMergeSessionParams(params); |
+ SetupGaiaServerWithAccessTokens(); |
+ } |
+ bool TryToLogin(const std::string& username, |
+ const std::string& password) { |
+ if (!AddUserTosession(username, password)) |
+ return false; |
+ |
+ if (const User* active_user = UserManager::Get()->GetActiveUser()) |
+ return active_user->email() == username; |
+ |
+ return false; |
+ } |
+ |
+ User::OAuthTokenStatus GetOAuthStatusFromLocalState( |
+ const std::string& user_id) const { |
+ PrefService* local_state = g_browser_process->local_state(); |
+ const DictionaryValue* prefs_oauth_status = |
+ local_state->GetDictionary("OAuthTokenStatus"); |
+ int oauth_token_status = User::OAUTH_TOKEN_STATUS_UNKNOWN; |
+ if (prefs_oauth_status && |
+ prefs_oauth_status->GetIntegerWithoutPathExpansion( |
+ user_id, &oauth_token_status)) { |
+ User::OAuthTokenStatus result = |
+ static_cast<User::OAuthTokenStatus>(oauth_token_status); |
+ return result; |
+ } |
+ return User::OAUTH_TOKEN_STATUS_UNKNOWN; |
+ } |
+ |
+ private: |
+ bool AddUserTosession(const std::string& username, |
+ const std::string& password) { |
+ ExistingUserController* controller = |
+ ExistingUserController::current_controller(); |
+ if (!controller) { |
+ ADD_FAILURE(); |
+ return false; |
+ } |
+ |
+ controller->Login(UserContext(username, password, std::string())); |
+ content::WindowedNotificationObserver( |
+ chrome::NOTIFICATION_SESSION_STARTED, |
+ content::NotificationService::AllSources()).Wait(); |
+ const UserList& logged_users = UserManager::Get()->GetLoggedInUsers(); |
+ for (UserList::const_iterator it = logged_users.begin(); |
+ it != logged_users.end(); ++it) { |
+ if ((*it)->email() == username) |
+ return true; |
+ } |
+ return false; |
+ } |
+ |
+ void SetupGaiaServerWithAccessTokens() { |
// Configure OAuth authentication. |
GaiaUrls* gaia_urls = GaiaUrls::GetInstance(); |
- fake_gaia_.SetAuthTokens(kTestAuthCode, |
- kTestRefreshToken, |
- kTestAuthLoginAccessToken, |
- kTestGaiaUberToken, |
- kTestSessionSIDCookie, |
- kTestSessionLSIDCookie); |
// This token satisfies the userinfo.email request from |
// DeviceOAuth2TokenService used in token validation. |
FakeGaia::AccessTokenInfo userinfo_token_info; |
@@ -89,10 +173,68 @@ class OAuth2Test : public OobeBaseTest { |
fake_gaia_.IssueOAuthToken(kTestRefreshToken, auth_login_token_info); |
} |
- private: |
DISALLOW_COPY_AND_ASSIGN(OAuth2Test); |
}; |
+class CookieReader : public base::RefCountedThreadSafe<CookieReader> { |
+ public: |
+ CookieReader() { |
+ } |
+ |
+ void ReadCookies(Profile* profile) { |
+ context_ = profile->GetRequestContext(); |
+ content::BrowserThread::PostTask( |
+ content::BrowserThread::IO, FROM_HERE, |
+ base::Bind(&CookieReader::ReadCookiesOnIOThread, |
+ this)); |
+ runner_ = new content::MessageLoopRunner; |
+ runner_->Run(); |
+ } |
+ |
+ std::string GetCookieValue(const std::string& name) { |
+ for (std::vector<net::CanonicalCookie>::const_iterator iter = |
+ cookie_list_.begin(); |
+ iter != cookie_list_.end(); |
+ ++iter) { |
+ if (iter->Name() == name) { |
+ return iter->Value(); |
+ } |
+ } |
+ return std::string(); |
+ } |
+ |
+ private: |
+ friend class base::RefCountedThreadSafe<CookieReader>; |
+ |
+ virtual ~CookieReader() { |
+ } |
+ |
+ void ReadCookiesOnIOThread() { |
+ context_->GetURLRequestContext()->cookie_store()->GetCookieMonster()-> |
+ GetAllCookiesAsync(base::Bind( |
+ &CookieReader::OnGetAllCookiesOnUIThread, |
+ this)); |
+ } |
+ |
+ void OnGetAllCookiesOnUIThread(const net::CookieList& cookies) { |
+ cookie_list_ = cookies; |
+ content::BrowserThread::PostTask( |
+ content::BrowserThread::UI, FROM_HERE, |
+ base::Bind(&CookieReader::OnCookiesReadyOnUIThread, |
+ this)); |
+ } |
+ |
+ void OnCookiesReadyOnUIThread() { |
+ runner_->Quit(); |
+ } |
+ |
+ scoped_refptr<net::URLRequestContextGetter> context_; |
+ net::CookieList cookie_list_; |
+ scoped_refptr<content::MessageLoopRunner> runner_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(CookieReader); |
+}; |
+ |
class OAuth2LoginManagerStateWaiter : public OAuth2LoginManager::Observer { |
public: |
explicit OAuth2LoginManagerStateWaiter(Profile* profile) |
@@ -146,7 +288,9 @@ class OAuth2LoginManagerStateWaiter : public OAuth2LoginManager::Observer { |
DISALLOW_COPY_AND_ASSIGN(OAuth2LoginManagerStateWaiter); |
}; |
-IN_PROC_BROWSER_TEST_F(OAuth2Test, NewUser) { |
+// PRE_MergeSession is testing merge session for a new profile. |
+IN_PROC_BROWSER_TEST_F(OAuth2Test, PRE_PRE_MergeSession) { |
+ SetupGaiaServerForNewAccount(); |
SimulateNetworkOnline(); |
chromeos::WizardController::SkipPostLoginScreensForTesting(); |
chromeos::WizardController* wizard_controller = |
@@ -157,14 +301,20 @@ IN_PROC_BROWSER_TEST_F(OAuth2Test, NewUser) { |
chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, |
content::NotificationService::AllSources()).Wait(); |
+ EXPECT_EQ(GetOAuthStatusFromLocalState(kTestAccountId), |
+ User::OAUTH_TOKEN_STATUS_UNKNOWN); |
+ |
// Use capitalized and dotted user name on purpose to make sure |
// our email normalization kicks in. |
- GetLoginDisplay()->ShowSigninScreenForCreds("User.Name", "password"); |
+ GetLoginDisplay()->ShowSigninScreenForCreds(kTestRawAccountId, |
+ kTestAccountPassword); |
content::WindowedNotificationObserver( |
chrome::NOTIFICATION_SESSION_STARTED, |
content::NotificationService::AllSources()).Wait(); |
+ Profile* profile = ProfileManager::GetPrimaryUserProfile(); |
+ // Wait for the session merge to finish. |
std::set<OAuth2LoginManager::SessionRestoreState> states; |
states.insert(OAuth2LoginManager::SESSION_RESTORE_DONE); |
states.insert(OAuth2LoginManager::SESSION_RESTORE_FAILED); |
@@ -174,6 +324,96 @@ IN_PROC_BROWSER_TEST_F(OAuth2Test, NewUser) { |
merge_session_waiter.WaitForStates(states); |
EXPECT_EQ(merge_session_waiter.final_state(), |
OAuth2LoginManager::SESSION_RESTORE_DONE); |
+ |
+ // Check for existance of refresh token. |
+ ProfileOAuth2TokenService* token_service = |
+ ProfileOAuth2TokenServiceFactory::GetForProfile( |
+ profile); |
+ EXPECT_TRUE(token_service->RefreshTokenIsAvailable(kTestAccountId)); |
+ |
+ EXPECT_EQ(GetOAuthStatusFromLocalState(kTestAccountId), |
+ User::OAUTH2_TOKEN_STATUS_VALID); |
+ |
+ scoped_refptr<CookieReader> cookie_reader(new CookieReader()); |
+ cookie_reader->ReadCookies(profile); |
+ EXPECT_EQ(cookie_reader->GetCookieValue("SID"), kTestSessionSIDCookie); |
+ EXPECT_EQ(cookie_reader->GetCookieValue("LSID"), kTestSessionLSIDCookie); |
+} |
+ |
+// MergeSession test is running merge session process for an existing profile |
+// that was generated in PRE_PRE_MergeSession test. |
+IN_PROC_BROWSER_TEST_F(OAuth2Test, PRE_MergeSession) { |
+ SetupGaiaServerForExistingAccount(); |
+ SimulateNetworkOnline(); |
+ |
+ content::WindowedNotificationObserver( |
+ chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, |
+ content::NotificationService::AllSources()).Wait(); |
+ |
+ JsExpect("!!document.querySelector('#account-picker')"); |
+ JsExpect("!!document.querySelector('#pod-row')"); |
+ |
+ EXPECT_EQ(GetOAuthStatusFromLocalState(kTestAccountId), |
+ User::OAUTH2_TOKEN_STATUS_VALID); |
+ |
+ EXPECT_TRUE(TryToLogin(kTestAccountId, kTestAccountPassword)); |
+ Profile* profile = ProfileManager::GetPrimaryUserProfile(); |
+ |
+ // Wait for the session merge to finish. |
+ std::set<OAuth2LoginManager::SessionRestoreState> states; |
+ states.insert(OAuth2LoginManager::SESSION_RESTORE_DONE); |
+ states.insert(OAuth2LoginManager::SESSION_RESTORE_FAILED); |
+ states.insert(OAuth2LoginManager::SESSION_RESTORE_CONNECTION_FAILED); |
+ OAuth2LoginManagerStateWaiter merge_session_waiter(profile); |
+ merge_session_waiter.WaitForStates(states); |
+ EXPECT_EQ(merge_session_waiter.final_state(), |
+ OAuth2LoginManager::SESSION_RESTORE_DONE); |
+ |
+ // Check for existance of refresh token. |
+ ProfileOAuth2TokenService* token_service = |
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile); |
+ EXPECT_TRUE(token_service->RefreshTokenIsAvailable(kTestAccountId)); |
+ |
+ EXPECT_EQ(GetOAuthStatusFromLocalState(kTestAccountId), |
+ User::OAUTH2_TOKEN_STATUS_VALID); |
+ |
+ scoped_refptr<CookieReader> cookie_reader(new CookieReader()); |
+ cookie_reader->ReadCookies(profile); |
+ EXPECT_EQ(cookie_reader->GetCookieValue("SID"), kTestSession2SIDCookie); |
+ EXPECT_EQ(cookie_reader->GetCookieValue("LSID"), kTestSession2LSIDCookie); |
+} |
+ |
+// MergeSession test is attempting to merge session for an existing profile |
+// that was generated in PRE_PRE_MergeSession test. This attempt should fail |
+// since FakeGaia instance isn't configured to return relevant tokens/cookies. |
+IN_PROC_BROWSER_TEST_F(OAuth2Test, MergeSession) { |
+ SimulateNetworkOnline(); |
+ |
+ content::WindowedNotificationObserver( |
+ chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, |
+ content::NotificationService::AllSources()).Wait(); |
+ |
+ JsExpect("!!document.querySelector('#account-picker')"); |
+ JsExpect("!!document.querySelector('#pod-row')"); |
+ |
+ EXPECT_EQ(GetOAuthStatusFromLocalState(kTestAccountId), |
+ User::OAUTH2_TOKEN_STATUS_VALID); |
+ |
+ EXPECT_TRUE(TryToLogin(kTestAccountId, kTestAccountPassword)); |
+ |
+ // Wait for the session merge to finish. |
+ std::set<OAuth2LoginManager::SessionRestoreState> states; |
+ states.insert(OAuth2LoginManager::SESSION_RESTORE_DONE); |
+ states.insert(OAuth2LoginManager::SESSION_RESTORE_FAILED); |
+ states.insert(OAuth2LoginManager::SESSION_RESTORE_CONNECTION_FAILED); |
+ OAuth2LoginManagerStateWaiter merge_session_waiter( |
+ ProfileManager::GetPrimaryUserProfile()); |
+ merge_session_waiter.WaitForStates(states); |
+ EXPECT_EQ(merge_session_waiter.final_state(), |
+ OAuth2LoginManager::SESSION_RESTORE_FAILED); |
+ |
+ EXPECT_EQ(GetOAuthStatusFromLocalState(kTestAccountId), |
+ User::OAUTH2_TOKEN_STATUS_INVALID); |
} |
} // namespace chromeos |