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