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 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 | |
| OLD | NEW |