Home | History | Annotate | Download | only in prefs
      1 // Copyright 2014 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/prefs/profile_pref_store_manager.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/callback.h"
      9 #include "base/files/file_util.h"
     10 #include "base/json/json_file_value_serializer.h"
     11 #include "base/logging.h"
     12 #include "base/metrics/histogram.h"
     13 #include "base/prefs/json_pref_store.h"
     14 #include "base/prefs/persistent_pref_store.h"
     15 #include "base/prefs/pref_registry_simple.h"
     16 #include "chrome/browser/prefs/pref_hash_store_impl.h"
     17 #include "chrome/browser/prefs/tracked/pref_service_hash_store_contents.h"
     18 #include "chrome/browser/prefs/tracked/segregated_pref_store.h"
     19 #include "chrome/browser/prefs/tracked/tracked_preferences_migration.h"
     20 #include "chrome/common/chrome_constants.h"
     21 #include "chrome/common/pref_names.h"
     22 #include "components/pref_registry/pref_registry_syncable.h"
     23 
     24 // TODO(erikwright): Enable this on Chrome OS and Android once MACs are moved
     25 // out of Local State. This will resolve a race condition on Android and a
     26 // privacy issue on ChromeOS. http://crbug.com/349158
     27 const bool ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking =
     28 #if defined(OS_ANDROID) || defined(OS_CHROMEOS)
     29     false;
     30 #else
     31     true;
     32 #endif
     33 
     34 ProfilePrefStoreManager::ProfilePrefStoreManager(
     35     const base::FilePath& profile_path,
     36     const std::vector<PrefHashFilter::TrackedPreferenceMetadata>&
     37         tracking_configuration,
     38     size_t reporting_ids_count,
     39     const std::string& seed,
     40     const std::string& device_id,
     41     PrefService* local_state)
     42     : profile_path_(profile_path),
     43       tracking_configuration_(tracking_configuration),
     44       reporting_ids_count_(reporting_ids_count),
     45       seed_(seed),
     46       device_id_(device_id),
     47       local_state_(local_state) {}
     48 
     49 ProfilePrefStoreManager::~ProfilePrefStoreManager() {}
     50 
     51 // static
     52 void ProfilePrefStoreManager::RegisterPrefs(PrefRegistrySimple* registry) {
     53   PrefServiceHashStoreContents::RegisterPrefs(registry);
     54 }
     55 
     56 // static
     57 void ProfilePrefStoreManager::RegisterProfilePrefs(
     58     user_prefs::PrefRegistrySyncable* registry) {
     59   PrefHashFilter::RegisterProfilePrefs(registry);
     60 }
     61 
     62 // static
     63 base::FilePath ProfilePrefStoreManager::GetPrefFilePathFromProfilePath(
     64     const base::FilePath& profile_path) {
     65   return profile_path.Append(chrome::kPreferencesFilename);
     66 }
     67 
     68 // static
     69 void ProfilePrefStoreManager::ResetAllPrefHashStores(PrefService* local_state) {
     70   PrefServiceHashStoreContents::ResetAllPrefHashStores(local_state);
     71 }
     72 
     73 //  static
     74 base::Time ProfilePrefStoreManager::GetResetTime(PrefService* pref_service) {
     75   return PrefHashFilter::GetResetTime(pref_service);
     76 }
     77 
     78 // static
     79 void ProfilePrefStoreManager::ClearResetTime(PrefService* pref_service) {
     80   PrefHashFilter::ClearResetTime(pref_service);
     81 }
     82 
     83 PersistentPrefStore* ProfilePrefStoreManager::CreateProfilePrefStore(
     84     const scoped_refptr<base::SequencedTaskRunner>& io_task_runner,
     85     const base::Closure& on_reset_on_load,
     86     TrackedPreferenceValidationDelegate* validation_delegate) {
     87   scoped_ptr<PrefFilter> pref_filter;
     88   if (!kPlatformSupportsPreferenceTracking) {
     89     return new JsonPrefStore(GetPrefFilePathFromProfilePath(profile_path_),
     90                              io_task_runner.get(),
     91                              scoped_ptr<PrefFilter>());
     92   }
     93 
     94   std::vector<PrefHashFilter::TrackedPreferenceMetadata>
     95       unprotected_configuration;
     96   std::vector<PrefHashFilter::TrackedPreferenceMetadata>
     97       protected_configuration;
     98   std::set<std::string> protected_pref_names;
     99   std::set<std::string> unprotected_pref_names;
    100   for (std::vector<PrefHashFilter::TrackedPreferenceMetadata>::const_iterator
    101            it = tracking_configuration_.begin();
    102        it != tracking_configuration_.end();
    103        ++it) {
    104     if (it->enforcement_level > PrefHashFilter::NO_ENFORCEMENT) {
    105       protected_configuration.push_back(*it);
    106       protected_pref_names.insert(it->name);
    107     } else {
    108       unprotected_configuration.push_back(*it);
    109       unprotected_pref_names.insert(it->name);
    110     }
    111   }
    112 
    113   scoped_ptr<PrefHashFilter> unprotected_pref_hash_filter(
    114       new PrefHashFilter(GetPrefHashStore(false),
    115                          unprotected_configuration,
    116                          base::Closure(),
    117                          validation_delegate,
    118                          reporting_ids_count_,
    119                          false));
    120   scoped_ptr<PrefHashFilter> protected_pref_hash_filter(
    121       new PrefHashFilter(GetPrefHashStore(true),
    122                          protected_configuration,
    123                          on_reset_on_load,
    124                          validation_delegate,
    125                          reporting_ids_count_,
    126                          true));
    127 
    128   PrefHashFilter* raw_unprotected_pref_hash_filter =
    129       unprotected_pref_hash_filter.get();
    130   PrefHashFilter* raw_protected_pref_hash_filter =
    131       protected_pref_hash_filter.get();
    132 
    133   scoped_refptr<JsonPrefStore> unprotected_pref_store(
    134       new JsonPrefStore(GetPrefFilePathFromProfilePath(profile_path_),
    135                         io_task_runner.get(),
    136                         unprotected_pref_hash_filter.PassAs<PrefFilter>()));
    137   // TODO(gab): Remove kDeprecatedProtectedPreferencesFilename as an alternate
    138   // file in M40+.
    139   scoped_refptr<JsonPrefStore> protected_pref_store(new JsonPrefStore(
    140       profile_path_.Append(chrome::kSecurePreferencesFilename),
    141       profile_path_.Append(chrome::kProtectedPreferencesFilenameDeprecated),
    142       io_task_runner.get(),
    143       protected_pref_hash_filter.PassAs<PrefFilter>()));
    144 
    145   SetupTrackedPreferencesMigration(
    146       unprotected_pref_names,
    147       protected_pref_names,
    148       base::Bind(&JsonPrefStore::RemoveValueSilently,
    149                  unprotected_pref_store->AsWeakPtr()),
    150       base::Bind(&JsonPrefStore::RemoveValueSilently,
    151                  protected_pref_store->AsWeakPtr()),
    152       base::Bind(&JsonPrefStore::RegisterOnNextSuccessfulWriteCallback,
    153                  unprotected_pref_store->AsWeakPtr()),
    154       base::Bind(&JsonPrefStore::RegisterOnNextSuccessfulWriteCallback,
    155                  protected_pref_store->AsWeakPtr()),
    156       GetPrefHashStore(false),
    157       GetPrefHashStore(true),
    158       scoped_ptr<HashStoreContents>(new PrefServiceHashStoreContents(
    159           profile_path_.AsUTF8Unsafe(), local_state_)),
    160       raw_unprotected_pref_hash_filter,
    161       raw_protected_pref_hash_filter);
    162 
    163   return new SegregatedPrefStore(unprotected_pref_store, protected_pref_store,
    164                                  protected_pref_names);
    165 }
    166 
    167 bool ProfilePrefStoreManager::InitializePrefsFromMasterPrefs(
    168     const base::DictionaryValue& master_prefs) {
    169   // Create the profile directory if it doesn't exist yet (very possible on
    170   // first run).
    171   if (!base::CreateDirectory(profile_path_))
    172     return false;
    173 
    174   const base::DictionaryValue* to_serialize = &master_prefs;
    175   scoped_ptr<base::DictionaryValue> copy;
    176 
    177   if (kPlatformSupportsPreferenceTracking) {
    178     copy.reset(master_prefs.DeepCopy());
    179     to_serialize = copy.get();
    180     PrefHashFilter(GetPrefHashStore(false),
    181                    tracking_configuration_,
    182                    base::Closure(),
    183                    NULL,
    184                    reporting_ids_count_,
    185                    false).Initialize(copy.get());
    186   }
    187 
    188   // This will write out to a single combined file which will be immediately
    189   // migrated to two files on load.
    190   JSONFileValueSerializer serializer(
    191       GetPrefFilePathFromProfilePath(profile_path_));
    192 
    193   // Call Serialize (which does IO) on the main thread, which would _normally_
    194   // be verboten. In this case however, we require this IO to synchronously
    195   // complete before Chrome can start (as master preferences seed the Local
    196   // State and Preferences files). This won't trip ThreadIORestrictions as they
    197   // won't have kicked in yet on the main thread.
    198   bool success = serializer.Serialize(*to_serialize);
    199 
    200   UMA_HISTOGRAM_BOOLEAN("Settings.InitializedFromMasterPrefs", success);
    201   return success;
    202 }
    203 
    204 PersistentPrefStore*
    205 ProfilePrefStoreManager::CreateDeprecatedCombinedProfilePrefStore(
    206     const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) {
    207   scoped_ptr<PrefFilter> pref_filter;
    208   if (kPlatformSupportsPreferenceTracking) {
    209     scoped_ptr<PrefHashStoreImpl> pref_hash_store_impl(
    210         new PrefHashStoreImpl(seed_, device_id_, true));
    211     pref_hash_store_impl->set_legacy_hash_store_contents(
    212         scoped_ptr<HashStoreContents>(new PrefServiceHashStoreContents(
    213             profile_path_.AsUTF8Unsafe(), local_state_)));
    214     pref_filter.reset(
    215         new PrefHashFilter(pref_hash_store_impl.PassAs<PrefHashStore>(),
    216                            tracking_configuration_,
    217                            base::Closure(),
    218                            NULL,
    219                            reporting_ids_count_,
    220                            false));
    221   }
    222   return new JsonPrefStore(GetPrefFilePathFromProfilePath(profile_path_),
    223                            io_task_runner.get(),
    224                            pref_filter.Pass());
    225 }
    226 
    227 scoped_ptr<PrefHashStore> ProfilePrefStoreManager::GetPrefHashStore(
    228     bool use_super_mac) {
    229   DCHECK(kPlatformSupportsPreferenceTracking);
    230 
    231   return scoped_ptr<PrefHashStore>(new PrefHashStoreImpl(
    232       seed_,
    233       device_id_,
    234       use_super_mac));
    235 }
    236