Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1221)

Side by Side Diff: chrome/browser/prefs/pref_metrics_service.cc

Issue 90563003: Fix a race condition in preference metric reporting. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Respond to Gab's comments. Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
gab 2013/12/06 17:23:38 Perhaps include this bug in this CL's description
erikwright (departed) 2013/12/09 17:59:40 I migrated the bug link into profile_impl.cc (wher
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(
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
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 13 matching lines...) Expand all
182 if (start_url.is_valid()) { 122 if (start_url.is_valid()) {
183 UMA_HISTOGRAM_ENUMERATION( 123 UMA_HISTOGRAM_ENUMERATION(
184 "Settings.PinnedTabEngineTypes", 124 "Settings.PinnedTabEngineTypes",
185 TemplateURLPrepopulateData::GetEngineType(start_url), 125 TemplateURLPrepopulateData::GetEngineType(start_url),
186 SEARCH_ENGINE_MAX); 126 SEARCH_ENGINE_MAX);
187 } 127 }
188 } 128 }
189 #endif 129 #endif
190 } 130 }
191 131
192 // static
193 void PrefMetricsService::RegisterPrefs(PrefRegistrySimple* registry) {
194 // Register the top level dictionary to map profile names to dictionaries of
195 // tracked preferences.
196 registry->RegisterDictionaryPref(prefs::kProfilePreferenceHashes);
197 }
198
199 void PrefMetricsService::RegisterSyncedPrefObservers() { 132 void PrefMetricsService::RegisterSyncedPrefObservers() {
200 LogHistogramValueCallback booleanHandler = base::Bind( 133 LogHistogramValueCallback booleanHandler = base::Bind(
201 &PrefMetricsService::LogBooleanPrefChange, base::Unretained(this)); 134 &PrefMetricsService::LogBooleanPrefChange, base::Unretained(this));
202 135
203 AddPrefObserver(prefs::kShowHomeButton, "ShowHomeButton", booleanHandler); 136 AddPrefObserver(prefs::kShowHomeButton, "ShowHomeButton", booleanHandler);
204 AddPrefObserver(prefs::kHomePageIsNewTabPage, "HomePageIsNewTabPage", 137 AddPrefObserver(prefs::kHomePageIsNewTabPage, "HomePageIsNewTabPage",
205 booleanHandler); 138 booleanHandler);
206 139
207 AddPrefObserver(prefs::kRestoreOnStartup, "StartupPageLoadSettings", 140 AddPrefObserver(prefs::kRestoreOnStartup, "StartupPageLoadSettings",
208 base::Bind(&PrefMetricsService::LogIntegerPrefChange, 141 base::Bind(&PrefMetricsService::LogIntegerPrefChange,
(...skipping 19 matching lines...) Expand all
228 PrefServiceSyncable* prefs = PrefServiceSyncable::FromProfile(profile_); 161 PrefServiceSyncable* prefs = PrefServiceSyncable::FromProfile(profile_);
229 const PrefService::Preference* pref = prefs->FindPreference(path.c_str()); 162 const PrefService::Preference* pref = prefs->FindPreference(path.c_str());
230 DCHECK(pref); 163 DCHECK(pref);
231 std::string source_name( 164 std::string source_name(
232 from_sync ? ".PulledFromSync" : ".PushedToSync"); 165 from_sync ? ".PulledFromSync" : ".PushedToSync");
233 std::string histogram_name("Settings." + histogram_name_prefix + source_name); 166 std::string histogram_name("Settings." + histogram_name_prefix + source_name);
234 callback.Run(histogram_name, pref->GetValue()); 167 callback.Run(histogram_name, pref->GetValue());
235 }; 168 };
236 169
237 void PrefMetricsService::LogBooleanPrefChange(const std::string& histogram_name, 170 void PrefMetricsService::LogBooleanPrefChange(const std::string& histogram_name,
238 const Value* value) { 171 const base::Value* value) {
239 bool boolean_value = false; 172 bool boolean_value = false;
240 if (!value->GetAsBoolean(&boolean_value)) 173 if (!value->GetAsBoolean(&boolean_value))
241 return; 174 return;
242 base::HistogramBase* histogram = base::BooleanHistogram::FactoryGet( 175 base::HistogramBase* histogram = base::BooleanHistogram::FactoryGet(
243 histogram_name, base::HistogramBase::kUmaTargetedHistogramFlag); 176 histogram_name, base::HistogramBase::kUmaTargetedHistogramFlag);
244 histogram->Add(boolean_value); 177 histogram->Add(boolean_value);
245 } 178 }
246 179
247 void PrefMetricsService::LogIntegerPrefChange(int boundary_value, 180 void PrefMetricsService::LogIntegerPrefChange(int boundary_value,
248 const std::string& histogram_name, 181 const std::string& histogram_name,
249 const Value* value) { 182 const base::Value* value) {
250 int integer_value = 0; 183 int integer_value = 0;
251 if (!value->GetAsInteger(&integer_value)) 184 if (!value->GetAsInteger(&integer_value))
252 return; 185 return;
253 base::HistogramBase* histogram = base::LinearHistogram::FactoryGet( 186 base::HistogramBase* histogram = base::LinearHistogram::FactoryGet(
254 histogram_name, 187 histogram_name,
255 1, 188 1,
256 boundary_value, 189 boundary_value,
257 boundary_value + 1, 190 boundary_value + 1,
258 base::HistogramBase::kUmaTargetedHistogramFlag); 191 base::HistogramBase::kUmaTargetedHistogramFlag);
259 histogram->Add(integer_value); 192 histogram->Add(integer_value);
260 } 193 }
261 194
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 195 // static
422 PrefMetricsService::Factory* PrefMetricsService::Factory::GetInstance() { 196 PrefMetricsService::Factory* PrefMetricsService::Factory::GetInstance() {
423 return Singleton<PrefMetricsService::Factory>::get(); 197 return Singleton<PrefMetricsService::Factory>::get();
424 } 198 }
425 199
426 // static 200 // static
427 PrefMetricsService* PrefMetricsService::Factory::GetForProfile( 201 PrefMetricsService* PrefMetricsService::Factory::GetForProfile(
428 Profile* profile) { 202 Profile* profile) {
429 return static_cast<PrefMetricsService*>( 203 return static_cast<PrefMetricsService*>(
430 GetInstance()->GetServiceForBrowserContext(profile, true)); 204 GetInstance()->GetServiceForBrowserContext(profile, true));
(...skipping 19 matching lines...) Expand all
450 } 224 }
451 225
452 bool PrefMetricsService::Factory::ServiceIsNULLWhileTesting() const { 226 bool PrefMetricsService::Factory::ServiceIsNULLWhileTesting() const {
453 return false; 227 return false;
454 } 228 }
455 229
456 content::BrowserContext* PrefMetricsService::Factory::GetBrowserContextToUse( 230 content::BrowserContext* PrefMetricsService::Factory::GetBrowserContextToUse(
457 content::BrowserContext* context) const { 231 content::BrowserContext* context) const {
458 return chrome::GetBrowserContextRedirectedInIncognito(context); 232 return chrome::GetBrowserContextRedirectedInIncognito(context);
459 } 233 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698