1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ios/chrome/browser/sync/sync_setup_service.h"
9 #include "base/prefs/pref_service.h"
10 #include "components/sync_driver/sync_prefs.h"
11 #include "components/sync_driver/sync_service.h"
12 #include "google_apis/gaia/google_service_auth_error.h"
13 #include "ios/chrome/browser/pref_names.h"
14 #include "ios/public/provider/chrome/browser/browser_state/chrome_browser_state.h"
15 #include "net/base/network_change_notifier.h"
16 #include "sync/protocol/sync_protocol_error.h"
19 // The set of user-selectable datatypes. This must be in the same order as
20 // |SyncSetupService::SyncableDatatype|.
21 syncer::ModelType kDataTypes
[] = {
30 SyncSetupService::SyncSetupService(sync_driver::SyncService
* sync_service
,
32 : sync_service_(sync_service
), prefs_(prefs
) {
33 DCHECK(sync_service_
);
35 for (unsigned int i
= 0; i
< arraysize(kDataTypes
); ++i
) {
36 user_selectable_types_
.Put(kDataTypes
[i
]);
40 SyncSetupService::~SyncSetupService() {
43 syncer::ModelType
SyncSetupService::GetModelType(SyncableDatatype datatype
) {
44 DCHECK(datatype
< arraysize(kDataTypes
));
45 return kDataTypes
[datatype
];
48 syncer::ModelTypeSet
SyncSetupService::GetDataTypes() const {
49 return sync_service_
->GetPreferredDataTypes();
52 bool SyncSetupService::IsDataTypeEnabled(syncer::ModelType datatype
) const {
53 return GetDataTypes().Has(datatype
);
56 void SyncSetupService::SetDataTypeEnabled(syncer::ModelType datatype
,
58 sync_service_
->SetSetupInProgress(true);
59 syncer::ModelTypeSet types
= GetDataTypes();
63 types
.Remove(datatype
);
64 types
.RetainAll(user_selectable_types_
);
65 if (enabled
&& !IsSyncEnabled())
66 SetSyncEnabledWithoutChangingDatatypes(true);
67 sync_service_
->OnUserChoseDatatypes(IsSyncingAllDataTypes(), types
);
68 if (GetDataTypes().Empty())
69 SetSyncEnabled(false);
72 bool SyncSetupService::UserActionIsRequiredToHaveSyncWork() {
73 if (!IsSyncEnabled() || !IsDataTypeEnabled(syncer::PROXY_TABS
)) {
76 switch (this->GetSyncServiceState()) {
78 case SyncSetupService::kNoSyncServiceError
:
79 // These errors are transient and don't mean that sync is off.
80 case SyncSetupService::kSyncServiceCouldNotConnect
:
81 case SyncSetupService::kSyncServiceServiceUnavailable
:
83 // These errors effectively amount to disabled sync and require a signin.
84 case SyncSetupService::kSyncServiceSignInNeedsUpdate
:
85 case SyncSetupService::kSyncServiceNeedsPassphrase
:
86 case SyncSetupService::kSyncServiceUnrecoverableError
:
89 NOTREACHED() << "Unknown sync service state.";
94 bool SyncSetupService::IsSyncingAllDataTypes() const {
95 sync_driver::SyncPrefs
sync_prefs(prefs_
);
96 return sync_prefs
.HasKeepEverythingSynced();
99 void SyncSetupService::SetSyncingAllDataTypes(bool sync_all
) {
100 sync_service_
->SetSetupInProgress(true);
101 if (sync_all
&& !IsSyncEnabled())
102 SetSyncEnabled(true);
103 sync_service_
->OnUserChoseDatatypes(sync_all
, GetDataTypes());
106 bool SyncSetupService::IsSyncEnabled() const {
107 return sync_service_
->CanSyncStart();
110 void SyncSetupService::SetSyncEnabled(bool sync_enabled
) {
111 SetSyncEnabledWithoutChangingDatatypes(sync_enabled
);
112 if (sync_enabled
&& GetDataTypes().Empty())
113 SetSyncingAllDataTypes(true);
116 SyncSetupService::SyncServiceState
SyncSetupService::GetSyncServiceState() {
117 switch (sync_service_
->GetAuthError().state()) {
118 case GoogleServiceAuthError::REQUEST_CANCELED
:
119 return kSyncServiceCouldNotConnect
;
120 // Based on sync_ui_util::GetStatusLabelsForAuthError, SERVICE_UNAVAILABLE
121 // corresponds to sync having been disabled for the user's domain.
122 case GoogleServiceAuthError::SERVICE_UNAVAILABLE
:
123 return kSyncServiceServiceUnavailable
;
124 case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS
:
125 return kSyncServiceSignInNeedsUpdate
;
126 // The following errors are not shown to the user.
127 case GoogleServiceAuthError::NONE
:
128 // Connection failed is not shown to the user, as this will happen if the
129 // service retuned a 500 error. A more detail error can always be checked
131 case GoogleServiceAuthError::CONNECTION_FAILED
:
132 case GoogleServiceAuthError::USER_NOT_SIGNED_UP
:
133 case GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE
:
135 // The following errors are unexpected on iOS.
136 case GoogleServiceAuthError::CAPTCHA_REQUIRED
:
137 case GoogleServiceAuthError::ACCOUNT_DELETED
:
138 case GoogleServiceAuthError::ACCOUNT_DISABLED
:
139 case GoogleServiceAuthError::TWO_FACTOR
:
140 case GoogleServiceAuthError::HOSTED_NOT_ALLOWED
:
141 case GoogleServiceAuthError::SERVICE_ERROR
:
142 case GoogleServiceAuthError::WEB_LOGIN_REQUIRED
:
143 // Conventional value for counting the states, never used.
144 case GoogleServiceAuthError::NUM_STATES
:
145 NOTREACHED() << "Unexpected Auth error ("
146 << sync_service_
->GetAuthError().state()
147 << "): " << sync_service_
->GetAuthError().error_message();
150 if (sync_service_
->HasUnrecoverableError())
151 return kSyncServiceUnrecoverableError
;
152 if (sync_service_
->IsPassphraseRequiredForDecryption())
153 return kSyncServiceNeedsPassphrase
;
154 return kNoSyncServiceError
;
157 bool SyncSetupService::HasFinishedInitialSetup() {
158 // Sync initial setup is considered to finished iff:
159 // 1. User is signed in with sync enabled and the sync setup was completed.
161 // 2. User is not signed in or has disabled sync.
162 return !sync_service_
->CanSyncStart() ||
163 sync_service_
->HasSyncSetupCompleted();
166 void SyncSetupService::PrepareForFirstSyncSetup() {
167 // |PrepareForFirstSyncSetup| should always be called while the user is signed
168 // out. At that time, sync setup is not completed.
169 DCHECK(!sync_service_
->HasSyncSetupCompleted());
170 sync_service_
->SetSetupInProgress(true);
173 void SyncSetupService::CommitChanges() {
174 if (sync_service_
->FirstSetupInProgress()) {
175 // Turn on the sync setup completed flag only if the user did not turn sync
177 if (sync_service_
->CanSyncStart()) {
178 sync_service_
->SetSyncSetupCompleted();
182 sync_service_
->SetSetupInProgress(false);
185 bool SyncSetupService::HasUncommittedChanges() {
186 return sync_service_
->setup_in_progress();
189 void SyncSetupService::SetSyncEnabledWithoutChangingDatatypes(
191 sync_service_
->SetSetupInProgress(true);
193 sync_service_
->RequestStart();
195 sync_service_
->RequestStop(sync_driver::SyncService::KEEP_DATA
);