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 19 SyncPrefObserver::~SyncPrefObserver() {} 20 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 32 SyncPrefs::SyncPrefs() : pref_service_(NULL) {} 33 34 SyncPrefs::~SyncPrefs() { DCHECK(CalledOnValidThread()); } 35 36 // static 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 150 void SyncPrefs::AddSyncPrefObserver(SyncPrefObserver* sync_pref_observer) { 151 DCHECK(CalledOnValidThread()); 152 sync_pref_observers_.AddObserver(sync_pref_observer); 153 } 154 155 void SyncPrefs::RemoveSyncPrefObserver(SyncPrefObserver* sync_pref_observer) { 156 DCHECK(CalledOnValidThread()); 157 sync_pref_observers_.RemoveObserver(sync_pref_observer); 158 } 159 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 171 bool SyncPrefs::HasSyncSetupCompleted() const { 172 DCHECK(CalledOnValidThread()); 173 return pref_service_->GetBoolean(prefs::kSyncHasSetupCompleted); 174 } 175 176 void SyncPrefs::SetSyncSetupCompleted() { 177 DCHECK(CalledOnValidThread()); 178 pref_service_->SetBoolean(prefs::kSyncHasSetupCompleted, true); 179 SetStartSuppressed(false); 180 } 181 182 bool SyncPrefs::SyncHasAuthError() const { 183 DCHECK(CalledOnValidThread()); 184 return pref_service_->GetBoolean(prefs::kSyncHasAuthError); 185 } 186 187 void SyncPrefs::SetSyncAuthError(bool error) { 188 DCHECK(CalledOnValidThread()); 189 pref_service_->SetBoolean(prefs::kSyncHasAuthError, error); 190 } 191 192 bool SyncPrefs::IsStartSuppressed() const { 193 DCHECK(CalledOnValidThread()); 194 return pref_service_->GetBoolean(prefs::kSyncSuppressStart); 195 } 196 197 void SyncPrefs::SetStartSuppressed(bool is_suppressed) { 198 DCHECK(CalledOnValidThread()); 199 pref_service_->SetBoolean(prefs::kSyncSuppressStart, is_suppressed); 200 } 201 202 base::Time SyncPrefs::GetLastSyncedTime() const { 203 DCHECK(CalledOnValidThread()); 204 return base::Time::FromInternalValue( 205 pref_service_->GetInt64(prefs::kSyncLastSyncedTime)); 206 } 207 208 void SyncPrefs::SetLastSyncedTime(base::Time time) { 209 DCHECK(CalledOnValidThread()); 210 pref_service_->SetInt64(prefs::kSyncLastSyncedTime, time.ToInternalValue()); 211 } 212 213 bool SyncPrefs::HasKeepEverythingSynced() const { 214 DCHECK(CalledOnValidThread()); 215 return pref_service_->GetBoolean(prefs::kSyncKeepEverythingSynced); 216 } 217 218 void SyncPrefs::SetKeepEverythingSynced(bool keep_everything_synced) { 219 DCHECK(CalledOnValidThread()); 220 pref_service_->SetBoolean(prefs::kSyncKeepEverythingSynced, 221 keep_everything_synced); 222 } 223 224 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 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 253 bool SyncPrefs::IsManaged() const { 254 DCHECK(CalledOnValidThread()); 255 return pref_service_->GetBoolean(prefs::kSyncManaged); 256 } 257 258 std::string SyncPrefs::GetEncryptionBootstrapToken() const { 259 DCHECK(CalledOnValidThread()); 260 return pref_service_->GetString(prefs::kSyncEncryptionBootstrapToken); 261 } 262 263 void SyncPrefs::SetEncryptionBootstrapToken(const std::string& token) { 264 DCHECK(CalledOnValidThread()); 265 pref_service_->SetString(prefs::kSyncEncryptionBootstrapToken, token); 266 } 267 268 std::string SyncPrefs::GetKeystoreEncryptionBootstrapToken() const { 269 DCHECK(CalledOnValidThread()); 270 return pref_service_->GetString(prefs::kSyncKeystoreEncryptionBootstrapToken); 271 } 272 273 void SyncPrefs::SetKeystoreEncryptionBootstrapToken(const std::string& token) { 274 DCHECK(CalledOnValidThread()); 275 pref_service_->SetString(prefs::kSyncKeystoreEncryptionBootstrapToken, token); 276 } 277 278 std::string SyncPrefs::GetSyncSessionsGUID() const { 279 DCHECK(CalledOnValidThread()); 280 return pref_service_->GetString(prefs::kSyncSessionsGUID); 281 } 282 283 void SyncPrefs::SetSyncSessionsGUID(const std::string& guid) { 284 DCHECK(CalledOnValidThread()); 285 pref_service_->SetString(prefs::kSyncSessionsGUID, guid); 286 } 287 288 // static 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) 353 std::string SyncPrefs::GetSpareBootstrapToken() const { 354 DCHECK(CalledOnValidThread()); 355 return pref_service_->GetString(prefs::kSyncSpareBootstrapToken); 356 } 357 358 void SyncPrefs::SetSpareBootstrapToken(const std::string& token) { 359 DCHECK(CalledOnValidThread()); 360 pref_service_->SetString(prefs::kSyncSpareBootstrapToken, token); 361 } 362 #endif 363 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 378 int SyncPrefs::GetRemainingRollbackTries() const { 379 return pref_service_->GetInteger(prefs::kSyncRemainingRollbackTries); 380 } 381 382 void SyncPrefs::SetRemainingRollbackTries(int times) { 383 pref_service_->SetInteger(prefs::kSyncRemainingRollbackTries, times); 384 } 385 386 void SyncPrefs::OnSyncManagedPrefChanged() { 387 DCHECK(CalledOnValidThread()); 388 FOR_EACH_OBSERVER(SyncPrefObserver, 389 sync_pref_observers_, 390 OnSyncManagedPrefChange(*pref_sync_managed_)); 391 } 392 393 void SyncPrefs::SetManagedForTest(bool is_managed) { 394 DCHECK(CalledOnValidThread()); 395 pref_service_->SetBoolean(prefs::kSyncManaged, is_managed); 396 } 397 398 syncer::ModelTypeSet SyncPrefs::GetAcknowledgeSyncedTypesForTest() const { 399 DCHECK(CalledOnValidThread()); 400 return syncer::ModelTypeSetFromValue( 401 *pref_service_->GetList(prefs::kSyncAcknowledgedSyncTypes)); 402 } 403 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 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 448 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 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 477 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 492 base::Time SyncPrefs::GetFirstSyncTime() const { 493 return base::Time::FromInternalValue( 494 pref_service_->GetInt64(prefs::kSyncFirstSyncTime)); 495 } 496 497 void SyncPrefs::SetFirstSyncTime(base::Time time) { 498 pref_service_->SetInt64(prefs::kSyncFirstSyncTime, time.ToInternalValue()); 499 } 500 501 void SyncPrefs::ClearFirstSyncTime() { 502 pref_service_->ClearPref(prefs::kSyncFirstSyncTime); 503 } 504 505 } // namespace browser_sync 506