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

Side by Side 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: Add commandline switch to toggle between OAuth2 and ClientLogin token Created 7 years, 6 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/sync/profile_sync_service.h" 5 #include "chrome/browser/sync/profile_sync_service.h"
6 6
7 #include <cstddef> 7 #include <cstddef>
8 #include <map> 8 #include <map>
9 #include <set> 9 #include <set>
10 #include <utility> 10 #include <utility>
(...skipping 12 matching lines...) Expand all
23 #include "base/threading/thread_restrictions.h" 23 #include "base/threading/thread_restrictions.h"
24 #include "build/build_config.h" 24 #include "build/build_config.h"
25 #include "chrome/browser/about_flags.h" 25 #include "chrome/browser/about_flags.h"
26 #include "chrome/browser/browser_process.h" 26 #include "chrome/browser/browser_process.h"
27 #include "chrome/browser/defaults.h" 27 #include "chrome/browser/defaults.h"
28 #include "chrome/browser/net/chrome_cookie_notification_details.h" 28 #include "chrome/browser/net/chrome_cookie_notification_details.h"
29 #include "chrome/browser/prefs/pref_service_syncable.h" 29 #include "chrome/browser/prefs/pref_service_syncable.h"
30 #include "chrome/browser/profiles/profile.h" 30 #include "chrome/browser/profiles/profile.h"
31 #include "chrome/browser/signin/about_signin_internals.h" 31 #include "chrome/browser/signin/about_signin_internals.h"
32 #include "chrome/browser/signin/about_signin_internals_factory.h" 32 #include "chrome/browser/signin/about_signin_internals_factory.h"
33 #include "chrome/browser/signin/profile_oauth2_token_service.h"
34 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
33 #include "chrome/browser/signin/signin_manager.h" 35 #include "chrome/browser/signin/signin_manager.h"
34 #include "chrome/browser/signin/signin_manager_factory.h" 36 #include "chrome/browser/signin/signin_manager_factory.h"
35 #include "chrome/browser/signin/token_service.h" 37 #include "chrome/browser/signin/token_service.h"
36 #include "chrome/browser/signin/token_service_factory.h" 38 #include "chrome/browser/signin/token_service_factory.h"
37 #include "chrome/browser/sync/backend_migrator.h" 39 #include "chrome/browser/sync/backend_migrator.h"
38 #include "chrome/browser/sync/glue/change_processor.h" 40 #include "chrome/browser/sync/glue/change_processor.h"
39 #include "chrome/browser/sync/glue/chrome_encryptor.h" 41 #include "chrome/browser/sync/glue/chrome_encryptor.h"
40 #include "chrome/browser/sync/glue/chrome_report_unrecoverable_error.h" 42 #include "chrome/browser/sync/glue/chrome_report_unrecoverable_error.h"
41 #include "chrome/browser/sync/glue/data_type_controller.h" 43 #include "chrome/browser/sync/glue/data_type_controller.h"
42 #include "chrome/browser/sync/glue/device_info.h" 44 #include "chrome/browser/sync/glue/device_info.h"
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 typedef GoogleServiceAuthError AuthError; 106 typedef GoogleServiceAuthError AuthError;
105 107
106 const char* ProfileSyncService::kSyncServerUrl = 108 const char* ProfileSyncService::kSyncServerUrl =
107 "https://clients4.google.com/chrome-sync"; 109 "https://clients4.google.com/chrome-sync";
108 110
109 const char* ProfileSyncService::kDevServerUrl = 111 const char* ProfileSyncService::kDevServerUrl =
110 "https://clients4.google.com/chrome-sync/dev"; 112 "https://clients4.google.com/chrome-sync/dev";
111 113
112 static const int kSyncClearDataTimeoutInSeconds = 60; // 1 minute. 114 static const int kSyncClearDataTimeoutInSeconds = 60; // 1 minute.
113 115
114 static const char* kRelevantTokenServices[] = { 116 static const char* kOAuth2Scopes[] = {
115 GaiaConstants::kSyncService 117 GaiaConstants::kChromeSyncOAuth2Scope,
118 // GoogleTalk scope is needed for notifications.
119 GaiaConstants::kGoogleTalkOAuth2Scope
116 }; 120 };
117 static const int kRelevantTokenServicesCount = 121
118 arraysize(kRelevantTokenServices);
119 122
120 static const char* kSyncUnrecoverableErrorHistogram = 123 static const char* kSyncUnrecoverableErrorHistogram =
121 "Sync.UnrecoverableErrors"; 124 "Sync.UnrecoverableErrors";
122 125
123 // Helper to check if the given token service is relevant for sync. 126 const net::BackoffEntry::Policy kRequestAccessTokenBackoffPolicy = {
124 static bool IsTokenServiceRelevant(const std::string& service) { 127 // Number of initial errors (in sequence) to ignore before applying
125 for (int i = 0; i < kRelevantTokenServicesCount; ++i) { 128 // exponential back-off rules.
126 if (service == kRelevantTokenServices[i]) 129 0,
127 return true; 130
128 } 131 // Initial delay for exponential back-off in ms.
129 return false; 132 2000,
130 } 133
134 // Factor by which the waiting time will be multiplied.
135 2,
136
137 // Fuzzing percentage. ex: 10% will spread requests randomly
138 // between 90%-100% of the calculated time.
139 0.2, // 20%
140
141 // Maximum amount of time we are willing to delay our request in ms.
142 // TODO(pavely): crbug.com/246686 ProfileSyncService should retry
143 // RequestAccessToken on connection state change after backoff
144 1000 * 3600 * 4, // 4 hours.
145
146 // Time to keep an entry from being discarded even when it
147 // has no significant state, -1 to never discard.
148 -1,
149
150 // Don't use initial delay unless the last request was an error.
151 false,
152 };
131 153
132 bool ShouldShowActionOnUI( 154 bool ShouldShowActionOnUI(
133 const syncer::SyncProtocolError& error) { 155 const syncer::SyncProtocolError& error) {
134 return (error.action != syncer::UNKNOWN_ACTION && 156 return (error.action != syncer::UNKNOWN_ACTION &&
135 error.action != syncer::DISABLE_SYNC_ON_CLIENT && 157 error.action != syncer::DISABLE_SYNC_ON_CLIENT &&
136 error.action != syncer::STOP_SYNC_FOR_DISABLED_ACCOUNT); 158 error.action != syncer::STOP_SYNC_FOR_DISABLED_ACCOUNT);
137 } 159 }
138 160
139 ProfileSyncService::ProfileSyncService(ProfileSyncComponentsFactory* factory, 161 ProfileSyncService::ProfileSyncService(ProfileSyncComponentsFactory* factory,
140 Profile* profile, 162 Profile* profile,
(...skipping 15 matching lines...) Expand all
156 signin_(signin_manager), 178 signin_(signin_manager),
157 unrecoverable_error_reason_(ERROR_REASON_UNSET), 179 unrecoverable_error_reason_(ERROR_REASON_UNSET),
158 weak_factory_(this), 180 weak_factory_(this),
159 expect_sync_configuration_aborted_(false), 181 expect_sync_configuration_aborted_(false),
160 encrypted_types_(syncer::SyncEncryptionHandler::SensitiveTypes()), 182 encrypted_types_(syncer::SyncEncryptionHandler::SensitiveTypes()),
161 encrypt_everything_(false), 183 encrypt_everything_(false),
162 encryption_pending_(false), 184 encryption_pending_(false),
163 auto_start_enabled_(start_behavior == AUTO_START), 185 auto_start_enabled_(start_behavior == AUTO_START),
164 configure_status_(DataTypeManager::UNKNOWN), 186 configure_status_(DataTypeManager::UNKNOWN),
165 setup_in_progress_(false), 187 setup_in_progress_(false),
166 invalidator_state_(syncer::DEFAULT_INVALIDATION_ERROR) { 188 invalidator_state_(syncer::DEFAULT_INVALIDATION_ERROR),
189 request_access_token_backoff_(&kRequestAccessTokenBackoffPolicy) {
167 // By default, dev, canary, and unbranded Chromium users will go to the 190 // By default, dev, canary, and unbranded Chromium users will go to the
168 // development servers. Development servers have more features than standard 191 // development servers. Development servers have more features than standard
169 // sync servers. Users with officially-branded Chrome stable and beta builds 192 // sync servers. Users with officially-branded Chrome stable and beta builds
170 // will go to the standard sync servers. 193 // will go to the standard sync servers.
171 // 194 //
172 // GetChannel hits the registry on Windows. See http://crbug.com/70380. 195 // GetChannel hits the registry on Windows. See http://crbug.com/70380.
173 base::ThreadRestrictions::ScopedAllowIO allow_io; 196 base::ThreadRestrictions::ScopedAllowIO allow_io;
174 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); 197 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
175 if (channel == chrome::VersionInfo::CHANNEL_STABLE || 198 if (channel == chrome::VersionInfo::CHANNEL_STABLE ||
176 channel == chrome::VersionInfo::CHANNEL_BETA) { 199 channel == chrome::VersionInfo::CHANNEL_BETA) {
(...skipping 11 matching lines...) Expand all
188 211
189 bool ProfileSyncService::IsSyncEnabledAndLoggedIn() { 212 bool ProfileSyncService::IsSyncEnabledAndLoggedIn() {
190 // Exit if sync is disabled. 213 // Exit if sync is disabled.
191 if (IsManaged() || sync_prefs_.IsStartSuppressed()) 214 if (IsManaged() || sync_prefs_.IsStartSuppressed())
192 return false; 215 return false;
193 216
194 // Sync is logged in if there is a non-empty effective username. 217 // Sync is logged in if there is a non-empty effective username.
195 return !GetEffectiveUsername().empty(); 218 return !GetEffectiveUsername().empty();
196 } 219 }
197 220
198 bool ProfileSyncService::IsSyncTokenAvailable() { 221 bool ProfileSyncService::IsOAuthRefreshTokenAvailable() {
199 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); 222 if (use_oauth2_token_) {
200 if (!token_service) 223 ProfileOAuth2TokenService* token_service =
201 return false; 224 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
202 return token_service->HasTokenForService(GaiaConstants::kSyncService); 225 if (!token_service)
226 return false;
227 return token_service->RefreshTokenIsAvailable();
228 } else {
229 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
230 if (!token_service)
231 return false;
232 return token_service->HasTokenForService(GaiaConstants::kSyncService);
233 }
203 } 234 }
204 235
205 void ProfileSyncService::Initialize() { 236 void ProfileSyncService::Initialize() {
206 DCHECK(!invalidator_registrar_.get()); 237 DCHECK(!invalidator_registrar_.get());
207 invalidator_registrar_.reset(new syncer::InvalidatorRegistrar()); 238 invalidator_registrar_.reset(new syncer::InvalidatorRegistrar());
208 239
209 InitSettings(); 240 InitSettings();
210 241
211 // We clear this here (vs Shutdown) because we want to remember that an error 242 // We clear this here (vs Shutdown) because we want to remember that an error
212 // happened on shutdown so we can display details (message, location) about it 243 // happened on shutdown so we can display details (message, location) about it
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 return; 301 return;
271 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); 302 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
272 if (!token_service) 303 if (!token_service)
273 return; 304 return;
274 // Don't start the backend if the token service hasn't finished loading tokens 305 // Don't start the backend if the token service hasn't finished loading tokens
275 // yet. Note if the backend is started before the sync token has been loaded, 306 // yet. Note if the backend is started before the sync token has been loaded,
276 // GetCredentials() will return bogus credentials. On auto_start platforms 307 // GetCredentials() will return bogus credentials. On auto_start platforms
277 // (like ChromeOS) we don't start sync until tokens are loaded, because the 308 // (like ChromeOS) we don't start sync until tokens are loaded, because the
278 // user can be "signed in" on those platforms long before the tokens get 309 // user can be "signed in" on those platforms long before the tokens get
279 // loaded, and we don't want to generate spurious auth errors. 310 // loaded, and we don't want to generate spurious auth errors.
280 if (!IsSyncTokenAvailable() && 311 if (!IsOAuthRefreshTokenAvailable() &&
281 !(!auto_start_enabled_ && token_service->TokensLoadedFromDB())) { 312 !(!auto_start_enabled_ && token_service->TokensLoadedFromDB())) {
282 return; 313 return;
283 } 314 }
284 315
316 if (use_oauth2_token_) {
317 // If we got here then tokens are loaded and user logged in and sync is
318 // enabled. If OAuth refresh token is not available then something is wrong.
319 // When PSS requests access token, OAuth2TokenService will return error and
320 // PSS will show error to user asking to reauthenticate.
321 UMA_HISTOGRAM_BOOLEAN("Sync.CredentialsLost",
322 !IsOAuthRefreshTokenAvailable());
323 }
324
285 // If sync setup has completed we always start the backend. If the user is in 325 // If sync setup has completed we always start the backend. If the user is in
286 // the process of setting up now, we should start the backend to download 326 // the process of setting up now, we should start the backend to download
287 // account control state / encryption information). If autostart is enabled, 327 // account control state / encryption information). If autostart is enabled,
288 // but we haven't completed sync setup, we try to start sync anyway, since 328 // but we haven't completed sync setup, we try to start sync anyway, since
289 // it's possible we crashed/shutdown after logging in but before the backend 329 // it's possible we crashed/shutdown after logging in but before the backend
290 // finished initializing the last time. 330 // finished initializing the last time.
291 // 331 //
292 // However, the only time we actually need to start sync _immediately_ is if 332 // However, the only time we actually need to start sync _immediately_ is if
293 // we haven't completed sync setup and the user is in the process of setting 333 // we haven't completed sync setup and the user is in the process of setting
294 // up - either they just signed in (for the first time) on an auto-start 334 // up - either they just signed in (for the first time) on an auto-start
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 if (!value.empty()) { 438 if (!value.empty()) {
399 GURL custom_sync_url(value); 439 GURL custom_sync_url(value);
400 if (custom_sync_url.is_valid()) { 440 if (custom_sync_url.is_valid()) {
401 sync_service_url_ = custom_sync_url; 441 sync_service_url_ = custom_sync_url;
402 } else { 442 } else {
403 LOG(WARNING) << "The following sync URL specified at the command-line " 443 LOG(WARNING) << "The following sync URL specified at the command-line "
404 << "is invalid: " << value; 444 << "is invalid: " << value;
405 } 445 }
406 } 446 }
407 } 447 }
448
449 use_oauth2_token_ = command_line.HasSwitch(switches::kSyncEnableOAuth2Token);
tim (not reviewing) 2013/06/12 20:07:37 Should the flag not be to disable OAuth2, and then
408 } 450 }
409 451
410 SyncCredentials ProfileSyncService::GetCredentials() { 452 SyncCredentials ProfileSyncService::GetCredentials() {
411 SyncCredentials credentials; 453 SyncCredentials credentials;
412 credentials.email = GetEffectiveUsername(); 454 credentials.email = GetEffectiveUsername();
413 DCHECK(!credentials.email.empty()); 455 DCHECK(!credentials.email.empty());
414 TokenService* service = TokenServiceFactory::GetForProfile(profile_); 456 if (use_oauth2_token_) {
415 if (service->HasTokenForService(GaiaConstants::kSyncService)) { 457 credentials.sync_token = access_token_;
416 credentials.sync_token = service->GetTokenForService(
417 GaiaConstants::kSyncService);
418 credentials.sync_token_time =
419 AboutSigninInternalsFactory::GetForProfile(profile_)->
420 GetTokenTime(GaiaConstants::kSyncService);
421 UMA_HISTOGRAM_BOOLEAN("Sync.CredentialsLost", false);
422 } else { 458 } else {
423 // We've lost our sync credentials (crbug.com/121755), so just make up some 459 TokenService* service = TokenServiceFactory::GetForProfile(profile_);
424 // invalid credentials so the backend will generate an auth error. 460 if (service->HasTokenForService(GaiaConstants::kSyncService)) {
425 UMA_HISTOGRAM_BOOLEAN("Sync.CredentialsLost", true); 461 credentials.sync_token = service->GetTokenForService(
462 GaiaConstants::kSyncService);
463 }
464 }
465
466 if (credentials.sync_token.empty())
426 credentials.sync_token = "credentials_lost"; 467 credentials.sync_token = "credentials_lost";
427 }
428 return credentials; 468 return credentials;
429 } 469 }
430 470
431 void ProfileSyncService::InitializeBackend(bool delete_stale_data) { 471 void ProfileSyncService::InitializeBackend(bool delete_stale_data) {
432 if (!backend_) { 472 if (!backend_) {
433 NOTREACHED(); 473 NOTREACHED();
434 return; 474 return;
435 } 475 }
436 476
437 SyncCredentials credentials = GetCredentials(); 477 SyncCredentials credentials = GetCredentials();
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 524
485 void ProfileSyncService::StartUp(StartUpDeferredOption deferred_option) { 525 void ProfileSyncService::StartUp(StartUpDeferredOption deferred_option) {
486 // Don't start up multiple times. 526 // Don't start up multiple times.
487 if (backend_) { 527 if (backend_) {
488 DVLOG(1) << "Skipping bringing up backend host."; 528 DVLOG(1) << "Skipping bringing up backend host.";
489 return; 529 return;
490 } 530 }
491 531
492 DCHECK(IsSyncEnabledAndLoggedIn()); 532 DCHECK(IsSyncEnabledAndLoggedIn());
493 533
534 if (use_oauth2_token_ && access_token_.empty()) {
535 RequestAccessToken();
536 return;
537 }
538
494 if (start_up_time_.is_null()) { 539 if (start_up_time_.is_null()) {
495 start_up_time_ = base::Time::Now(); 540 start_up_time_ = base::Time::Now();
496 last_synced_time_ = sync_prefs_.GetLastSyncedTime(); 541 last_synced_time_ = sync_prefs_.GetLastSyncedTime();
497 542
498 #if defined(OS_CHROMEOS) 543 #if defined(OS_CHROMEOS)
499 std::string bootstrap_token = sync_prefs_.GetEncryptionBootstrapToken(); 544 std::string bootstrap_token = sync_prefs_.GetEncryptionBootstrapToken();
500 if (bootstrap_token.empty()) { 545 if (bootstrap_token.empty()) {
501 sync_prefs_.SetEncryptionBootstrapToken( 546 sync_prefs_.SetEncryptionBootstrapToken(
502 sync_prefs_.GetSpareBootstrapToken()); 547 sync_prefs_.GetSpareBootstrapToken());
503 } 548 }
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
631 // If |backend_| is NULL, save the acknowledgements to replay when 676 // If |backend_| is NULL, save the acknowledgements to replay when
632 // it's created and initialized. 677 // it's created and initialized.
633 ack_replay_queue_.push_back(std::make_pair(id, ack_handle)); 678 ack_replay_queue_.push_back(std::make_pair(id, ack_handle));
634 } 679 }
635 } 680 }
636 681
637 syncer::InvalidatorState ProfileSyncService::GetInvalidatorState() const { 682 syncer::InvalidatorState ProfileSyncService::GetInvalidatorState() const {
638 return invalidator_registrar_->GetInvalidatorState(); 683 return invalidator_registrar_->GetInvalidatorState();
639 } 684 }
640 685
686 void ProfileSyncService::OnGetTokenSuccess(
687 const OAuth2TokenService::Request* request,
688 const std::string& access_token,
689 const base::Time& expiration_time) {
690 DCHECK_EQ(access_token_request_, request);
691 access_token_request_.reset();
692 // Reset backoff time after successful response.
693 request_access_token_backoff_.Reset();
694 access_token_ = access_token;
695 if (backend_)
696 backend_->UpdateCredentials(GetCredentials());
697 else
698 TryStart();
699 }
700
701 void ProfileSyncService::OnGetTokenFailure(
702 const OAuth2TokenService::Request* request,
703 const GoogleServiceAuthError& error) {
704 DCHECK_EQ(access_token_request_, request);
705 DCHECK_NE(error.state(), GoogleServiceAuthError::NONE);
706 access_token_request_.reset();
707 switch (error.state()) {
708 case GoogleServiceAuthError::CONNECTION_FAILED:
709 case GoogleServiceAuthError::SERVICE_UNAVAILABLE: {
710 // Transient error. Retry after some time.
711 request_access_token_backoff_.InformOfRequest(false);
712 request_access_token_retry_timer_.Start(
713 FROM_HERE,
714 request_access_token_backoff_.GetTimeUntilRelease(),
715 base::Bind(&ProfileSyncService::RequestAccessToken,
716 weak_factory_.GetWeakPtr()));
717 break;
718 }
719 case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS: {
720 // Report time since token was issued for invalid credentials error.
721 // TODO(pavely): crbug.com/246817 Collect UMA histogram for auth token
722 // rejections from invalidation service.
723 base::Time auth_token_time =
724 AboutSigninInternalsFactory::GetForProfile(profile_)->
725 GetTokenTime(GaiaConstants::kGaiaOAuth2LoginRefreshToken);
726 if (!auth_token_time.is_null()) {
727 base::TimeDelta age = base::Time::Now() - auth_token_time;
728 if (age < base::TimeDelta::FromHours(1)) {
729 UMA_HISTOGRAM_CUSTOM_TIMES("Sync.AuthServerRejectedTokenAgeShort",
730 age,
731 base::TimeDelta::FromSeconds(1),
732 base::TimeDelta::FromHours(1),
733 50);
734 }
735 UMA_HISTOGRAM_COUNTS("Sync.AuthServerRejectedTokenAgeLong",
736 age.InDays());
737 }
738 // Fallthrough.
739 }
740 default: {
741 // Show error to user.
742 UpdateAuthErrorState(error);
743 }
744 }
745 }
746
641 void ProfileSyncService::EmitInvalidationForTest( 747 void ProfileSyncService::EmitInvalidationForTest(
642 const invalidation::ObjectId& id, 748 const invalidation::ObjectId& id,
643 const std::string& payload) { 749 const std::string& payload) {
644 syncer::ObjectIdSet notify_ids; 750 syncer::ObjectIdSet notify_ids;
645 notify_ids.insert(id); 751 notify_ids.insert(id);
646 752
647 const syncer::ObjectIdInvalidationMap& invalidation_map = 753 const syncer::ObjectIdInvalidationMap& invalidation_map =
648 ObjectIdSetToInvalidationMap(notify_ids, payload); 754 ObjectIdSetToInvalidationMap(notify_ids, payload);
649 OnIncomingInvalidation(invalidation_map); 755 OnIncomingInvalidation(invalidation_map);
650 } 756 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
710 is_auth_in_progress_ = false; 816 is_auth_in_progress_ = false;
711 backend_initialized_ = false; 817 backend_initialized_ = false;
712 // NULL if we're called from Shutdown(). 818 // NULL if we're called from Shutdown().
713 if (invalidator_registrar_) 819 if (invalidator_registrar_)
714 UpdateInvalidatorRegistrarState(); 820 UpdateInvalidatorRegistrarState();
715 cached_passphrase_.clear(); 821 cached_passphrase_.clear();
716 encryption_pending_ = false; 822 encryption_pending_ = false;
717 encrypt_everything_ = false; 823 encrypt_everything_ = false;
718 encrypted_types_ = syncer::SyncEncryptionHandler::SensitiveTypes(); 824 encrypted_types_ = syncer::SyncEncryptionHandler::SensitiveTypes();
719 passphrase_required_reason_ = syncer::REASON_PASSPHRASE_NOT_REQUIRED; 825 passphrase_required_reason_ = syncer::REASON_PASSPHRASE_NOT_REQUIRED;
720 start_up_time_ = base::Time(); 826 request_access_token_retry_timer_.Stop();
721 // Revert to "no auth error". 827 // Revert to "no auth error".
722 if (last_auth_error_.state() != GoogleServiceAuthError::NONE) 828 if (last_auth_error_.state() != GoogleServiceAuthError::NONE)
723 UpdateAuthErrorState(GoogleServiceAuthError::AuthErrorNone()); 829 UpdateAuthErrorState(GoogleServiceAuthError::AuthErrorNone());
724 830
725 if (sync_global_error_) { 831 if (sync_global_error_) {
726 GlobalErrorServiceFactory::GetForProfile(profile_)->RemoveGlobalError( 832 GlobalErrorServiceFactory::GetForProfile(profile_)->RemoveGlobalError(
727 sync_global_error_.get()); 833 sync_global_error_.get());
728 RemoveObserver(sync_global_error_.get()); 834 RemoveObserver(sync_global_error_.get());
729 sync_global_error_.reset(NULL); 835 sync_global_error_.reset(NULL);
730 } 836 }
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after
1060 default: 1166 default:
1061 NOTREACHED(); 1167 NOTREACHED();
1062 return AuthError(AuthError::CONNECTION_FAILED); 1168 return AuthError(AuthError::CONNECTION_FAILED);
1063 } 1169 }
1064 } 1170 }
1065 1171
1066 } // namespace 1172 } // namespace
1067 1173
1068 void ProfileSyncService::OnConnectionStatusChange( 1174 void ProfileSyncService::OnConnectionStatusChange(
1069 syncer::ConnectionStatus status) { 1175 syncer::ConnectionStatus status) {
1070 const GoogleServiceAuthError auth_error = 1176 if (use_oauth2_token_ && status == syncer::CONNECTION_AUTH_ERROR) {
1071 ConnectionStatusToAuthError(status); 1177 // Sync or Tango server returned error indicating that access token is
1072 DVLOG(1) << "Connection status change: " << auth_error.ToString(); 1178 // invalid. It could be either expired or access is revoked. Let's request
1073 UpdateAuthErrorState(auth_error); 1179 // another access token and if access is revoked then request for token will
1180 // fail with corresponding error.
1181 RequestAccessToken();
1182 } else {
1183 const GoogleServiceAuthError auth_error =
1184 ConnectionStatusToAuthError(status);
1185 DVLOG(1) << "Connection status change: " << auth_error.ToString();
1186 UpdateAuthErrorState(auth_error);
1187 }
1074 } 1188 }
1075 1189
1076 void ProfileSyncService::OnStopSyncingPermanently() { 1190 void ProfileSyncService::OnStopSyncingPermanently() {
1077 sync_prefs_.SetStartSuppressed(true); 1191 sync_prefs_.SetStartSuppressed(true);
1078 DisableForUser(); 1192 DisableForUser();
1079 } 1193 }
1080 1194
1081 void ProfileSyncService::OnPassphraseRequired( 1195 void ProfileSyncService::OnPassphraseRequired(
1082 syncer::PassphraseRequiredReason reason, 1196 syncer::PassphraseRequiredReason reason,
1083 const sync_pb::EncryptedData& pending_keys) { 1197 const sync_pb::EncryptedData& pending_keys) {
(...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after
1787 } 1901 }
1788 } 1902 }
1789 1903
1790 // If we get here, we don't have pending keys (or at least, the passphrase 1904 // If we get here, we don't have pending keys (or at least, the passphrase
1791 // doesn't decrypt them) - just try to re-encrypt using the encryption 1905 // doesn't decrypt them) - just try to re-encrypt using the encryption
1792 // passphrase. 1906 // passphrase.
1793 if (!IsUsingSecondaryPassphrase()) 1907 if (!IsUsingSecondaryPassphrase())
1794 SetEncryptionPassphrase(passphrase, IMPLICIT); 1908 SetEncryptionPassphrase(passphrase, IMPLICIT);
1795 } 1909 }
1796 1910
1911 void ProfileSyncService::RequestAccessToken() {
1912 // Only one active request at a time.
1913 if (access_token_request_ != NULL)
1914 return;
1915 request_access_token_retry_timer_.Stop();
1916 OAuth2TokenService::ScopeSet oauth2_scopes;
1917 for (size_t i = 0; i < arraysize(kOAuth2Scopes); i++)
1918 oauth2_scopes.insert(kOAuth2Scopes[i]);
1919 OAuth2TokenService* token_service =
1920 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
1921 // Invalidate previous token, otherwise token service will return the same
1922 // token again.
1923 token_service->InvalidateToken(oauth2_scopes, access_token_);
1924 access_token_.clear();
1925 access_token_request_ = token_service->StartRequest(oauth2_scopes, this);
1926 }
1927
1797 void ProfileSyncService::SetEncryptionPassphrase(const std::string& passphrase, 1928 void ProfileSyncService::SetEncryptionPassphrase(const std::string& passphrase,
1798 PassphraseType type) { 1929 PassphraseType type) {
1799 // This should only be called when the backend has been initialized. 1930 // This should only be called when the backend has been initialized.
1800 DCHECK(sync_initialized()); 1931 DCHECK(sync_initialized());
1801 DCHECK(!(type == IMPLICIT && IsUsingSecondaryPassphrase())) << 1932 DCHECK(!(type == IMPLICIT && IsUsingSecondaryPassphrase())) <<
1802 "Data is already encrypted using an explicit passphrase"; 1933 "Data is already encrypted using an explicit passphrase";
1803 DCHECK(!(type == EXPLICIT && 1934 DCHECK(!(type == EXPLICIT &&
1804 passphrase_required_reason_ == syncer::REASON_DECRYPTION)) << 1935 passphrase_required_reason_ == syncer::REASON_DECRYPTION)) <<
1805 "Can not set explicit passphrase when decryption is needed."; 1936 "Can not set explicit passphrase when decryption is needed.";
1806 1937
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1866 DisableForUser(); 1997 DisableForUser();
1867 } else { 1998 } else {
1868 // Sync is no longer disabled by policy. Try starting it up if appropriate. 1999 // Sync is no longer disabled by policy. Try starting it up if appropriate.
1869 TryStart(); 2000 TryStart();
1870 } 2001 }
1871 } 2002 }
1872 2003
1873 void ProfileSyncService::Observe(int type, 2004 void ProfileSyncService::Observe(int type,
1874 const content::NotificationSource& source, 2005 const content::NotificationSource& source,
1875 const content::NotificationDetails& details) { 2006 const content::NotificationDetails& details) {
2007 const char* sync_token_service = use_oauth2_token_ ?
2008 GaiaConstants::kGaiaOAuth2LoginRefreshToken : GaiaConstants::kSyncService;
1876 switch (type) { 2009 switch (type) {
1877 case chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL: { 2010 case chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL: {
1878 const GoogleServiceSigninSuccessDetails* successful = 2011 const GoogleServiceSigninSuccessDetails* successful =
1879 content::Details<const GoogleServiceSigninSuccessDetails>( 2012 content::Details<const GoogleServiceSigninSuccessDetails>(
1880 details).ptr(); 2013 details).ptr();
1881 if (!sync_prefs_.IsStartSuppressed() && 2014 if (!sync_prefs_.IsStartSuppressed() &&
1882 !successful->password.empty()) { 2015 !successful->password.empty()) {
1883 cached_passphrase_ = successful->password; 2016 cached_passphrase_ = successful->password;
1884 // Try to consume the passphrase we just cached. If the sync backend 2017 // Try to consume the passphrase we just cached. If the sync backend
1885 // is not running yet, the passphrase will remain cached until the 2018 // is not running yet, the passphrase will remain cached until the
1886 // backend starts up. 2019 // backend starts up.
1887 ConsumeCachedPassphraseIfPossible(); 2020 ConsumeCachedPassphraseIfPossible();
1888 } 2021 }
1889 #if defined(OS_CHROMEOS) 2022 #if defined(OS_CHROMEOS)
1890 RefreshSpareBootstrapToken(successful->password); 2023 RefreshSpareBootstrapToken(successful->password);
1891 #endif 2024 #endif
1892 if (!sync_initialized() || 2025 if (!sync_initialized() ||
1893 GetAuthError().state() != AuthError::NONE) { 2026 GetAuthError().state() != AuthError::NONE) {
1894 // Track the fact that we're still waiting for auth to complete. 2027 // Track the fact that we're still waiting for auth to complete.
1895 is_auth_in_progress_ = true; 2028 is_auth_in_progress_ = true;
1896 } 2029 }
1897 break; 2030 break;
1898 } 2031 }
1899 case chrome::NOTIFICATION_TOKEN_REQUEST_FAILED: { 2032 case chrome::NOTIFICATION_TOKEN_REQUEST_FAILED: {
2033 // TODO(atwilson): sync shouldn't report refresh token request failures.
2034 // TokenService should do that instead.
1900 const TokenService::TokenRequestFailedDetails& token_details = 2035 const TokenService::TokenRequestFailedDetails& token_details =
1901 *(content::Details<const TokenService::TokenRequestFailedDetails>( 2036 *(content::Details<const TokenService::TokenRequestFailedDetails>(
1902 details).ptr()); 2037 details).ptr());
1903 if (IsTokenServiceRelevant(token_details.service()) && 2038 if (token_details.service() == sync_token_service &&
1904 !IsSyncTokenAvailable()) { 2039 !IsOAuthRefreshTokenAvailable()) {
1905 // The additional check around IsSyncTokenAvailable() above prevents us 2040 // The additional check around IsOAuthRefreshTokenAvailable() above
1906 // sounding the alarm if we actually have a valid token but a refresh 2041 // prevents us sounding the alarm if we actually have a valid token but
1907 // attempt by TokenService failed for any variety of reasons (e.g. flaky 2042 // a refresh attempt by TokenService failed for any variety of reasons
1908 // network). It's possible the token we do have is also invalid, but in 2043 // (e.g. flaky network). It's possible the token we do have is also
1909 // that case we should already have (or can expect) an auth error sent 2044 // invalid, but in that case we should already have (or can expect) an
1910 // from the sync backend. 2045 // auth error sent from the sync backend.
1911 AuthError error(AuthError::INVALID_GAIA_CREDENTIALS); 2046 AuthError error(AuthError::INVALID_GAIA_CREDENTIALS);
1912 UpdateAuthErrorState(error); 2047 UpdateAuthErrorState(error);
1913 } 2048 }
1914 break; 2049 break;
1915 } 2050 }
1916 case chrome::NOTIFICATION_TOKEN_AVAILABLE: { 2051 case chrome::NOTIFICATION_TOKEN_AVAILABLE: {
2052 // TODO(atwilson): Listen for notifications on OAuth2TokenService
2053 // (crbug.com/243737)
1917 const TokenService::TokenAvailableDetails& token_details = 2054 const TokenService::TokenAvailableDetails& token_details =
1918 *(content::Details<const TokenService::TokenAvailableDetails>( 2055 *(content::Details<const TokenService::TokenAvailableDetails>(
1919 details).ptr()); 2056 details).ptr());
1920 if (!IsTokenServiceRelevant(token_details.service())) 2057 if (token_details.service() != sync_token_service)
1921 break; 2058 break;
1922 } // Fall through. 2059 } // Fall through.
1923 case chrome::NOTIFICATION_TOKEN_LOADING_FINISHED: { 2060 case chrome::NOTIFICATION_TOKEN_LOADING_FINISHED: {
1924 // This notification gets fired when TokenService loads the tokens 2061 // This notification gets fired when TokenService loads the tokens
1925 // from storage. 2062 // from storage.
1926 // Initialize the backend if sync is enabled. If the sync token was 2063 // Initialize the backend if sync is enabled. If the sync token was
1927 // not loaded, GetCredentials() will generate invalid credentials to 2064 // not loaded, GetCredentials() will generate invalid credentials to
1928 // cause the backend to generate an auth error (crbug.com/121755). 2065 // cause the backend to generate an auth error (crbug.com/121755).
1929 if (backend_) 2066 if (backend_) {
1930 backend_->UpdateCredentials(GetCredentials()); 2067 if (use_oauth2_token_)
1931 else 2068 RequestAccessToken();
2069 else
2070 backend_->UpdateCredentials(GetCredentials());
2071 } else {
1932 TryStart(); 2072 TryStart();
2073 }
1933 break; 2074 break;
1934 } 2075 }
1935 case chrome::NOTIFICATION_TOKENS_CLEARED: { 2076 case chrome::NOTIFICATION_TOKENS_CLEARED: {
1936 // GetCredentials() will generate invalid credentials to cause the backend 2077 // GetCredentials() will generate invalid credentials to cause the backend
1937 // to generate an auth error. 2078 // to generate an auth error.
2079 access_token_.clear();
1938 if (backend_) 2080 if (backend_)
1939 backend_->UpdateCredentials(GetCredentials()); 2081 backend_->UpdateCredentials(GetCredentials());
1940 break; 2082 break;
1941 } 2083 }
1942 case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT: 2084 case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT:
1943 sync_disabled_by_admin_ = false; 2085 sync_disabled_by_admin_ = false;
1944 DisableForUser(); 2086 DisableForUser();
1945 break; 2087 break;
1946 default: { 2088 default: {
1947 NOTREACHED(); 2089 NOTREACHED();
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
2064 std::string ProfileSyncService::GetEffectiveUsername() { 2206 std::string ProfileSyncService::GetEffectiveUsername() {
2065 #if defined(ENABLE_MANAGED_USERS) 2207 #if defined(ENABLE_MANAGED_USERS)
2066 if (ManagedUserService::ProfileIsManaged(profile_)) { 2208 if (ManagedUserService::ProfileIsManaged(profile_)) {
2067 DCHECK_EQ(std::string(), signin_->GetAuthenticatedUsername()); 2209 DCHECK_EQ(std::string(), signin_->GetAuthenticatedUsername());
2068 return ManagedUserService::GetManagedUserPseudoEmail(); 2210 return ManagedUserService::GetManagedUserPseudoEmail();
2069 } 2211 }
2070 #endif 2212 #endif
2071 2213
2072 return signin_->GetAuthenticatedUsername(); 2214 return signin_->GetAuthenticatedUsername();
2073 } 2215 }
2074
OLDNEW
« no previous file with comments | « chrome/browser/sync/profile_sync_service.h ('k') | chrome/browser/sync/profile_sync_service_android.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698