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 struct ProfileCounts
{
31 ProfileCounts() : total(0), signedin(0), managed(0), unused(0) {}
34 ProfileMetrics::ProfileType
GetProfileType(
35 const base::FilePath
& profile_path
) {
36 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
37 ProfileMetrics::ProfileType metric
= ProfileMetrics::SECONDARY
;
38 ProfileManager
* manager
= g_browser_process
->profile_manager();
39 base::FilePath user_data_dir
;
40 // In unittests, we do not always have a profile_manager so check.
42 user_data_dir
= manager
->user_data_dir();
44 if (profile_path
== user_data_dir
.AppendASCII(chrome::kInitialProfile
)) {
45 metric
= ProfileMetrics::ORIGINAL
;
50 void UpdateReportedOSProfileStatistics(int active
, int signedin
) {
52 GoogleUpdateSettings::UpdateProfileCounts(active
, signedin
);
56 bool CountProfileInformation(ProfileManager
* manager
, ProfileCounts
* counts
) {
57 const ProfileInfoCache
& info_cache
= manager
->GetProfileInfoCache();
58 size_t number_of_profiles
= info_cache
.GetNumberOfProfiles();
59 counts
->total
= number_of_profiles
;
61 // Ignore other metrics if we have no profiles, e.g. in Chrome Frame tests.
62 if (!number_of_profiles
)
65 // Maximum age for "active" profile is 4 weeks.
66 base::Time oldest
= base::Time::Now() -
67 base::TimeDelta::FromDays(kMaximumDaysOfDisuse
);
69 for (size_t i
= 0; i
< number_of_profiles
; ++i
) {
70 if (info_cache
.GetProfileActiveTimeAtIndex(i
) < oldest
) {
73 if (info_cache
.ProfileIsManagedAtIndex(i
))
75 if (!info_cache
.GetUserNameOfProfileAtIndex(i
).empty())
85 AVATAR_GENERIC
= 0, // The names for avatar icons
89 AVATAR_GENERIC_ORANGE
,
90 AVATAR_GENERIC_PURPLE
,
92 AVATAR_GENERIC_YELLOW
,
95 AVATAR_VOLLEYBALL
, // 10
105 AVATAR_CUPCAKE
, // 20
112 AVATAR_UNKNOWN
, // 27
114 NUM_PROFILE_AVATAR_METRICS
117 void ProfileMetrics::UpdateReportedProfilesStatistics(ProfileManager
* manager
) {
118 ProfileCounts counts
;
119 if (CountProfileInformation(manager
, &counts
)) {
120 int limited_total
= counts
.total
;
121 int limited_signedin
= counts
.signedin
;
122 if (limited_total
> kMaximumReportedProfileCount
) {
123 limited_total
= kMaximumReportedProfileCount
+ 1;
125 (int)((float)(counts
.signedin
* limited_total
)
126 / counts
.total
+ 0.5);
128 UpdateReportedOSProfileStatistics(limited_total
, limited_signedin
);
132 void ProfileMetrics::LogNumberOfProfiles(ProfileManager
* manager
) {
133 ProfileCounts counts
;
134 bool success
= CountProfileInformation(manager
, &counts
);
135 UMA_HISTOGRAM_COUNTS_100("Profile.NumberOfProfiles", counts
.total
);
137 // Ignore other metrics if we have no profiles, e.g. in Chrome Frame tests.
139 UMA_HISTOGRAM_COUNTS_100("Profile.NumberOfManagedProfiles",
141 UMA_HISTOGRAM_COUNTS_100("Profile.PercentageOfManagedProfiles",
142 100 * counts
.managed
/ counts
.total
);
143 UMA_HISTOGRAM_COUNTS_100("Profile.NumberOfSignedInProfiles",
145 UMA_HISTOGRAM_COUNTS_100("Profile.NumberOfUnusedProfiles",
148 UpdateReportedOSProfileStatistics(counts
.total
, counts
.signedin
);
152 void ProfileMetrics::LogProfileAddNewUser(ProfileAdd metric
) {
153 DCHECK(metric
< NUM_PROFILE_ADD_METRICS
);
154 UMA_HISTOGRAM_ENUMERATION("Profile.AddNewUser", metric
,
155 NUM_PROFILE_ADD_METRICS
);
156 UMA_HISTOGRAM_ENUMERATION("Profile.NetUserCount", ADD_NEW_USER
,
157 NUM_PROFILE_NET_METRICS
);
160 void ProfileMetrics::LogProfileAvatarSelection(size_t icon_index
) {
161 DCHECK(icon_index
< NUM_PROFILE_AVATAR_METRICS
);
162 ProfileAvatar icon_name
= AVATAR_UNKNOWN
;
163 switch (icon_index
) {
165 icon_name
= AVATAR_GENERIC
;
168 icon_name
= AVATAR_GENERIC_AQUA
;
171 icon_name
= AVATAR_GENERIC_BLUE
;
174 icon_name
= AVATAR_GENERIC_GREEN
;
177 icon_name
= AVATAR_GENERIC_ORANGE
;
180 icon_name
= AVATAR_GENERIC_PURPLE
;
183 icon_name
= AVATAR_GENERIC_RED
;
186 icon_name
= AVATAR_GENERIC_YELLOW
;
189 icon_name
= AVATAR_SECRET_AGENT
;
192 icon_name
= AVATAR_SUPERHERO
;
195 icon_name
= AVATAR_VOLLEYBALL
;
198 icon_name
= AVATAR_BUSINESSMAN
;
201 icon_name
= AVATAR_NINJA
;
204 icon_name
= AVATAR_ALIEN
;
207 icon_name
= AVATAR_AWESOME
;
210 icon_name
= AVATAR_FLOWER
;
213 icon_name
= AVATAR_PIZZA
;
216 icon_name
= AVATAR_SOCCER
;
219 icon_name
= AVATAR_BURGER
;
222 icon_name
= AVATAR_CAT
;
225 icon_name
= AVATAR_CUPCAKE
;
228 icon_name
= AVATAR_DOG
;
231 icon_name
= AVATAR_HORSE
;
234 icon_name
= AVATAR_MARGARITA
;
237 icon_name
= AVATAR_NOTE
;
240 icon_name
= AVATAR_SUN_CLOUD
;
243 icon_name
= AVATAR_PLACEHOLDER
;
246 icon_name
= AVATAR_GAIA
;
248 default: // We should never actually get here.
252 UMA_HISTOGRAM_ENUMERATION("Profile.Avatar", icon_name
,
253 NUM_PROFILE_AVATAR_METRICS
);
256 void ProfileMetrics::LogProfileDeleteUser(ProfileNetUserCounts metric
) {
257 DCHECK(metric
< NUM_PROFILE_NET_METRICS
);
258 UMA_HISTOGRAM_ENUMERATION("Profile.NetUserCount", metric
,
259 NUM_PROFILE_NET_METRICS
);
262 void ProfileMetrics::LogProfileOpenMethod(ProfileOpen metric
) {
263 DCHECK(metric
< NUM_PROFILE_OPEN_METRICS
);
264 UMA_HISTOGRAM_ENUMERATION("Profile.OpenMethod", metric
,
265 NUM_PROFILE_OPEN_METRICS
);
268 void ProfileMetrics::LogProfileSwitchGaia(ProfileGaia metric
) {
269 if (metric
== GAIA_OPT_IN
)
270 LogProfileAvatarSelection(AVATAR_GAIA
);
271 UMA_HISTOGRAM_ENUMERATION("Profile.SwitchGaiaPhotoSettings",
273 NUM_PROFILE_GAIA_METRICS
);
276 void ProfileMetrics::LogProfileSwitchUser(ProfileOpen metric
) {
277 DCHECK(metric
< NUM_PROFILE_OPEN_METRICS
);
278 UMA_HISTOGRAM_ENUMERATION("Profile.OpenMethod", metric
,
279 NUM_PROFILE_OPEN_METRICS
);
282 void ProfileMetrics::LogProfileSyncInfo(ProfileSync metric
) {
283 DCHECK(metric
< NUM_PROFILE_SYNC_METRICS
);
284 UMA_HISTOGRAM_ENUMERATION("Profile.SyncCustomize", metric
,
285 NUM_PROFILE_SYNC_METRICS
);
288 void ProfileMetrics::LogProfileAuthResult(ProfileAuth metric
) {
289 UMA_HISTOGRAM_ENUMERATION("Profile.AuthResult", metric
,
290 NUM_PROFILE_AUTH_METRICS
);
293 void ProfileMetrics::LogProfileUpgradeEnrollment(
294 ProfileUpgradeEnrollment metric
) {
295 UMA_HISTOGRAM_ENUMERATION("Profile.UpgradeEnrollment", metric
,
296 NUM_PROFILE_ENROLLMENT_METRICS
);
299 void ProfileMetrics::LogProfileDesktopMenu(
300 ProfileDesktopMenu metric
,
301 signin::GAIAServiceType gaia_service
) {
302 // The first parameter to the histogram needs to be literal, because of the
303 // optimized implementation of |UMA_HISTOGRAM_ENUMERATION|. Do not attempt
305 switch (gaia_service
) {
306 case signin::GAIA_SERVICE_TYPE_NONE
:
307 UMA_HISTOGRAM_ENUMERATION("Profile.DesktopMenu.NonGAIA", metric
,
308 NUM_PROFILE_DESKTOP_MENU_METRICS
);
310 case signin::GAIA_SERVICE_TYPE_SIGNOUT
:
311 UMA_HISTOGRAM_ENUMERATION("Profile.DesktopMenu.GAIASignout", metric
,
312 NUM_PROFILE_DESKTOP_MENU_METRICS
);
314 case signin::GAIA_SERVICE_TYPE_INCOGNITO
:
315 UMA_HISTOGRAM_ENUMERATION("Profile.DesktopMenu.GAIAIncognito",
316 metric
, NUM_PROFILE_DESKTOP_MENU_METRICS
);
318 case signin::GAIA_SERVICE_TYPE_ADDSESSION
:
319 UMA_HISTOGRAM_ENUMERATION("Profile.DesktopMenu.GAIAAddSession", metric
,
320 NUM_PROFILE_DESKTOP_MENU_METRICS
);
322 case signin::GAIA_SERVICE_TYPE_REAUTH
:
323 UMA_HISTOGRAM_ENUMERATION("Profile.DesktopMenu.GAIAReAuth", metric
,
324 NUM_PROFILE_DESKTOP_MENU_METRICS
);
326 case signin::GAIA_SERVICE_TYPE_DEFAULT
:
327 UMA_HISTOGRAM_ENUMERATION("Profile.DesktopMenu.GAIADefault", metric
,
328 NUM_PROFILE_DESKTOP_MENU_METRICS
);
333 #if defined(OS_ANDROID)
334 void ProfileMetrics::LogProfileAndroidAccountManagementMenu(
335 ProfileAndroidAccountManagementMenu metric
,
336 signin::GAIAServiceType gaia_service
) {
337 // The first parameter to the histogram needs to be literal, because of the
338 // optimized implementation of |UMA_HISTOGRAM_ENUMERATION|. Do not attempt
340 switch (gaia_service
) {
341 case signin::GAIA_SERVICE_TYPE_NONE
:
342 UMA_HISTOGRAM_ENUMERATION(
343 "Profile.AndroidAccountManagementMenu.NonGAIA",
345 NUM_PROFILE_ANDROID_ACCOUNT_MANAGEMENT_MENU_METRICS
);
347 case signin::GAIA_SERVICE_TYPE_SIGNOUT
:
348 UMA_HISTOGRAM_ENUMERATION(
349 "Profile.AndroidAccountManagementMenu.GAIASignout",
351 NUM_PROFILE_ANDROID_ACCOUNT_MANAGEMENT_MENU_METRICS
);
353 case signin::GAIA_SERVICE_TYPE_INCOGNITO
:
354 UMA_HISTOGRAM_ENUMERATION(
355 "Profile.AndroidAccountManagementMenu.GAIASignoutIncognito",
357 NUM_PROFILE_ANDROID_ACCOUNT_MANAGEMENT_MENU_METRICS
);
359 case signin::GAIA_SERVICE_TYPE_ADDSESSION
:
360 UMA_HISTOGRAM_ENUMERATION(
361 "Profile.AndroidAccountManagementMenu.GAIAAddSession",
363 NUM_PROFILE_ANDROID_ACCOUNT_MANAGEMENT_MENU_METRICS
);
365 case signin::GAIA_SERVICE_TYPE_REAUTH
:
366 UMA_HISTOGRAM_ENUMERATION(
367 "Profile.AndroidAccountManagementMenu.GAIAReAuth",
369 NUM_PROFILE_ANDROID_ACCOUNT_MANAGEMENT_MENU_METRICS
);
371 case signin::GAIA_SERVICE_TYPE_DEFAULT
:
372 UMA_HISTOGRAM_ENUMERATION(
373 "Profile.AndroidAccountManagementMenu.GAIADefault",
375 NUM_PROFILE_ANDROID_ACCOUNT_MANAGEMENT_MENU_METRICS
);
379 #endif // defined(OS_ANDROID)
381 void ProfileMetrics::LogProfileLaunch(Profile
* profile
) {
382 base::FilePath profile_path
= profile
->GetPath();
383 UMA_HISTOGRAM_ENUMERATION("Profile.LaunchBrowser",
384 GetProfileType(profile_path
),
385 NUM_PROFILE_TYPE_METRICS
);
387 if (profile
->IsManaged()) {
388 content::RecordAction(
389 base::UserMetricsAction("ManagedMode_NewManagedUserWindow"));
393 void ProfileMetrics::LogProfileSyncSignIn(const base::FilePath
& profile_path
) {
394 UMA_HISTOGRAM_ENUMERATION("Profile.SyncSignIn",
395 GetProfileType(profile_path
),
396 NUM_PROFILE_TYPE_METRICS
);
399 void ProfileMetrics::LogProfileUpdate(const base::FilePath
& profile_path
) {
400 UMA_HISTOGRAM_ENUMERATION("Profile.Update",
401 GetProfileType(profile_path
),
402 NUM_PROFILE_TYPE_METRICS
);