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

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: 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 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;

Powered by Google App Engine
This is Rietveld 408576698