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