OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/prefs/pref_metrics_service.h" | 5 #include "chrome/browser/prefs/pref_metrics_service.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/json/json_string_value_serializer.h" | |
10 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
11 #include "base/prefs/pref_registry_simple.h" | 10 #include "base/prefs/pref_registry_simple.h" |
12 #include "base/prefs/pref_service.h" | 11 #include "base/prefs/pref_service.h" |
13 #include "base/prefs/scoped_user_pref_update.h" | |
14 #include "base/strings/string_number_conversions.h" | 12 #include "base/strings/string_number_conversions.h" |
15 #include "chrome/browser/browser_process.h" | 13 #include "chrome/browser/browser_process.h" |
16 #include "chrome/browser/browser_shutdown.h" | 14 #include "chrome/browser/browser_shutdown.h" |
17 // Accessing the Device ID API here is a layering violation. | |
18 // TODO(bbudge) Move the API so it's usable here. | |
19 // http://crbug.com/276485 | |
20 #include "chrome/browser/extensions/api/music_manager_private/device_id.h" | |
21 #include "chrome/browser/prefs/pref_service_syncable.h" | 15 #include "chrome/browser/prefs/pref_service_syncable.h" |
22 #include "chrome/browser/prefs/session_startup_pref.h" | 16 #include "chrome/browser/prefs/session_startup_pref.h" |
23 #include "chrome/browser/prefs/synced_pref_change_registrar.h" | 17 #include "chrome/browser/prefs/synced_pref_change_registrar.h" |
24 #include "chrome/browser/profiles/incognito_helpers.h" | 18 #include "chrome/browser/profiles/incognito_helpers.h" |
25 #include "chrome/browser/profiles/profile.h" | 19 #include "chrome/browser/profiles/profile.h" |
26 #include "chrome/browser/search_engines/template_url_prepopulate_data.h" | 20 #include "chrome/browser/search_engines/template_url_prepopulate_data.h" |
27 #include "chrome/browser/ui/tabs/pinned_tab_codec.h" | 21 #include "chrome/browser/ui/tabs/pinned_tab_codec.h" |
28 #include "chrome/common/chrome_switches.h" | 22 #include "chrome/common/chrome_switches.h" |
29 #include "chrome/common/pref_names.h" | 23 #include "chrome/common/pref_names.h" |
30 #include "components/browser_context_keyed_service/browser_context_dependency_ma
nager.h" | 24 #include "components/browser_context_keyed_service/browser_context_dependency_ma
nager.h" |
31 #include "crypto/hmac.h" | 25 #include "crypto/hmac.h" |
32 #include "grit/browser_resources.h" | |
33 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" | 26 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" |
34 #include "ui/base/resource/resource_bundle.h" | |
35 | 27 |
36 namespace { | 28 namespace { |
37 | 29 |
38 const int kSessionStartupPrefValueMax = SessionStartupPref::kPrefValueMax; | 30 const int kSessionStartupPrefValueMax = SessionStartupPref::kPrefValueMax; |
39 | 31 |
40 // An unregistered preference to fill in indices in kTrackedPrefs below for | |
41 // preferences that aren't defined on every platform. This is fine as the code | |
42 // below (e.g. CheckTrackedPreferences()) skips unregistered preferences and | |
43 // should thus never report any data about that index on the platforms where | |
44 // that preference is unimplemented. | |
45 const char kUnregisteredPreference[] = "_"; | |
46 | |
47 // These preferences must be kept in sync with the TrackedPreference enum in | |
48 // tools/metrics/histograms/histograms.xml. To add a new preference, append it | |
49 // to the array and add a corresponding value to the histogram enum. | |
50 const char* kTrackedPrefs[] = { | |
51 prefs::kShowHomeButton, | |
52 prefs::kHomePageIsNewTabPage, | |
53 prefs::kHomePage, | |
54 prefs::kRestoreOnStartup, | |
55 prefs::kURLsToRestoreOnStartup, | |
56 prefs::kExtensionsPref, | |
57 prefs::kGoogleServicesLastUsername, | |
58 prefs::kSearchProviderOverrides, | |
59 prefs::kDefaultSearchProviderSearchURL, | |
60 prefs::kDefaultSearchProviderKeyword, | |
61 prefs::kDefaultSearchProviderName, | |
62 #if !defined(OS_ANDROID) | |
63 prefs::kPinnedTabs, | |
64 #else | |
65 kUnregisteredPreference, | |
66 #endif | |
67 prefs::kExtensionKnownDisabled, | |
68 prefs::kProfileResetPromptMemento, | |
69 }; | |
70 | |
71 const size_t kSHA256DigestSize = 32; | |
72 | |
73 } // namespace | 32 } // namespace |
74 | 33 |
75 PrefMetricsService::PrefMetricsService(Profile* profile) | 34 PrefMetricsService::PrefMetricsService(Profile* profile) |
76 : profile_(profile), | 35 : profile_(profile), |
77 prefs_(profile_->GetPrefs()), | 36 prefs_(profile_->GetPrefs()), |
78 local_state_(g_browser_process->local_state()), | 37 local_state_(g_browser_process->local_state()), |
79 profile_name_(profile_->GetPath().AsUTF8Unsafe()), | |
80 tracked_pref_paths_(kTrackedPrefs), | |
81 tracked_pref_path_count_(arraysize(kTrackedPrefs)), | |
82 checked_tracked_prefs_(false), | |
83 weak_factory_(this) { | 38 weak_factory_(this) { |
84 pref_hash_seed_ = ResourceBundle::GetSharedInstance().GetRawDataResource( | |
85 IDR_PREF_HASH_SEED_BIN).as_string(); | |
86 | |
87 RecordLaunchPrefs(); | 39 RecordLaunchPrefs(); |
88 | 40 |
89 PrefServiceSyncable* prefs = PrefServiceSyncable::FromProfile(profile_); | 41 PrefServiceSyncable* prefs = PrefServiceSyncable::FromProfile(profile_); |
90 synced_pref_change_registrar_.reset(new SyncedPrefChangeRegistrar(prefs)); | 42 synced_pref_change_registrar_.reset(new SyncedPrefChangeRegistrar(prefs)); |
91 | 43 |
92 RegisterSyncedPrefObservers(); | 44 RegisterSyncedPrefObservers(); |
93 | |
94 // The following code might cause callbacks into this instance before we exit | |
95 // the constructor. This instance should be initialized at this point. | |
96 #if defined(OS_WIN) || defined(OS_MACOSX) | |
97 // We need the machine id to compute pref value hashes. Fetch that, and then | |
98 // call CheckTrackedPreferences in the callback. | |
99 extensions::api::DeviceId::GetDeviceId( | |
100 "PrefMetricsService", // non-empty string to obfuscate the device id. | |
101 Bind(&PrefMetricsService::GetDeviceIdCallback, | |
102 weak_factory_.GetWeakPtr())); | |
103 #endif // defined(OS_WIN) || defined(OS_MACOSX) | |
104 } | 45 } |
105 | 46 |
106 // For unit testing only. | 47 // For unit testing only. |
107 PrefMetricsService::PrefMetricsService(Profile* profile, | 48 PrefMetricsService::PrefMetricsService(Profile* profile, |
108 PrefService* local_state, | 49 PrefService* local_state) |
109 const std::string& device_id, | |
110 const char** tracked_pref_paths, | |
111 int tracked_pref_path_count) | |
112 : profile_(profile), | 50 : profile_(profile), |
113 prefs_(profile->GetPrefs()), | 51 prefs_(profile->GetPrefs()), |
114 local_state_(local_state), | 52 local_state_(local_state), |
115 profile_name_(profile_->GetPath().AsUTF8Unsafe()), | |
116 pref_hash_seed_(kSHA256DigestSize, 0), | |
117 device_id_(device_id), | |
118 tracked_pref_paths_(tracked_pref_paths), | |
119 tracked_pref_path_count_(tracked_pref_path_count), | |
120 checked_tracked_prefs_(false), | |
121 weak_factory_(this) { | 53 weak_factory_(this) { |
122 CheckTrackedPreferences(); | |
123 } | 54 } |
124 | 55 |
125 PrefMetricsService::~PrefMetricsService() { | 56 PrefMetricsService::~PrefMetricsService() { |
126 } | 57 } |
127 | 58 |
128 void PrefMetricsService::RecordLaunchPrefs() { | 59 void PrefMetricsService::RecordLaunchPrefs() { |
129 bool show_home_button = prefs_->GetBoolean(prefs::kShowHomeButton); | 60 bool show_home_button = prefs_->GetBoolean(prefs::kShowHomeButton); |
130 bool home_page_is_ntp = prefs_->GetBoolean(prefs::kHomePageIsNewTabPage); | 61 bool home_page_is_ntp = prefs_->GetBoolean(prefs::kHomePageIsNewTabPage); |
131 UMA_HISTOGRAM_BOOLEAN("Settings.ShowHomeButton", show_home_button); | 62 UMA_HISTOGRAM_BOOLEAN("Settings.ShowHomeButton", show_home_button); |
132 if (show_home_button) { | 63 if (show_home_button) { |
(...skipping 14 matching lines...) Expand all Loading... |
147 "Settings.HomePageEngineType", | 78 "Settings.HomePageEngineType", |
148 TemplateURLPrepopulateData::GetEngineType(homepage_url), | 79 TemplateURLPrepopulateData::GetEngineType(homepage_url), |
149 SEARCH_ENGINE_MAX); | 80 SEARCH_ENGINE_MAX); |
150 } | 81 } |
151 } | 82 } |
152 | 83 |
153 int restore_on_startup = prefs_->GetInteger(prefs::kRestoreOnStartup); | 84 int restore_on_startup = prefs_->GetInteger(prefs::kRestoreOnStartup); |
154 UMA_HISTOGRAM_ENUMERATION("Settings.StartupPageLoadSettings", | 85 UMA_HISTOGRAM_ENUMERATION("Settings.StartupPageLoadSettings", |
155 restore_on_startup, kSessionStartupPrefValueMax); | 86 restore_on_startup, kSessionStartupPrefValueMax); |
156 if (restore_on_startup == SessionStartupPref::kPrefValueURLs) { | 87 if (restore_on_startup == SessionStartupPref::kPrefValueURLs) { |
157 const ListValue* url_list = prefs_->GetList(prefs::kURLsToRestoreOnStartup); | 88 const base::ListValue* url_list = |
| 89 prefs_->GetList(prefs::kURLsToRestoreOnStartup); |
158 UMA_HISTOGRAM_CUSTOM_COUNTS("Settings.StartupPageLoadURLs", | 90 UMA_HISTOGRAM_CUSTOM_COUNTS("Settings.StartupPageLoadURLs", |
159 url_list->GetSize(), 1, 50, 20); | 91 url_list->GetSize(), 1, 50, 20); |
160 // Similarly, check startup pages for known search engine TLD+1s. | 92 // Similarly, check startup pages for known search engine TLD+1s. |
161 std::string url_text; | 93 std::string url_text; |
162 for (size_t i = 0; i < url_list->GetSize(); ++i) { | 94 for (size_t i = 0; i < url_list->GetSize(); ++i) { |
163 if (url_list->GetString(i, &url_text)) { | 95 if (url_list->GetString(i, &url_text)) { |
164 GURL start_url(url_text); | 96 GURL start_url(url_text); |
165 if (start_url.is_valid()) { | 97 if (start_url.is_valid()) { |
166 UMA_HISTOGRAM_ENUMERATION( | 98 UMA_HISTOGRAM_ENUMERATION( |
167 "Settings.StartupPageEngineTypes", | 99 "Settings.StartupPageEngineTypes", |
(...skipping 13 matching lines...) Expand all Loading... |
181 if (start_url.is_valid()) { | 113 if (start_url.is_valid()) { |
182 UMA_HISTOGRAM_ENUMERATION( | 114 UMA_HISTOGRAM_ENUMERATION( |
183 "Settings.PinnedTabEngineTypes", | 115 "Settings.PinnedTabEngineTypes", |
184 TemplateURLPrepopulateData::GetEngineType(start_url), | 116 TemplateURLPrepopulateData::GetEngineType(start_url), |
185 SEARCH_ENGINE_MAX); | 117 SEARCH_ENGINE_MAX); |
186 } | 118 } |
187 } | 119 } |
188 #endif | 120 #endif |
189 } | 121 } |
190 | 122 |
191 // static | |
192 void PrefMetricsService::RegisterPrefs(PrefRegistrySimple* registry) { | |
193 // Register the top level dictionary to map profile names to dictionaries of | |
194 // tracked preferences. | |
195 registry->RegisterDictionaryPref(prefs::kProfilePreferenceHashes); | |
196 } | |
197 | |
198 void PrefMetricsService::RegisterSyncedPrefObservers() { | 123 void PrefMetricsService::RegisterSyncedPrefObservers() { |
199 LogHistogramValueCallback booleanHandler = base::Bind( | 124 LogHistogramValueCallback booleanHandler = base::Bind( |
200 &PrefMetricsService::LogBooleanPrefChange, base::Unretained(this)); | 125 &PrefMetricsService::LogBooleanPrefChange, base::Unretained(this)); |
201 | 126 |
202 AddPrefObserver(prefs::kShowHomeButton, "ShowHomeButton", booleanHandler); | 127 AddPrefObserver(prefs::kShowHomeButton, "ShowHomeButton", booleanHandler); |
203 AddPrefObserver(prefs::kHomePageIsNewTabPage, "HomePageIsNewTabPage", | 128 AddPrefObserver(prefs::kHomePageIsNewTabPage, "HomePageIsNewTabPage", |
204 booleanHandler); | 129 booleanHandler); |
205 | 130 |
206 AddPrefObserver(prefs::kRestoreOnStartup, "StartupPageLoadSettings", | 131 AddPrefObserver(prefs::kRestoreOnStartup, "StartupPageLoadSettings", |
207 base::Bind(&PrefMetricsService::LogIntegerPrefChange, | 132 base::Bind(&PrefMetricsService::LogIntegerPrefChange, |
(...skipping 19 matching lines...) Expand all Loading... |
227 PrefServiceSyncable* prefs = PrefServiceSyncable::FromProfile(profile_); | 152 PrefServiceSyncable* prefs = PrefServiceSyncable::FromProfile(profile_); |
228 const PrefService::Preference* pref = prefs->FindPreference(path.c_str()); | 153 const PrefService::Preference* pref = prefs->FindPreference(path.c_str()); |
229 DCHECK(pref); | 154 DCHECK(pref); |
230 std::string source_name( | 155 std::string source_name( |
231 from_sync ? ".PulledFromSync" : ".PushedToSync"); | 156 from_sync ? ".PulledFromSync" : ".PushedToSync"); |
232 std::string histogram_name("Settings." + histogram_name_prefix + source_name); | 157 std::string histogram_name("Settings." + histogram_name_prefix + source_name); |
233 callback.Run(histogram_name, pref->GetValue()); | 158 callback.Run(histogram_name, pref->GetValue()); |
234 }; | 159 }; |
235 | 160 |
236 void PrefMetricsService::LogBooleanPrefChange(const std::string& histogram_name, | 161 void PrefMetricsService::LogBooleanPrefChange(const std::string& histogram_name, |
237 const Value* value) { | 162 const base::Value* value) { |
238 bool boolean_value = false; | 163 bool boolean_value = false; |
239 if (!value->GetAsBoolean(&boolean_value)) | 164 if (!value->GetAsBoolean(&boolean_value)) |
240 return; | 165 return; |
241 base::HistogramBase* histogram = base::BooleanHistogram::FactoryGet( | 166 base::HistogramBase* histogram = base::BooleanHistogram::FactoryGet( |
242 histogram_name, base::HistogramBase::kUmaTargetedHistogramFlag); | 167 histogram_name, base::HistogramBase::kUmaTargetedHistogramFlag); |
243 histogram->Add(boolean_value); | 168 histogram->Add(boolean_value); |
244 } | 169 } |
245 | 170 |
246 void PrefMetricsService::LogIntegerPrefChange(int boundary_value, | 171 void PrefMetricsService::LogIntegerPrefChange(int boundary_value, |
247 const std::string& histogram_name, | 172 const std::string& histogram_name, |
248 const Value* value) { | 173 const base::Value* value) { |
249 int integer_value = 0; | 174 int integer_value = 0; |
250 if (!value->GetAsInteger(&integer_value)) | 175 if (!value->GetAsInteger(&integer_value)) |
251 return; | 176 return; |
252 base::HistogramBase* histogram = base::LinearHistogram::FactoryGet( | 177 base::HistogramBase* histogram = base::LinearHistogram::FactoryGet( |
253 histogram_name, | 178 histogram_name, |
254 1, | 179 1, |
255 boundary_value, | 180 boundary_value, |
256 boundary_value + 1, | 181 boundary_value + 1, |
257 base::HistogramBase::kUmaTargetedHistogramFlag); | 182 base::HistogramBase::kUmaTargetedHistogramFlag); |
258 histogram->Add(integer_value); | 183 histogram->Add(integer_value); |
259 } | 184 } |
260 | 185 |
261 void PrefMetricsService::GetDeviceIdCallback(const std::string& device_id) { | |
262 #if !defined(OS_WIN) || defined(ENABLE_RLZ) | |
263 // A device_id is expected in all scenarios except when RLZ is disabled on | |
264 // Windows. | |
265 DCHECK(!device_id.empty()); | |
266 #endif | |
267 | |
268 device_id_ = device_id; | |
269 CheckTrackedPreferences(); | |
270 } | |
271 | |
272 // To detect changes to Preferences that happen outside of Chrome, we hash | |
273 // selected pref values and save them in local state. CheckTrackedPreferences | |
274 // compares the saved values to the values observed in the profile's prefs. A | |
275 // dictionary of dictionaries in local state holds the hashed values, grouped by | |
276 // profile. To make the system more resistant to spoofing, pref values are | |
277 // hashed with the pref path and the device id. | |
278 void PrefMetricsService::CheckTrackedPreferences() { | |
279 // Make sure this is only called once per instance of this service. | |
280 DCHECK(!checked_tracked_prefs_); | |
281 checked_tracked_prefs_ = true; | |
282 | |
283 const base::DictionaryValue* pref_hash_dicts = | |
284 local_state_->GetDictionary(prefs::kProfilePreferenceHashes); | |
285 // Get the hashed prefs dictionary if it exists. If it doesn't, it will be | |
286 // created if we set preference values below. | |
287 const base::DictionaryValue* hashed_prefs = NULL; | |
288 pref_hash_dicts->GetDictionaryWithoutPathExpansion(profile_name_, | |
289 &hashed_prefs); | |
290 for (int i = 0; i < tracked_pref_path_count_; ++i) { | |
291 if (!prefs_->FindPreference(tracked_pref_paths_[i])) { | |
292 // All tracked preferences need to have been registered already. | |
293 DCHECK_EQ(kUnregisteredPreference, tracked_pref_paths_[i]); | |
294 continue; | |
295 } | |
296 | |
297 const base::Value* value = prefs_->GetUserPrefValue(tracked_pref_paths_[i]); | |
298 std::string last_hash; | |
299 // First try to get the stored expected hash... | |
300 if (hashed_prefs && | |
301 hashed_prefs->GetString(tracked_pref_paths_[i], &last_hash)) { | |
302 // ... if we have one get the hash of the current value... | |
303 const std::string value_hash = | |
304 GetHashedPrefValue(tracked_pref_paths_[i], value, | |
305 HASHED_PREF_STYLE_NEW); | |
306 // ... and check that it matches... | |
307 if (value_hash == last_hash) { | |
308 UMA_HISTOGRAM_ENUMERATION("Settings.TrackedPreferenceUnchanged", | |
309 i, tracked_pref_path_count_); | |
310 } else { | |
311 // ... if it doesn't: was the value simply cleared? | |
312 if (!value) { | |
313 UMA_HISTOGRAM_ENUMERATION("Settings.TrackedPreferenceCleared", | |
314 i, tracked_pref_path_count_); | |
315 } else { | |
316 // ... or does it match the old style hash? | |
317 std::string old_style_hash = | |
318 GetHashedPrefValue(tracked_pref_paths_[i], value, | |
319 HASHED_PREF_STYLE_DEPRECATED); | |
320 if (old_style_hash == last_hash) { | |
321 UMA_HISTOGRAM_ENUMERATION("Settings.TrackedPreferenceMigrated", | |
322 i, tracked_pref_path_count_); | |
323 } else { | |
324 // ... or was it simply changed to something else? | |
325 UMA_HISTOGRAM_ENUMERATION("Settings.TrackedPreferenceChanged", | |
326 i, tracked_pref_path_count_); | |
327 } | |
328 } | |
329 | |
330 // ... either way update the expected hash to match the new value. | |
331 UpdateTrackedPreference(tracked_pref_paths_[i]); | |
332 } | |
333 } else { | |
334 // Record that we haven't tracked this preference yet, or the hash in | |
335 // local state was removed. | |
336 UMA_HISTOGRAM_ENUMERATION("Settings.TrackedPreferenceInitialized", | |
337 i, tracked_pref_path_count_); | |
338 UpdateTrackedPreference(tracked_pref_paths_[i]); | |
339 } | |
340 } | |
341 | |
342 // Now that we've checked the incoming preferences, register for change | |
343 // notifications, unless this is test code. | |
344 // TODO(bbudge) Fix failing browser_tests and so we can remove this test. | |
345 // Several tests fail when they shutdown before they can write local state. | |
346 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType) && | |
347 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kChromeFrame)) { | |
348 InitializePrefObservers(); | |
349 } | |
350 } | |
351 | |
352 void PrefMetricsService::UpdateTrackedPreference(const char* path) { | |
353 const base::Value* value = prefs_->GetUserPrefValue(path); | |
354 DictionaryPrefUpdate update(local_state_, prefs::kProfilePreferenceHashes); | |
355 DictionaryValue* child_dictionary = NULL; | |
356 | |
357 // Get the dictionary corresponding to the profile name, | |
358 // which may have a '.' | |
359 if (!update->GetDictionaryWithoutPathExpansion(profile_name_, | |
360 &child_dictionary)) { | |
361 child_dictionary = new DictionaryValue; | |
362 update->SetWithoutPathExpansion(profile_name_, child_dictionary); | |
363 } | |
364 | |
365 child_dictionary->SetString(path, | |
366 GetHashedPrefValue(path, value, | |
367 HASHED_PREF_STYLE_NEW)); | |
368 } | |
369 | |
370 std::string PrefMetricsService::GetHashedPrefValue( | |
371 const char* path, | |
372 const base::Value* value, | |
373 HashedPrefStyle desired_style) { | |
374 // Dictionary values may contain empty lists and sub-dictionaries. Make a | |
375 // deep copy with those removed to make the hash more stable. | |
376 const DictionaryValue* dict_value; | |
377 scoped_ptr<DictionaryValue> canonical_dict_value; | |
378 if (value && | |
379 value->GetAsDictionary(&dict_value)) { | |
380 canonical_dict_value.reset(dict_value->DeepCopyWithoutEmptyChildren()); | |
381 value = canonical_dict_value.get(); | |
382 } | |
383 | |
384 std::string value_as_string; | |
385 // If |value| is NULL, we will still build a unique hash based on |device_id_| | |
386 // and |path| below. | |
387 if (value) { | |
388 JSONStringValueSerializer serializer(&value_as_string); | |
389 serializer.Serialize(*value); | |
390 } | |
391 | |
392 std::string string_to_hash; | |
393 // TODO(gab): Remove this as the old style is phased out. | |
394 if (desired_style == HASHED_PREF_STYLE_NEW) { | |
395 string_to_hash.append(device_id_); | |
396 string_to_hash.append(path); | |
397 } | |
398 string_to_hash.append(value_as_string); | |
399 | |
400 crypto::HMAC hmac(crypto::HMAC::SHA256); | |
401 unsigned char digest[kSHA256DigestSize]; | |
402 if (!hmac.Init(pref_hash_seed_) || | |
403 !hmac.Sign(string_to_hash, digest, kSHA256DigestSize)) { | |
404 NOTREACHED(); | |
405 return std::string(); | |
406 } | |
407 | |
408 return base::HexEncode(digest, kSHA256DigestSize); | |
409 } | |
410 | |
411 void PrefMetricsService::InitializePrefObservers() { | |
412 pref_registrar_.Init(prefs_); | |
413 for (int i = 0; i < tracked_pref_path_count_; ++i) { | |
414 if (!prefs_->FindPreference(tracked_pref_paths_[i])) { | |
415 // All tracked preferences need to have been registered already. | |
416 DCHECK_EQ(kUnregisteredPreference, tracked_pref_paths_[i]); | |
417 continue; | |
418 } | |
419 | |
420 pref_registrar_.Add( | |
421 tracked_pref_paths_[i], | |
422 base::Bind(&PrefMetricsService::UpdateTrackedPreference, | |
423 weak_factory_.GetWeakPtr(), | |
424 tracked_pref_paths_[i])); | |
425 } | |
426 } | |
427 | |
428 // static | 186 // static |
429 PrefMetricsService::Factory* PrefMetricsService::Factory::GetInstance() { | 187 PrefMetricsService::Factory* PrefMetricsService::Factory::GetInstance() { |
430 return Singleton<PrefMetricsService::Factory>::get(); | 188 return Singleton<PrefMetricsService::Factory>::get(); |
431 } | 189 } |
432 | 190 |
433 // static | 191 // static |
434 PrefMetricsService* PrefMetricsService::Factory::GetForProfile( | 192 PrefMetricsService* PrefMetricsService::Factory::GetForProfile( |
435 Profile* profile) { | 193 Profile* profile) { |
436 return static_cast<PrefMetricsService*>( | 194 return static_cast<PrefMetricsService*>( |
437 GetInstance()->GetServiceForBrowserContext(profile, true)); | 195 GetInstance()->GetServiceForBrowserContext(profile, true)); |
(...skipping 19 matching lines...) Expand all Loading... |
457 } | 215 } |
458 | 216 |
459 bool PrefMetricsService::Factory::ServiceIsNULLWhileTesting() const { | 217 bool PrefMetricsService::Factory::ServiceIsNULLWhileTesting() const { |
460 return false; | 218 return false; |
461 } | 219 } |
462 | 220 |
463 content::BrowserContext* PrefMetricsService::Factory::GetBrowserContextToUse( | 221 content::BrowserContext* PrefMetricsService::Factory::GetBrowserContextToUse( |
464 content::BrowserContext* context) const { | 222 content::BrowserContext* context) const { |
465 return chrome::GetBrowserContextRedirectedInIncognito(context); | 223 return chrome::GetBrowserContextRedirectedInIncognito(context); |
466 } | 224 } |
OLD | NEW |