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