1 // Copyright (c) 2011 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/profiles/profile_metrics.h"
7 #include "base/files/file_path.h"
8 #include "base/logging.h"
9 #include "base/metrics/histogram.h"
10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/profiles/profile_info_cache.h"
13 #include "chrome/browser/profiles/profile_manager.h"
14 #include "chrome/browser/signin/signin_header_helper.h"
15 #include "chrome/common/chrome_constants.h"
16 #include "chrome/installer/util/google_update_settings.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "content/public/browser/user_metrics.h"
22 const int kMaximumReportedProfileCount
= 5;
23 const int kMaximumDaysOfDisuse
= 4 * 7; // Should be integral number of weeks.
25 ProfileMetrics::ProfileType
GetProfileType(
26 const base::FilePath
& profile_path
) {
27 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
28 ProfileMetrics::ProfileType metric
= ProfileMetrics::SECONDARY
;
29 ProfileManager
* manager
= g_browser_process
->profile_manager();
30 base::FilePath user_data_dir
;
31 // In unittests, we do not always have a profile_manager so check.
33 user_data_dir
= manager
->user_data_dir();
35 if (profile_path
== user_data_dir
.AppendASCII(chrome::kInitialProfile
)) {
36 metric
= ProfileMetrics::ORIGINAL
;
41 void UpdateReportedOSProfileStatistics(int active
, int signedin
) {
43 GoogleUpdateSettings::UpdateProfileCounts(active
, signedin
);
47 void LogLockedProfileInformation(ProfileManager
* manager
) {
48 const ProfileInfoCache
& info_cache
= manager
->GetProfileInfoCache();
49 size_t number_of_profiles
= info_cache
.GetNumberOfProfiles();
51 base::Time now
= base::Time::Now();
52 const int kMinutesInProfileValidDuration
=
53 base::TimeDelta::FromDays(28).InMinutes();
54 for (size_t i
= 0; i
< number_of_profiles
; ++i
) {
55 // Find when locked profiles were locked
56 if (info_cache
.ProfileIsSigninRequiredAtIndex(i
)) {
57 base::TimeDelta time_since_lock
= now
-
58 info_cache
.GetProfileActiveTimeAtIndex(i
);
59 // Specifying 100 buckets for the histogram to get a higher level of
60 // granularity in the reported data, given the large number of possible
61 // values (kMinutesInProfileValidDuration > 40,000).
62 UMA_HISTOGRAM_CUSTOM_COUNTS("Profile.LockedProfilesDuration",
63 time_since_lock
.InMinutes(),
65 kMinutesInProfileValidDuration
,
71 bool HasProfileAtIndexBeenActiveSince(const ProfileInfoCache
& info_cache
,
73 const base::Time
& active_limit
) {
74 #if !defined(OS_ANDROID) && !defined(OS_IOS)
75 // TODO(mlerman): iOS and Android should set an ActiveTime in the
76 // ProfileInfoCache. (see ProfileManager::OnBrowserSetLastActive)
77 if (info_cache
.GetProfileActiveTimeAtIndex(index
) < active_limit
)
86 AVATAR_GENERIC
= 0, // The names for avatar icons
90 AVATAR_GENERIC_ORANGE
,
91 AVATAR_GENERIC_PURPLE
,
93 AVATAR_GENERIC_YELLOW
,
96 AVATAR_VOLLEYBALL
, // 10
106 AVATAR_CUPCAKE
, // 20
113 AVATAR_UNKNOWN
, // 27
115 NUM_PROFILE_AVATAR_METRICS
118 bool ProfileMetrics::CountProfileInformation(ProfileManager
* manager
,
119 ProfileCounts
* counts
) {
120 const ProfileInfoCache
& info_cache
= manager
->GetProfileInfoCache();
121 size_t number_of_profiles
= info_cache
.GetNumberOfProfiles();
122 counts
->total
= number_of_profiles
;
124 // Ignore other metrics if we have no profiles, e.g. in Chrome Frame tests.
125 if (!number_of_profiles
)
128 // Maximum age for "active" profile is 4 weeks.
129 base::Time oldest
= base::Time::Now() -
130 base::TimeDelta::FromDays(kMaximumDaysOfDisuse
);
132 for (size_t i
= 0; i
< number_of_profiles
; ++i
) {
133 if (!HasProfileAtIndexBeenActiveSince(info_cache
, i
, oldest
)) {
136 if (info_cache
.ProfileIsSupervisedAtIndex(i
))
137 counts
->supervised
++;
138 if (!info_cache
.GetUserNameOfProfileAtIndex(i
).empty()) {
140 if (info_cache
.IsUsingGAIAPictureOfProfileAtIndex(i
))
149 void ProfileMetrics::UpdateReportedProfilesStatistics(ProfileManager
* manager
) {
150 ProfileCounts counts
;
151 if (CountProfileInformation(manager
, &counts
)) {
152 int limited_total
= counts
.total
;
153 int limited_signedin
= counts
.signedin
;
154 if (limited_total
> kMaximumReportedProfileCount
) {
155 limited_total
= kMaximumReportedProfileCount
+ 1;
157 (int)((float)(counts
.signedin
* limited_total
)
158 / counts
.total
+ 0.5);
160 UpdateReportedOSProfileStatistics(limited_total
, limited_signedin
);
164 void ProfileMetrics::LogNumberOfProfiles(ProfileManager
* manager
) {
165 ProfileCounts counts
;
166 bool success
= CountProfileInformation(manager
, &counts
);
167 UMA_HISTOGRAM_COUNTS_100("Profile.NumberOfProfiles", counts
.total
);
169 // Ignore other metrics if we have no profiles, e.g. in Chrome Frame tests.
171 UMA_HISTOGRAM_COUNTS_100("Profile.NumberOfManagedProfiles",
173 UMA_HISTOGRAM_COUNTS_100("Profile.PercentageOfManagedProfiles",
174 100 * counts
.supervised
/ counts
.total
);
175 UMA_HISTOGRAM_COUNTS_100("Profile.NumberOfSignedInProfiles",
177 UMA_HISTOGRAM_COUNTS_100("Profile.NumberOfUnusedProfiles",
179 UMA_HISTOGRAM_COUNTS_100("Profile.NumberOfSignedInProfilesWithGAIAIcons",
182 LogLockedProfileInformation(manager
);
183 UpdateReportedOSProfileStatistics(counts
.total
, counts
.signedin
);
187 void ProfileMetrics::LogProfileAddNewUser(ProfileAdd metric
) {
188 DCHECK(metric
< NUM_PROFILE_ADD_METRICS
);
189 UMA_HISTOGRAM_ENUMERATION("Profile.AddNewUser", metric
,
190 NUM_PROFILE_ADD_METRICS
);
191 UMA_HISTOGRAM_ENUMERATION("Profile.NetUserCount", ADD_NEW_USER
,
192 NUM_PROFILE_NET_METRICS
);
195 void ProfileMetrics::LogProfileAvatarSelection(size_t icon_index
) {
196 DCHECK(icon_index
< NUM_PROFILE_AVATAR_METRICS
);
197 ProfileAvatar icon_name
= AVATAR_UNKNOWN
;
198 switch (icon_index
) {
200 icon_name
= AVATAR_GENERIC
;
203 icon_name
= AVATAR_GENERIC_AQUA
;
206 icon_name
= AVATAR_GENERIC_BLUE
;
209 icon_name
= AVATAR_GENERIC_GREEN
;
212 icon_name
= AVATAR_GENERIC_ORANGE
;
215 icon_name
= AVATAR_GENERIC_PURPLE
;
218 icon_name
= AVATAR_GENERIC_RED
;
221 icon_name
= AVATAR_GENERIC_YELLOW
;
224 icon_name
= AVATAR_SECRET_AGENT
;
227 icon_name
= AVATAR_SUPERHERO
;
230 icon_name
= AVATAR_VOLLEYBALL
;
233 icon_name
= AVATAR_BUSINESSMAN
;
236 icon_name
= AVATAR_NINJA
;
239 icon_name
= AVATAR_ALIEN
;
242 icon_name
= AVATAR_AWESOME
;
245 icon_name
= AVATAR_FLOWER
;
248 icon_name
= AVATAR_PIZZA
;
251 icon_name
= AVATAR_SOCCER
;
254 icon_name
= AVATAR_BURGER
;
257 icon_name
= AVATAR_CAT
;
260 icon_name
= AVATAR_CUPCAKE
;
263 icon_name
= AVATAR_DOG
;
266 icon_name
= AVATAR_HORSE
;
269 icon_name
= AVATAR_MARGARITA
;
272 icon_name
= AVATAR_NOTE
;
275 icon_name
= AVATAR_SUN_CLOUD
;
278 icon_name
= AVATAR_PLACEHOLDER
;
281 icon_name
= AVATAR_GAIA
;
283 default: // We should never actually get here.
287 UMA_HISTOGRAM_ENUMERATION("Profile.Avatar", icon_name
,
288 NUM_PROFILE_AVATAR_METRICS
);
291 void ProfileMetrics::LogProfileDeleteUser(ProfileDelete metric
) {
292 DCHECK(metric
< NUM_DELETE_PROFILE_METRICS
);
293 UMA_HISTOGRAM_ENUMERATION("Profile.DeleteProfileAction", metric
,
294 NUM_DELETE_PROFILE_METRICS
);
295 UMA_HISTOGRAM_ENUMERATION("Profile.NetUserCount", PROFILE_DELETED
,
296 NUM_PROFILE_NET_METRICS
);
299 void ProfileMetrics::LogProfileOpenMethod(ProfileOpen metric
) {
300 DCHECK(metric
< NUM_PROFILE_OPEN_METRICS
);
301 UMA_HISTOGRAM_ENUMERATION("Profile.OpenMethod", metric
,
302 NUM_PROFILE_OPEN_METRICS
);
305 void ProfileMetrics::LogProfileSwitchGaia(ProfileGaia metric
) {
306 if (metric
== GAIA_OPT_IN
)
307 LogProfileAvatarSelection(AVATAR_GAIA
);
308 UMA_HISTOGRAM_ENUMERATION("Profile.SwitchGaiaPhotoSettings",
310 NUM_PROFILE_GAIA_METRICS
);
313 void ProfileMetrics::LogProfileSwitchUser(ProfileOpen metric
) {
314 DCHECK(metric
< NUM_PROFILE_OPEN_METRICS
);
315 UMA_HISTOGRAM_ENUMERATION("Profile.OpenMethod", metric
,
316 NUM_PROFILE_OPEN_METRICS
);
319 void ProfileMetrics::LogProfileSyncInfo(ProfileSync metric
) {
320 DCHECK(metric
< NUM_PROFILE_SYNC_METRICS
);
321 UMA_HISTOGRAM_ENUMERATION("Profile.SyncCustomize", metric
,
322 NUM_PROFILE_SYNC_METRICS
);
325 void ProfileMetrics::LogProfileAuthResult(ProfileAuth metric
) {
326 UMA_HISTOGRAM_ENUMERATION("Profile.AuthResult", metric
,
327 NUM_PROFILE_AUTH_METRICS
);
330 void ProfileMetrics::LogProfileDesktopMenu(
331 ProfileDesktopMenu metric
,
332 signin::GAIAServiceType gaia_service
) {
333 // The first parameter to the histogram needs to be literal, because of the
334 // optimized implementation of |UMA_HISTOGRAM_ENUMERATION|. Do not attempt
336 switch (gaia_service
) {
337 case signin::GAIA_SERVICE_TYPE_NONE
:
338 UMA_HISTOGRAM_ENUMERATION("Profile.DesktopMenu.NonGAIA", metric
,
339 NUM_PROFILE_DESKTOP_MENU_METRICS
);
341 case signin::GAIA_SERVICE_TYPE_SIGNOUT
:
342 UMA_HISTOGRAM_ENUMERATION("Profile.DesktopMenu.GAIASignout", metric
,
343 NUM_PROFILE_DESKTOP_MENU_METRICS
);
345 case signin::GAIA_SERVICE_TYPE_INCOGNITO
:
346 UMA_HISTOGRAM_ENUMERATION("Profile.DesktopMenu.GAIAIncognito",
347 metric
, NUM_PROFILE_DESKTOP_MENU_METRICS
);
349 case signin::GAIA_SERVICE_TYPE_ADDSESSION
:
350 UMA_HISTOGRAM_ENUMERATION("Profile.DesktopMenu.GAIAAddSession", metric
,
351 NUM_PROFILE_DESKTOP_MENU_METRICS
);
353 case signin::GAIA_SERVICE_TYPE_REAUTH
:
354 UMA_HISTOGRAM_ENUMERATION("Profile.DesktopMenu.GAIAReAuth", metric
,
355 NUM_PROFILE_DESKTOP_MENU_METRICS
);
357 case signin::GAIA_SERVICE_TYPE_SIGNUP
:
358 UMA_HISTOGRAM_ENUMERATION("Profile.DesktopMenu.GAIASignup", metric
,
359 NUM_PROFILE_DESKTOP_MENU_METRICS
);
361 case signin::GAIA_SERVICE_TYPE_DEFAULT
:
362 UMA_HISTOGRAM_ENUMERATION("Profile.DesktopMenu.GAIADefault", metric
,
363 NUM_PROFILE_DESKTOP_MENU_METRICS
);
368 void ProfileMetrics::LogProfileDelete(bool profile_was_signed_in
) {
369 UMA_HISTOGRAM_BOOLEAN("Profile.Delete", profile_was_signed_in
);
372 void ProfileMetrics::LogProfileNewAvatarMenuNotYou(
373 ProfileNewAvatarMenuNotYou metric
) {
374 DCHECK_LT(metric
, NUM_PROFILE_AVATAR_MENU_NOT_YOU_METRICS
);
375 UMA_HISTOGRAM_ENUMERATION("Profile.NewAvatarMenu.NotYou", metric
,
376 NUM_PROFILE_AVATAR_MENU_NOT_YOU_METRICS
);
379 void ProfileMetrics::LogProfileNewAvatarMenuSignin(
380 ProfileNewAvatarMenuSignin metric
) {
381 DCHECK_LT(metric
, NUM_PROFILE_AVATAR_MENU_SIGNIN_METRICS
);
382 UMA_HISTOGRAM_ENUMERATION("Profile.NewAvatarMenu.Signin", metric
,
383 NUM_PROFILE_AVATAR_MENU_SIGNIN_METRICS
);
386 void ProfileMetrics::LogProfileNewAvatarMenuUpgrade(
387 ProfileNewAvatarMenuUpgrade metric
) {
388 DCHECK_LT(metric
, NUM_PROFILE_AVATAR_MENU_UPGRADE_METRICS
);
389 UMA_HISTOGRAM_ENUMERATION("Profile.NewAvatarMenu.Upgrade", metric
,
390 NUM_PROFILE_AVATAR_MENU_UPGRADE_METRICS
);
393 #if defined(OS_ANDROID)
394 void ProfileMetrics::LogProfileAndroidAccountManagementMenu(
395 ProfileAndroidAccountManagementMenu metric
,
396 signin::GAIAServiceType gaia_service
) {
397 // The first parameter to the histogram needs to be literal, because of the
398 // optimized implementation of |UMA_HISTOGRAM_ENUMERATION|. Do not attempt
400 switch (gaia_service
) {
401 case signin::GAIA_SERVICE_TYPE_NONE
:
402 UMA_HISTOGRAM_ENUMERATION(
403 "Profile.AndroidAccountManagementMenu.NonGAIA",
405 NUM_PROFILE_ANDROID_ACCOUNT_MANAGEMENT_MENU_METRICS
);
407 case signin::GAIA_SERVICE_TYPE_SIGNOUT
:
408 UMA_HISTOGRAM_ENUMERATION(
409 "Profile.AndroidAccountManagementMenu.GAIASignout",
411 NUM_PROFILE_ANDROID_ACCOUNT_MANAGEMENT_MENU_METRICS
);
413 case signin::GAIA_SERVICE_TYPE_INCOGNITO
:
414 UMA_HISTOGRAM_ENUMERATION(
415 "Profile.AndroidAccountManagementMenu.GAIASignoutIncognito",
417 NUM_PROFILE_ANDROID_ACCOUNT_MANAGEMENT_MENU_METRICS
);
419 case signin::GAIA_SERVICE_TYPE_ADDSESSION
:
420 UMA_HISTOGRAM_ENUMERATION(
421 "Profile.AndroidAccountManagementMenu.GAIAAddSession",
423 NUM_PROFILE_ANDROID_ACCOUNT_MANAGEMENT_MENU_METRICS
);
425 case signin::GAIA_SERVICE_TYPE_REAUTH
:
426 UMA_HISTOGRAM_ENUMERATION(
427 "Profile.AndroidAccountManagementMenu.GAIAReAuth",
429 NUM_PROFILE_ANDROID_ACCOUNT_MANAGEMENT_MENU_METRICS
);
431 case signin::GAIA_SERVICE_TYPE_SIGNUP
:
432 UMA_HISTOGRAM_ENUMERATION(
433 "Profile.AndroidAccountManagementMenu.GAIASignup",
435 NUM_PROFILE_ANDROID_ACCOUNT_MANAGEMENT_MENU_METRICS
);
437 case signin::GAIA_SERVICE_TYPE_DEFAULT
:
438 UMA_HISTOGRAM_ENUMERATION(
439 "Profile.AndroidAccountManagementMenu.GAIADefault",
441 NUM_PROFILE_ANDROID_ACCOUNT_MANAGEMENT_MENU_METRICS
);
445 #endif // defined(OS_ANDROID)
447 void ProfileMetrics::LogProfileLaunch(Profile
* profile
) {
448 base::FilePath profile_path
= profile
->GetPath();
449 UMA_HISTOGRAM_ENUMERATION("Profile.LaunchBrowser",
450 GetProfileType(profile_path
),
451 NUM_PROFILE_TYPE_METRICS
);
453 if (profile
->IsSupervised()) {
454 content::RecordAction(
455 base::UserMetricsAction("ManagedMode_NewManagedUserWindow"));
459 void ProfileMetrics::LogProfileSyncSignIn(const base::FilePath
& profile_path
) {
460 UMA_HISTOGRAM_ENUMERATION("Profile.SyncSignIn",
461 GetProfileType(profile_path
),
462 NUM_PROFILE_TYPE_METRICS
);
465 void ProfileMetrics::LogProfileUpdate(const base::FilePath
& profile_path
) {
466 UMA_HISTOGRAM_ENUMERATION("Profile.Update",
467 GetProfileType(profile_path
),
468 NUM_PROFILE_TYPE_METRICS
);