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 20using base::ListValue; 21using base::FundamentalValue; 22 23namespace password_manager { 24 25namespace metrics_util { 26 27namespace { 28 29// The number of domain groups. 30const 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. 38struct DomainGroupsPair { 39 const char* const domain_name; 40 const size_t group_ids[kGroupsPerDomain]; 41}; 42const 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}; 54const 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. 59size_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 78size_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 88void 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 104void 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 113std::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 120void 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 142void LogUIDismissalReason(UIDismissalReason reason) { 143 UMA_HISTOGRAM_ENUMERATION("PasswordManager.UIDismissalReason", 144 reason, 145 NUM_UI_RESPONSES); 146} 147 148void 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