Chromium Code Reviews| Index: chrome/browser/chromeos/login/login_utils.cc |
| diff --git a/chrome/browser/chromeos/login/login_utils.cc b/chrome/browser/chromeos/login/login_utils.cc |
| index e4bd18a52da67256ce19790e56df6a2e9e956d0d..522217650e6a9ac59ab1ec370b34002454b6c65b 100644 |
| --- a/chrome/browser/chromeos/login/login_utils.cc |
| +++ b/chrome/browser/chromeos/login/login_utils.cc |
| @@ -103,22 +103,24 @@ const char kServiceScopeChromeOSDeviceManagement[] = |
| // Task for fetching tokens from UI thread. |
| class StartSyncOnUIThreadTask : public Task { |
| public: |
| - StartSyncOnUIThreadTask( |
| + explicit StartSyncOnUIThreadTask( |
| const GaiaAuthConsumer::ClientLoginResult& credentials) |
| : credentials_(credentials) {} |
| virtual ~StartSyncOnUIThreadTask() {} |
| // Task override. |
| - virtual void Run() { |
| + virtual void Run() OVERRIDE { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| LoginUtils::Get()->FetchCookies(ProfileManager::GetDefaultProfile(), |
| credentials_); |
| LoginUtils::Get()->StartSync(ProfileManager::GetDefaultProfile(), |
| - credentials_); |
| + credentials_); |
| } |
| private: |
| GaiaAuthConsumer::ClientLoginResult credentials_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(StartSyncOnUIThreadTask); |
| }; |
| // Transfers initial set of Profile cookies from the default profile. |
| @@ -132,7 +134,7 @@ class TransferDefaultCookiesOnIOThreadTask : public Task { |
| virtual ~TransferDefaultCookiesOnIOThreadTask() {} |
| // Task override. |
| - virtual void Run() { |
| + virtual void Run() OVERRIDE { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| net::CookieStore* default_store = |
| auth_context_->GetURLRequestContext()->cookie_store(); |
| @@ -147,7 +149,7 @@ class TransferDefaultCookiesOnIOThreadTask : public Task { |
| void InitializeCookieMonster(const net::CookieList& cookies) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| net::CookieStore* new_store = |
| - new_context_->GetURLRequestContext()->cookie_store(); |
| + new_context_->GetURLRequestContext()->cookie_store(); |
| net::CookieMonster* new_monster = new_store->GetCookieMonster(); |
| if (!new_monster->InitializeFrom(cookies)) { |
| @@ -224,8 +226,8 @@ class OAuthLoginVerifier : public GaiaOAuthConsumer { |
| virtual void OnOAuthLoginSuccess(const std::string& sid, |
| const std::string& lsid, |
| const std::string& auth) OVERRIDE { |
| - GaiaAuthConsumer::ClientLoginResult credentials(sid, |
| - lsid, auth, std::string()); |
| + GaiaAuthConsumer::ClientLoginResult credentials( |
| + sid, lsid, auth, std::string()); |
| UserManager::Get()->set_offline_login(false); |
| BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| new StartSyncOnUIThreadTask(credentials)); |
| @@ -310,10 +312,15 @@ class UserSessionCookieFetcher : public GaiaAuthConsumer { |
| DISALLOW_COPY_AND_ASSIGN(UserSessionCookieFetcher); |
| }; |
| - |
| -// Fetches an OAuth token and initializes user policy with it. |
| +// Fetches the oauth token for the device management service. Since Profile |
| +// creation might be blocking on a user policy fetch, this fetcher must always |
| +// send a (possibly empty) token to the BrowserPolicyConnector, which will then |
| +// let the policy subsystem proceed and resume Profile creation. |
| +// Sending the token even when no Profile is pending is also OK. |
| class PolicyOAuthFetcher : public GaiaOAuthConsumer { |
| public: |
| + // Fetches the device management service's oauth token using |oauth1_token| |
| + // and |oauth1_secret| as access tokens. |
| PolicyOAuthFetcher(Profile* profile, |
| const std::string& oauth1_token, |
| const std::string& oauth1_secret) |
| @@ -323,34 +330,79 @@ class PolicyOAuthFetcher : public GaiaOAuthConsumer { |
| kServiceScopeChromeOSDeviceManagement), |
| oauth1_token_(oauth1_token), |
| oauth1_secret_(oauth1_secret) { |
| - oauth_fetcher_.SetAutoFetchLimit( |
| - GaiaOAuthFetcher::OAUTH2_SERVICE_ACCESS_TOKEN); |
| } |
| + |
| + // Fetches the device management service's oauth token, after also retrieving |
| + // the access tokens. |
| + explicit PolicyOAuthFetcher(Profile* profile) |
| + : oauth_fetcher_(this, |
| + profile->GetRequestContext(), |
| + profile, |
| + kServiceScopeChromeOSDeviceManagement) { |
| + } |
| + |
| virtual ~PolicyOAuthFetcher() {} |
| void Start() { |
| - oauth_fetcher_.StartOAuthWrapBridge( |
| - oauth1_token_, oauth1_secret_, GaiaConstants::kGaiaOAuthDuration, |
| - std::string(kServiceScopeChromeOSDeviceManagement)); |
| + oauth_fetcher_.SetAutoFetchLimit( |
| + GaiaOAuthFetcher::OAUTH2_SERVICE_ACCESS_TOKEN); |
| + |
| + if (oauth1_token_.empty()) { |
| + oauth_fetcher_.StartGetOAuthTokenRequest(); |
| + } else { |
| + oauth_fetcher_.StartOAuthWrapBridge( |
| + oauth1_token_, oauth1_secret_, GaiaConstants::kGaiaOAuthDuration, |
| + std::string(kServiceScopeChromeOSDeviceManagement)); |
| + } |
| + } |
| + |
| + const std::string& oauth1_token() const { return oauth1_token_; } |
| + const std::string& oauth1_secret() const { return oauth1_secret_; } |
| + |
| + private: |
| + virtual void OnGetOAuthTokenSuccess(const std::string& oauth_token) OVERRIDE { |
| + VLOG(1) << "Got OAuth request token"; |
| + } |
| + |
| + virtual void OnGetOAuthTokenFailure( |
| + const GoogleServiceAuthError& error) OVERRIDE { |
| + LOG(WARNING) << "Failed to get OAuth request token"; |
| + SetPolicyToken(""); |
| + } |
| + |
| + virtual void OnOAuthGetAccessTokenSuccess( |
| + const std::string& token, |
| + const std::string& secret) OVERRIDE { |
| + VLOG(1) << "Got OAuth access token"; |
| + oauth1_token_ = token; |
| + oauth1_secret_ = secret; |
| + } |
| + |
| + virtual void OnOAuthGetAccessTokenFailure( |
| + const GoogleServiceAuthError& error) OVERRIDE { |
| + LOG(WARNING) << "Failed to get OAuth access token"; |
| + SetPolicyToken(""); |
| } |
| - // GaiaOAuthConsumer implementation: |
| virtual void OnOAuthWrapBridgeSuccess( |
| const std::string& service_name, |
| const std::string& token, |
| const std::string& expires_in) OVERRIDE { |
| - policy::BrowserPolicyConnector* browser_policy_connector = |
| - g_browser_process->browser_policy_connector(); |
| - browser_policy_connector->RegisterForUserPolicy(token); |
| + VLOG(1) << "Got OAuth access token for " << service_name; |
| + SetPolicyToken(token); |
| } |
| virtual void OnOAuthWrapBridgeFailure( |
| const std::string& service_name, |
| const GoogleServiceAuthError& error) OVERRIDE { |
| LOG(WARNING) << "Failed to get OAuth access token for " << service_name; |
| + SetPolicyToken(""); |
| + } |
| + |
| + void SetPolicyToken(const std::string& token) { |
| + g_browser_process->browser_policy_connector()->RegisterForUserPolicy(token); |
| } |
| - private: |
| GaiaOAuthFetcher oauth_fetcher_; |
| std::string oauth1_token_; |
| std::string oauth1_secret_; |
| @@ -460,7 +512,7 @@ class LoginUtilsImpl : public LoginUtils, |
| // GaiaOAuthConsumer overrides. |
| virtual void OnGetOAuthTokenSuccess(const std::string& oauth_token) OVERRIDE; |
| virtual void OnGetOAuthTokenFailure( |
| - const GoogleServiceAuthError& error) OVERRIDE; |
| + const GoogleServiceAuthError& error) OVERRIDE; |
| virtual void OnOAuthGetAccessTokenSuccess(const std::string& token, |
| const std::string& secret) OVERRIDE; |
| virtual void OnOAuthGetAccessTokenFailure( |
| @@ -527,6 +579,7 @@ class LoginUtilsImpl : public LoginUtils, |
| scoped_refptr<Authenticator> authenticator_; |
| scoped_ptr<GaiaOAuthFetcher> oauth_fetcher_; |
| scoped_ptr<PolicyOAuthFetcher> policy_oauth_fetcher_; |
| + scoped_ptr<PolicyOAuthFetcher> policy_oauth_early_fetcher_; |
|
Mattias Nissler (ping if slow)
2011/11/11 11:41:23
I don't see why we need two pointers here, wouldn'
Joao da Silva
2011/11/11 12:55:14
The 2nd pointer was used to distinguish early poli
|
| scoped_ptr<OAuthLoginVerifier> oauth_login_verifier_; |
| // Delegate to be fired when the profile will be prepared. |
| @@ -602,8 +655,23 @@ void LoginUtilsImpl::PrepareProfile( |
| delegate_ = delegate; |
| // Initialize user policy before the profile is created so the profile |
| - // initialization code sees the policy settings. |
| - g_browser_process->browser_policy_connector()->InitializeUserPolicy(username); |
| + // initialization code sees the cached policy settings. |
| + policy::BrowserPolicyConnector* connector = |
| + g_browser_process->browser_policy_connector(); |
| + bool user_policy_needs_fetch = connector->InitializeUserPolicy(username); |
| + if (user_policy_needs_fetch) { |
| + if (using_oauth_ && authenticator_.get()) { |
| + // Profile creation will block until user policy is fetched, which |
| + // requires the DeviceManagement token. Try to fetch it now. |
| + VLOG(1) << "Profile creation requires policy token, fetching now"; |
| + policy_oauth_early_fetcher_.reset( |
| + new PolicyOAuthFetcher(authenticator_->authentication_profile())); |
| + policy_oauth_early_fetcher_->Start(); |
| + } else { |
| + // Tell the policy subsystem to resume without a policy fetch. |
| + connector->RegisterForUserPolicy(""); |
| + } |
| + } |
| // The default profile will have been changed because the ProfileManager |
| // will process the notification that the UserManager sends out. |
| @@ -632,12 +700,9 @@ void LoginUtilsImpl::OnProfileCreated(Profile* user_profile, Status status) { |
| } |
| // Initialize the user-policy backend. |
| - policy::BrowserPolicyConnector* browser_policy_connector = |
| - g_browser_process->browser_policy_connector(); |
| - |
| if (!using_oauth_) { |
| - browser_policy_connector->SetUserPolicyTokenService( |
| - user_profile->GetTokenService()); |
| + g_browser_process->browser_policy_connector()-> |
| + SetUserPolicyTokenService(user_profile->GetTokenService()); |
| } |
| // We suck. This is a hack since we do not have the enterprise feature |
| @@ -653,6 +718,15 @@ void LoginUtilsImpl::OnProfileCreated(Profile* user_profile, Status status) { |
| btl->AddLoginTimeMarker("UserProfileGotten", false); |
| if (using_oauth_) { |
| + // Reuse the access token fetched by the PolicyOAuthFetcher, if it was |
| + // used to fetch policies before Profile creation. |
| + if (policy_oauth_early_fetcher_.get()) { |
| + VLOG(1) << "Resuming profile creation after fetching policy token"; |
| + StoreOAuth1AccessToken(user_profile, |
| + policy_oauth_early_fetcher_->oauth1_token(), |
| + policy_oauth_early_fetcher_->oauth1_secret()); |
| + } |
| + |
| // Transfer cookies when user signs in using extension. |
| if (has_cookies_) { |
| // Transfer cookies from the profile that was used for authentication. |
| @@ -746,8 +820,8 @@ void LoginUtilsImpl::FetchOAuth1AccessToken(Profile* auth_profile) { |
| auth_profile, |
| kServiceScopeChromeOS)); |
| // Let's first get the Oauth request token and OAuth1 token+secret. |
| - // One we get that, we will kick off individial requests for OAuth2 tokens for |
| - // all our services. |
| + // Once we get that, we will kick off individual requests for OAuth2 tokens |
| + // for all our services. |
| oauth_fetcher_->SetAutoFetchLimit(GaiaOAuthFetcher::OAUTH1_ALL_ACCESS_TOKEN); |
| oauth_fetcher_->StartGetOAuthTokenRequest(); |
| } |
| @@ -800,7 +874,6 @@ void LoginUtilsImpl::StartSync( |
| token_service->UpdateCredentials(credentials); |
| if (token_service->AreCredentialsValid()) |
| token_service->StartFetchingTokens(); |
| - |
| } |
| void LoginUtilsImpl::RespectLocalePreference(Profile* profile) { |
| @@ -1068,6 +1141,12 @@ void LoginUtilsImpl::OnOAuthGetAccessTokenSuccess(const std::string& token, |
| VerifyOAuth1AccessToken(user_profile, token, secret); |
| } |
| +void LoginUtilsImpl::OnOAuthGetAccessTokenFailure( |
| + const GoogleServiceAuthError& error) { |
| + // TODO(zelidrag): Pop up sync setup UI here? |
| + LOG(WARNING) << "Failed fetching OAuth request token"; |
|
Mattias Nissler (ping if slow)
2011/11/11 11:41:23
This logged error.state() before, why did you drop
Joao da Silva
2011/11/11 12:55:14
Done.
|
| +} |
| + |
| void LoginUtilsImpl::FetchSecondaryTokens(Profile* offrecord_profile, |
| const std::string& token, |
| const std::string& secret) { |
| @@ -1142,11 +1221,18 @@ void LoginUtilsImpl::FetchCredentials(Profile* user_profile, |
| void LoginUtilsImpl::FetchPolicyToken(Profile* offrecord_profile, |
| const std::string& token, |
| const std::string& secret) { |
| - // Trigger oauth token fetch for user policy. |
| - policy_oauth_fetcher_.reset(new PolicyOAuthFetcher(offrecord_profile, |
| - token, |
| - secret)); |
| - policy_oauth_fetcher_->Start(); |
| + if (policy_oauth_early_fetcher_.get()) { |
| + // User policy has already been fetched. Reset the early policy fetcher |
| + // now, so that subsequent calls of FetchSecondaryTokens fetch the policy |
| + // token again. |
| + policy_oauth_early_fetcher_.reset(); |
| + } else { |
| + // Trigger oauth token fetch for user policy. |
| + policy_oauth_fetcher_.reset(new PolicyOAuthFetcher(offrecord_profile, |
| + token, |
| + secret)); |
| + policy_oauth_fetcher_->Start(); |
| + } |
| // TODO(zelidrag): We should add initialization of other services somewhere |
| // here as well. This could be handled with TokenService class once it is |
| @@ -1159,12 +1245,6 @@ void LoginUtilsImpl::FetchPolicyToken(Profile* offrecord_profile, |
| authenticator_ = NULL; |
| } |
| -void LoginUtilsImpl::OnOAuthGetAccessTokenFailure( |
| - const GoogleServiceAuthError& error) { |
| - // TODO(zelidrag): Pop up sync setup UI here? |
| - LOG(WARNING) << "Failed fetching OAuth v1 token, error: " << error.state(); |
| -} |
| - |
| void LoginUtilsImpl::OnOnlineStateChanged(bool online) { |
| // If we come online for the first time after successful offline login, |
| // we need to kick of OAuth token verification process again. |