• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/browser/profiles/profile_metrics.h"
6 
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"
19 
20 namespace {
21 
22 const int kMaximumReportedProfileCount = 5;
23 const int kMaximumDaysOfDisuse = 4 * 7;  // Should be integral number of weeks.
24 
25 struct ProfileCounts {
26   size_t total;
27   size_t signedin;
28   size_t supervised;
29   size_t unused;
30   size_t gaia_icon;
31 
ProfileCounts__anon735b6b3d0111::ProfileCounts32   ProfileCounts()
33       : total(0), signedin(0), supervised(0), unused(0), gaia_icon(0) {}
34 };
35 
GetProfileType(const base::FilePath & profile_path)36 ProfileMetrics::ProfileType GetProfileType(
37     const base::FilePath& profile_path) {
38   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
39   ProfileMetrics::ProfileType metric = ProfileMetrics::SECONDARY;
40   ProfileManager* manager = g_browser_process->profile_manager();
41   base::FilePath user_data_dir;
42   // In unittests, we do not always have a profile_manager so check.
43   if (manager) {
44     user_data_dir = manager->user_data_dir();
45   }
46   if (profile_path == user_data_dir.AppendASCII(chrome::kInitialProfile)) {
47     metric = ProfileMetrics::ORIGINAL;
48   }
49   return metric;
50 }
51 
UpdateReportedOSProfileStatistics(int active,int signedin)52 void UpdateReportedOSProfileStatistics(int active, int signedin) {
53 #if defined(OS_WIN)
54   GoogleUpdateSettings::UpdateProfileCounts(active, signedin);
55 #endif
56 }
57 
CountProfileInformation(ProfileManager * manager,ProfileCounts * counts)58 bool CountProfileInformation(ProfileManager* manager, ProfileCounts* counts) {
59   const ProfileInfoCache& info_cache = manager->GetProfileInfoCache();
60   size_t number_of_profiles = info_cache.GetNumberOfProfiles();
61   counts->total = number_of_profiles;
62 
63   // Ignore other metrics if we have no profiles, e.g. in Chrome Frame tests.
64   if (!number_of_profiles)
65     return false;
66 
67   // Maximum age for "active" profile is 4 weeks.
68   base::Time oldest = base::Time::Now() -
69       base::TimeDelta::FromDays(kMaximumDaysOfDisuse);
70 
71   for (size_t i = 0; i < number_of_profiles; ++i) {
72     if (info_cache.GetProfileActiveTimeAtIndex(i) < oldest) {
73       counts->unused++;
74     } else {
75       if (info_cache.ProfileIsSupervisedAtIndex(i))
76         counts->supervised++;
77       if (!info_cache.GetUserNameOfProfileAtIndex(i).empty()) {
78         counts->signedin++;
79         if (info_cache.IsUsingGAIAPictureOfProfileAtIndex(i))
80           counts->gaia_icon++;
81       }
82     }
83   }
84   return true;
85 }
86 
LogLockedProfileInformation(ProfileManager * manager)87 void LogLockedProfileInformation(ProfileManager* manager) {
88   const ProfileInfoCache& info_cache = manager->GetProfileInfoCache();
89   size_t number_of_profiles = info_cache.GetNumberOfProfiles();
90 
91   base::Time now = base::Time::Now();
92   const int kMinutesInProfileValidDuration =
93       base::TimeDelta::FromDays(28).InMinutes();
94   for (size_t i = 0; i < number_of_profiles; ++i) {
95     // Find when locked profiles were locked
96     if (info_cache.ProfileIsSigninRequiredAtIndex(i)) {
97       base::TimeDelta time_since_lock = now -
98           info_cache.GetProfileActiveTimeAtIndex(i);
99       // Specifying 100 buckets for the histogram to get a higher level of
100       // granularity in the reported data, given the large number of possible
101       // values (kMinutesInProfileValidDuration > 40,000).
102       UMA_HISTOGRAM_CUSTOM_COUNTS("Profile.LockedProfilesDuration",
103                                   time_since_lock.InMinutes(),
104                                   1,
105                                   kMinutesInProfileValidDuration,
106                                   100);
107     }
108   }
109 }
110 
111 }  // namespace
112 
113 enum ProfileAvatar {
114   AVATAR_GENERIC = 0,       // The names for avatar icons
115   AVATAR_GENERIC_AQUA,
116   AVATAR_GENERIC_BLUE,
117   AVATAR_GENERIC_GREEN,
118   AVATAR_GENERIC_ORANGE,
119   AVATAR_GENERIC_PURPLE,
120   AVATAR_GENERIC_RED,
121   AVATAR_GENERIC_YELLOW,
122   AVATAR_SECRET_AGENT,
123   AVATAR_SUPERHERO,
124   AVATAR_VOLLEYBALL,        // 10
125   AVATAR_BUSINESSMAN,
126   AVATAR_NINJA,
127   AVATAR_ALIEN,
128   AVATAR_AWESOME,
129   AVATAR_FLOWER,
130   AVATAR_PIZZA,
131   AVATAR_SOCCER,
132   AVATAR_BURGER,
133   AVATAR_CAT,
134   AVATAR_CUPCAKE,           // 20
135   AVATAR_DOG,
136   AVATAR_HORSE,
137   AVATAR_MARGARITA,
138   AVATAR_NOTE,
139   AVATAR_SUN_CLOUD,
140   AVATAR_PLACEHOLDER,
141   AVATAR_UNKNOWN,           // 27
142   AVATAR_GAIA,              // 28
143   NUM_PROFILE_AVATAR_METRICS
144 };
145 
UpdateReportedProfilesStatistics(ProfileManager * manager)146 void ProfileMetrics::UpdateReportedProfilesStatistics(ProfileManager* manager) {
147   ProfileCounts counts;
148   if (CountProfileInformation(manager, &counts)) {
149     int limited_total = counts.total;
150     int limited_signedin = counts.signedin;
151     if (limited_total > kMaximumReportedProfileCount) {
152       limited_total = kMaximumReportedProfileCount + 1;
153       limited_signedin =
154           (int)((float)(counts.signedin * limited_total)
155           / counts.total + 0.5);
156     }
157     UpdateReportedOSProfileStatistics(limited_total, limited_signedin);
158   }
159 }
160 
LogNumberOfProfiles(ProfileManager * manager)161 void ProfileMetrics::LogNumberOfProfiles(ProfileManager* manager) {
162   ProfileCounts counts;
163   bool success = CountProfileInformation(manager, &counts);
164   UMA_HISTOGRAM_COUNTS_100("Profile.NumberOfProfiles", counts.total);
165 
166   // Ignore other metrics if we have no profiles, e.g. in Chrome Frame tests.
167   if (success) {
168     UMA_HISTOGRAM_COUNTS_100("Profile.NumberOfManagedProfiles",
169                              counts.supervised);
170     UMA_HISTOGRAM_COUNTS_100("Profile.PercentageOfManagedProfiles",
171                              100 * counts.supervised / counts.total);
172     UMA_HISTOGRAM_COUNTS_100("Profile.NumberOfSignedInProfiles",
173                              counts.signedin);
174     UMA_HISTOGRAM_COUNTS_100("Profile.NumberOfUnusedProfiles",
175                              counts.unused);
176     UMA_HISTOGRAM_COUNTS_100("Profile.NumberOfSignedInProfilesWithGAIAIcons",
177                              counts.gaia_icon);
178 
179     LogLockedProfileInformation(manager);
180     UpdateReportedOSProfileStatistics(counts.total, counts.signedin);
181   }
182 }
183 
LogProfileAddNewUser(ProfileAdd metric)184 void ProfileMetrics::LogProfileAddNewUser(ProfileAdd metric) {
185   DCHECK(metric < NUM_PROFILE_ADD_METRICS);
186   UMA_HISTOGRAM_ENUMERATION("Profile.AddNewUser", metric,
187                             NUM_PROFILE_ADD_METRICS);
188   UMA_HISTOGRAM_ENUMERATION("Profile.NetUserCount", ADD_NEW_USER,
189                             NUM_PROFILE_NET_METRICS);
190 }
191 
LogProfileAvatarSelection(size_t icon_index)192 void ProfileMetrics::LogProfileAvatarSelection(size_t icon_index) {
193   DCHECK(icon_index < NUM_PROFILE_AVATAR_METRICS);
194   ProfileAvatar icon_name = AVATAR_UNKNOWN;
195   switch (icon_index) {
196     case 0:
197       icon_name = AVATAR_GENERIC;
198       break;
199     case 1:
200       icon_name = AVATAR_GENERIC_AQUA;
201       break;
202     case 2:
203       icon_name = AVATAR_GENERIC_BLUE;
204       break;
205     case 3:
206       icon_name = AVATAR_GENERIC_GREEN;
207       break;
208     case 4:
209       icon_name = AVATAR_GENERIC_ORANGE;
210       break;
211     case 5:
212       icon_name = AVATAR_GENERIC_PURPLE;
213       break;
214     case 6:
215       icon_name = AVATAR_GENERIC_RED;
216       break;
217     case 7:
218       icon_name = AVATAR_GENERIC_YELLOW;
219       break;
220     case 8:
221       icon_name = AVATAR_SECRET_AGENT;
222       break;
223     case 9:
224       icon_name = AVATAR_SUPERHERO;
225       break;
226     case 10:
227       icon_name = AVATAR_VOLLEYBALL;
228       break;
229     case 11:
230       icon_name = AVATAR_BUSINESSMAN;
231       break;
232     case 12:
233       icon_name = AVATAR_NINJA;
234       break;
235     case 13:
236       icon_name = AVATAR_ALIEN;
237       break;
238     case 14:
239       icon_name = AVATAR_AWESOME;
240       break;
241     case 15:
242       icon_name = AVATAR_FLOWER;
243       break;
244     case 16:
245       icon_name = AVATAR_PIZZA;
246       break;
247     case 17:
248       icon_name = AVATAR_SOCCER;
249       break;
250     case 18:
251       icon_name = AVATAR_BURGER;
252       break;
253     case 19:
254       icon_name = AVATAR_CAT;
255       break;
256     case 20:
257       icon_name = AVATAR_CUPCAKE;
258       break;
259     case 21:
260       icon_name = AVATAR_DOG;
261       break;
262     case 22:
263       icon_name = AVATAR_HORSE;
264       break;
265     case 23:
266       icon_name = AVATAR_MARGARITA;
267       break;
268     case 24:
269       icon_name = AVATAR_NOTE;
270       break;
271     case 25:
272       icon_name = AVATAR_SUN_CLOUD;
273       break;
274     case 26:
275       icon_name = AVATAR_PLACEHOLDER;
276       break;
277     case 28:
278       icon_name = AVATAR_GAIA;
279       break;
280     default:  // We should never actually get here.
281       NOTREACHED();
282       break;
283   }
284   UMA_HISTOGRAM_ENUMERATION("Profile.Avatar", icon_name,
285                             NUM_PROFILE_AVATAR_METRICS);
286 }
287 
LogProfileDeleteUser(ProfileNetUserCounts metric)288 void ProfileMetrics::LogProfileDeleteUser(ProfileNetUserCounts metric) {
289   DCHECK(metric < NUM_PROFILE_NET_METRICS);
290   UMA_HISTOGRAM_ENUMERATION("Profile.NetUserCount", metric,
291                             NUM_PROFILE_NET_METRICS);
292 }
293 
LogProfileOpenMethod(ProfileOpen metric)294 void ProfileMetrics::LogProfileOpenMethod(ProfileOpen metric) {
295   DCHECK(metric < NUM_PROFILE_OPEN_METRICS);
296   UMA_HISTOGRAM_ENUMERATION("Profile.OpenMethod", metric,
297                             NUM_PROFILE_OPEN_METRICS);
298 }
299 
LogProfileSwitchGaia(ProfileGaia metric)300 void ProfileMetrics::LogProfileSwitchGaia(ProfileGaia metric) {
301   if (metric == GAIA_OPT_IN)
302     LogProfileAvatarSelection(AVATAR_GAIA);
303   UMA_HISTOGRAM_ENUMERATION("Profile.SwitchGaiaPhotoSettings",
304                             metric,
305                             NUM_PROFILE_GAIA_METRICS);
306 }
307 
LogProfileSwitchUser(ProfileOpen metric)308 void ProfileMetrics::LogProfileSwitchUser(ProfileOpen metric) {
309   DCHECK(metric < NUM_PROFILE_OPEN_METRICS);
310   UMA_HISTOGRAM_ENUMERATION("Profile.OpenMethod", metric,
311                             NUM_PROFILE_OPEN_METRICS);
312 }
313 
LogProfileSyncInfo(ProfileSync metric)314 void ProfileMetrics::LogProfileSyncInfo(ProfileSync metric) {
315   DCHECK(metric < NUM_PROFILE_SYNC_METRICS);
316   UMA_HISTOGRAM_ENUMERATION("Profile.SyncCustomize", metric,
317                             NUM_PROFILE_SYNC_METRICS);
318 }
319 
LogProfileAuthResult(ProfileAuth metric)320 void ProfileMetrics::LogProfileAuthResult(ProfileAuth metric) {
321   UMA_HISTOGRAM_ENUMERATION("Profile.AuthResult", metric,
322                             NUM_PROFILE_AUTH_METRICS);
323 }
324 
LogProfileUpgradeEnrollment(ProfileUpgradeEnrollment metric)325 void ProfileMetrics::LogProfileUpgradeEnrollment(
326     ProfileUpgradeEnrollment metric) {
327   UMA_HISTOGRAM_ENUMERATION("Profile.UpgradeEnrollment", metric,
328                             NUM_PROFILE_ENROLLMENT_METRICS);
329 }
330 
LogProfileDesktopMenu(ProfileDesktopMenu metric,signin::GAIAServiceType gaia_service)331 void ProfileMetrics::LogProfileDesktopMenu(
332     ProfileDesktopMenu metric,
333     signin::GAIAServiceType gaia_service) {
334   // The first parameter to the histogram needs to be literal, because of the
335   // optimized implementation of |UMA_HISTOGRAM_ENUMERATION|. Do not attempt
336   // to refactor.
337   switch (gaia_service) {
338     case signin::GAIA_SERVICE_TYPE_NONE:
339       UMA_HISTOGRAM_ENUMERATION("Profile.DesktopMenu.NonGAIA", metric,
340                                 NUM_PROFILE_DESKTOP_MENU_METRICS);
341       break;
342     case signin::GAIA_SERVICE_TYPE_SIGNOUT:
343       UMA_HISTOGRAM_ENUMERATION("Profile.DesktopMenu.GAIASignout", metric,
344                                 NUM_PROFILE_DESKTOP_MENU_METRICS);
345       break;
346     case signin::GAIA_SERVICE_TYPE_INCOGNITO:
347       UMA_HISTOGRAM_ENUMERATION("Profile.DesktopMenu.GAIAIncognito",
348                                 metric, NUM_PROFILE_DESKTOP_MENU_METRICS);
349       break;
350     case signin::GAIA_SERVICE_TYPE_ADDSESSION:
351       UMA_HISTOGRAM_ENUMERATION("Profile.DesktopMenu.GAIAAddSession", metric,
352                                 NUM_PROFILE_DESKTOP_MENU_METRICS);
353       break;
354     case signin::GAIA_SERVICE_TYPE_REAUTH:
355       UMA_HISTOGRAM_ENUMERATION("Profile.DesktopMenu.GAIAReAuth", metric,
356                                 NUM_PROFILE_DESKTOP_MENU_METRICS);
357       break;
358     case signin::GAIA_SERVICE_TYPE_DEFAULT:
359       UMA_HISTOGRAM_ENUMERATION("Profile.DesktopMenu.GAIADefault", metric,
360                                 NUM_PROFILE_DESKTOP_MENU_METRICS);
361       break;
362   }
363 }
364 
LogProfileDelete(bool profile_was_signed_in)365 void ProfileMetrics::LogProfileDelete(bool profile_was_signed_in) {
366   UMA_HISTOGRAM_BOOLEAN("Profile.Delete", profile_was_signed_in);
367 }
368 
369 #if defined(OS_ANDROID)
LogProfileAndroidAccountManagementMenu(ProfileAndroidAccountManagementMenu metric,signin::GAIAServiceType gaia_service)370 void ProfileMetrics::LogProfileAndroidAccountManagementMenu(
371     ProfileAndroidAccountManagementMenu metric,
372     signin::GAIAServiceType gaia_service) {
373   // The first parameter to the histogram needs to be literal, because of the
374   // optimized implementation of |UMA_HISTOGRAM_ENUMERATION|. Do not attempt
375   // to refactor.
376   switch (gaia_service) {
377     case signin::GAIA_SERVICE_TYPE_NONE:
378       UMA_HISTOGRAM_ENUMERATION(
379           "Profile.AndroidAccountManagementMenu.NonGAIA",
380           metric,
381           NUM_PROFILE_ANDROID_ACCOUNT_MANAGEMENT_MENU_METRICS);
382       break;
383     case signin::GAIA_SERVICE_TYPE_SIGNOUT:
384       UMA_HISTOGRAM_ENUMERATION(
385           "Profile.AndroidAccountManagementMenu.GAIASignout",
386           metric,
387           NUM_PROFILE_ANDROID_ACCOUNT_MANAGEMENT_MENU_METRICS);
388       break;
389     case signin::GAIA_SERVICE_TYPE_INCOGNITO:
390       UMA_HISTOGRAM_ENUMERATION(
391           "Profile.AndroidAccountManagementMenu.GAIASignoutIncognito",
392           metric,
393           NUM_PROFILE_ANDROID_ACCOUNT_MANAGEMENT_MENU_METRICS);
394       break;
395     case signin::GAIA_SERVICE_TYPE_ADDSESSION:
396       UMA_HISTOGRAM_ENUMERATION(
397           "Profile.AndroidAccountManagementMenu.GAIAAddSession",
398           metric,
399           NUM_PROFILE_ANDROID_ACCOUNT_MANAGEMENT_MENU_METRICS);
400       break;
401     case signin::GAIA_SERVICE_TYPE_REAUTH:
402       UMA_HISTOGRAM_ENUMERATION(
403           "Profile.AndroidAccountManagementMenu.GAIAReAuth",
404           metric,
405           NUM_PROFILE_ANDROID_ACCOUNT_MANAGEMENT_MENU_METRICS);
406       break;
407     case signin::GAIA_SERVICE_TYPE_DEFAULT:
408       UMA_HISTOGRAM_ENUMERATION(
409           "Profile.AndroidAccountManagementMenu.GAIADefault",
410           metric,
411           NUM_PROFILE_ANDROID_ACCOUNT_MANAGEMENT_MENU_METRICS);
412       break;
413   }
414 }
415 #endif  // defined(OS_ANDROID)
416 
LogProfileLaunch(Profile * profile)417 void ProfileMetrics::LogProfileLaunch(Profile* profile) {
418   base::FilePath profile_path = profile->GetPath();
419   UMA_HISTOGRAM_ENUMERATION("Profile.LaunchBrowser",
420                             GetProfileType(profile_path),
421                             NUM_PROFILE_TYPE_METRICS);
422 
423   if (profile->IsSupervised()) {
424     content::RecordAction(
425         base::UserMetricsAction("ManagedMode_NewManagedUserWindow"));
426   }
427 }
428 
LogProfileSyncSignIn(const base::FilePath & profile_path)429 void ProfileMetrics::LogProfileSyncSignIn(const base::FilePath& profile_path) {
430   UMA_HISTOGRAM_ENUMERATION("Profile.SyncSignIn",
431                             GetProfileType(profile_path),
432                             NUM_PROFILE_TYPE_METRICS);
433 }
434 
LogProfileUpdate(const base::FilePath & profile_path)435 void ProfileMetrics::LogProfileUpdate(const base::FilePath& profile_path) {
436   UMA_HISTOGRAM_ENUMERATION("Profile.Update",
437                             GetProfileType(profile_path),
438                             NUM_PROFILE_TYPE_METRICS);
439 }
440