Chromium Code Reviews| Index: chrome/browser/sync/profile_sync_service.cc |
| diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc |
| index da473e4540cc2246f0b555ceeb573a97581237ae..c6ba85b50633bf7eebeb1442c2b1c8fe27fdeede 100644 |
| --- a/chrome/browser/sync/profile_sync_service.cc |
| +++ b/chrome/browser/sync/profile_sync_service.cc |
| @@ -28,6 +28,8 @@ |
| #include "chrome/browser/net/chrome_cookie_notification_details.h" |
| #include "chrome/browser/prefs/pref_service_syncable.h" |
| #include "chrome/browser/profiles/profile.h" |
| +#include "chrome/browser/signin/profile_oauth2_token_service.h" |
| +#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" |
| #include "chrome/browser/signin/signin_manager.h" |
| #include "chrome/browser/signin/signin_manager_factory.h" |
| #include "chrome/browser/signin/token_service.h" |
| @@ -104,24 +106,15 @@ const char* ProfileSyncService::kDevServerUrl = |
| static const int kSyncClearDataTimeoutInSeconds = 60; // 1 minute. |
| -static const char* kRelevantTokenServices[] = { |
| - GaiaConstants::kSyncService |
| +static const char* kOAuth2Scopes[] = { |
|
tim (not reviewing)
2013/05/23 19:03:41
These belong in google_apis / GaiaConstants.
pavely
2013/05/30 07:42:12
Done.
Andrew T Wilson (Slow)
2013/05/31 12:57:28
That's too bad - I guess we need to move a little
|
| + "https://www.googleapis.com/auth/chromesync", |
| + "https://www.googleapis.com/auth/googletalk" |
|
Andrew T Wilson (Slow)
2013/05/31 12:57:28
So, this means we *cannot* sync if the user has th
pavely
2013/06/04 00:49:59
Currently if notifications server returns auth err
|
| }; |
| -static const int kRelevantTokenServicesCount = |
| - arraysize(kRelevantTokenServices); |
| + |
| static const char* kSyncUnrecoverableErrorHistogram = |
| "Sync.UnrecoverableErrors"; |
| -// Helper to check if the given token service is relevant for sync. |
| -static bool IsTokenServiceRelevant(const std::string& service) { |
| - for (int i = 0; i < kRelevantTokenServicesCount; ++i) { |
| - if (service == kRelevantTokenServices[i]) |
| - return true; |
| - } |
| - return false; |
| -} |
| - |
| bool ShouldShowActionOnUI( |
| const syncer::SyncProtocolError& error) { |
| return (error.action != syncer::UNKNOWN_ACTION && |
| @@ -154,7 +147,9 @@ ProfileSyncService::ProfileSyncService(ProfileSyncComponentsFactory* factory, |
| failed_datatypes_handler_(this), |
| configure_status_(DataTypeManager::UNKNOWN), |
| setup_in_progress_(false), |
| - invalidator_state_(syncer::DEFAULT_INVALIDATION_ERROR) { |
| + invalidator_state_(syncer::DEFAULT_INVALIDATION_ERROR), |
| + access_token_(), |
|
tim (not reviewing)
2013/05/23 19:03:41
Remove these two initializers as they are not nece
pavely
2013/05/30 07:42:12
Done.
|
| + access_token_request_() { |
| // By default, dev, canary, and unbranded Chromium users will go to the |
| // development servers. Development servers have more features than standard |
| // sync servers. Users with officially-branded Chrome stable and beta builds |
| @@ -190,7 +185,7 @@ bool ProfileSyncService::IsSyncTokenAvailable() { |
| TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); |
| if (!token_service) |
| return false; |
| - return token_service->HasTokenForService(GaiaConstants::kSyncService); |
| + return token_service->HasOAuthLoginToken(); |
|
tim (not reviewing)
2013/05/23 19:03:41
Is there a better name than just "OAuthLoginToken"
Andrew T Wilson (Slow)
2013/05/24 14:10:15
I wonder if it's better to call OAuth2TokenService
pavely
2013/05/30 07:42:12
Done.
|
| } |
| #if defined(OS_ANDROID) |
| bool ProfileSyncService::ShouldEnablePasswordSyncForAndroid() const { |
| @@ -238,6 +233,12 @@ void ProfileSyncService::Initialize() { |
| TrySyncDatatypePrefRecovery(); |
| + if (IsSyncTokenAvailable()) { |
| + // Tell token service to pre-request access token. We likely don't need it |
| + // right away but it will be available when we decide to initialize backend. |
| + RequestAccessToken(false, false); |
| + } |
| + |
| TryStart(); |
| } |
| @@ -414,10 +415,8 @@ SyncCredentials ProfileSyncService::GetCredentials() { |
| SyncCredentials credentials; |
| credentials.email = signin_->GetAuthenticatedUsername(); |
| DCHECK(!credentials.email.empty()); |
| - TokenService* service = TokenServiceFactory::GetForProfile(profile_); |
| - if (service->HasTokenForService(GaiaConstants::kSyncService)) { |
| - credentials.sync_token = service->GetTokenForService( |
| - GaiaConstants::kSyncService); |
| + if (!access_token_.empty()) { |
|
tim (not reviewing)
2013/05/23 19:03:41
Can you explain the semantics here in a comment if
Andrew T Wilson (Slow)
2013/05/24 14:10:15
Note the varying UMAs being logged. I do wonder if
pavely
2013/05/30 07:42:12
Like it was before if access token is empty then s
pavely
2013/05/30 07:42:12
Let me explain cases that you listed:
- In tempora
Andrew T Wilson (Slow)
2013/05/31 12:57:28
Is this true? I thought that sync would generate a
|
| + credentials.sync_token = access_token_; |
| UMA_HISTOGRAM_BOOLEAN("Sync.CredentialsLost", false); |
| } else { |
| // We've lost our sync credentials (crbug.com/121755), so just make up some |
| @@ -499,6 +498,11 @@ void ProfileSyncService::StartUp(StartUpDeferredOption deferred_option) { |
| DCHECK(IsSyncEnabledAndLoggedIn()); |
| + if (access_token_.empty()) { |
|
tim (not reviewing)
2013/05/23 19:03:41
The relationship between TryStart and StartUp is t
pavely
2013/05/30 07:42:12
TryStart gathers all local information to decide i
|
| + RequestAccessToken(false, true); |
|
Andrew T Wilson (Slow)
2013/05/31 12:57:28
Should we only do this if deferred_option = STARTU
|
| + return; |
| + } |
| + |
| last_synced_time_ = sync_prefs_.GetLastSyncedTime(); |
| DCHECK(start_up_time_.is_null()); |
| @@ -607,6 +611,25 @@ syncer::InvalidatorState ProfileSyncService::GetInvalidatorState() const { |
| return invalidator_registrar_->GetInvalidatorState(); |
| } |
| +void ProfileSyncService::OnGetTokenSuccess( |
| + const OAuth2TokenService::Request* request, |
| + const std::string& access_token, |
| + const base::Time& expiration_time) { |
| + access_token_request_.reset(); |
|
tim (not reviewing)
2013/05/23 19:03:42
DCHECK(access_token_request_.get()) in both these
Andrew T Wilson (Slow)
2013/05/24 14:10:15
Actually, I think you should do DCHECK_EQ(access_t
pavely
2013/05/30 07:42:12
Done.
|
| + access_token_ = access_token; |
| + if (backend_) |
| + backend_->UpdateCredentials(GetCredentials()); |
| + else |
| + TryStart(); |
| +} |
| + |
| +void ProfileSyncService::OnGetTokenFailure( |
| + const OAuth2TokenService::Request* request, |
| + const GoogleServiceAuthError& error) { |
| + access_token_request_.reset(); |
| + UpdateAuthErrorState(error); |
| +} |
| + |
| void ProfileSyncService::EmitInvalidationForTest( |
| const invalidation::ObjectId& id, |
| const std::string& payload) { |
| @@ -1029,10 +1052,14 @@ AuthError ConnectionStatusToAuthError( |
| void ProfileSyncService::OnConnectionStatusChange( |
| syncer::ConnectionStatus status) { |
| - const GoogleServiceAuthError auth_error = |
| - ConnectionStatusToAuthError(status); |
| - DVLOG(1) << "Connection status change: " << auth_error.ToString(); |
| - UpdateAuthErrorState(auth_error); |
| + if (status == syncer::CONNECTION_AUTH_ERROR) { |
|
tim (not reviewing)
2013/05/23 19:03:42
Comment this - is this known to be a transient acc
pavely
2013/05/30 07:42:12
Done.
|
| + RequestAccessToken(true, true); |
| + } else { |
| + const GoogleServiceAuthError auth_error = |
| + ConnectionStatusToAuthError(status); |
| + DVLOG(1) << "Connection status change: " << auth_error.ToString(); |
| + UpdateAuthErrorState(auth_error); |
| + } |
| } |
| void ProfileSyncService::OnStopSyncingPermanently() { |
| @@ -1777,6 +1804,31 @@ void ProfileSyncService::ConsumeCachedPassphraseIfPossible() { |
| SetEncryptionPassphrase(passphrase, IMPLICIT); |
| } |
| +void ProfileSyncService::RequestAccessToken( |
| + bool invalidate_previous_token, |
| + bool invoke_callback) |
| +{ |
|
tim (not reviewing)
2013/05/23 19:03:42
nit: { on previous line.
pavely
2013/05/30 07:42:12
Done.
|
| + // Only one active request at a time. |
| + if (access_token_request_ != NULL) |
|
tim (not reviewing)
2013/05/23 19:03:42
Think this should be a DCHECK?
Andrew T Wilson (Slow)
2013/05/24 14:10:15
I think this can happen in practice - there's noth
pavely
2013/05/30 07:42:12
Yes, there could be multiple calls to RequestAcces
|
| + return; |
| + OAuth2TokenService::ScopeSet oauth2_scopes; |
| + for (size_t i = 0; i < arraysize(kOAuth2Scopes); i++) |
| + oauth2_scopes.insert(kOAuth2Scopes[i]); |
| + OAuth2TokenService* token_service = |
| + ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); |
| + if (invalidate_previous_token) { |
| + // Invalidate previous token, othervise token service will return the same |
| + // token again |
| + token_service->InvalidateToken(oauth2_scopes, access_token_); |
| + access_token_ = std::string(); |
|
tim (not reviewing)
2013/05/23 19:03:42
use access_token_.clear()
pavely
2013/05/30 07:42:12
Done.
|
| + } |
| + access_token_request_ = token_service->StartRequest(oauth2_scopes, this); |
| + if (!invoke_callback) { |
| + // Deleting request will not cancel RPC but callbacks won't be invoked. |
| + access_token_request_.reset(); |
|
Andrew T Wilson (Slow)
2013/05/24 14:10:15
I am confused by this - on startup, won't this cau
pavely
2013/05/30 07:42:12
I discussed this with Tim, the question was whenev
Andrew T Wilson (Slow)
2013/05/31 12:57:28
Is this a real concern? I didn't think we were tha
|
| + } |
| +} |
| + |
| void ProfileSyncService::SetEncryptionPassphrase(const std::string& passphrase, |
| PassphraseType type) { |
| // This should only be called when the backend has been initialized. |
| @@ -1883,7 +1935,8 @@ void ProfileSyncService::Observe(int type, |
| const TokenService::TokenRequestFailedDetails& token_details = |
| *(content::Details<const TokenService::TokenRequestFailedDetails>( |
| details).ptr()); |
| - if (IsTokenServiceRelevant(token_details.service()) && |
| + if (token_details.service() == |
| + GaiaConstants::kGaiaOAuth2LoginRefreshToken && |
|
Andrew T Wilson (Slow)
2013/05/24 14:10:15
I'd really like to see us get out of the "listen f
pavely
2013/05/30 07:42:12
Done.
|
| !IsSyncTokenAvailable()) { |
| // The additional check around IsSyncTokenAvailable() above prevents us |
| // sounding the alarm if we actually have a valid token but a refresh |
| @@ -1900,7 +1953,8 @@ void ProfileSyncService::Observe(int type, |
| const TokenService::TokenAvailableDetails& token_details = |
| *(content::Details<const TokenService::TokenAvailableDetails>( |
| details).ptr()); |
| - if (!IsTokenServiceRelevant(token_details.service())) |
| + if (token_details.service() != |
| + GaiaConstants::kGaiaOAuth2LoginRefreshToken) |
|
Andrew T Wilson (Slow)
2013/05/24 14:10:15
We should really move NOTIFICATION_TOKEN_AVAILABLE
pavely
2013/05/30 07:42:12
Done.
|
| break; |
| } // Fall through. |
| case chrome::NOTIFICATION_TOKEN_LOADING_FINISHED: { |
| @@ -1910,14 +1964,16 @@ void ProfileSyncService::Observe(int type, |
| // not loaded, GetCredentials() will generate invalid credentials to |
| // cause the backend to generate an auth error (crbug.com/121755). |
| if (backend_) |
| - backend_->UpdateCredentials(GetCredentials()); |
| + RequestAccessToken(true, true); |
| else |
| + RequestAccessToken(true, false); |
| TryStart(); |
| break; |
| } |
| case chrome::NOTIFICATION_TOKENS_CLEARED: { |
| // GetCredentials() will generate invalid credentials to cause the backend |
| // to generate an auth error. |
| + access_token_ = std::string(); |
|
tim (not reviewing)
2013/05/23 19:03:42
use .clear()
pavely
2013/05/30 07:42:12
Done.
|
| if (backend_) |
| backend_->UpdateCredentials(GetCredentials()); |
| break; |