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.
5 #include "chrome/browser/prefs/profile_pref_store_manager.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 "base/sequenced_task_runner.h"
17 #include "chrome/browser/prefs/tracked/pref_hash_store_impl.h"
18 #include "chrome/browser/prefs/tracked/pref_service_hash_store_contents.h"
19 #include "chrome/browser/prefs/tracked/segregated_pref_store.h"
20 #include "chrome/browser/prefs/tracked/tracked_preferences_migration.h"
21 #include "chrome/common/chrome_constants.h"
22 #include "chrome/common/pref_names.h"
23 #include "components/pref_registry/pref_registry_syncable.h"
27 void RemoveValueSilently(const base::WeakPtr
<JsonPrefStore
> pref_store
,
28 const std::string
& key
) {
30 pref_store
->RemoveValueSilently(
31 key
, WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS
);
37 // Preference tracking and protection is not required on platforms where other
38 // apps do not have access to chrome's persistent storage.
39 const bool ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking
=
40 #if defined(OS_ANDROID) || defined(OS_CHROMEOS) || defined(OS_IOS)
46 ProfilePrefStoreManager::ProfilePrefStoreManager(
47 const base::FilePath
& profile_path
,
48 const std::vector
<PrefHashFilter::TrackedPreferenceMetadata
>&
49 tracking_configuration
,
50 size_t reporting_ids_count
,
51 const std::string
& seed
,
52 const std::string
& device_id
,
53 PrefService
* local_state
)
54 : profile_path_(profile_path
),
55 tracking_configuration_(tracking_configuration
),
56 reporting_ids_count_(reporting_ids_count
),
58 device_id_(device_id
),
59 local_state_(local_state
) {}
61 ProfilePrefStoreManager::~ProfilePrefStoreManager() {}
64 void ProfilePrefStoreManager::RegisterPrefs(PrefRegistrySimple
* registry
) {
65 PrefServiceHashStoreContents::RegisterPrefs(registry
);
69 void ProfilePrefStoreManager::RegisterProfilePrefs(
70 user_prefs::PrefRegistrySyncable
* registry
) {
71 PrefHashFilter::RegisterProfilePrefs(registry
);
75 base::FilePath
ProfilePrefStoreManager::GetPrefFilePathFromProfilePath(
76 const base::FilePath
& profile_path
) {
77 return profile_path
.Append(chrome::kPreferencesFilename
);
81 void ProfilePrefStoreManager::ResetAllPrefHashStores(PrefService
* local_state
) {
82 PrefServiceHashStoreContents::ResetAllPrefHashStores(local_state
);
86 base::Time
ProfilePrefStoreManager::GetResetTime(PrefService
* pref_service
) {
87 return PrefHashFilter::GetResetTime(pref_service
);
91 void ProfilePrefStoreManager::ClearResetTime(PrefService
* pref_service
) {
92 PrefHashFilter::ClearResetTime(pref_service
);
95 PersistentPrefStore
* ProfilePrefStoreManager::CreateProfilePrefStore(
96 const scoped_refptr
<base::SequencedTaskRunner
>& io_task_runner
,
97 const base::Closure
& on_reset_on_load
,
98 TrackedPreferenceValidationDelegate
* validation_delegate
) {
99 scoped_ptr
<PrefFilter
> pref_filter
;
100 if (!kPlatformSupportsPreferenceTracking
) {
101 return new JsonPrefStore(GetPrefFilePathFromProfilePath(profile_path_
),
102 io_task_runner
.get(),
103 scoped_ptr
<PrefFilter
>());
106 std::vector
<PrefHashFilter::TrackedPreferenceMetadata
>
107 unprotected_configuration
;
108 std::vector
<PrefHashFilter::TrackedPreferenceMetadata
>
109 protected_configuration
;
110 std::set
<std::string
> protected_pref_names
;
111 std::set
<std::string
> unprotected_pref_names
;
112 for (std::vector
<PrefHashFilter::TrackedPreferenceMetadata
>::const_iterator
113 it
= tracking_configuration_
.begin();
114 it
!= tracking_configuration_
.end();
116 if (it
->enforcement_level
> PrefHashFilter::NO_ENFORCEMENT
) {
117 protected_configuration
.push_back(*it
);
118 protected_pref_names
.insert(it
->name
);
120 unprotected_configuration
.push_back(*it
);
121 unprotected_pref_names
.insert(it
->name
);
125 scoped_ptr
<PrefHashFilter
> unprotected_pref_hash_filter(
126 new PrefHashFilter(GetPrefHashStore(false),
127 unprotected_configuration
,
130 reporting_ids_count_
,
132 scoped_ptr
<PrefHashFilter
> protected_pref_hash_filter(
133 new PrefHashFilter(GetPrefHashStore(true),
134 protected_configuration
,
137 reporting_ids_count_
,
140 PrefHashFilter
* raw_unprotected_pref_hash_filter
=
141 unprotected_pref_hash_filter
.get();
142 PrefHashFilter
* raw_protected_pref_hash_filter
=
143 protected_pref_hash_filter
.get();
145 scoped_refptr
<JsonPrefStore
> unprotected_pref_store(
146 new JsonPrefStore(GetPrefFilePathFromProfilePath(profile_path_
),
147 io_task_runner
.get(),
148 unprotected_pref_hash_filter
.Pass()));
149 // TODO(gab): Remove kDeprecatedProtectedPreferencesFilename as an alternate
151 scoped_refptr
<JsonPrefStore
> protected_pref_store(new JsonPrefStore(
152 profile_path_
.Append(chrome::kSecurePreferencesFilename
),
153 profile_path_
.Append(chrome::kProtectedPreferencesFilenameDeprecated
),
154 io_task_runner
.get(),
155 protected_pref_hash_filter
.Pass()));
157 SetupTrackedPreferencesMigration(
158 unprotected_pref_names
, protected_pref_names
,
159 base::Bind(&RemoveValueSilently
, unprotected_pref_store
->AsWeakPtr()),
160 base::Bind(&RemoveValueSilently
, protected_pref_store
->AsWeakPtr()),
161 base::Bind(&JsonPrefStore::RegisterOnNextSuccessfulWriteCallback
,
162 unprotected_pref_store
->AsWeakPtr()),
163 base::Bind(&JsonPrefStore::RegisterOnNextSuccessfulWriteCallback
,
164 protected_pref_store
->AsWeakPtr()),
165 GetPrefHashStore(false), GetPrefHashStore(true),
166 scoped_ptr
<HashStoreContents
>(new PrefServiceHashStoreContents(
167 profile_path_
.AsUTF8Unsafe(), local_state_
)),
168 raw_unprotected_pref_hash_filter
, raw_protected_pref_hash_filter
);
170 return new SegregatedPrefStore(unprotected_pref_store
, protected_pref_store
,
171 protected_pref_names
);
174 bool ProfilePrefStoreManager::InitializePrefsFromMasterPrefs(
175 const base::DictionaryValue
& master_prefs
) {
176 // Create the profile directory if it doesn't exist yet (very possible on
178 if (!base::CreateDirectory(profile_path_
))
181 const base::DictionaryValue
* to_serialize
= &master_prefs
;
182 scoped_ptr
<base::DictionaryValue
> copy
;
184 if (kPlatformSupportsPreferenceTracking
) {
185 copy
.reset(master_prefs
.DeepCopy());
186 to_serialize
= copy
.get();
187 PrefHashFilter(GetPrefHashStore(false),
188 tracking_configuration_
,
191 reporting_ids_count_
,
192 false).Initialize(copy
.get());
195 // This will write out to a single combined file which will be immediately
196 // migrated to two files on load.
197 JSONFileValueSerializer
serializer(
198 GetPrefFilePathFromProfilePath(profile_path_
));
200 // Call Serialize (which does IO) on the main thread, which would _normally_
201 // be verboten. In this case however, we require this IO to synchronously
202 // complete before Chrome can start (as master preferences seed the Local
203 // State and Preferences files). This won't trip ThreadIORestrictions as they
204 // won't have kicked in yet on the main thread.
205 bool success
= serializer
.Serialize(*to_serialize
);
207 UMA_HISTOGRAM_BOOLEAN("Settings.InitializedFromMasterPrefs", success
);
212 ProfilePrefStoreManager::CreateDeprecatedCombinedProfilePrefStore(
213 const scoped_refptr
<base::SequencedTaskRunner
>& io_task_runner
) {
214 scoped_ptr
<PrefFilter
> pref_filter
;
215 if (kPlatformSupportsPreferenceTracking
) {
216 scoped_ptr
<PrefHashStoreImpl
> pref_hash_store_impl(
217 new PrefHashStoreImpl(seed_
, device_id_
, true));
218 pref_hash_store_impl
->set_legacy_hash_store_contents(
219 scoped_ptr
<HashStoreContents
>(new PrefServiceHashStoreContents(
220 profile_path_
.AsUTF8Unsafe(), local_state_
)));
221 pref_filter
.reset(new PrefHashFilter(pref_hash_store_impl
.Pass(),
222 tracking_configuration_
,
225 reporting_ids_count_
,
228 return new JsonPrefStore(GetPrefFilePathFromProfilePath(profile_path_
),
229 io_task_runner
.get(),
233 scoped_ptr
<PrefHashStore
> ProfilePrefStoreManager::GetPrefHashStore(
234 bool use_super_mac
) {
235 DCHECK(kPlatformSupportsPreferenceTracking
);
237 return scoped_ptr
<PrefHashStore
>(new PrefHashStoreImpl(