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