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