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.
5 #include "chrome/browser/sync/sync_prefs.h"
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 "chrome/browser/chrome_notification_types.h"
15 #include "chrome/browser/profiles/profile_io_data.h"
16 #include "chrome/browser/sync/profile_sync_service.h"
17 #include "chrome/common/chrome_switches.h"
18 #include "chrome/common/pref_names.h"
19 #include "components/user_prefs/pref_registry_syncable.h"
20 #include "content/public/browser/browser_thread.h"
21 #include "content/public/browser/notification_details.h"
22 #include "content/public/browser/notification_source.h"
24 namespace browser_sync {
26 SyncPrefObserver::~SyncPrefObserver() {}
28 SyncPrefs::SyncPrefs(PrefService* pref_service)
29 : pref_service_(pref_service) {
31 // TODO(tim): Create a Mock instead of maintaining the if(!pref_service_) case
32 // throughout this file. This is a problem now due to lack of injection at
33 // ProfileSyncService. Bug 130176.
35 // Watch the preference that indicates sync is managed so we can take
36 // appropriate action.
37 pref_sync_managed_.Init(prefs::kSyncManaged, pref_service_,
38 base::Bind(&SyncPrefs::OnSyncManagedPrefChanged,
39 base::Unretained(this)));
43 SyncPrefs::~SyncPrefs() {
44 DCHECK(CalledOnValidThread());
48 void SyncPrefs::RegisterProfilePrefs(
49 user_prefs::PrefRegistrySyncable* registry) {
50 registry->RegisterBooleanPref(
51 prefs::kSyncHasSetupCompleted,
53 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
54 registry->RegisterBooleanPref(
55 prefs::kSyncSuppressStart,
57 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
58 registry->RegisterInt64Pref(
59 prefs::kSyncLastSyncedTime,
61 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
63 // All datatypes are on by default, but this gets set explicitly
64 // when you configure sync (when turning it on), in
65 // ProfileSyncService::OnUserChoseDatatypes.
66 registry->RegisterBooleanPref(
67 prefs::kSyncKeepEverythingSynced,
69 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
71 syncer::ModelTypeSet user_types = syncer::UserTypes();
73 // Include proxy types as well, as they can be individually selected,
74 // although they don't have sync representations.
75 user_types.PutAll(syncer::ProxyTypes());
77 // Treat bookmarks specially.
78 RegisterDataTypePreferredPref(registry, syncer::BOOKMARKS, true);
79 user_types.Remove(syncer::BOOKMARKS);
81 // All types are set to off by default, which forces a configuration to
82 // explicitly enable them. GetPreferredTypes() will ensure that any new
83 // implicit types are enabled when their pref group is, or via
84 // KeepEverythingSynced.
85 for (syncer::ModelTypeSet::Iterator it = user_types.First();
86 it.Good(); it.Inc()) {
87 RegisterDataTypePreferredPref(registry, it.Get(), false);
90 registry->RegisterBooleanPref(
93 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
94 registry->RegisterStringPref(
95 prefs::kSyncEncryptionBootstrapToken,
97 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
98 registry->RegisterStringPref(
99 prefs::kSyncKeystoreEncryptionBootstrapToken,
101 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
102 #if defined(OS_CHROMEOS)
103 registry->RegisterStringPref(
104 prefs::kSyncSpareBootstrapToken,
106 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
109 registry->RegisterStringPref(
110 prefs::kSyncSessionsGUID,
112 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
114 // We will start prompting people about new data types after the launch of
115 // SESSIONS - all previously launched data types are treated as if they are
116 // already acknowledged.
117 syncer::ModelTypeSet model_set;
118 model_set.Put(syncer::BOOKMARKS);
119 model_set.Put(syncer::PREFERENCES);
120 model_set.Put(syncer::PASSWORDS);
121 model_set.Put(syncer::AUTOFILL_PROFILE);
122 model_set.Put(syncer::AUTOFILL);
123 model_set.Put(syncer::THEMES);
124 model_set.Put(syncer::EXTENSIONS);
125 model_set.Put(syncer::NIGORI);
126 model_set.Put(syncer::SEARCH_ENGINES);
127 model_set.Put(syncer::APPS);
128 model_set.Put(syncer::TYPED_URLS);
129 model_set.Put(syncer::SESSIONS);
130 model_set.Put(syncer::ARTICLES);
131 registry->RegisterListPref(prefs::kSyncAcknowledgedSyncTypes,
132 syncer::ModelTypeSetToValue(model_set),
133 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
136 void SyncPrefs::AddSyncPrefObserver(SyncPrefObserver* sync_pref_observer) {
137 DCHECK(CalledOnValidThread());
138 sync_pref_observers_.AddObserver(sync_pref_observer);
141 void SyncPrefs::RemoveSyncPrefObserver(SyncPrefObserver* sync_pref_observer) {
142 DCHECK(CalledOnValidThread());
143 sync_pref_observers_.RemoveObserver(sync_pref_observer);
146 void SyncPrefs::ClearPreferences() {
147 DCHECK(CalledOnValidThread());
148 CHECK(pref_service_);
149 pref_service_->ClearPref(prefs::kSyncLastSyncedTime);
150 pref_service_->ClearPref(prefs::kSyncHasSetupCompleted);
151 pref_service_->ClearPref(prefs::kSyncEncryptionBootstrapToken);
152 pref_service_->ClearPref(prefs::kSyncKeystoreEncryptionBootstrapToken);
154 // TODO(nick): The current behavior does not clear
155 // e.g. prefs::kSyncBookmarks. Is that really what we want?
158 bool SyncPrefs::HasSyncSetupCompleted() const {
159 DCHECK(CalledOnValidThread());
162 pref_service_->GetBoolean(prefs::kSyncHasSetupCompleted);
165 void SyncPrefs::SetSyncSetupCompleted() {
166 DCHECK(CalledOnValidThread());
167 CHECK(pref_service_);
168 pref_service_->SetBoolean(prefs::kSyncHasSetupCompleted, true);
169 SetStartSuppressed(false);
172 bool SyncPrefs::IsStartSuppressed() const {
173 DCHECK(CalledOnValidThread());
176 pref_service_->GetBoolean(prefs::kSyncSuppressStart);
179 void SyncPrefs::SetStartSuppressed(bool is_suppressed) {
180 DCHECK(CalledOnValidThread());
181 CHECK(pref_service_);
182 pref_service_->SetBoolean(prefs::kSyncSuppressStart, is_suppressed);
185 std::string SyncPrefs::GetGoogleServicesUsername() const {
186 DCHECK(CalledOnValidThread());
188 ? pref_service_->GetString(prefs::kGoogleServicesUsername)
192 base::Time SyncPrefs::GetLastSyncedTime() const {
193 DCHECK(CalledOnValidThread());
195 base::Time::FromInternalValue(
197 pref_service_->GetInt64(prefs::kSyncLastSyncedTime) : 0);
200 void SyncPrefs::SetLastSyncedTime(base::Time time) {
201 DCHECK(CalledOnValidThread());
202 CHECK(pref_service_);
203 pref_service_->SetInt64(prefs::kSyncLastSyncedTime, time.ToInternalValue());
206 bool SyncPrefs::HasKeepEverythingSynced() const {
207 DCHECK(CalledOnValidThread());
210 pref_service_->GetBoolean(prefs::kSyncKeepEverythingSynced);
213 void SyncPrefs::SetKeepEverythingSynced(bool keep_everything_synced) {
214 DCHECK(CalledOnValidThread());
215 CHECK(pref_service_);
216 pref_service_->SetBoolean(prefs::kSyncKeepEverythingSynced,
217 keep_everything_synced);
220 syncer::ModelTypeSet SyncPrefs::GetPreferredDataTypes(
221 syncer::ModelTypeSet registered_types) const {
222 DCHECK(CalledOnValidThread());
223 if (!pref_service_) {
224 return syncer::ModelTypeSet();
227 // First remove any datatypes that are inconsistent with the current policies
228 // on the client (so that "keep everything synced" doesn't include them).
229 if (pref_service_->HasPrefPath(prefs::kSavingBrowserHistoryDisabled) &&
230 pref_service_->GetBoolean(prefs::kSavingBrowserHistoryDisabled)) {
231 registered_types.Remove(syncer::TYPED_URLS);
234 if (pref_service_->GetBoolean(prefs::kSyncKeepEverythingSynced)) {
235 return registered_types;
238 syncer::ModelTypeSet preferred_types;
239 for (syncer::ModelTypeSet::Iterator it = registered_types.First();
240 it.Good(); it.Inc()) {
241 if (GetDataTypePreferred(it.Get())) {
242 preferred_types.Put(it.Get());
245 return ResolvePrefGroups(registered_types, preferred_types);
248 void SyncPrefs::SetPreferredDataTypes(
249 syncer::ModelTypeSet registered_types,
250 syncer::ModelTypeSet preferred_types) {
251 DCHECK(CalledOnValidThread());
252 CHECK(pref_service_);
253 DCHECK(registered_types.HasAll(preferred_types));
254 preferred_types = ResolvePrefGroups(registered_types, preferred_types);
255 for (syncer::ModelTypeSet::Iterator i = registered_types.First();
257 SetDataTypePreferred(i.Get(), preferred_types.Has(i.Get()));
261 bool SyncPrefs::IsManaged() const {
262 DCHECK(CalledOnValidThread());
263 return pref_service_ && pref_service_->GetBoolean(prefs::kSyncManaged);
266 std::string SyncPrefs::GetEncryptionBootstrapToken() const {
267 DCHECK(CalledOnValidThread());
269 ? pref_service_->GetString(prefs::kSyncEncryptionBootstrapToken)
273 void SyncPrefs::SetEncryptionBootstrapToken(const std::string& token) {
274 DCHECK(CalledOnValidThread());
275 pref_service_->SetString(prefs::kSyncEncryptionBootstrapToken, token);
278 std::string SyncPrefs::GetKeystoreEncryptionBootstrapToken() const {
279 DCHECK(CalledOnValidThread());
280 return pref_service_ ? pref_service_->GetString(
281 prefs::kSyncKeystoreEncryptionBootstrapToken)
285 void SyncPrefs::SetKeystoreEncryptionBootstrapToken(const std::string& token) {
286 DCHECK(CalledOnValidThread());
287 pref_service_->SetString(prefs::kSyncKeystoreEncryptionBootstrapToken, token);
290 std::string SyncPrefs::GetSyncSessionsGUID() const {
291 DCHECK(CalledOnValidThread());
292 return pref_service_ ? pref_service_->GetString(prefs::kSyncSessionsGUID)
296 void SyncPrefs::SetSyncSessionsGUID(const std::string& guid) {
297 DCHECK(CalledOnValidThread());
298 pref_service_->SetString(prefs::kSyncSessionsGUID, guid);
302 const char* SyncPrefs::GetPrefNameForDataType(syncer::ModelType data_type) {
304 case syncer::BOOKMARKS:
305 return prefs::kSyncBookmarks;
306 case syncer::PASSWORDS:
307 return prefs::kSyncPasswords;
308 case syncer::PREFERENCES:
309 return prefs::kSyncPreferences;
310 case syncer::AUTOFILL:
311 return prefs::kSyncAutofill;
312 case syncer::AUTOFILL_PROFILE:
313 return prefs::kSyncAutofillProfile;
315 return prefs::kSyncThemes;
316 case syncer::TYPED_URLS:
317 return prefs::kSyncTypedUrls;
318 case syncer::EXTENSION_SETTINGS:
319 return prefs::kSyncExtensionSettings;
320 case syncer::EXTENSIONS:
321 return prefs::kSyncExtensions;
322 case syncer::APP_SETTINGS:
323 return prefs::kSyncAppSettings;
325 return prefs::kSyncApps;
326 case syncer::SEARCH_ENGINES:
327 return prefs::kSyncSearchEngines;
328 case syncer::SESSIONS:
329 return prefs::kSyncSessions;
330 case syncer::APP_NOTIFICATIONS:
331 return prefs::kSyncAppNotifications;
332 case syncer::HISTORY_DELETE_DIRECTIVES:
333 return prefs::kSyncHistoryDeleteDirectives;
334 case syncer::SYNCED_NOTIFICATIONS:
335 return prefs::kSyncSyncedNotifications;
336 case syncer::DICTIONARY:
337 return prefs::kSyncDictionary;
338 case syncer::FAVICON_IMAGES:
339 return prefs::kSyncFaviconImages;
340 case syncer::FAVICON_TRACKING:
341 return prefs::kSyncFaviconTracking;
342 case syncer::MANAGED_USER_SETTINGS:
343 return prefs::kSyncManagedUserSettings;
344 case syncer::PROXY_TABS:
345 return prefs::kSyncTabs;
346 case syncer::PRIORITY_PREFERENCES:
347 return prefs::kSyncPriorityPreferences;
348 case syncer::MANAGED_USERS:
349 return prefs::kSyncManagedUsers;
350 case syncer::ARTICLES:
351 return prefs::kSyncArticles;
359 #if defined(OS_CHROMEOS)
360 std::string SyncPrefs::GetSpareBootstrapToken() const {
361 DCHECK(CalledOnValidThread());
362 return pref_service_ ?
363 pref_service_->GetString(prefs::kSyncSpareBootstrapToken) : "";
366 void SyncPrefs::SetSpareBootstrapToken(const std::string& token) {
367 DCHECK(CalledOnValidThread());
368 pref_service_->SetString(prefs::kSyncSpareBootstrapToken, token);
372 void SyncPrefs::AcknowledgeSyncedTypes(syncer::ModelTypeSet types) {
373 DCHECK(CalledOnValidThread());
374 CHECK(pref_service_);
375 // Add the types to the current set of acknowledged
376 // types, and then store the resulting set in prefs.
377 const syncer::ModelTypeSet acknowledged_types =
379 syncer::ModelTypeSetFromValue(
380 *pref_service_->GetList(prefs::kSyncAcknowledgedSyncTypes)));
382 scoped_ptr<ListValue> value(
383 syncer::ModelTypeSetToValue(acknowledged_types));
384 pref_service_->Set(prefs::kSyncAcknowledgedSyncTypes, *value);
387 void SyncPrefs::OnSyncManagedPrefChanged() {
388 DCHECK(CalledOnValidThread());
389 FOR_EACH_OBSERVER(SyncPrefObserver, sync_pref_observers_,
390 OnSyncManagedPrefChange(*pref_sync_managed_));
393 void SyncPrefs::SetManagedForTest(bool is_managed) {
394 DCHECK(CalledOnValidThread());
395 CHECK(pref_service_);
396 pref_service_->SetBoolean(prefs::kSyncManaged, is_managed);
399 syncer::ModelTypeSet SyncPrefs::GetAcknowledgeSyncedTypesForTest() const {
400 DCHECK(CalledOnValidThread());
401 if (!pref_service_) {
402 return syncer::ModelTypeSet();
404 return syncer::ModelTypeSetFromValue(
405 *pref_service_->GetList(prefs::kSyncAcknowledgedSyncTypes));
408 void SyncPrefs::RegisterPrefGroups() {
409 pref_groups_[syncer::APPS].Put(syncer::APP_NOTIFICATIONS);
410 pref_groups_[syncer::APPS].Put(syncer::APP_SETTINGS);
412 pref_groups_[syncer::AUTOFILL].Put(syncer::AUTOFILL_PROFILE);
414 pref_groups_[syncer::EXTENSIONS].Put(syncer::EXTENSION_SETTINGS);
416 pref_groups_[syncer::PREFERENCES].Put(syncer::DICTIONARY);
417 pref_groups_[syncer::PREFERENCES].Put(syncer::PRIORITY_PREFERENCES);
418 pref_groups_[syncer::PREFERENCES].Put(syncer::SEARCH_ENGINES);
420 pref_groups_[syncer::TYPED_URLS].Put(syncer::HISTORY_DELETE_DIRECTIVES);
421 if (!CommandLine::ForCurrentProcess()->HasSwitch(
422 switches::kHistoryDisableFullHistorySync)) {
423 pref_groups_[syncer::TYPED_URLS].Put(syncer::SESSIONS);
424 pref_groups_[syncer::TYPED_URLS].Put(syncer::FAVICON_IMAGES);
425 pref_groups_[syncer::TYPED_URLS].Put(syncer::FAVICON_TRACKING);
428 pref_groups_[syncer::PROXY_TABS].Put(syncer::SESSIONS);
429 pref_groups_[syncer::PROXY_TABS].Put(syncer::FAVICON_IMAGES);
430 pref_groups_[syncer::PROXY_TABS].Put(syncer::FAVICON_TRACKING);
432 pref_groups_[syncer::MANAGED_USER_SETTINGS].Put(syncer::SESSIONS);
434 // TODO(zea): put favicons in the bookmarks group as well once it handles
439 void SyncPrefs::RegisterDataTypePreferredPref(
440 user_prefs::PrefRegistrySyncable* registry,
441 syncer::ModelType type,
443 const char* pref_name = GetPrefNameForDataType(type);
448 registry->RegisterBooleanPref(
451 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
454 bool SyncPrefs::GetDataTypePreferred(syncer::ModelType type) const {
455 DCHECK(CalledOnValidThread());
456 if (!pref_service_) {
459 const char* pref_name = GetPrefNameForDataType(type);
464 if (type == syncer::PROXY_TABS &&
465 pref_service_->GetUserPrefValue(pref_name) == NULL &&
466 pref_service_->IsUserModifiablePreference(pref_name)) {
467 // If there is no tab sync preference yet (i.e. newly enabled type),
468 // default to the session sync preference value.
469 pref_name = GetPrefNameForDataType(syncer::SESSIONS);
472 return pref_service_->GetBoolean(pref_name);
475 void SyncPrefs::SetDataTypePreferred(
476 syncer::ModelType type, bool is_preferred) {
477 DCHECK(CalledOnValidThread());
478 CHECK(pref_service_);
479 const char* pref_name = GetPrefNameForDataType(type);
484 pref_service_->SetBoolean(pref_name, is_preferred);
487 syncer::ModelTypeSet SyncPrefs::ResolvePrefGroups(
488 syncer::ModelTypeSet registered_types,
489 syncer::ModelTypeSet types) const {
490 DCHECK(registered_types.HasAll(types));
491 syncer::ModelTypeSet types_with_groups = types;
492 for (PrefGroupsMap::const_iterator i = pref_groups_.begin();
493 i != pref_groups_.end(); ++i) {
494 if (types.Has(i->first))
495 types_with_groups.PutAll(i->second);
497 types_with_groups.RetainAll(registered_types);
498 return types_with_groups;
501 } // namespace browser_sync