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
3 // found in the LICENSE file.
4
5 #include "components/sync_driver/sync_prefs.h"
6
7 #include "base/command_line.h"
8 #include "base/logging.h"
9 #include "base/prefs/pref_member.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/values.h"
13 #include "build/build_config.h"
14 #include "components/pref_registry/pref_registry_syncable.h"
15 #include "components/sync_driver/pref_names.h"
16
17 namespace sync_driver {
18
~SyncPrefObserver()19 SyncPrefObserver::~SyncPrefObserver() {}
20
SyncPrefs(PrefService * pref_service)21 SyncPrefs::SyncPrefs(PrefService* pref_service) : pref_service_(pref_service) {
22 DCHECK(pref_service);
23 RegisterPrefGroups();
24 // Watch the preference that indicates sync is managed so we can take
25 // appropriate action.
26 pref_sync_managed_.Init(
27 prefs::kSyncManaged,
28 pref_service_,
29 base::Bind(&SyncPrefs::OnSyncManagedPrefChanged, base::Unretained(this)));
30 }
31
SyncPrefs()32 SyncPrefs::SyncPrefs() : pref_service_(NULL) {}
33
~SyncPrefs()34 SyncPrefs::~SyncPrefs() { DCHECK(CalledOnValidThread()); }
35
36 // static
RegisterProfilePrefs(user_prefs::PrefRegistrySyncable * registry)37 void SyncPrefs::RegisterProfilePrefs(
38 user_prefs::PrefRegistrySyncable* registry) {
39 registry->RegisterBooleanPref(
40 prefs::kSyncHasSetupCompleted,
41 false,
42 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
43 registry->RegisterBooleanPref(
44 prefs::kSyncSuppressStart,
45 false,
46 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
47 registry->RegisterInt64Pref(
48 prefs::kSyncLastSyncedTime,
49 0,
50 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
51 registry->RegisterInt64Pref(
52 prefs::kSyncFirstSyncTime,
53 0,
54 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
55
56 // All datatypes are on by default, but this gets set explicitly
57 // when you configure sync (when turning it on), in
58 // ProfileSyncService::OnUserChoseDatatypes.
59 registry->RegisterBooleanPref(
60 prefs::kSyncKeepEverythingSynced,
61 true,
62 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
63
64 syncer::ModelTypeSet user_types = syncer::UserTypes();
65
66 // Include proxy types as well, as they can be individually selected,
67 // although they don't have sync representations.
68 user_types.PutAll(syncer::ProxyTypes());
69
70 // Treat bookmarks specially.
71 RegisterDataTypePreferredPref(registry, syncer::BOOKMARKS, true);
72 user_types.Remove(syncer::BOOKMARKS);
73
74 // These two prefs are set from sync experiment to enable enhanced bookmarks.
75 registry->RegisterIntegerPref(
76 prefs::kEnhancedBookmarksExperimentEnabled,
77 0,
78 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
79
80 registry->RegisterStringPref(
81 prefs::kEnhancedBookmarksExtensionId,
82 std::string(),
83 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
84
85 // All types are set to off by default, which forces a configuration to
86 // explicitly enable them. GetPreferredTypes() will ensure that any new
87 // implicit types are enabled when their pref group is, or via
88 // KeepEverythingSynced.
89 for (syncer::ModelTypeSet::Iterator it = user_types.First(); it.Good();
90 it.Inc()) {
91 RegisterDataTypePreferredPref(registry, it.Get(), false);
92 }
93
94 registry->RegisterBooleanPref(
95 prefs::kSyncManaged,
96 false,
97 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
98 registry->RegisterStringPref(
99 prefs::kSyncEncryptionBootstrapToken,
100 std::string(),
101 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
102 registry->RegisterStringPref(
103 prefs::kSyncKeystoreEncryptionBootstrapToken,
104 std::string(),
105 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
106 #if defined(OS_CHROMEOS)
107 registry->RegisterStringPref(
108 prefs::kSyncSpareBootstrapToken,
109 "",
110 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
111 #endif
112
113 registry->RegisterBooleanPref(
114 prefs::kSyncHasAuthError,
115 false,
116 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
117
118 registry->RegisterStringPref(
119 prefs::kSyncSessionsGUID,
120 std::string(),
121 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
122
123 // We will start prompting people about new data types after the launch of
124 // SESSIONS - all previously launched data types are treated as if they are
125 // already acknowledged.
126 syncer::ModelTypeSet model_set;
127 model_set.Put(syncer::BOOKMARKS);
128 model_set.Put(syncer::PREFERENCES);
129 model_set.Put(syncer::PASSWORDS);
130 model_set.Put(syncer::AUTOFILL_PROFILE);
131 model_set.Put(syncer::AUTOFILL);
132 model_set.Put(syncer::THEMES);
133 model_set.Put(syncer::EXTENSIONS);
134 model_set.Put(syncer::NIGORI);
135 model_set.Put(syncer::SEARCH_ENGINES);
136 model_set.Put(syncer::APPS);
137 model_set.Put(syncer::APP_LIST);
138 model_set.Put(syncer::TYPED_URLS);
139 model_set.Put(syncer::SESSIONS);
140 model_set.Put(syncer::ARTICLES);
141 registry->RegisterListPref(prefs::kSyncAcknowledgedSyncTypes,
142 syncer::ModelTypeSetToValue(model_set),
143 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
144
145 registry->RegisterIntegerPref(
146 prefs::kSyncRemainingRollbackTries, 0,
147 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
148 }
149
AddSyncPrefObserver(SyncPrefObserver * sync_pref_observer)150 void SyncPrefs::AddSyncPrefObserver(SyncPrefObserver* sync_pref_observer) {
151 DCHECK(CalledOnValidThread());
152 sync_pref_observers_.AddObserver(sync_pref_observer);
153 }
154
RemoveSyncPrefObserver(SyncPrefObserver * sync_pref_observer)155 void SyncPrefs::RemoveSyncPrefObserver(SyncPrefObserver* sync_pref_observer) {
156 DCHECK(CalledOnValidThread());
157 sync_pref_observers_.RemoveObserver(sync_pref_observer);
158 }
159
ClearPreferences()160 void SyncPrefs::ClearPreferences() {
161 DCHECK(CalledOnValidThread());
162 pref_service_->ClearPref(prefs::kSyncLastSyncedTime);
163 pref_service_->ClearPref(prefs::kSyncHasSetupCompleted);
164 pref_service_->ClearPref(prefs::kSyncEncryptionBootstrapToken);
165 pref_service_->ClearPref(prefs::kSyncKeystoreEncryptionBootstrapToken);
166
167 // TODO(nick): The current behavior does not clear
168 // e.g. prefs::kSyncBookmarks. Is that really what we want?
169 }
170
HasSyncSetupCompleted() const171 bool SyncPrefs::HasSyncSetupCompleted() const {
172 DCHECK(CalledOnValidThread());
173 return pref_service_->GetBoolean(prefs::kSyncHasSetupCompleted);
174 }
175
SetSyncSetupCompleted()176 void SyncPrefs::SetSyncSetupCompleted() {
177 DCHECK(CalledOnValidThread());
178 pref_service_->SetBoolean(prefs::kSyncHasSetupCompleted, true);
179 SetStartSuppressed(false);
180 }
181
SyncHasAuthError() const182 bool SyncPrefs::SyncHasAuthError() const {
183 DCHECK(CalledOnValidThread());
184 return pref_service_->GetBoolean(prefs::kSyncHasAuthError);
185 }
186
SetSyncAuthError(bool error)187 void SyncPrefs::SetSyncAuthError(bool error) {
188 DCHECK(CalledOnValidThread());
189 pref_service_->SetBoolean(prefs::kSyncHasAuthError, error);
190 }
191
IsStartSuppressed() const192 bool SyncPrefs::IsStartSuppressed() const {
193 DCHECK(CalledOnValidThread());
194 return pref_service_->GetBoolean(prefs::kSyncSuppressStart);
195 }
196
SetStartSuppressed(bool is_suppressed)197 void SyncPrefs::SetStartSuppressed(bool is_suppressed) {
198 DCHECK(CalledOnValidThread());
199 pref_service_->SetBoolean(prefs::kSyncSuppressStart, is_suppressed);
200 }
201
GetLastSyncedTime() const202 base::Time SyncPrefs::GetLastSyncedTime() const {
203 DCHECK(CalledOnValidThread());
204 return base::Time::FromInternalValue(
205 pref_service_->GetInt64(prefs::kSyncLastSyncedTime));
206 }
207
SetLastSyncedTime(base::Time time)208 void SyncPrefs::SetLastSyncedTime(base::Time time) {
209 DCHECK(CalledOnValidThread());
210 pref_service_->SetInt64(prefs::kSyncLastSyncedTime, time.ToInternalValue());
211 }
212
HasKeepEverythingSynced() const213 bool SyncPrefs::HasKeepEverythingSynced() const {
214 DCHECK(CalledOnValidThread());
215 return pref_service_->GetBoolean(prefs::kSyncKeepEverythingSynced);
216 }
217
SetKeepEverythingSynced(bool keep_everything_synced)218 void SyncPrefs::SetKeepEverythingSynced(bool keep_everything_synced) {
219 DCHECK(CalledOnValidThread());
220 pref_service_->SetBoolean(prefs::kSyncKeepEverythingSynced,
221 keep_everything_synced);
222 }
223
GetPreferredDataTypes(syncer::ModelTypeSet registered_types) const224 syncer::ModelTypeSet SyncPrefs::GetPreferredDataTypes(
225 syncer::ModelTypeSet registered_types) const {
226 DCHECK(CalledOnValidThread());
227
228 if (pref_service_->GetBoolean(prefs::kSyncKeepEverythingSynced)) {
229 return registered_types;
230 }
231
232 syncer::ModelTypeSet preferred_types;
233 for (syncer::ModelTypeSet::Iterator it = registered_types.First(); it.Good();
234 it.Inc()) {
235 if (GetDataTypePreferred(it.Get())) {
236 preferred_types.Put(it.Get());
237 }
238 }
239 return ResolvePrefGroups(registered_types, preferred_types);
240 }
241
SetPreferredDataTypes(syncer::ModelTypeSet registered_types,syncer::ModelTypeSet preferred_types)242 void SyncPrefs::SetPreferredDataTypes(syncer::ModelTypeSet registered_types,
243 syncer::ModelTypeSet preferred_types) {
244 DCHECK(CalledOnValidThread());
245 DCHECK(registered_types.HasAll(preferred_types));
246 preferred_types = ResolvePrefGroups(registered_types, preferred_types);
247 for (syncer::ModelTypeSet::Iterator i = registered_types.First(); i.Good();
248 i.Inc()) {
249 SetDataTypePreferred(i.Get(), preferred_types.Has(i.Get()));
250 }
251 }
252
IsManaged() const253 bool SyncPrefs::IsManaged() const {
254 DCHECK(CalledOnValidThread());
255 return pref_service_->GetBoolean(prefs::kSyncManaged);
256 }
257
GetEncryptionBootstrapToken() const258 std::string SyncPrefs::GetEncryptionBootstrapToken() const {
259 DCHECK(CalledOnValidThread());
260 return pref_service_->GetString(prefs::kSyncEncryptionBootstrapToken);
261 }
262
SetEncryptionBootstrapToken(const std::string & token)263 void SyncPrefs::SetEncryptionBootstrapToken(const std::string& token) {
264 DCHECK(CalledOnValidThread());
265 pref_service_->SetString(prefs::kSyncEncryptionBootstrapToken, token);
266 }
267
GetKeystoreEncryptionBootstrapToken() const268 std::string SyncPrefs::GetKeystoreEncryptionBootstrapToken() const {
269 DCHECK(CalledOnValidThread());
270 return pref_service_->GetString(prefs::kSyncKeystoreEncryptionBootstrapToken);
271 }
272
SetKeystoreEncryptionBootstrapToken(const std::string & token)273 void SyncPrefs::SetKeystoreEncryptionBootstrapToken(const std::string& token) {
274 DCHECK(CalledOnValidThread());
275 pref_service_->SetString(prefs::kSyncKeystoreEncryptionBootstrapToken, token);
276 }
277
GetSyncSessionsGUID() const278 std::string SyncPrefs::GetSyncSessionsGUID() const {
279 DCHECK(CalledOnValidThread());
280 return pref_service_->GetString(prefs::kSyncSessionsGUID);
281 }
282
SetSyncSessionsGUID(const std::string & guid)283 void SyncPrefs::SetSyncSessionsGUID(const std::string& guid) {
284 DCHECK(CalledOnValidThread());
285 pref_service_->SetString(prefs::kSyncSessionsGUID, guid);
286 }
287
288 // static
GetPrefNameForDataType(syncer::ModelType data_type)289 const char* SyncPrefs::GetPrefNameForDataType(syncer::ModelType data_type) {
290 switch (data_type) {
291 case syncer::BOOKMARKS:
292 return prefs::kSyncBookmarks;
293 case syncer::PASSWORDS:
294 return prefs::kSyncPasswords;
295 case syncer::PREFERENCES:
296 return prefs::kSyncPreferences;
297 case syncer::AUTOFILL:
298 return prefs::kSyncAutofill;
299 case syncer::AUTOFILL_PROFILE:
300 return prefs::kSyncAutofillProfile;
301 case syncer::THEMES:
302 return prefs::kSyncThemes;
303 case syncer::TYPED_URLS:
304 return prefs::kSyncTypedUrls;
305 case syncer::EXTENSION_SETTINGS:
306 return prefs::kSyncExtensionSettings;
307 case syncer::EXTENSIONS:
308 return prefs::kSyncExtensions;
309 case syncer::APP_LIST:
310 return prefs::kSyncAppList;
311 case syncer::APP_SETTINGS:
312 return prefs::kSyncAppSettings;
313 case syncer::APPS:
314 return prefs::kSyncApps;
315 case syncer::SEARCH_ENGINES:
316 return prefs::kSyncSearchEngines;
317 case syncer::SESSIONS:
318 return prefs::kSyncSessions;
319 case syncer::APP_NOTIFICATIONS:
320 return prefs::kSyncAppNotifications;
321 case syncer::HISTORY_DELETE_DIRECTIVES:
322 return prefs::kSyncHistoryDeleteDirectives;
323 case syncer::SYNCED_NOTIFICATIONS:
324 return prefs::kSyncSyncedNotifications;
325 case syncer::SYNCED_NOTIFICATION_APP_INFO:
326 return prefs::kSyncSyncedNotificationAppInfo;
327 case syncer::DICTIONARY:
328 return prefs::kSyncDictionary;
329 case syncer::FAVICON_IMAGES:
330 return prefs::kSyncFaviconImages;
331 case syncer::FAVICON_TRACKING:
332 return prefs::kSyncFaviconTracking;
333 case syncer::SUPERVISED_USER_SETTINGS:
334 return prefs::kSyncSupervisedUserSettings;
335 case syncer::PROXY_TABS:
336 return prefs::kSyncTabs;
337 case syncer::PRIORITY_PREFERENCES:
338 return prefs::kSyncPriorityPreferences;
339 case syncer::SUPERVISED_USERS:
340 return prefs::kSyncSupervisedUsers;
341 case syncer::ARTICLES:
342 return prefs::kSyncArticles;
343 case syncer::SUPERVISED_USER_SHARED_SETTINGS:
344 return prefs::kSyncSupervisedUserSharedSettings;
345 default:
346 break;
347 }
348 NOTREACHED();
349 return NULL;
350 }
351
352 #if defined(OS_CHROMEOS)
GetSpareBootstrapToken() const353 std::string SyncPrefs::GetSpareBootstrapToken() const {
354 DCHECK(CalledOnValidThread());
355 return pref_service_->GetString(prefs::kSyncSpareBootstrapToken);
356 }
357
SetSpareBootstrapToken(const std::string & token)358 void SyncPrefs::SetSpareBootstrapToken(const std::string& token) {
359 DCHECK(CalledOnValidThread());
360 pref_service_->SetString(prefs::kSyncSpareBootstrapToken, token);
361 }
362 #endif
363
AcknowledgeSyncedTypes(syncer::ModelTypeSet types)364 void SyncPrefs::AcknowledgeSyncedTypes(syncer::ModelTypeSet types) {
365 DCHECK(CalledOnValidThread());
366 // Add the types to the current set of acknowledged
367 // types, and then store the resulting set in prefs.
368 const syncer::ModelTypeSet acknowledged_types =
369 Union(types,
370 syncer::ModelTypeSetFromValue(
371 *pref_service_->GetList(prefs::kSyncAcknowledgedSyncTypes)));
372
373 scoped_ptr<base::ListValue> value(
374 syncer::ModelTypeSetToValue(acknowledged_types));
375 pref_service_->Set(prefs::kSyncAcknowledgedSyncTypes, *value);
376 }
377
GetRemainingRollbackTries() const378 int SyncPrefs::GetRemainingRollbackTries() const {
379 return pref_service_->GetInteger(prefs::kSyncRemainingRollbackTries);
380 }
381
SetRemainingRollbackTries(int times)382 void SyncPrefs::SetRemainingRollbackTries(int times) {
383 pref_service_->SetInteger(prefs::kSyncRemainingRollbackTries, times);
384 }
385
OnSyncManagedPrefChanged()386 void SyncPrefs::OnSyncManagedPrefChanged() {
387 DCHECK(CalledOnValidThread());
388 FOR_EACH_OBSERVER(SyncPrefObserver,
389 sync_pref_observers_,
390 OnSyncManagedPrefChange(*pref_sync_managed_));
391 }
392
SetManagedForTest(bool is_managed)393 void SyncPrefs::SetManagedForTest(bool is_managed) {
394 DCHECK(CalledOnValidThread());
395 pref_service_->SetBoolean(prefs::kSyncManaged, is_managed);
396 }
397
GetAcknowledgeSyncedTypesForTest() const398 syncer::ModelTypeSet SyncPrefs::GetAcknowledgeSyncedTypesForTest() const {
399 DCHECK(CalledOnValidThread());
400 return syncer::ModelTypeSetFromValue(
401 *pref_service_->GetList(prefs::kSyncAcknowledgedSyncTypes));
402 }
403
RegisterPrefGroups()404 void SyncPrefs::RegisterPrefGroups() {
405 pref_groups_[syncer::APPS].Put(syncer::APP_NOTIFICATIONS);
406 pref_groups_[syncer::APPS].Put(syncer::APP_SETTINGS);
407 pref_groups_[syncer::APPS].Put(syncer::APP_LIST);
408
409 pref_groups_[syncer::AUTOFILL].Put(syncer::AUTOFILL_PROFILE);
410
411 pref_groups_[syncer::EXTENSIONS].Put(syncer::EXTENSION_SETTINGS);
412
413 pref_groups_[syncer::PREFERENCES].Put(syncer::DICTIONARY);
414 pref_groups_[syncer::PREFERENCES].Put(syncer::PRIORITY_PREFERENCES);
415 pref_groups_[syncer::PREFERENCES].Put(syncer::SEARCH_ENGINES);
416
417 pref_groups_[syncer::TYPED_URLS].Put(syncer::HISTORY_DELETE_DIRECTIVES);
418 pref_groups_[syncer::TYPED_URLS].Put(syncer::SESSIONS);
419 pref_groups_[syncer::TYPED_URLS].Put(syncer::FAVICON_IMAGES);
420 pref_groups_[syncer::TYPED_URLS].Put(syncer::FAVICON_TRACKING);
421
422 pref_groups_[syncer::PROXY_TABS].Put(syncer::SESSIONS);
423 pref_groups_[syncer::PROXY_TABS].Put(syncer::FAVICON_IMAGES);
424 pref_groups_[syncer::PROXY_TABS].Put(syncer::FAVICON_TRACKING);
425
426 pref_groups_[syncer::SUPERVISED_USER_SETTINGS].Put(syncer::SESSIONS);
427
428 // TODO(zea): put favicons in the bookmarks group as well once it handles
429 // those favicons.
430 }
431
432 // static
RegisterDataTypePreferredPref(user_prefs::PrefRegistrySyncable * registry,syncer::ModelType type,bool is_preferred)433 void SyncPrefs::RegisterDataTypePreferredPref(
434 user_prefs::PrefRegistrySyncable* registry,
435 syncer::ModelType type,
436 bool is_preferred) {
437 const char* pref_name = GetPrefNameForDataType(type);
438 if (!pref_name) {
439 NOTREACHED();
440 return;
441 }
442 registry->RegisterBooleanPref(
443 pref_name,
444 is_preferred,
445 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
446 }
447
GetDataTypePreferred(syncer::ModelType type) const448 bool SyncPrefs::GetDataTypePreferred(syncer::ModelType type) const {
449 DCHECK(CalledOnValidThread());
450 const char* pref_name = GetPrefNameForDataType(type);
451 if (!pref_name) {
452 NOTREACHED();
453 return false;
454 }
455 if (type == syncer::PROXY_TABS &&
456 pref_service_->GetUserPrefValue(pref_name) == NULL &&
457 pref_service_->IsUserModifiablePreference(pref_name)) {
458 // If there is no tab sync preference yet (i.e. newly enabled type),
459 // default to the session sync preference value.
460 pref_name = GetPrefNameForDataType(syncer::SESSIONS);
461 }
462
463 return pref_service_->GetBoolean(pref_name);
464 }
465
SetDataTypePreferred(syncer::ModelType type,bool is_preferred)466 void SyncPrefs::SetDataTypePreferred(syncer::ModelType type,
467 bool is_preferred) {
468 DCHECK(CalledOnValidThread());
469 const char* pref_name = GetPrefNameForDataType(type);
470 if (!pref_name) {
471 NOTREACHED();
472 return;
473 }
474 pref_service_->SetBoolean(pref_name, is_preferred);
475 }
476
ResolvePrefGroups(syncer::ModelTypeSet registered_types,syncer::ModelTypeSet types) const477 syncer::ModelTypeSet SyncPrefs::ResolvePrefGroups(
478 syncer::ModelTypeSet registered_types,
479 syncer::ModelTypeSet types) const {
480 DCHECK(registered_types.HasAll(types));
481 syncer::ModelTypeSet types_with_groups = types;
482 for (PrefGroupsMap::const_iterator i = pref_groups_.begin();
483 i != pref_groups_.end();
484 ++i) {
485 if (types.Has(i->first))
486 types_with_groups.PutAll(i->second);
487 }
488 types_with_groups.RetainAll(registered_types);
489 return types_with_groups;
490 }
491
GetFirstSyncTime() const492 base::Time SyncPrefs::GetFirstSyncTime() const {
493 return base::Time::FromInternalValue(
494 pref_service_->GetInt64(prefs::kSyncFirstSyncTime));
495 }
496
SetFirstSyncTime(base::Time time)497 void SyncPrefs::SetFirstSyncTime(base::Time time) {
498 pref_service_->SetInt64(prefs::kSyncFirstSyncTime, time.ToInternalValue());
499 }
500
ClearFirstSyncTime()501 void SyncPrefs::ClearFirstSyncTime() {
502 pref_service_->ClearPref(prefs::kSyncFirstSyncTime);
503 }
504
505 } // namespace browser_sync
506