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