Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / profiles / profile_metrics.cc
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 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.
32   if (manager) {
33     user_data_dir = manager->user_data_dir();
34   }
35   if (profile_path == user_data_dir.AppendASCII(chrome::kInitialProfile)) {
36     metric = ProfileMetrics::ORIGINAL;
37   }
38   return metric;
39 }
40
41 void UpdateReportedOSProfileStatistics(int active, int signedin) {
42 #if defined(OS_WIN)
43   GoogleUpdateSettings::UpdateProfileCounts(active, signedin);
44 #endif
45 }
46
47 void LogLockedProfileInformation(ProfileManager* manager) {
48   const ProfileInfoCache& info_cache = manager->GetProfileInfoCache();
49   size_t number_of_profiles = info_cache.GetNumberOfProfiles();
50
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(),
64                                   1,
65                                   kMinutesInProfileValidDuration,
66                                   100);
67     }
68   }
69 }
70
71 bool HasProfileAtIndexBeenActiveSince(const ProfileInfoCache& info_cache,
72                                       int index,
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)
78     return false;
79 #endif
80   return true;
81 }
82
83 }  // namespace
84
85 enum ProfileAvatar {
86   AVATAR_GENERIC = 0,       // The names for avatar icons
87   AVATAR_GENERIC_AQUA,
88   AVATAR_GENERIC_BLUE,
89   AVATAR_GENERIC_GREEN,
90   AVATAR_GENERIC_ORANGE,
91   AVATAR_GENERIC_PURPLE,
92   AVATAR_GENERIC_RED,
93   AVATAR_GENERIC_YELLOW,
94   AVATAR_SECRET_AGENT,
95   AVATAR_SUPERHERO,
96   AVATAR_VOLLEYBALL,        // 10
97   AVATAR_BUSINESSMAN,
98   AVATAR_NINJA,
99   AVATAR_ALIEN,
100   AVATAR_AWESOME,
101   AVATAR_FLOWER,
102   AVATAR_PIZZA,
103   AVATAR_SOCCER,
104   AVATAR_BURGER,
105   AVATAR_CAT,
106   AVATAR_CUPCAKE,           // 20
107   AVATAR_DOG,
108   AVATAR_HORSE,
109   AVATAR_MARGARITA,
110   AVATAR_NOTE,
111   AVATAR_SUN_CLOUD,
112   AVATAR_PLACEHOLDER,
113   AVATAR_UNKNOWN,           // 27
114   AVATAR_GAIA,              // 28
115   NUM_PROFILE_AVATAR_METRICS
116 };
117
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;
123
124   // Ignore other metrics if we have no profiles, e.g. in Chrome Frame tests.
125   if (!number_of_profiles)
126     return false;
127
128   // Maximum age for "active" profile is 4 weeks.
129   base::Time oldest = base::Time::Now() -
130       base::TimeDelta::FromDays(kMaximumDaysOfDisuse);
131
132   for (size_t i = 0; i < number_of_profiles; ++i) {
133     if (!HasProfileAtIndexBeenActiveSince(info_cache, i, oldest)) {
134       counts->unused++;
135     } else {
136       if (info_cache.ProfileIsSupervisedAtIndex(i))
137         counts->supervised++;
138       if (!info_cache.GetUserNameOfProfileAtIndex(i).empty()) {
139         counts->signedin++;
140         if (info_cache.IsUsingGAIAPictureOfProfileAtIndex(i))
141           counts->gaia_icon++;
142       }
143     }
144   }
145   return true;
146 }
147
148
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;
156       limited_signedin =
157           (int)((float)(counts.signedin * limited_total)
158           / counts.total + 0.5);
159     }
160     UpdateReportedOSProfileStatistics(limited_total, limited_signedin);
161   }
162 }
163
164 void ProfileMetrics::LogNumberOfProfiles(ProfileManager* manager) {
165   ProfileCounts counts;
166   bool success = CountProfileInformation(manager, &counts);
167   UMA_HISTOGRAM_COUNTS_100("Profile.NumberOfProfiles", counts.total);
168
169   // Ignore other metrics if we have no profiles, e.g. in Chrome Frame tests.
170   if (success) {
171     UMA_HISTOGRAM_COUNTS_100("Profile.NumberOfManagedProfiles",
172                              counts.supervised);
173     UMA_HISTOGRAM_COUNTS_100("Profile.PercentageOfManagedProfiles",
174                              100 * counts.supervised / counts.total);
175     UMA_HISTOGRAM_COUNTS_100("Profile.NumberOfSignedInProfiles",
176                              counts.signedin);
177     UMA_HISTOGRAM_COUNTS_100("Profile.NumberOfUnusedProfiles",
178                              counts.unused);
179     UMA_HISTOGRAM_COUNTS_100("Profile.NumberOfSignedInProfilesWithGAIAIcons",
180                              counts.gaia_icon);
181
182     LogLockedProfileInformation(manager);
183     UpdateReportedOSProfileStatistics(counts.total, counts.signedin);
184   }
185 }
186
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);
193 }
194
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) {
199     case 0:
200       icon_name = AVATAR_GENERIC;
201       break;
202     case 1:
203       icon_name = AVATAR_GENERIC_AQUA;
204       break;
205     case 2:
206       icon_name = AVATAR_GENERIC_BLUE;
207       break;
208     case 3:
209       icon_name = AVATAR_GENERIC_GREEN;
210       break;
211     case 4:
212       icon_name = AVATAR_GENERIC_ORANGE;
213       break;
214     case 5:
215       icon_name = AVATAR_GENERIC_PURPLE;
216       break;
217     case 6:
218       icon_name = AVATAR_GENERIC_RED;
219       break;
220     case 7:
221       icon_name = AVATAR_GENERIC_YELLOW;
222       break;
223     case 8:
224       icon_name = AVATAR_SECRET_AGENT;
225       break;
226     case 9:
227       icon_name = AVATAR_SUPERHERO;
228       break;
229     case 10:
230       icon_name = AVATAR_VOLLEYBALL;
231       break;
232     case 11:
233       icon_name = AVATAR_BUSINESSMAN;
234       break;
235     case 12:
236       icon_name = AVATAR_NINJA;
237       break;
238     case 13:
239       icon_name = AVATAR_ALIEN;
240       break;
241     case 14:
242       icon_name = AVATAR_AWESOME;
243       break;
244     case 15:
245       icon_name = AVATAR_FLOWER;
246       break;
247     case 16:
248       icon_name = AVATAR_PIZZA;
249       break;
250     case 17:
251       icon_name = AVATAR_SOCCER;
252       break;
253     case 18:
254       icon_name = AVATAR_BURGER;
255       break;
256     case 19:
257       icon_name = AVATAR_CAT;
258       break;
259     case 20:
260       icon_name = AVATAR_CUPCAKE;
261       break;
262     case 21:
263       icon_name = AVATAR_DOG;
264       break;
265     case 22:
266       icon_name = AVATAR_HORSE;
267       break;
268     case 23:
269       icon_name = AVATAR_MARGARITA;
270       break;
271     case 24:
272       icon_name = AVATAR_NOTE;
273       break;
274     case 25:
275       icon_name = AVATAR_SUN_CLOUD;
276       break;
277     case 26:
278       icon_name = AVATAR_PLACEHOLDER;
279       break;
280     case 28:
281       icon_name = AVATAR_GAIA;
282       break;
283     default:  // We should never actually get here.
284       NOTREACHED();
285       break;
286   }
287   UMA_HISTOGRAM_ENUMERATION("Profile.Avatar", icon_name,
288                             NUM_PROFILE_AVATAR_METRICS);
289 }
290
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);
297 }
298
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);
303 }
304
305 void ProfileMetrics::LogProfileSwitchGaia(ProfileGaia metric) {
306   if (metric == GAIA_OPT_IN)
307     LogProfileAvatarSelection(AVATAR_GAIA);
308   UMA_HISTOGRAM_ENUMERATION("Profile.SwitchGaiaPhotoSettings",
309                             metric,
310                             NUM_PROFILE_GAIA_METRICS);
311 }
312
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);
317 }
318
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);
323 }
324
325 void ProfileMetrics::LogProfileAuthResult(ProfileAuth metric) {
326   UMA_HISTOGRAM_ENUMERATION("Profile.AuthResult", metric,
327                             NUM_PROFILE_AUTH_METRICS);
328 }
329
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
335   // to refactor.
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);
340       break;
341     case signin::GAIA_SERVICE_TYPE_SIGNOUT:
342       UMA_HISTOGRAM_ENUMERATION("Profile.DesktopMenu.GAIASignout", metric,
343                                 NUM_PROFILE_DESKTOP_MENU_METRICS);
344       break;
345     case signin::GAIA_SERVICE_TYPE_INCOGNITO:
346       UMA_HISTOGRAM_ENUMERATION("Profile.DesktopMenu.GAIAIncognito",
347                                 metric, NUM_PROFILE_DESKTOP_MENU_METRICS);
348       break;
349     case signin::GAIA_SERVICE_TYPE_ADDSESSION:
350       UMA_HISTOGRAM_ENUMERATION("Profile.DesktopMenu.GAIAAddSession", metric,
351                                 NUM_PROFILE_DESKTOP_MENU_METRICS);
352       break;
353     case signin::GAIA_SERVICE_TYPE_REAUTH:
354       UMA_HISTOGRAM_ENUMERATION("Profile.DesktopMenu.GAIAReAuth", metric,
355                                 NUM_PROFILE_DESKTOP_MENU_METRICS);
356       break;
357     case signin::GAIA_SERVICE_TYPE_SIGNUP:
358       UMA_HISTOGRAM_ENUMERATION("Profile.DesktopMenu.GAIASignup", metric,
359                                 NUM_PROFILE_DESKTOP_MENU_METRICS);
360       break;
361     case signin::GAIA_SERVICE_TYPE_DEFAULT:
362       UMA_HISTOGRAM_ENUMERATION("Profile.DesktopMenu.GAIADefault", metric,
363                                 NUM_PROFILE_DESKTOP_MENU_METRICS);
364       break;
365   }
366 }
367
368 void ProfileMetrics::LogProfileDelete(bool profile_was_signed_in) {
369   UMA_HISTOGRAM_BOOLEAN("Profile.Delete", profile_was_signed_in);
370 }
371
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);
377 }
378
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);
384 }
385
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);
391 }
392
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
399   // to refactor.
400   switch (gaia_service) {
401     case signin::GAIA_SERVICE_TYPE_NONE:
402       UMA_HISTOGRAM_ENUMERATION(
403           "Profile.AndroidAccountManagementMenu.NonGAIA",
404           metric,
405           NUM_PROFILE_ANDROID_ACCOUNT_MANAGEMENT_MENU_METRICS);
406       break;
407     case signin::GAIA_SERVICE_TYPE_SIGNOUT:
408       UMA_HISTOGRAM_ENUMERATION(
409           "Profile.AndroidAccountManagementMenu.GAIASignout",
410           metric,
411           NUM_PROFILE_ANDROID_ACCOUNT_MANAGEMENT_MENU_METRICS);
412       break;
413     case signin::GAIA_SERVICE_TYPE_INCOGNITO:
414       UMA_HISTOGRAM_ENUMERATION(
415           "Profile.AndroidAccountManagementMenu.GAIASignoutIncognito",
416           metric,
417           NUM_PROFILE_ANDROID_ACCOUNT_MANAGEMENT_MENU_METRICS);
418       break;
419     case signin::GAIA_SERVICE_TYPE_ADDSESSION:
420       UMA_HISTOGRAM_ENUMERATION(
421           "Profile.AndroidAccountManagementMenu.GAIAAddSession",
422           metric,
423           NUM_PROFILE_ANDROID_ACCOUNT_MANAGEMENT_MENU_METRICS);
424       break;
425     case signin::GAIA_SERVICE_TYPE_REAUTH:
426       UMA_HISTOGRAM_ENUMERATION(
427           "Profile.AndroidAccountManagementMenu.GAIAReAuth",
428           metric,
429           NUM_PROFILE_ANDROID_ACCOUNT_MANAGEMENT_MENU_METRICS);
430       break;
431     case signin::GAIA_SERVICE_TYPE_SIGNUP:
432       UMA_HISTOGRAM_ENUMERATION(
433           "Profile.AndroidAccountManagementMenu.GAIASignup",
434           metric,
435           NUM_PROFILE_ANDROID_ACCOUNT_MANAGEMENT_MENU_METRICS);
436       break;
437     case signin::GAIA_SERVICE_TYPE_DEFAULT:
438       UMA_HISTOGRAM_ENUMERATION(
439           "Profile.AndroidAccountManagementMenu.GAIADefault",
440           metric,
441           NUM_PROFILE_ANDROID_ACCOUNT_MANAGEMENT_MENU_METRICS);
442       break;
443   }
444 }
445 #endif  // defined(OS_ANDROID)
446
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);
452
453   if (profile->IsSupervised()) {
454     content::RecordAction(
455         base::UserMetricsAction("ManagedMode_NewManagedUserWindow"));
456   }
457 }
458
459 void ProfileMetrics::LogProfileSyncSignIn(const base::FilePath& profile_path) {
460   UMA_HISTOGRAM_ENUMERATION("Profile.SyncSignIn",
461                             GetProfileType(profile_path),
462                             NUM_PROFILE_TYPE_METRICS);
463 }
464
465 void ProfileMetrics::LogProfileUpdate(const base::FilePath& profile_path) {
466   UMA_HISTOGRAM_ENUMERATION("Profile.Update",
467                             GetProfileType(profile_path),
468                             NUM_PROFILE_TYPE_METRICS);
469 }