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/logging.h"
8 #include "base/string_number_conversions.h"
9 #include "base/values.h"
10 #include "build/build_config.h"
11 #include "chrome/browser/prefs/pref_service.h"
12 #include "chrome/common/chrome_notification_types.h"
13 #include "chrome/common/pref_names.h"
14 #include "content/public/browser/notification_details.h"
15 #include "content/public/browser/notification_source.h"
17 namespace browser_sync
{
19 SyncPrefObserver::~SyncPrefObserver() {}
21 SyncPrefs::SyncPrefs(PrefService
* pref_service
)
22 : pref_service_(pref_service
) {
24 // TODO(tim): Create a Mock instead of maintaining the if(!pref_service_) case
25 // throughout this file. This is a problem now due to lack of injection at
26 // ProfileSyncService. Bug 130176.
28 RegisterPreferences();
29 // Watch the preference that indicates sync is managed so we can take
30 // appropriate action.
31 pref_sync_managed_
.Init(prefs::kSyncManaged
, pref_service_
, this);
35 SyncPrefs::~SyncPrefs() {
36 DCHECK(CalledOnValidThread());
39 void SyncPrefs::AddSyncPrefObserver(SyncPrefObserver
* sync_pref_observer
) {
40 DCHECK(CalledOnValidThread());
41 sync_pref_observers_
.AddObserver(sync_pref_observer
);
44 void SyncPrefs::RemoveSyncPrefObserver(SyncPrefObserver
* sync_pref_observer
) {
45 DCHECK(CalledOnValidThread());
46 sync_pref_observers_
.RemoveObserver(sync_pref_observer
);
49 void SyncPrefs::ClearPreferences() {
50 DCHECK(CalledOnValidThread());
52 pref_service_
->ClearPref(prefs::kSyncLastSyncedTime
);
53 pref_service_
->ClearPref(prefs::kSyncHasSetupCompleted
);
54 pref_service_
->ClearPref(prefs::kSyncEncryptionBootstrapToken
);
55 pref_service_
->ClearPref(prefs::kSyncKeystoreEncryptionBootstrapToken
);
57 // TODO(nick): The current behavior does not clear
58 // e.g. prefs::kSyncBookmarks. Is that really what we want?
61 bool SyncPrefs::HasSyncSetupCompleted() const {
62 DCHECK(CalledOnValidThread());
65 pref_service_
->GetBoolean(prefs::kSyncHasSetupCompleted
);
68 void SyncPrefs::SetSyncSetupCompleted() {
69 DCHECK(CalledOnValidThread());
71 pref_service_
->SetBoolean(prefs::kSyncHasSetupCompleted
, true);
72 SetStartSuppressed(false);
75 bool SyncPrefs::IsStartSuppressed() const {
76 DCHECK(CalledOnValidThread());
79 pref_service_
->GetBoolean(prefs::kSyncSuppressStart
);
82 void SyncPrefs::SetStartSuppressed(bool is_suppressed
) {
83 DCHECK(CalledOnValidThread());
85 pref_service_
->SetBoolean(prefs::kSyncSuppressStart
, is_suppressed
);
88 std::string
SyncPrefs::GetGoogleServicesUsername() const {
89 DCHECK(CalledOnValidThread());
92 pref_service_
->GetString(prefs::kGoogleServicesUsername
) : "";
95 base::Time
SyncPrefs::GetLastSyncedTime() const {
96 DCHECK(CalledOnValidThread());
98 base::Time::FromInternalValue(
100 pref_service_
->GetInt64(prefs::kSyncLastSyncedTime
) : 0);
103 void SyncPrefs::SetLastSyncedTime(base::Time time
) {
104 DCHECK(CalledOnValidThread());
105 CHECK(pref_service_
);
106 pref_service_
->SetInt64(prefs::kSyncLastSyncedTime
, time
.ToInternalValue());
109 bool SyncPrefs::HasKeepEverythingSynced() const {
110 DCHECK(CalledOnValidThread());
113 pref_service_
->GetBoolean(prefs::kSyncKeepEverythingSynced
);
116 void SyncPrefs::SetKeepEverythingSynced(bool keep_everything_synced
) {
117 DCHECK(CalledOnValidThread());
118 CHECK(pref_service_
);
119 pref_service_
->SetBoolean(prefs::kSyncKeepEverythingSynced
,
120 keep_everything_synced
);
123 // TODO(akalin): If encryption is turned on for all data types,
124 // history delete directives are useless and so we shouldn't bother
127 syncer::ModelTypeSet
SyncPrefs::GetPreferredDataTypes(
128 syncer::ModelTypeSet registered_types
) const {
129 DCHECK(CalledOnValidThread());
130 if (!pref_service_
) {
131 return syncer::ModelTypeSet();
134 // First remove any datatypes that are inconsistent with the current policies
135 // on the client (so that "keep everything synced" doesn't include them).
136 if (pref_service_
->HasPrefPath(prefs::kSavingBrowserHistoryDisabled
) &&
137 pref_service_
->GetBoolean(prefs::kSavingBrowserHistoryDisabled
)) {
138 registered_types
.Remove(syncer::TYPED_URLS
);
141 if (pref_service_
->GetBoolean(prefs::kSyncKeepEverythingSynced
)) {
142 return registered_types
;
145 syncer::ModelTypeSet preferred_types
;
146 for (syncer::ModelTypeSet::Iterator it
= registered_types
.First();
147 it
.Good(); it
.Inc()) {
148 if (GetDataTypePreferred(it
.Get())) {
149 preferred_types
.Put(it
.Get());
152 return ResolvePrefGroups(registered_types
, preferred_types
);
155 void SyncPrefs::SetPreferredDataTypes(
156 syncer::ModelTypeSet registered_types
,
157 syncer::ModelTypeSet preferred_types
) {
158 DCHECK(CalledOnValidThread());
159 CHECK(pref_service_
);
160 DCHECK(registered_types
.HasAll(preferred_types
));
161 preferred_types
= ResolvePrefGroups(registered_types
, preferred_types
);
162 for (syncer::ModelTypeSet::Iterator i
= registered_types
.First();
164 SetDataTypePreferred(i
.Get(), preferred_types
.Has(i
.Get()));
168 bool SyncPrefs::IsManaged() const {
169 DCHECK(CalledOnValidThread());
170 return pref_service_
&& pref_service_
->GetBoolean(prefs::kSyncManaged
);
173 std::string
SyncPrefs::GetEncryptionBootstrapToken() const {
174 DCHECK(CalledOnValidThread());
177 pref_service_
->GetString(prefs::kSyncEncryptionBootstrapToken
) : "";
180 void SyncPrefs::SetEncryptionBootstrapToken(const std::string
& token
) {
181 DCHECK(CalledOnValidThread());
182 pref_service_
->SetString(prefs::kSyncEncryptionBootstrapToken
, token
);
185 std::string
SyncPrefs::GetKeystoreEncryptionBootstrapToken() const {
186 DCHECK(CalledOnValidThread());
189 pref_service_
->GetString(prefs::kSyncKeystoreEncryptionBootstrapToken
) :
193 void SyncPrefs::SetKeystoreEncryptionBootstrapToken(const std::string
& token
) {
194 DCHECK(CalledOnValidThread());
195 pref_service_
->SetString(prefs::kSyncKeystoreEncryptionBootstrapToken
, token
);
199 const char* SyncPrefs::GetPrefNameForDataType(syncer::ModelType data_type
) {
201 case syncer::BOOKMARKS
:
202 return prefs::kSyncBookmarks
;
203 case syncer::PASSWORDS
:
204 return prefs::kSyncPasswords
;
205 case syncer::PREFERENCES
:
206 return prefs::kSyncPreferences
;
207 case syncer::AUTOFILL
:
208 return prefs::kSyncAutofill
;
209 case syncer::AUTOFILL_PROFILE
:
210 return prefs::kSyncAutofillProfile
;
212 return prefs::kSyncThemes
;
213 case syncer::TYPED_URLS
:
214 return prefs::kSyncTypedUrls
;
215 case syncer::EXTENSION_SETTINGS
:
216 return prefs::kSyncExtensionSettings
;
217 case syncer::EXTENSIONS
:
218 return prefs::kSyncExtensions
;
219 case syncer::APP_SETTINGS
:
220 return prefs::kSyncAppSettings
;
222 return prefs::kSyncApps
;
223 case syncer::SEARCH_ENGINES
:
224 return prefs::kSyncSearchEngines
;
225 case syncer::SESSIONS
:
226 return prefs::kSyncSessions
;
227 case syncer::APP_NOTIFICATIONS
:
228 return prefs::kSyncAppNotifications
;
229 case syncer::HISTORY_DELETE_DIRECTIVES
:
230 return prefs::kSyncHistoryDeleteDirectives
;
238 #if defined(OS_CHROMEOS)
239 std::string
SyncPrefs::GetSpareBootstrapToken() const {
240 DCHECK(CalledOnValidThread());
241 return pref_service_
?
242 pref_service_
->GetString(prefs::kSyncSpareBootstrapToken
) : "";
245 void SyncPrefs::SetSpareBootstrapToken(const std::string
& token
) {
246 DCHECK(CalledOnValidThread());
247 pref_service_
->SetString(prefs::kSyncSpareBootstrapToken
, token
);
251 void SyncPrefs::AcknowledgeSyncedTypes(syncer::ModelTypeSet types
) {
252 DCHECK(CalledOnValidThread());
253 CHECK(pref_service_
);
254 // Add the types to the current set of acknowledged
255 // types, and then store the resulting set in prefs.
256 const syncer::ModelTypeSet acknowledged_types
=
258 syncer::ModelTypeSetFromValue(
259 *pref_service_
->GetList(prefs::kSyncAcknowledgedSyncTypes
)));
261 scoped_ptr
<ListValue
> value(
262 syncer::ModelTypeSetToValue(acknowledged_types
));
263 pref_service_
->Set(prefs::kSyncAcknowledgedSyncTypes
, *value
);
266 void SyncPrefs::OnPreferenceChanged(PrefServiceBase
* service
,
267 const std::string
& pref_name
) {
268 DCHECK(CalledOnValidThread());
269 DCHECK_EQ(pref_service_
, service
);
270 if (pref_name
== prefs::kSyncManaged
) {
271 FOR_EACH_OBSERVER(SyncPrefObserver
, sync_pref_observers_
,
272 OnSyncManagedPrefChange(*pref_sync_managed_
));
276 void SyncPrefs::SetManagedForTest(bool is_managed
) {
277 DCHECK(CalledOnValidThread());
278 CHECK(pref_service_
);
279 pref_service_
->SetBoolean(prefs::kSyncManaged
, is_managed
);
282 syncer::ModelTypeSet
SyncPrefs::GetAcknowledgeSyncedTypesForTest() const {
283 DCHECK(CalledOnValidThread());
284 if (!pref_service_
) {
285 return syncer::ModelTypeSet();
287 return syncer::ModelTypeSetFromValue(
288 *pref_service_
->GetList(prefs::kSyncAcknowledgedSyncTypes
));
291 void SyncPrefs::RegisterPrefGroups() {
292 pref_groups_
[syncer::APPS
].Put(syncer::APP_NOTIFICATIONS
);
293 pref_groups_
[syncer::APPS
].Put(syncer::APP_SETTINGS
);
295 pref_groups_
[syncer::AUTOFILL
].Put(syncer::AUTOFILL_PROFILE
);
297 pref_groups_
[syncer::EXTENSIONS
].Put(syncer::EXTENSION_SETTINGS
);
299 pref_groups_
[syncer::PREFERENCES
].Put(syncer::SEARCH_ENGINES
);
301 // TODO(akalin): Revisit this once UI lands.
302 pref_groups_
[syncer::SESSIONS
].Put(syncer::HISTORY_DELETE_DIRECTIVES
);
305 void SyncPrefs::RegisterPreferences() {
306 DCHECK(CalledOnValidThread());
307 CHECK(pref_service_
);
308 if (pref_service_
->FindPreference(prefs::kSyncLastSyncedTime
)) {
312 pref_service_
->RegisterBooleanPref(prefs::kSyncHasSetupCompleted
,
314 PrefService::UNSYNCABLE_PREF
);
315 pref_service_
->RegisterBooleanPref(prefs::kSyncSuppressStart
,
317 PrefService::UNSYNCABLE_PREF
);
318 pref_service_
->RegisterInt64Pref(prefs::kSyncLastSyncedTime
,
320 PrefService::UNSYNCABLE_PREF
);
322 // If you've never synced before, or if you're using Chrome OS or Android,
323 // all datatypes are on by default.
324 // TODO(nick): Perhaps a better model would be to always default to false,
325 // and explicitly call SetDataTypes() when the user shows the wizard.
326 #if defined(OS_CHROMEOS) || defined(OS_ANDROID)
327 bool enable_by_default
= true;
329 bool enable_by_default
=
330 !pref_service_
->HasPrefPath(prefs::kSyncHasSetupCompleted
);
333 pref_service_
->RegisterBooleanPref(prefs::kSyncKeepEverythingSynced
,
335 PrefService::UNSYNCABLE_PREF
);
337 syncer::ModelTypeSet user_types
= syncer::UserTypes();
339 // Treat bookmarks specially.
340 RegisterDataTypePreferredPref(syncer::BOOKMARKS
, true);
341 user_types
.Remove(syncer::BOOKMARKS
);
343 for (syncer::ModelTypeSet::Iterator it
= user_types
.First();
344 it
.Good(); it
.Inc()) {
345 RegisterDataTypePreferredPref(it
.Get(), enable_by_default
);
348 pref_service_
->RegisterBooleanPref(prefs::kSyncManaged
,
350 PrefService::UNSYNCABLE_PREF
);
351 pref_service_
->RegisterStringPref(prefs::kSyncEncryptionBootstrapToken
,
353 PrefService::UNSYNCABLE_PREF
);
354 pref_service_
->RegisterStringPref(
355 prefs::kSyncKeystoreEncryptionBootstrapToken
,
357 PrefService::UNSYNCABLE_PREF
);
358 #if defined(OS_CHROMEOS)
359 pref_service_
->RegisterStringPref(prefs::kSyncSpareBootstrapToken
,
361 PrefService::UNSYNCABLE_PREF
);
364 // We will start prompting people about new data types after the launch of
365 // SESSIONS - all previously launched data types are treated as if they are
366 // already acknowledged.
367 syncer::ModelTypeSet model_set
;
368 model_set
.Put(syncer::BOOKMARKS
);
369 model_set
.Put(syncer::PREFERENCES
);
370 model_set
.Put(syncer::PASSWORDS
);
371 model_set
.Put(syncer::AUTOFILL_PROFILE
);
372 model_set
.Put(syncer::AUTOFILL
);
373 model_set
.Put(syncer::THEMES
);
374 model_set
.Put(syncer::EXTENSIONS
);
375 model_set
.Put(syncer::NIGORI
);
376 model_set
.Put(syncer::SEARCH_ENGINES
);
377 model_set
.Put(syncer::APPS
);
378 model_set
.Put(syncer::TYPED_URLS
);
379 model_set
.Put(syncer::SESSIONS
);
380 pref_service_
->RegisterListPref(prefs::kSyncAcknowledgedSyncTypes
,
381 syncer::ModelTypeSetToValue(model_set
),
382 PrefService::UNSYNCABLE_PREF
);
385 void SyncPrefs::RegisterDataTypePreferredPref(syncer::ModelType type
,
387 DCHECK(CalledOnValidThread());
388 CHECK(pref_service_
);
389 const char* pref_name
= GetPrefNameForDataType(type
);
394 pref_service_
->RegisterBooleanPref(pref_name
, is_preferred
,
395 PrefService::UNSYNCABLE_PREF
);
398 bool SyncPrefs::GetDataTypePreferred(syncer::ModelType type
) const {
399 DCHECK(CalledOnValidThread());
400 if (!pref_service_
) {
403 const char* pref_name
= GetPrefNameForDataType(type
);
409 return pref_service_
->GetBoolean(pref_name
);
412 void SyncPrefs::SetDataTypePreferred(
413 syncer::ModelType type
, bool is_preferred
) {
414 DCHECK(CalledOnValidThread());
415 CHECK(pref_service_
);
416 const char* pref_name
= GetPrefNameForDataType(type
);
421 pref_service_
->SetBoolean(pref_name
, is_preferred
);
424 syncer::ModelTypeSet
SyncPrefs::ResolvePrefGroups(
425 syncer::ModelTypeSet registered_types
,
426 syncer::ModelTypeSet types
) const {
427 DCHECK(registered_types
.HasAll(types
));
428 syncer::ModelTypeSet types_with_groups
= types
;
429 for (PrefGroupsMap::const_iterator i
= pref_groups_
.begin();
430 i
!= pref_groups_
.end(); ++i
) {
431 if (types
.Has(i
->first
))
432 types_with_groups
.PutAll(i
->second
);
434 types_with_groups
.RemoveAll(i
->second
);
436 types_with_groups
.RetainAll(registered_types
);
437 return types_with_groups
;
440 } // namespace browser_sync