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. 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 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 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 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 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 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 142 void LogUIDismissalReason(UIDismissalReason reason) { 143 UMA_HISTOGRAM_ENUMERATION("PasswordManager.UIDismissalReason", 144 reason, 145 NUM_UI_RESPONSES); 146 } 147 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