Home | History | Annotate | Download | only in browser
      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