Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 103 typedef GoogleServiceAuthError AuthError; | 105 typedef GoogleServiceAuthError AuthError; |
| 104 | 106 |
| 105 const char* ProfileSyncService::kSyncServerUrl = | 107 const char* ProfileSyncService::kSyncServerUrl = |
| 106 "https://clients4.google.com/chrome-sync"; | 108 "https://clients4.google.com/chrome-sync"; |
| 107 | 109 |
| 108 const char* ProfileSyncService::kDevServerUrl = | 110 const char* ProfileSyncService::kDevServerUrl = |
| 109 "https://clients4.google.com/chrome-sync/dev"; | 111 "https://clients4.google.com/chrome-sync/dev"; |
| 110 | 112 |
| 111 static const int kSyncClearDataTimeoutInSeconds = 60; // 1 minute. | 113 static const int kSyncClearDataTimeoutInSeconds = 60; // 1 minute. |
| 112 | 114 |
| 113 static const char* kRelevantTokenServices[] = { | 115 static const char* kOAuth2Scopes[] = { |
| 114 GaiaConstants::kSyncService | 116 GaiaConstants::kChromeSyncOAuth2Scope, |
| 117 // GoogleTalk scope is needed for notifications. | |
| 118 GaiaConstants::kGoogleTalkOAuth2Scope | |
| 115 }; | 119 }; |
| 116 static const int kRelevantTokenServicesCount = | 120 |
| 117 arraysize(kRelevantTokenServices); | |
| 118 | 121 |
| 119 static const char* kSyncUnrecoverableErrorHistogram = | 122 static const char* kSyncUnrecoverableErrorHistogram = |
| 120 "Sync.UnrecoverableErrors"; | 123 "Sync.UnrecoverableErrors"; |
| 121 | 124 |
| 122 // Helper to check if the given token service is relevant for sync. | 125 const net::BackoffEntry::Policy kRequestAccessTokenBackoffPolicy = { |
| 123 static bool IsTokenServiceRelevant(const std::string& service) { | 126 // Number of initial errors (in sequence) to ignore before applying |
| 124 for (int i = 0; i < kRelevantTokenServicesCount; ++i) { | 127 // exponential back-off rules. |
| 125 if (service == kRelevantTokenServices[i]) | 128 0, |
| 126 return true; | 129 |
| 127 } | 130 // Initial delay for exponential back-off in ms. |
| 128 return false; | 131 2000, |
| 129 } | 132 |
| 133 // Factor by which the waiting time will be multiplied. | |
| 134 2, | |
| 135 | |
| 136 // Fuzzing percentage. ex: 10% will spread requests randomly | |
| 137 // between 90%-100% of the calculated time. | |
| 138 0, | |
|
Andrew T Wilson (Slow)
2013/06/04 14:37:32
Do we want some kind of fuzzing here? I think the
pavely
2013/06/04 20:11:13
Done.
| |
| 139 | |
| 140 // Maximum amount of time we are willing to delay our request in ms. | |
| 141 1000 * 3600 * 4, // 4 hours. | |
|
Andrew T Wilson (Slow)
2013/06/04 14:37:32
I'm OK with this, but I wonder if maybe we should
pavely
2013/06/04 20:11:13
I put 4 hours here because that's max backoff time
| |
| 142 | |
| 143 // Time to keep an entry from being discarded even when it | |
| 144 // has no significant state, -1 to never discard. | |
| 145 -1, | |
| 146 | |
| 147 // Don't use initial delay unless the last request was an error. | |
| 148 false, | |
| 149 }; | |
| 130 | 150 |
| 131 bool ShouldShowActionOnUI( | 151 bool ShouldShowActionOnUI( |
| 132 const syncer::SyncProtocolError& error) { | 152 const syncer::SyncProtocolError& error) { |
| 133 return (error.action != syncer::UNKNOWN_ACTION && | 153 return (error.action != syncer::UNKNOWN_ACTION && |
| 134 error.action != syncer::DISABLE_SYNC_ON_CLIENT && | 154 error.action != syncer::DISABLE_SYNC_ON_CLIENT && |
| 135 error.action != syncer::STOP_SYNC_FOR_DISABLED_ACCOUNT); | 155 error.action != syncer::STOP_SYNC_FOR_DISABLED_ACCOUNT); |
| 136 } | 156 } |
| 137 | 157 |
| 138 ProfileSyncService::ProfileSyncService(ProfileSyncComponentsFactory* factory, | 158 ProfileSyncService::ProfileSyncService(ProfileSyncComponentsFactory* factory, |
| 139 Profile* profile, | 159 Profile* profile, |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 156 unrecoverable_error_reason_(ERROR_REASON_UNSET), | 176 unrecoverable_error_reason_(ERROR_REASON_UNSET), |
| 157 weak_factory_(this), | 177 weak_factory_(this), |
| 158 expect_sync_configuration_aborted_(false), | 178 expect_sync_configuration_aborted_(false), |
| 159 encrypted_types_(syncer::SyncEncryptionHandler::SensitiveTypes()), | 179 encrypted_types_(syncer::SyncEncryptionHandler::SensitiveTypes()), |
| 160 encrypt_everything_(false), | 180 encrypt_everything_(false), |
| 161 encryption_pending_(false), | 181 encryption_pending_(false), |
| 162 auto_start_enabled_(start_behavior == AUTO_START), | 182 auto_start_enabled_(start_behavior == AUTO_START), |
| 163 failed_datatypes_handler_(this), | 183 failed_datatypes_handler_(this), |
| 164 configure_status_(DataTypeManager::UNKNOWN), | 184 configure_status_(DataTypeManager::UNKNOWN), |
| 165 setup_in_progress_(false), | 185 setup_in_progress_(false), |
| 166 invalidator_state_(syncer::DEFAULT_INVALIDATION_ERROR) { | 186 invalidator_state_(syncer::DEFAULT_INVALIDATION_ERROR), |
| 187 request_access_token_backoff_(&kRequestAccessTokenBackoffPolicy) { | |
| 167 // By default, dev, canary, and unbranded Chromium users will go to the | 188 // By default, dev, canary, and unbranded Chromium users will go to the |
| 168 // development servers. Development servers have more features than standard | 189 // development servers. Development servers have more features than standard |
| 169 // sync servers. Users with officially-branded Chrome stable and beta builds | 190 // sync servers. Users with officially-branded Chrome stable and beta builds |
| 170 // will go to the standard sync servers. | 191 // will go to the standard sync servers. |
| 171 // | 192 // |
| 172 // GetChannel hits the registry on Windows. See http://crbug.com/70380. | 193 // GetChannel hits the registry on Windows. See http://crbug.com/70380. |
| 173 base::ThreadRestrictions::ScopedAllowIO allow_io; | 194 base::ThreadRestrictions::ScopedAllowIO allow_io; |
| 174 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); | 195 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); |
| 175 if (channel == chrome::VersionInfo::CHANNEL_STABLE || | 196 if (channel == chrome::VersionInfo::CHANNEL_STABLE || |
| 176 channel == chrome::VersionInfo::CHANNEL_BETA) { | 197 channel == chrome::VersionInfo::CHANNEL_BETA) { |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 188 | 209 |
| 189 bool ProfileSyncService::IsSyncEnabledAndLoggedIn() { | 210 bool ProfileSyncService::IsSyncEnabledAndLoggedIn() { |
| 190 // Exit if sync is disabled. | 211 // Exit if sync is disabled. |
| 191 if (IsManaged() || sync_prefs_.IsStartSuppressed()) | 212 if (IsManaged() || sync_prefs_.IsStartSuppressed()) |
| 192 return false; | 213 return false; |
| 193 | 214 |
| 194 // Sync is logged in if there is a non-empty effective username. | 215 // Sync is logged in if there is a non-empty effective username. |
| 195 return !GetEffectiveUsername().empty(); | 216 return !GetEffectiveUsername().empty(); |
| 196 } | 217 } |
| 197 | 218 |
| 198 bool ProfileSyncService::IsSyncTokenAvailable() { | 219 bool ProfileSyncService::IsOAuthRefreshTokenAvailable() { |
| 199 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); | 220 ProfileOAuth2TokenService* token_service = |
| 221 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); | |
| 200 if (!token_service) | 222 if (!token_service) |
| 201 return false; | 223 return false; |
| 202 return token_service->HasTokenForService(GaiaConstants::kSyncService); | 224 return token_service->RefreshTokenIsAvailable(); |
| 203 } | 225 } |
| 204 #if defined(OS_ANDROID) | 226 #if defined(OS_ANDROID) |
| 205 bool ProfileSyncService::ShouldEnablePasswordSyncForAndroid() const { | 227 bool ProfileSyncService::ShouldEnablePasswordSyncForAndroid() const { |
| 206 const syncer::ModelTypeSet registered_types = GetRegisteredDataTypes(); | 228 const syncer::ModelTypeSet registered_types = GetRegisteredDataTypes(); |
| 207 const syncer::ModelTypeSet preferred_types = | 229 const syncer::ModelTypeSet preferred_types = |
| 208 sync_prefs_.GetPreferredDataTypes(registered_types); | 230 sync_prefs_.GetPreferredDataTypes(registered_types); |
| 209 if (!preferred_types.Has(syncer::PASSWORDS)) | 231 if (!preferred_types.Has(syncer::PASSWORDS)) |
| 210 return false; | 232 return false; |
| 211 // If backend has not completed initializing we cannot check if the | 233 // If backend has not completed initializing we cannot check if the |
| 212 // cryptographer is ready. | 234 // cryptographer is ready. |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 287 return; | 309 return; |
| 288 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); | 310 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); |
| 289 if (!token_service) | 311 if (!token_service) |
| 290 return; | 312 return; |
| 291 // Don't start the backend if the token service hasn't finished loading tokens | 313 // Don't start the backend if the token service hasn't finished loading tokens |
| 292 // yet. Note if the backend is started before the sync token has been loaded, | 314 // yet. Note if the backend is started before the sync token has been loaded, |
| 293 // GetCredentials() will return bogus credentials. On auto_start platforms | 315 // GetCredentials() will return bogus credentials. On auto_start platforms |
| 294 // (like ChromeOS) we don't start sync until tokens are loaded, because the | 316 // (like ChromeOS) we don't start sync until tokens are loaded, because the |
| 295 // user can be "signed in" on those platforms long before the tokens get | 317 // user can be "signed in" on those platforms long before the tokens get |
| 296 // loaded, and we don't want to generate spurious auth errors. | 318 // loaded, and we don't want to generate spurious auth errors. |
| 297 if (!IsSyncTokenAvailable() && | 319 if (!IsOAuthRefreshTokenAvailable() && |
| 298 !(!auto_start_enabled_ && token_service->TokensLoadedFromDB())) { | 320 !(!auto_start_enabled_ && token_service->TokensLoadedFromDB())) { |
| 299 return; | 321 return; |
| 300 } | 322 } |
| 301 | 323 |
| 324 // If we got here then tokens are loaded and user logged in and sync is | |
| 325 // enabled. If OAuth refresh token is not available then something is wrong. | |
| 326 // When PSS requests access token, OAuth2TokenService will return error and | |
| 327 // PSS will show error to user asking to reauthenticate. | |
| 328 UMA_HISTOGRAM_BOOLEAN("Sync.CredentialsLost", | |
| 329 !IsOAuthRefreshTokenAvailable()); | |
| 330 | |
| 302 // If sync setup has completed we always start the backend. If the user is in | 331 // If sync setup has completed we always start the backend. If the user is in |
| 303 // the process of setting up now, we should start the backend to download | 332 // the process of setting up now, we should start the backend to download |
| 304 // account control state / encryption information). If autostart is enabled, | 333 // account control state / encryption information). If autostart is enabled, |
| 305 // but we haven't completed sync setup, we try to start sync anyway, since | 334 // but we haven't completed sync setup, we try to start sync anyway, since |
| 306 // it's possible we crashed/shutdown after logging in but before the backend | 335 // it's possible we crashed/shutdown after logging in but before the backend |
| 307 // finished initializing the last time. | 336 // finished initializing the last time. |
| 308 // | 337 // |
| 309 // However, the only time we actually need to start sync _immediately_ is if | 338 // However, the only time we actually need to start sync _immediately_ is if |
| 310 // we haven't completed sync setup and the user is in the process of setting | 339 // we haven't completed sync setup and the user is in the process of setting |
| 311 // up - either they just signed in (for the first time) on an auto-start | 340 // up - either they just signed in (for the first time) on an auto-start |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 421 << "is invalid: " << value; | 450 << "is invalid: " << value; |
| 422 } | 451 } |
| 423 } | 452 } |
| 424 } | 453 } |
| 425 } | 454 } |
| 426 | 455 |
| 427 SyncCredentials ProfileSyncService::GetCredentials() { | 456 SyncCredentials ProfileSyncService::GetCredentials() { |
| 428 SyncCredentials credentials; | 457 SyncCredentials credentials; |
| 429 credentials.email = GetEffectiveUsername(); | 458 credentials.email = GetEffectiveUsername(); |
| 430 DCHECK(!credentials.email.empty()); | 459 DCHECK(!credentials.email.empty()); |
| 431 TokenService* service = TokenServiceFactory::GetForProfile(profile_); | 460 if (!access_token_.empty()) { |
| 432 if (service->HasTokenForService(GaiaConstants::kSyncService)) { | 461 credentials.sync_token = access_token_; |
| 433 credentials.sync_token = service->GetTokenForService( | |
| 434 GaiaConstants::kSyncService); | |
| 435 credentials.sync_token_time = | |
| 436 AboutSigninInternalsFactory::GetForProfile(profile_)-> | |
| 437 GetTokenTime(GaiaConstants::kSyncService); | |
| 438 UMA_HISTOGRAM_BOOLEAN("Sync.CredentialsLost", false); | |
| 439 } else { | 462 } else { |
| 440 // We've lost our sync credentials (crbug.com/121755), so just make up some | |
| 441 // invalid credentials so the backend will generate an auth error. | |
| 442 UMA_HISTOGRAM_BOOLEAN("Sync.CredentialsLost", true); | |
| 443 credentials.sync_token = "credentials_lost"; | 463 credentials.sync_token = "credentials_lost"; |
| 444 } | 464 } |
| 445 return credentials; | 465 return credentials; |
| 446 } | 466 } |
| 447 | 467 |
| 448 void ProfileSyncService::InitializeBackend(bool delete_stale_data) { | 468 void ProfileSyncService::InitializeBackend(bool delete_stale_data) { |
| 449 if (!backend_) { | 469 if (!backend_) { |
| 450 NOTREACHED(); | 470 NOTREACHED(); |
| 451 return; | 471 return; |
| 452 } | 472 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 509 | 529 |
| 510 void ProfileSyncService::StartUp(StartUpDeferredOption deferred_option) { | 530 void ProfileSyncService::StartUp(StartUpDeferredOption deferred_option) { |
| 511 // Don't start up multiple times. | 531 // Don't start up multiple times. |
| 512 if (backend_) { | 532 if (backend_) { |
| 513 DVLOG(1) << "Skipping bringing up backend host."; | 533 DVLOG(1) << "Skipping bringing up backend host."; |
| 514 return; | 534 return; |
| 515 } | 535 } |
| 516 | 536 |
| 517 DCHECK(IsSyncEnabledAndLoggedIn()); | 537 DCHECK(IsSyncEnabledAndLoggedIn()); |
| 518 | 538 |
| 539 if (access_token_.empty()) { | |
| 540 RequestAccessToken(); | |
| 541 return; | |
| 542 } | |
| 543 | |
| 519 if (start_up_time_.is_null()) { | 544 if (start_up_time_.is_null()) { |
| 520 start_up_time_ = base::Time::Now(); | 545 start_up_time_ = base::Time::Now(); |
| 521 last_synced_time_ = sync_prefs_.GetLastSyncedTime(); | 546 last_synced_time_ = sync_prefs_.GetLastSyncedTime(); |
| 522 | 547 |
| 523 #if defined(OS_CHROMEOS) | 548 #if defined(OS_CHROMEOS) |
| 524 std::string bootstrap_token = sync_prefs_.GetEncryptionBootstrapToken(); | 549 std::string bootstrap_token = sync_prefs_.GetEncryptionBootstrapToken(); |
| 525 if (bootstrap_token.empty()) { | 550 if (bootstrap_token.empty()) { |
| 526 sync_prefs_.SetEncryptionBootstrapToken( | 551 sync_prefs_.SetEncryptionBootstrapToken( |
| 527 sync_prefs_.GetSpareBootstrapToken()); | 552 sync_prefs_.GetSpareBootstrapToken()); |
| 528 } | 553 } |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 656 // If |backend_| is NULL, save the acknowledgements to replay when | 681 // If |backend_| is NULL, save the acknowledgements to replay when |
| 657 // it's created and initialized. | 682 // it's created and initialized. |
| 658 ack_replay_queue_.push_back(std::make_pair(id, ack_handle)); | 683 ack_replay_queue_.push_back(std::make_pair(id, ack_handle)); |
| 659 } | 684 } |
| 660 } | 685 } |
| 661 | 686 |
| 662 syncer::InvalidatorState ProfileSyncService::GetInvalidatorState() const { | 687 syncer::InvalidatorState ProfileSyncService::GetInvalidatorState() const { |
| 663 return invalidator_registrar_->GetInvalidatorState(); | 688 return invalidator_registrar_->GetInvalidatorState(); |
| 664 } | 689 } |
| 665 | 690 |
| 691 void ProfileSyncService::OnGetTokenSuccess( | |
| 692 const OAuth2TokenService::Request* request, | |
| 693 const std::string& access_token, | |
| 694 const base::Time& expiration_time) { | |
| 695 DCHECK_EQ(access_token_request_, request); | |
| 696 access_token_request_.reset(); | |
| 697 // Reset backoff time after successful response. | |
| 698 request_access_token_backoff_.Reset(); | |
| 699 access_token_ = access_token; | |
| 700 if (backend_) | |
| 701 backend_->UpdateCredentials(GetCredentials()); | |
| 702 else | |
| 703 TryStart(); | |
| 704 } | |
| 705 | |
| 706 void ProfileSyncService::OnGetTokenFailure( | |
| 707 const OAuth2TokenService::Request* request, | |
| 708 const GoogleServiceAuthError& error) { | |
| 709 DCHECK_EQ(access_token_request_, request); | |
| 710 DCHECK_NE(error.state(), GoogleServiceAuthError::NONE); | |
| 711 access_token_request_.reset(); | |
| 712 switch (error.state()) { | |
| 713 case GoogleServiceAuthError::CONNECTION_FAILED: | |
| 714 case GoogleServiceAuthError::SERVICE_UNAVAILABLE: { | |
| 715 // Transient error. Retry after some time. | |
| 716 request_access_token_backoff_.InformOfRequest(false); | |
| 717 request_access_token_retry_timer_.Start( | |
|
Andrew T Wilson (Slow)
2013/06/04 14:37:32
Should we stop this timer if someone else calls Re
pavely
2013/06/04 20:11:13
Done.
| |
| 718 FROM_HERE, | |
| 719 request_access_token_backoff_.GetTimeUntilRelease(), | |
| 720 base::Bind(&ProfileSyncService::RequestAccessToken, | |
| 721 weak_factory_.GetWeakPtr())); | |
| 722 break; | |
| 723 } | |
| 724 default: { | |
| 725 // Report time since token was issued for invalid credentials error. | |
| 726 if (error.state() == GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS) { | |
|
Andrew T Wilson (Slow)
2013/06/04 14:37:32
It's weird to check this here given that we're in
pavely
2013/06/04 20:11:13
Done.
| |
| 727 base::Time auth_token_time = | |
| 728 AboutSigninInternalsFactory::GetForProfile(profile_)-> | |
| 729 GetTokenTime(GaiaConstants::kGaiaOAuth2LoginRefreshToken); | |
| 730 if (!auth_token_time.is_null()) { | |
| 731 base::TimeDelta age = base::Time::Now() - auth_token_time; | |
| 732 if (age < base::TimeDelta::FromHours(1)) { | |
| 733 UMA_HISTOGRAM_CUSTOM_TIMES("Sync.AuthServerRejectedTokenAgeShort", | |
| 734 age, | |
| 735 base::TimeDelta::FromSeconds(1), | |
| 736 base::TimeDelta::FromHours(1), | |
| 737 50); | |
| 738 } | |
| 739 UMA_HISTOGRAM_COUNTS("Sync.AuthServerRejectedTokenAgeLong", | |
| 740 age.InDays()); | |
| 741 } | |
| 742 } | |
| 743 // Show error to user. | |
| 744 UpdateAuthErrorState(error); | |
| 745 } | |
| 746 } | |
| 747 | |
|
Nicolas Zea
2013/06/04 20:13:59
nit: remove newline
| |
| 748 } | |
| 749 | |
| 666 void ProfileSyncService::EmitInvalidationForTest( | 750 void ProfileSyncService::EmitInvalidationForTest( |
| 667 const invalidation::ObjectId& id, | 751 const invalidation::ObjectId& id, |
| 668 const std::string& payload) { | 752 const std::string& payload) { |
| 669 syncer::ObjectIdSet notify_ids; | 753 syncer::ObjectIdSet notify_ids; |
| 670 notify_ids.insert(id); | 754 notify_ids.insert(id); |
| 671 | 755 |
| 672 const syncer::ObjectIdInvalidationMap& invalidation_map = | 756 const syncer::ObjectIdInvalidationMap& invalidation_map = |
| 673 ObjectIdSetToInvalidationMap(notify_ids, payload); | 757 ObjectIdSetToInvalidationMap(notify_ids, payload); |
| 674 OnIncomingInvalidation(invalidation_map); | 758 OnIncomingInvalidation(invalidation_map); |
| 675 } | 759 } |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 735 is_auth_in_progress_ = false; | 819 is_auth_in_progress_ = false; |
| 736 backend_initialized_ = false; | 820 backend_initialized_ = false; |
| 737 // NULL if we're called from Shutdown(). | 821 // NULL if we're called from Shutdown(). |
| 738 if (invalidator_registrar_) | 822 if (invalidator_registrar_) |
| 739 UpdateInvalidatorRegistrarState(); | 823 UpdateInvalidatorRegistrarState(); |
| 740 cached_passphrase_.clear(); | 824 cached_passphrase_.clear(); |
| 741 encryption_pending_ = false; | 825 encryption_pending_ = false; |
| 742 encrypt_everything_ = false; | 826 encrypt_everything_ = false; |
| 743 encrypted_types_ = syncer::SyncEncryptionHandler::SensitiveTypes(); | 827 encrypted_types_ = syncer::SyncEncryptionHandler::SensitiveTypes(); |
| 744 passphrase_required_reason_ = syncer::REASON_PASSPHRASE_NOT_REQUIRED; | 828 passphrase_required_reason_ = syncer::REASON_PASSPHRASE_NOT_REQUIRED; |
| 745 start_up_time_ = base::Time(); | 829 request_access_token_retry_timer_.Stop(); |
| 746 // Revert to "no auth error". | 830 // Revert to "no auth error". |
| 747 if (last_auth_error_.state() != GoogleServiceAuthError::NONE) | 831 if (last_auth_error_.state() != GoogleServiceAuthError::NONE) |
| 748 UpdateAuthErrorState(GoogleServiceAuthError::AuthErrorNone()); | 832 UpdateAuthErrorState(GoogleServiceAuthError::AuthErrorNone()); |
| 749 | 833 |
| 750 if (sync_global_error_) { | 834 if (sync_global_error_) { |
| 751 GlobalErrorServiceFactory::GetForProfile(profile_)->RemoveGlobalError( | 835 GlobalErrorServiceFactory::GetForProfile(profile_)->RemoveGlobalError( |
| 752 sync_global_error_.get()); | 836 sync_global_error_.get()); |
| 753 RemoveObserver(sync_global_error_.get()); | 837 RemoveObserver(sync_global_error_.get()); |
| 754 sync_global_error_.reset(NULL); | 838 sync_global_error_.reset(NULL); |
| 755 } | 839 } |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1082 default: | 1166 default: |
| 1083 NOTREACHED(); | 1167 NOTREACHED(); |
| 1084 return AuthError(AuthError::CONNECTION_FAILED); | 1168 return AuthError(AuthError::CONNECTION_FAILED); |
| 1085 } | 1169 } |
| 1086 } | 1170 } |
| 1087 | 1171 |
| 1088 } // namespace | 1172 } // namespace |
| 1089 | 1173 |
| 1090 void ProfileSyncService::OnConnectionStatusChange( | 1174 void ProfileSyncService::OnConnectionStatusChange( |
| 1091 syncer::ConnectionStatus status) { | 1175 syncer::ConnectionStatus status) { |
| 1092 const GoogleServiceAuthError auth_error = | 1176 if (status == syncer::CONNECTION_AUTH_ERROR) { |
| 1093 ConnectionStatusToAuthError(status); | 1177 // Sync or Tango server returned error indicating that access token is |
| 1094 DVLOG(1) << "Connection status change: " << auth_error.ToString(); | 1178 // invalid. It could be either expired or access is revoked. Let's request |
| 1095 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 } | |
| 1096 } | 1188 } |
| 1097 | 1189 |
| 1098 void ProfileSyncService::OnStopSyncingPermanently() { | 1190 void ProfileSyncService::OnStopSyncingPermanently() { |
| 1099 sync_prefs_.SetStartSuppressed(true); | 1191 sync_prefs_.SetStartSuppressed(true); |
| 1100 DisableForUser(); | 1192 DisableForUser(); |
| 1101 } | 1193 } |
| 1102 | 1194 |
| 1103 void ProfileSyncService::OnPassphraseRequired( | 1195 void ProfileSyncService::OnPassphraseRequired( |
| 1104 syncer::PassphraseRequiredReason reason, | 1196 syncer::PassphraseRequiredReason reason, |
| 1105 const sync_pb::EncryptedData& pending_keys) { | 1197 const sync_pb::EncryptedData& pending_keys) { |
| (...skipping 728 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1834 } | 1926 } |
| 1835 } | 1927 } |
| 1836 | 1928 |
| 1837 // If we get here, we don't have pending keys (or at least, the passphrase | 1929 // If we get here, we don't have pending keys (or at least, the passphrase |
| 1838 // doesn't decrypt them) - just try to re-encrypt using the encryption | 1930 // doesn't decrypt them) - just try to re-encrypt using the encryption |
| 1839 // passphrase. | 1931 // passphrase. |
| 1840 if (!IsUsingSecondaryPassphrase()) | 1932 if (!IsUsingSecondaryPassphrase()) |
| 1841 SetEncryptionPassphrase(passphrase, IMPLICIT); | 1933 SetEncryptionPassphrase(passphrase, IMPLICIT); |
| 1842 } | 1934 } |
| 1843 | 1935 |
| 1936 void ProfileSyncService::RequestAccessToken() { | |
| 1937 // Only one active request at a time. | |
| 1938 if (access_token_request_ != NULL) | |
| 1939 return; | |
| 1940 OAuth2TokenService::ScopeSet oauth2_scopes; | |
| 1941 for (size_t i = 0; i < arraysize(kOAuth2Scopes); i++) | |
| 1942 oauth2_scopes.insert(kOAuth2Scopes[i]); | |
| 1943 OAuth2TokenService* token_service = | |
| 1944 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); | |
| 1945 // Invalidate previous token, otherwise token service will return the same | |
| 1946 // token again. | |
| 1947 token_service->InvalidateToken(oauth2_scopes, access_token_); | |
|
Andrew T Wilson (Slow)
2013/06/04 14:37:32
Should we only do this if access_token_ is non-emp
pavely
2013/06/04 20:11:13
OAuth2TokenService handles this case correctly and
| |
| 1948 access_token_.clear(); | |
| 1949 access_token_request_ = token_service->StartRequest(oauth2_scopes, this); | |
| 1950 } | |
| 1951 | |
| 1844 void ProfileSyncService::SetEncryptionPassphrase(const std::string& passphrase, | 1952 void ProfileSyncService::SetEncryptionPassphrase(const std::string& passphrase, |
| 1845 PassphraseType type) { | 1953 PassphraseType type) { |
| 1846 // This should only be called when the backend has been initialized. | 1954 // This should only be called when the backend has been initialized. |
| 1847 DCHECK(sync_initialized()); | 1955 DCHECK(sync_initialized()); |
| 1848 DCHECK(!(type == IMPLICIT && IsUsingSecondaryPassphrase())) << | 1956 DCHECK(!(type == IMPLICIT && IsUsingSecondaryPassphrase())) << |
| 1849 "Data is already encrypted using an explicit passphrase"; | 1957 "Data is already encrypted using an explicit passphrase"; |
| 1850 DCHECK(!(type == EXPLICIT && | 1958 DCHECK(!(type == EXPLICIT && |
| 1851 passphrase_required_reason_ == syncer::REASON_DECRYPTION)) << | 1959 passphrase_required_reason_ == syncer::REASON_DECRYPTION)) << |
| 1852 "Can not set explicit passphrase when decryption is needed."; | 1960 "Can not set explicit passphrase when decryption is needed."; |
| 1853 | 1961 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1937 RefreshSpareBootstrapToken(successful->password); | 2045 RefreshSpareBootstrapToken(successful->password); |
| 1938 #endif | 2046 #endif |
| 1939 if (!sync_initialized() || | 2047 if (!sync_initialized() || |
| 1940 GetAuthError().state() != AuthError::NONE) { | 2048 GetAuthError().state() != AuthError::NONE) { |
| 1941 // Track the fact that we're still waiting for auth to complete. | 2049 // Track the fact that we're still waiting for auth to complete. |
| 1942 is_auth_in_progress_ = true; | 2050 is_auth_in_progress_ = true; |
| 1943 } | 2051 } |
| 1944 break; | 2052 break; |
| 1945 } | 2053 } |
| 1946 case chrome::NOTIFICATION_TOKEN_REQUEST_FAILED: { | 2054 case chrome::NOTIFICATION_TOKEN_REQUEST_FAILED: { |
| 2055 // TODO(atwilson): sync shouldn't report refresh token request failures. | |
| 2056 // TokenService should do that instead. | |
| 1947 const TokenService::TokenRequestFailedDetails& token_details = | 2057 const TokenService::TokenRequestFailedDetails& token_details = |
| 1948 *(content::Details<const TokenService::TokenRequestFailedDetails>( | 2058 *(content::Details<const TokenService::TokenRequestFailedDetails>( |
| 1949 details).ptr()); | 2059 details).ptr()); |
| 1950 if (IsTokenServiceRelevant(token_details.service()) && | 2060 if (token_details.service() == |
| 1951 !IsSyncTokenAvailable()) { | 2061 GaiaConstants::kGaiaOAuth2LoginRefreshToken && |
| 1952 // The additional check around IsSyncTokenAvailable() above prevents us | 2062 !IsOAuthRefreshTokenAvailable()) { |
| 1953 // sounding the alarm if we actually have a valid token but a refresh | 2063 // The additional check around IsOAuthRefreshTokenAvailable() above |
| 1954 // attempt by TokenService failed for any variety of reasons (e.g. flaky | 2064 // prevents us sounding the alarm if we actually have a valid token but |
| 1955 // network). It's possible the token we do have is also invalid, but in | 2065 // a refresh attempt by TokenService failed for any variety of reasons |
| 1956 // that case we should already have (or can expect) an auth error sent | 2066 // (e.g. flaky network). It's possible the token we do have is also |
| 1957 // from the sync backend. | 2067 // invalid, but in that case we should already have (or can expect) an |
| 2068 // auth error sent from the sync backend. | |
| 1958 AuthError error(AuthError::INVALID_GAIA_CREDENTIALS); | 2069 AuthError error(AuthError::INVALID_GAIA_CREDENTIALS); |
| 1959 UpdateAuthErrorState(error); | 2070 UpdateAuthErrorState(error); |
| 1960 } | 2071 } |
| 1961 break; | 2072 break; |
| 1962 } | 2073 } |
| 1963 case chrome::NOTIFICATION_TOKEN_AVAILABLE: { | 2074 case chrome::NOTIFICATION_TOKEN_AVAILABLE: { |
| 2075 // TODO(atwilson): Listen for notifications on OAuth2TokenService | |
| 2076 // (crbug.com/243737) | |
| 1964 const TokenService::TokenAvailableDetails& token_details = | 2077 const TokenService::TokenAvailableDetails& token_details = |
| 1965 *(content::Details<const TokenService::TokenAvailableDetails>( | 2078 *(content::Details<const TokenService::TokenAvailableDetails>( |
| 1966 details).ptr()); | 2079 details).ptr()); |
| 1967 if (!IsTokenServiceRelevant(token_details.service())) | 2080 if (token_details.service() != |
| 2081 GaiaConstants::kGaiaOAuth2LoginRefreshToken) | |
| 1968 break; | 2082 break; |
| 1969 } // Fall through. | 2083 } // Fall through. |
| 1970 case chrome::NOTIFICATION_TOKEN_LOADING_FINISHED: { | 2084 case chrome::NOTIFICATION_TOKEN_LOADING_FINISHED: { |
| 1971 // This notification gets fired when TokenService loads the tokens | 2085 // This notification gets fired when TokenService loads the tokens |
| 1972 // from storage. | 2086 // from storage. |
| 1973 // Initialize the backend if sync is enabled. If the sync token was | 2087 // Initialize the backend if sync is enabled. If the sync token was |
| 1974 // not loaded, GetCredentials() will generate invalid credentials to | 2088 // not loaded, GetCredentials() will generate invalid credentials to |
| 1975 // cause the backend to generate an auth error (crbug.com/121755). | 2089 // cause the backend to generate an auth error (crbug.com/121755). |
| 1976 if (backend_) | 2090 if (backend_) |
| 1977 backend_->UpdateCredentials(GetCredentials()); | 2091 RequestAccessToken(); |
| 1978 else | 2092 else |
| 1979 TryStart(); | 2093 TryStart(); |
| 1980 break; | 2094 break; |
| 1981 } | 2095 } |
| 1982 case chrome::NOTIFICATION_TOKENS_CLEARED: { | 2096 case chrome::NOTIFICATION_TOKENS_CLEARED: { |
| 1983 // GetCredentials() will generate invalid credentials to cause the backend | 2097 // GetCredentials() will generate invalid credentials to cause the backend |
| 1984 // to generate an auth error. | 2098 // to generate an auth error. |
| 2099 access_token_.clear(); | |
| 1985 if (backend_) | 2100 if (backend_) |
| 1986 backend_->UpdateCredentials(GetCredentials()); | 2101 backend_->UpdateCredentials(GetCredentials()); |
| 1987 break; | 2102 break; |
| 1988 } | 2103 } |
| 1989 case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT: | 2104 case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT: |
| 1990 sync_disabled_by_admin_ = false; | 2105 sync_disabled_by_admin_ = false; |
| 1991 DisableForUser(); | 2106 DisableForUser(); |
| 1992 break; | 2107 break; |
| 1993 default: { | 2108 default: { |
| 1994 NOTREACHED(); | 2109 NOTREACHED(); |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2111 std::string ProfileSyncService::GetEffectiveUsername() { | 2226 std::string ProfileSyncService::GetEffectiveUsername() { |
| 2112 #if defined(ENABLE_MANAGED_USERS) | 2227 #if defined(ENABLE_MANAGED_USERS) |
| 2113 if (ManagedUserService::ProfileIsManaged(profile_)) { | 2228 if (ManagedUserService::ProfileIsManaged(profile_)) { |
| 2114 DCHECK_EQ(std::string(), signin_->GetAuthenticatedUsername()); | 2229 DCHECK_EQ(std::string(), signin_->GetAuthenticatedUsername()); |
| 2115 return ManagedUserService::GetManagedUserPseudoEmail(); | 2230 return ManagedUserService::GetManagedUserPseudoEmail(); |
| 2116 } | 2231 } |
| 2117 #endif | 2232 #endif |
| 2118 | 2233 |
| 2119 return signin_->GetAuthenticatedUsername(); | 2234 return signin_->GetAuthenticatedUsername(); |
| 2120 } | 2235 } |
| 2121 | |
| OLD | NEW |