Upstreaming browser/ui/uikit_ui_util from iOS.
[chromium-blink-merge.git] / ios / chrome / browser / sync / sync_setup_service.cc
blobbc446abf7abc7ab11093885d27866ab442fe45af
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"
7 #include <stdio.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"
18 namespace {
19 // The set of user-selectable datatypes. This must be in the same order as
20 // |SyncSetupService::SyncableDatatype|.
21 syncer::ModelType kDataTypes[] = {
22 syncer::BOOKMARKS,
23 syncer::TYPED_URLS,
24 syncer::PASSWORDS,
25 syncer::PROXY_TABS,
26 syncer::AUTOFILL,
28 } // namespace
30 SyncSetupService::SyncSetupService(sync_driver::SyncService* sync_service,
31 PrefService* prefs)
32 : sync_service_(sync_service), prefs_(prefs) {
33 DCHECK(sync_service_);
34 DCHECK(prefs_);
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,
57 bool enabled) {
58 sync_service_->SetSetupInProgress(true);
59 syncer::ModelTypeSet types = GetDataTypes();
60 if (enabled)
61 types.Put(datatype);
62 else
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)) {
74 return true;
76 switch (this->GetSyncServiceState()) {
77 // No error.
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:
82 return false;
83 // These errors effectively amount to disabled sync and require a signin.
84 case SyncSetupService::kSyncServiceSignInNeedsUpdate:
85 case SyncSetupService::kSyncServiceNeedsPassphrase:
86 case SyncSetupService::kSyncServiceUnrecoverableError:
87 return true;
88 default:
89 NOTREACHED() << "Unknown sync service state.";
90 return true;
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
130 // on about:sync.
131 case GoogleServiceAuthError::CONNECTION_FAILED:
132 case GoogleServiceAuthError::USER_NOT_SIGNED_UP:
133 case GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE:
134 break;
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();
148 break;
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.
160 // OR
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
176 // off.
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(
190 bool sync_enabled) {
191 sync_service_->SetSetupInProgress(true);
192 if (sync_enabled)
193 sync_service_->RequestStart();
194 else
195 sync_service_->RequestStop(sync_driver::SyncService::KEEP_DATA);