Home | History | Annotate | Download | only in sync
      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