Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4900)

Unified Diff: chrome/browser/sync/profile_sync_service.cc

Issue 15421011: Use OAuth2 token for sync (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix issues based on feedback Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 bfea304d422f680c4dc02f746109fd8162f2c7ef..8b9f3cf646cb4ae286d5fd89e33f03c861e4fabe 100644
--- a/chrome/browser/sync/profile_sync_service.cc
+++ b/chrome/browser/sync/profile_sync_service.cc
@@ -30,6 +30,8 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/about_signin_internals.h"
#include "chrome/browser/signin/about_signin_internals_factory.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"
@@ -110,24 +112,16 @@ const char* ProfileSyncService::kDevServerUrl =
static const int kSyncClearDataTimeoutInSeconds = 60; // 1 minute.
-static const char* kRelevantTokenServices[] = {
- GaiaConstants::kSyncService
+static const char* kOAuth2Scopes[] = {
+ GaiaConstants::kChromeSyncOAuth2Scope,
+ // GoogleTalk scope is needed for notifications
Andrew T Wilson (Slow) 2013/05/31 12:57:28 nit: add period at the end for sentence punctuatio
pavely 2013/06/04 00:49:59 Done.
+ GaiaConstants::kGoogleTalkOAuth2Scope
};
-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 &&
@@ -193,11 +187,12 @@ bool ProfileSyncService::IsSyncEnabledAndLoggedIn() {
return !GetEffectiveUsername().empty();
}
-bool ProfileSyncService::IsSyncTokenAvailable() {
- TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
+bool ProfileSyncService::IsOAuthRefreshTokenAvailable() {
+ ProfileOAuth2TokenService* token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
if (!token_service)
return false;
- return token_service->HasTokenForService(GaiaConstants::kSyncService);
+ return token_service->RefreshTokenIsAvailable();
}
#if defined(OS_ANDROID)
bool ProfileSyncService::ShouldEnablePasswordSyncForAndroid() const {
@@ -245,6 +240,12 @@ void ProfileSyncService::Initialize() {
TrySyncDatatypePrefRecovery();
+ if (IsOAuthRefreshTokenAvailable()) {
+ // 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();
}
@@ -292,7 +293,7 @@ void ProfileSyncService::TryStart() {
// (like ChromeOS) we don't start sync until tokens are loaded, because the
// user can be "signed in" on those platforms long before the tokens get
// loaded, and we don't want to generate spurious auth errors.
- if (!IsSyncTokenAvailable() &&
+ if (!IsOAuthRefreshTokenAvailable() &&
!(!auto_start_enabled_ && token_service->TokensLoadedFromDB())) {
return;
}
@@ -426,13 +427,11 @@ SyncCredentials ProfileSyncService::GetCredentials() {
SyncCredentials credentials;
credentials.email = GetEffectiveUsername();
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()) {
+ credentials.sync_token = access_token_;
credentials.sync_token_time =
AboutSigninInternalsFactory::GetForProfile(profile_)->
- GetTokenTime(GaiaConstants::kSyncService);
+ GetTokenTime(GaiaConstants::kGaiaOAuth2LoginRefreshToken);
UMA_HISTOGRAM_BOOLEAN("Sync.CredentialsLost", false);
} else {
// We've lost our sync credentials (crbug.com/121755), so just make up some
@@ -514,6 +513,11 @@ void ProfileSyncService::StartUp(StartUpDeferredOption deferred_option) {
DCHECK(IsSyncEnabledAndLoggedIn());
+ if (access_token_.empty()) {
+ RequestAccessToken(false, true);
+ return;
+ }
+
if (start_up_time_.is_null()) {
start_up_time_ = base::Time::Now();
last_synced_time_ = sync_prefs_.GetLastSyncedTime();
@@ -661,6 +665,27 @@ 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) {
+ DCHECK_EQ(access_token_request_, request);
+ access_token_request_.reset();
+ access_token_ = access_token;
+ if (backend_)
+ backend_->UpdateCredentials(GetCredentials());
+ else
+ TryStart();
+}
+
+void ProfileSyncService::OnGetTokenFailure(
+ const OAuth2TokenService::Request* request,
+ const GoogleServiceAuthError& error) {
+ DCHECK_EQ(access_token_request_, request);
+ access_token_request_.reset();
+ UpdateAuthErrorState(error);
+}
+
void ProfileSyncService::EmitInvalidationForTest(
const invalidation::ObjectId& id,
const std::string& payload) {
@@ -1087,10 +1112,18 @@ 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) {
+ // Sync or Tango server returned error indicating that access token is
+ // invalid. It could be either expired or access is revoked. Let's request
+ // another access token and if access is revoked then request for token will
+ // fail with corresponding error.
+ RequestAccessToken(true, true);
+ } else {
+ const GoogleServiceAuthError auth_error =
+ ConnectionStatusToAuthError(status);
+ DVLOG(1) << "Connection status change: " << auth_error.ToString();
+ UpdateAuthErrorState(auth_error);
+ }
}
void ProfileSyncService::OnStopSyncingPermanently() {
@@ -1833,6 +1866,30 @@ void ProfileSyncService::ConsumeCachedPassphraseIfPossible() {
SetEncryptionPassphrase(passphrase, IMPLICIT);
}
+void ProfileSyncService::RequestAccessToken(
+ bool invalidate_previous_token,
+ bool invoke_callback) {
+ // Only one active request at a time.
+ if (access_token_request_ != NULL)
+ 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
Andrew T Wilson (Slow) 2013/05/31 12:57:28 nit:othervise->otherwise. Also add a period at the
pavely 2013/06/04 00:49:59 Done.
+ // token again
+ token_service->InvalidateToken(oauth2_scopes, access_token_);
+ access_token_.clear();
+ }
+ 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();
+ }
+}
+
void ProfileSyncService::SetEncryptionPassphrase(const std::string& passphrase,
PassphraseType type) {
// This should only be called when the backend has been initialized.
@@ -1936,27 +1993,33 @@ void ProfileSyncService::Observe(int type,
break;
}
case chrome::NOTIFICATION_TOKEN_REQUEST_FAILED: {
+ // TODO(atwilson): sync shouldn't report refresh token request failures.
+ // TokenService should do that instead.
const TokenService::TokenRequestFailedDetails& token_details =
*(content::Details<const TokenService::TokenRequestFailedDetails>(
details).ptr());
- if (IsTokenServiceRelevant(token_details.service()) &&
- !IsSyncTokenAvailable()) {
- // The additional check around IsSyncTokenAvailable() above prevents us
- // sounding the alarm if we actually have a valid token but a refresh
- // attempt by TokenService failed for any variety of reasons (e.g. flaky
- // network). It's possible the token we do have is also invalid, but in
- // that case we should already have (or can expect) an auth error sent
- // from the sync backend.
+ if (token_details.service() ==
+ GaiaConstants::kGaiaOAuth2LoginRefreshToken &&
+ !IsOAuthRefreshTokenAvailable()) {
+ // The additional check around IsOAuthRefreshTokenAvailable() above
+ // prevents us sounding the alarm if we actually have a valid token but
+ // a refresh attempt by TokenService failed for any variety of reasons
+ // (e.g. flaky network). It's possible the token we do have is also
+ // invalid, but in that case we should already have (or can expect) an
+ // auth error sent from the sync backend.
AuthError error(AuthError::INVALID_GAIA_CREDENTIALS);
UpdateAuthErrorState(error);
}
break;
}
case chrome::NOTIFICATION_TOKEN_AVAILABLE: {
+ // TODO(atwilson): Listen for notifications on OAuth2TokenService
+ // (crbug.com/243737)
const TokenService::TokenAvailableDetails& token_details =
*(content::Details<const TokenService::TokenAvailableDetails>(
details).ptr());
- if (!IsTokenServiceRelevant(token_details.service()))
+ if (token_details.service() !=
+ GaiaConstants::kGaiaOAuth2LoginRefreshToken)
break;
} // Fall through.
case chrome::NOTIFICATION_TOKEN_LOADING_FINISHED: {
@@ -1966,14 +2029,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);
Andrew T Wilson (Slow) 2013/05/31 12:57:28 Doesn't this fetch a token on every startup even i
TryStart();
break;
}
case chrome::NOTIFICATION_TOKENS_CLEARED: {
// GetCredentials() will generate invalid credentials to cause the backend
// to generate an auth error.
+ access_token_.clear();
if (backend_)
backend_->UpdateCredentials(GetCredentials());
break;
@@ -2110,4 +2175,3 @@ std::string ProfileSyncService::GetEffectiveUsername() {
return signin_->GetAuthenticatedUsername();
}
-

Powered by Google App Engine
This is Rietveld 408576698