• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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 "components/password_manager/core/browser/password_manager_metrics_util.h"
6 
7 #include "base/basictypes.h"
8 #include "base/metrics/histogram.h"
9 #include "base/numerics/safe_conversions.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/prefs/scoped_user_pref_update.h"
12 #include "base/rand_util.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_util.h"
15 #include "base/time/time.h"
16 #include "base/values.h"
17 #include "components/password_manager/core/common/password_manager_pref_names.h"
18 #include "url/gurl.h"
19 
20 using base::ListValue;
21 using base::FundamentalValue;
22 
23 namespace password_manager {
24 
25 namespace metrics_util {
26 
27 namespace {
28 
29 // The number of domain groups.
30 const size_t kNumGroups = 2u * kGroupsPerDomain;
31 
32 // |kDomainMapping| contains each monitored website together with all ids of
33 // groups which contain the website. Each website appears in
34 // |kGroupsPerDomain| groups, and each group includes an equal number of
35 // websites, so that no two websites have the same set of groups that they
36 // belong to. All ids are in the range [1, |kNumGroups|].
37 // For more information about the algorithm used see http://goo.gl/vUuFd5.
38 struct DomainGroupsPair {
39   const char* const domain_name;
40   const size_t group_ids[kGroupsPerDomain];
41 };
42 const DomainGroupsPair kDomainMapping[] = {
43     {"google.com", {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}},
44     {"yahoo.com", {1, 2, 3, 4, 5, 11, 12, 13, 14, 15}},
45     {"baidu.com", {1, 2, 3, 4, 6, 7, 11, 12, 16, 17}},
46     {"wikipedia.org", {1, 2, 3, 4, 5, 6, 11, 12, 16, 18}},
47     {"linkedin.com", {1, 6, 8, 11, 13, 14, 15, 16, 17, 19}},
48     {"twitter.com", {5, 6, 7, 8, 9, 11, 13, 17, 19, 20}},
49     {"facebook.com", {7, 8, 9, 10, 13, 14, 16, 17, 18, 20}},
50     {"amazon.com", {2, 5, 9, 10, 12, 14, 15, 18, 19, 20}},
51     {"ebay.com", {3, 7, 9, 10, 14, 15, 17, 18, 19, 20}},
52     {"tumblr.com", {4, 8, 10, 12, 13, 15, 16, 18, 19, 20}},
53 };
54 const size_t kNumDomains = arraysize(kDomainMapping);
55 
56 // For every monitored domain, this function chooses which of the groups
57 // containing that domain should be used for reporting. That number is chosen
58 // randomly and stored in the user's preferences.
GetGroupIndex(size_t domain_index,PrefService * pref_service)59 size_t GetGroupIndex(size_t domain_index, PrefService* pref_service) {
60   DCHECK_LT(domain_index, kNumDomains);
61 
62   const base::ListValue* group_indices =
63       pref_service->GetList(prefs::kPasswordManagerGroupsForDomains);
64   int result = 0;
65   if (!group_indices->GetInteger(domain_index, &result)) {
66     ListPrefUpdate group_indices_updater(
67         pref_service, prefs::kPasswordManagerGroupsForDomains);
68     // This value has not been generated yet.
69     result =
70         base::checked_cast<int>(base::RandGenerator(kGroupsPerDomain));
71     group_indices_updater->Set(domain_index, new FundamentalValue(result));
72   }
73   return base::checked_cast<size_t>(result);
74 }
75 
76 }  // namespace
77 
MonitoredDomainGroupId(const std::string & url_host,PrefService * pref_service)78 size_t MonitoredDomainGroupId(const std::string& url_host,
79                               PrefService* pref_service) {
80   GURL url(url_host);
81   for (size_t i = 0; i < kNumDomains; ++i) {
82     if (url.DomainIs(kDomainMapping[i].domain_name))
83       return kDomainMapping[i].group_ids[GetGroupIndex(i, pref_service)];
84   }
85   return 0;
86 }
87 
LogUMAHistogramEnumeration(const std::string & name,int sample,int boundary_value)88 void LogUMAHistogramEnumeration(const std::string& name,
89                                 int sample,
90                                 int boundary_value) {
91   DCHECK_LT(sample, boundary_value);
92 
93   // Note: This leaks memory, which is expected behavior.
94   base::HistogramBase* histogram =
95       base::LinearHistogram::FactoryGet(
96           name,
97           1,
98           boundary_value,
99           boundary_value + 1,
100           base::HistogramBase::kUmaTargetedHistogramFlag);
101   histogram->Add(sample);
102 }
103 
LogUMAHistogramBoolean(const std::string & name,bool sample)104 void LogUMAHistogramBoolean(const std::string& name, bool sample) {
105   // Note: This leaks memory, which is expected behavior.
106   base::HistogramBase* histogram =
107       base::BooleanHistogram::FactoryGet(
108           name,
109           base::Histogram::kNoFlags);
110           histogram->AddBoolean(sample);
111 }
112 
GroupIdToString(size_t group_id)113 std::string GroupIdToString(size_t group_id) {
114   DCHECK_LE(group_id, kNumGroups);
115   if (group_id > 0)
116     return "group_" + base::IntToString(group_id);
117   return std::string();
118 }
119 
LogUIDismissalReason(ResponseType type)120 void LogUIDismissalReason(ResponseType type) {
121   UIDismissalReason reason = NO_DIRECT_INTERACTION;
122   switch (type) {
123     case NO_RESPONSE:
124       reason = NO_DIRECT_INTERACTION;
125       break;
126     case REMEMBER_PASSWORD:
127       reason = CLICKED_SAVE;
128       break;
129     case NEVER_REMEMBER_PASSWORD:
130       reason = CLICKED_NEVER;
131       break;
132     case INFOBAR_DISMISSED:
133       reason = CLICKED_NOPE;
134       break;
135     case NUM_RESPONSE_TYPES:
136       NOTREACHED();
137       break;
138   }
139   LogUIDismissalReason(reason);
140 }
141 
LogUIDismissalReason(UIDismissalReason reason)142 void LogUIDismissalReason(UIDismissalReason reason) {
143   UMA_HISTOGRAM_ENUMERATION("PasswordManager.UIDismissalReason",
144                             reason,
145                             NUM_UI_RESPONSES);
146 }
147 
LogUIDisplayDisposition(UIDisplayDisposition disposition)148 void LogUIDisplayDisposition(UIDisplayDisposition disposition) {
149   UMA_HISTOGRAM_ENUMERATION("PasswordBubble.DisplayDisposition",
150                             disposition,
151                             NUM_DISPLAY_DISPOSITIONS);
152 }
153 
154 }  // namespace metrics_util
155 
156 }  // namespace password_manager
157