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 30 matching lines...) Expand all Loading... | |
| 41 #include "chrome/browser/sync/js/js_event_details.h" | 41 #include "chrome/browser/sync/js/js_event_details.h" |
| 42 #include "chrome/browser/sync/profile_sync_components_factory_impl.h" | 42 #include "chrome/browser/sync/profile_sync_components_factory_impl.h" |
| 43 #include "chrome/browser/sync/sync_global_error.h" | 43 #include "chrome/browser/sync/sync_global_error.h" |
| 44 #include "chrome/browser/sync/util/cryptographer.h" | 44 #include "chrome/browser/sync/util/cryptographer.h" |
| 45 #include "chrome/browser/sync/util/oauth.h" | 45 #include "chrome/browser/sync/util/oauth.h" |
| 46 #include "chrome/browser/ui/browser.h" | 46 #include "chrome/browser/ui/browser.h" |
| 47 #include "chrome/browser/ui/browser_list.h" | 47 #include "chrome/browser/ui/browser_list.h" |
| 48 #include "chrome/browser/ui/browser_window.h" | 48 #include "chrome/browser/ui/browser_window.h" |
| 49 #include "chrome/browser/ui/global_error_service.h" | 49 #include "chrome/browser/ui/global_error_service.h" |
| 50 #include "chrome/browser/ui/global_error_service_factory.h" | 50 #include "chrome/browser/ui/global_error_service_factory.h" |
| 51 #include "chrome/browser/ui/webui/signin/login_ui_service.h" | |
| 52 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" | |
| 51 #include "chrome/common/chrome_notification_types.h" | 53 #include "chrome/common/chrome_notification_types.h" |
| 52 #include "chrome/common/chrome_switches.h" | 54 #include "chrome/common/chrome_switches.h" |
| 53 #include "chrome/common/chrome_version_info.h" | 55 #include "chrome/common/chrome_version_info.h" |
| 54 #include "chrome/common/net/gaia/gaia_constants.h" | 56 #include "chrome/common/net/gaia/gaia_constants.h" |
| 55 #include "chrome/common/time_format.h" | 57 #include "chrome/common/time_format.h" |
| 56 #include "chrome/common/url_constants.h" | 58 #include "chrome/common/url_constants.h" |
| 57 #include "content/public/browser/notification_details.h" | 59 #include "content/public/browser/notification_details.h" |
| 58 #include "content/public/browser/notification_source.h" | 60 #include "content/public/browser/notification_source.h" |
| 59 #include "grit/generated_resources.h" | 61 #include "grit/generated_resources.h" |
| 60 #include "net/base/cookie_monster.h" | 62 #include "net/base/cookie_monster.h" |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 150 bool ProfileSyncService::AreCredentialsAvailable() { | 152 bool ProfileSyncService::AreCredentialsAvailable() { |
| 151 return AreCredentialsAvailable(false); | 153 return AreCredentialsAvailable(false); |
| 152 } | 154 } |
| 153 | 155 |
| 154 bool ProfileSyncService::AreCredentialsAvailable( | 156 bool ProfileSyncService::AreCredentialsAvailable( |
| 155 bool check_oauth_login_token) { | 157 bool check_oauth_login_token) { |
| 156 if (IsManaged()) { | 158 if (IsManaged()) { |
| 157 return false; | 159 return false; |
| 158 } | 160 } |
| 159 | 161 |
| 162 // If we have start suppressed, then basically just act like we have no | |
| 163 // credentials (login is required to fix this, since we need the user's | |
| 164 // passphrase to encrypt/decrypt anyway). | |
| 165 // TODO(sync): Revisit this when we move to a server-based keystore. | |
| 166 if (sync_prefs_.IsStartSuppressed()) | |
| 167 return false; | |
| 168 | |
| 160 // CrOS user is always logged in. Chrome uses signin_ to check logged in. | 169 // CrOS user is always logged in. Chrome uses signin_ to check logged in. |
| 161 if (signin_->GetAuthenticatedUsername().empty()) | 170 if (signin_->GetAuthenticatedUsername().empty()) |
| 162 return false; | 171 return false; |
| 163 | 172 |
| 164 TokenService* token_service = profile()->GetTokenService(); | 173 TokenService* token_service = profile()->GetTokenService(); |
| 165 if (!token_service) | 174 if (!token_service) |
| 166 return false; | 175 return false; |
| 167 | 176 |
| 168 // TODO(chron): Verify CrOS unit test behavior. | 177 // TODO(chron): Verify CrOS unit test behavior. |
| 169 if (!token_service->HasTokenForService(browser_sync::SyncServiceName())) | 178 if (!token_service->HasTokenForService(browser_sync::SyncServiceName())) |
| (...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 711 if (!to_register.Empty() && HasSyncSetupCompleted() && migrator_.get()) { | 720 if (!to_register.Empty() && HasSyncSetupCompleted() && migrator_.get()) { |
| 712 DVLOG(1) << "Dynamically enabling new datatypes: " | 721 DVLOG(1) << "Dynamically enabling new datatypes: " |
| 713 << syncable::ModelTypeSetToString(to_register); | 722 << syncable::ModelTypeSetToString(to_register); |
| 714 OnMigrationNeededForTypes(to_register); | 723 OnMigrationNeededForTypes(to_register); |
| 715 } | 724 } |
| 716 } | 725 } |
| 717 } | 726 } |
| 718 | 727 |
| 719 void ProfileSyncService::UpdateAuthErrorState( | 728 void ProfileSyncService::UpdateAuthErrorState( |
| 720 const GoogleServiceAuthError& error) { | 729 const GoogleServiceAuthError& error) { |
| 730 is_auth_in_progress_ = false; | |
| 721 last_auth_error_ = error; | 731 last_auth_error_ = error; |
| 722 // Protect against the in-your-face dialogs that pop out of nowhere. | |
| 723 // Require the user to click somewhere to run the setup wizard in the case | |
| 724 // of a steady-state auth failure. | |
| 725 if (WizardIsVisible()) { | |
| 726 wizard_.Step(last_auth_error_.state() == AuthError::NONE ? | |
| 727 SyncSetupWizard::GAIA_SUCCESS : SyncSetupWizard::GetLoginState()); | |
| 728 } else { | |
| 729 auth_error_time_ = base::TimeTicks::Now(); | |
| 730 } | |
| 731 | 732 |
| 732 if (!auth_start_time_.is_null()) { | 733 if (WizardIsVisible() && last_auth_error_.state() != AuthError::NONE) { |
| 733 UMA_HISTOGRAM_TIMES("Sync.AuthorizationTimeInNetwork", | 734 // Got some kind of auth error while the wizard is visible. Exit out of |
|
tim (not reviewing)
2012/02/14 02:11:21
err... why is this fatal? what happens to any com
Andrew T Wilson (Slow)
2012/02/14 05:23:52
Remember that this is dealing with a GAIA error *a
| |
| 734 base::TimeTicks::Now() - auth_start_time_); | 735 // the config flow (UI handler can notify the user or bring up the signin |
| 735 auth_start_time_ = base::TimeTicks(); | 736 // flow as appropriate). |
| 737 wizard_.Step(SyncSetupWizard::FATAL_ERROR); | |
| 736 } | 738 } |
| 737 | 739 |
| 738 // Fan the notification out to interested UI-thread components. | 740 // Fan the notification out to interested UI-thread components. |
| 739 NotifyObservers(); | 741 NotifyObservers(); |
| 740 } | 742 } |
| 741 | 743 |
| 742 void ProfileSyncService::OnAuthError() { | 744 void ProfileSyncService::OnAuthError() { |
| 743 UpdateAuthErrorState(backend_->GetAuthError()); | 745 UpdateAuthErrorState(backend_->GetAuthError()); |
| 744 } | 746 } |
| 745 | 747 |
| 746 void ProfileSyncService::OnStopSyncingPermanently() { | 748 void ProfileSyncService::OnStopSyncingPermanently() { |
| 749 UpdateAuthErrorState( | |
| 750 GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE)); | |
| 751 | |
| 747 if (SetupInProgress()) { | 752 if (SetupInProgress()) { |
|
Andrew T Wilson (Slow)
2012/02/14 05:23:52
BTW, I'm changing this to abort whenever the wizar
| |
| 748 wizard_.Step(SyncSetupWizard::SETUP_ABORTED_BY_PENDING_CLEAR); | 753 wizard_.Step(SyncSetupWizard::ABORT); |
| 749 expect_sync_configuration_aborted_ = true; | 754 expect_sync_configuration_aborted_ = true; |
| 750 } | 755 } |
| 751 sync_prefs_.SetStartSuppressed(true); | 756 sync_prefs_.SetStartSuppressed(true); |
| 752 DisableForUser(); | 757 DisableForUser(); |
| 753 } | 758 } |
| 754 | 759 |
| 755 void ProfileSyncService::OnClearServerDataTimeout() { | 760 void ProfileSyncService::OnClearServerDataTimeout() { |
| 756 if (clear_server_data_state_ != CLEAR_SUCCEEDED && | 761 if (clear_server_data_state_ != CLEAR_SUCCEEDED && |
| 757 clear_server_data_state_ != CLEAR_FAILED) { | 762 clear_server_data_state_ != CLEAR_FAILED) { |
| 758 clear_server_data_state_ = CLEAR_FAILED; | 763 clear_server_data_state_ = CLEAR_FAILED; |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 938 case browser_sync::DISABLE_SYNC_ON_CLIENT: | 943 case browser_sync::DISABLE_SYNC_ON_CLIENT: |
| 939 OnStopSyncingPermanently(); | 944 OnStopSyncingPermanently(); |
| 940 break; | 945 break; |
| 941 default: | 946 default: |
| 942 NOTREACHED(); | 947 NOTREACHED(); |
| 943 } | 948 } |
| 944 NotifyObservers(); | 949 NotifyObservers(); |
| 945 } | 950 } |
| 946 | 951 |
| 947 void ProfileSyncService::ShowLoginDialog() { | 952 void ProfileSyncService::ShowLoginDialog() { |
| 948 if (WizardIsVisible()) { | 953 // TODO(atwilson): Remove this API and have the callers directly call |
| 949 wizard_.Focus(); | 954 // LoginUIService. |
| 950 // Force the wizard to step to the login screen (which will only actually | 955 LoginUIServiceFactory::GetForProfile(profile_)->ShowLoginUI(); |
| 951 // happen if the transition is valid). | |
| 952 wizard_.Step(SyncSetupWizard::GetLoginState()); | |
| 953 return; | |
| 954 } | |
| 955 | |
| 956 if (!auth_error_time_.is_null()) { | |
| 957 UMA_HISTOGRAM_LONG_TIMES("Sync.ReauthorizationTime", | |
| 958 base::TimeTicks::Now() - auth_error_time_); | |
| 959 auth_error_time_ = base::TimeTicks(); // Reset auth_error_time_ to null. | |
| 960 } | |
| 961 | |
| 962 ShowSyncSetupWithWizard(SyncSetupWizard::GetLoginState()); | |
| 963 | |
| 964 NotifyObservers(); | |
| 965 } | 956 } |
| 966 | 957 |
| 967 void ProfileSyncService::ShowErrorUI() { | 958 void ProfileSyncService::ShowErrorUI() { |
| 968 if (WizardIsVisible()) { | 959 if (WizardIsVisible()) { |
| 969 wizard_.Focus(); | 960 wizard_.Focus(); |
| 970 return; | 961 return; |
| 971 } | 962 } |
| 972 | 963 |
| 973 if (last_auth_error_.state() != AuthError::NONE) | 964 // Figure out what kind of error we've encountered. There are only 3 kinds: |
| 965 // 1) auth error. | |
| 966 // 2) server-initiated error | |
| 967 // 3) passphrase error | |
| 968 // Any other errors (such as unrecoverable error) should be handled by the UI | |
| 969 // itself and should not result in a call to ShowErrorUI. | |
|
tim (not reviewing)
2012/02/14 02:11:21
hm. so what about a failure to initialize / load t
Andrew T Wilson (Slow)
2012/02/14 05:23:52
This change just makes explicit what was previousl
| |
| 970 if (last_auth_error_.state() != AuthError::NONE) { | |
| 974 ShowLoginDialog(); | 971 ShowLoginDialog(); |
| 975 else if (ShouldShowActionOnUI(last_actionable_error_)) | 972 } else if (ShouldShowActionOnUI(last_actionable_error_)) { |
| 976 ShowSyncSetup(chrome::kPersonalOptionsSubPage); | 973 ShowSyncSetup(chrome::kPersonalOptionsSubPage); |
| 977 else | 974 } else { |
| 978 ShowSyncSetupWithWizard(SyncSetupWizard::NONFATAL_ERROR); | 975 // We should only get here for passphrase error. |
| 976 DCHECK(IsPassphraseRequired()); | |
| 977 ShowSyncSetupWithWizard(SyncSetupWizard::ENTER_PASSPHRASE); | |
| 978 } | |
| 979 } | 979 } |
| 980 | 980 |
| 981 void ProfileSyncService::ShowConfigure(bool sync_everything) { | 981 void ProfileSyncService::ShowConfigure(bool sync_everything) { |
| 982 if (!sync_initialized()) { | 982 if (!sync_initialized()) { |
| 983 LOG(ERROR) << "Attempted to show sync configure before backend ready."; | 983 LOG(ERROR) << "Attempted to show sync configure before backend ready."; |
| 984 return; | 984 return; |
| 985 } | 985 } |
| 986 if (WizardIsVisible()) { | 986 if (WizardIsVisible()) { |
| 987 wizard_.Focus(); | 987 wizard_.Focus(); |
| 988 return; | 988 return; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1054 | 1054 |
| 1055 bool ProfileSyncService::sync_initialized() const { | 1055 bool ProfileSyncService::sync_initialized() const { |
| 1056 return backend_initialized_; | 1056 return backend_initialized_; |
| 1057 } | 1057 } |
| 1058 | 1058 |
| 1059 bool ProfileSyncService::unrecoverable_error_detected() const { | 1059 bool ProfileSyncService::unrecoverable_error_detected() const { |
| 1060 return unrecoverable_error_detected_; | 1060 return unrecoverable_error_detected_; |
| 1061 } | 1061 } |
| 1062 | 1062 |
| 1063 bool ProfileSyncService::UIShouldDepictAuthInProgress() const { | 1063 bool ProfileSyncService::UIShouldDepictAuthInProgress() const { |
| 1064 return is_auth_in_progress_; | 1064 return signin()->AuthInProgress(); |
| 1065 } | |
| 1066 | |
| 1067 void ProfileSyncService::SetUIShouldDepictAuthInProgress( | |
| 1068 bool auth_in_progress) { | |
| 1069 is_auth_in_progress_ = auth_in_progress; | |
| 1070 // TODO(atwilson): Figure out if we still need to track this or if we should | |
| 1071 // move this up to the UI (or break it out into two stats that track GAIA | |
| 1072 // auth and sync auth separately). | |
| 1073 if (is_auth_in_progress_) | |
| 1074 auth_start_time_ = base::TimeTicks::Now(); | |
| 1075 NotifyObservers(); | |
| 1076 } | 1065 } |
| 1077 | 1066 |
| 1078 bool ProfileSyncService::IsPassphraseRequired() const { | 1067 bool ProfileSyncService::IsPassphraseRequired() const { |
| 1079 return passphrase_required_reason_ != | 1068 return passphrase_required_reason_ != |
| 1080 sync_api::REASON_PASSPHRASE_NOT_REQUIRED; | 1069 sync_api::REASON_PASSPHRASE_NOT_REQUIRED; |
| 1081 } | 1070 } |
| 1082 | 1071 |
| 1083 // TODO(zea): Rename this IsPassphraseNeededFromUI and ensure it's used | 1072 // TODO(zea): Rename this IsPassphraseNeededFromUI and ensure it's used |
| 1084 // appropriately (see http://crbug.com/91379). | 1073 // appropriately (see http://crbug.com/91379). |
| 1085 bool ProfileSyncService::IsPassphraseRequiredForDecryption() const { | 1074 bool ProfileSyncService::IsPassphraseRequiredForDecryption() const { |
| (...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1442 *(content::Details<const GoogleServiceAuthError>(details).ptr()); | 1431 *(content::Details<const GoogleServiceAuthError>(details).ptr()); |
| 1443 UpdateAuthErrorState(error); | 1432 UpdateAuthErrorState(error); |
| 1444 break; | 1433 break; |
| 1445 } | 1434 } |
| 1446 case chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL: { | 1435 case chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL: { |
| 1447 const GoogleServiceSigninSuccessDetails* successful = | 1436 const GoogleServiceSigninSuccessDetails* successful = |
| 1448 content::Details<const GoogleServiceSigninSuccessDetails>( | 1437 content::Details<const GoogleServiceSigninSuccessDetails>( |
| 1449 details).ptr(); | 1438 details).ptr(); |
| 1450 // The user has submitted credentials, which indicates they don't | 1439 // The user has submitted credentials, which indicates they don't |
| 1451 // want to suppress start up anymore. | 1440 // want to suppress start up anymore. |
| 1441 // TODO(sync): Remove this when sync is no longer tied to browser signin. | |
|
tim (not reviewing)
2012/02/14 02:11:21
should tie this to a bug (and mention in the bug t
Andrew T Wilson (Slow)
2012/02/14 05:23:52
Done.
| |
| 1452 sync_prefs_.SetStartSuppressed(false); | 1442 sync_prefs_.SetStartSuppressed(false); |
| 1453 | 1443 |
| 1454 // Because we specify IMPLICIT to SetPassphrase, we know it won't override | 1444 // Because we specify IMPLICIT to SetPassphrase, we know it won't override |
| 1455 // an explicit one. Thus, we either update the implicit passphrase | 1445 // an explicit one. Thus, we either update the implicit passphrase |
| 1456 // (idempotent if the passphrase didn't actually change), or the user has | 1446 // (idempotent if the passphrase didn't actually change), or the user has |
| 1457 // an explicit passphrase set so this becomes a no-op. | 1447 // an explicit passphrase set so this becomes a no-op. |
| 1458 if (!successful->password.empty()) | 1448 if (!successful->password.empty()) |
| 1459 SetPassphrase(successful->password, IMPLICIT, INTERNAL); | 1449 SetPassphrase(successful->password, IMPLICIT, INTERNAL); |
| 1450 | |
| 1451 if (!sync_initialized() || | |
|
tim (not reviewing)
2012/02/14 02:11:21
Hm, so there's no way we can call UpdateAuthErrorS
Andrew T Wilson (Slow)
2012/02/14 05:23:52
We aren't actually changing the state - all we're
| |
| 1452 GetAuthError().state() != GoogleServiceAuthError::NONE) { | |
| 1453 // Track the fact that we're still waiting for auth to complete. | |
| 1454 is_auth_in_progress_ = true; | |
| 1455 } | |
| 1460 break; | 1456 break; |
| 1461 } | 1457 } |
| 1462 case chrome::NOTIFICATION_TOKEN_REQUEST_FAILED: { | 1458 case chrome::NOTIFICATION_TOKEN_REQUEST_FAILED: { |
| 1463 const TokenService::TokenRequestFailedDetails& token_details = | 1459 const TokenService::TokenRequestFailedDetails& token_details = |
| 1464 *(content::Details<const TokenService::TokenRequestFailedDetails>( | 1460 *(content::Details<const TokenService::TokenRequestFailedDetails>( |
| 1465 details).ptr()); | 1461 details).ptr()); |
| 1466 if (IsTokenServiceRelevant(token_details.service())) { | 1462 if (IsTokenServiceRelevant(token_details.service())) { |
| 1467 GoogleServiceAuthError error( | 1463 GoogleServiceAuthError error( |
| 1468 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); | 1464 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); |
| 1469 UpdateAuthErrorState(error); | 1465 UpdateAuthErrorState(error); |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1611 << "Unrecoverable error."; | 1607 << "Unrecoverable error."; |
| 1612 } else { | 1608 } else { |
| 1613 DVLOG(0) << "ConfigureDataTypeManager not invoked because backend is not " | 1609 DVLOG(0) << "ConfigureDataTypeManager not invoked because backend is not " |
| 1614 << "initialized"; | 1610 << "initialized"; |
| 1615 } | 1611 } |
| 1616 } | 1612 } |
| 1617 | 1613 |
| 1618 const FailedDatatypesHandler& ProfileSyncService::failed_datatypes_handler() { | 1614 const FailedDatatypesHandler& ProfileSyncService::failed_datatypes_handler() { |
| 1619 return failed_datatypes_handler_; | 1615 return failed_datatypes_handler_; |
| 1620 } | 1616 } |
| OLD | NEW |