1 // Copyright 2015 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.
5 #include "components/security_interstitials/core/metrics_helper.h"
7 #include "base/metrics/histogram.h"
8 #include "components/history/core/browser/history_service.h"
9 #include "components/rappor/rappor_service.h"
10 #include "components/rappor/rappor_utils.h"
11 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
13 namespace security_interstitials
{
17 // Used for setting bits in Rappor's "interstitial.*.flags"
18 enum InterstitialFlagBits
{
24 // Directly adds to the UMA histograms, using the same properties as
25 // UMA_HISTOGRAM_ENUMERATION, because the macro doesn't allow non-constant
27 void RecordSingleDecisionToMetrics(MetricsHelper::Decision decision
,
28 const std::string
& histogram_name
) {
29 base::HistogramBase
* histogram
= base::LinearHistogram::FactoryGet(
30 histogram_name
, 1, MetricsHelper::MAX_DECISION
,
31 MetricsHelper::MAX_DECISION
+ 1,
32 base::HistogramBase::kUmaTargetedHistogramFlag
);
33 histogram
->Add(decision
);
36 void RecordSingleInteractionToMetrics(MetricsHelper::Interaction interaction
,
37 const std::string
& histogram_name
) {
38 base::HistogramBase
* histogram
= base::LinearHistogram::FactoryGet(
39 histogram_name
, 1, MetricsHelper::MAX_INTERACTION
,
40 MetricsHelper::MAX_INTERACTION
+ 1,
41 base::HistogramBase::kUmaTargetedHistogramFlag
);
42 histogram
->Add(interaction
);
47 MetricsHelper::ReportDetails::ReportDetails()
48 : rappor_report_type(rappor::NUM_RAPPOR_TYPES
) {}
50 MetricsHelper::MetricsHelper(const GURL
& request_url
,
51 const ReportDetails settings
,
52 history::HistoryService
* history_service
,
53 rappor::RapporService
* rappor_service
)
54 : request_url_(request_url
),
56 rappor_service_(rappor_service
),
58 DCHECK(!settings_
.metric_prefix
.empty());
59 if (settings_
.rappor_report_type
== rappor::NUM_RAPPOR_TYPES
) // Default.
60 rappor_service_
= nullptr;
61 DCHECK(!rappor_service_
|| !settings_
.rappor_prefix
.empty());
62 if (history_service
) {
63 history_service
->GetVisibleVisitCountToHost(
65 base::Bind(&MetricsHelper::OnGotHistoryCount
, base::Unretained(this)),
70 void MetricsHelper::RecordUserDecision(Decision decision
) {
71 const std::string
histogram_name(
72 "interstitial." + settings_
.metric_prefix
+ ".decision");
74 RecordUserDecisionToMetrics(decision
, histogram_name
);
75 // Record additional information about sites that users have visited before.
76 // Report |decision| and SHOW together, filtered by the same history state
77 // so they they are paired regardless of when if num_visits_ is populated.
78 if (num_visits_
> 0 && (decision
== PROCEED
|| decision
== DONT_PROCEED
)) {
79 RecordUserDecisionToMetrics(SHOW
, histogram_name
+ ".repeat_visit");
80 RecordUserDecisionToMetrics(decision
, histogram_name
+ ".repeat_visit");
82 RecordUserDecisionToRappor(decision
);
83 RecordExtraUserDecisionMetrics(decision
);
86 void MetricsHelper::RecordUserDecisionToMetrics(
88 const std::string
& histogram_name
) {
89 // Record the decision, and additionally |with extra_suffix|.
90 RecordSingleDecisionToMetrics(decision
, histogram_name
);
91 if (!settings_
.extra_suffix
.empty()) {
92 RecordSingleDecisionToMetrics(
93 decision
, histogram_name
+ "." + settings_
.extra_suffix
);
97 void MetricsHelper::RecordUserDecisionToRappor(Decision decision
) {
98 if (!rappor_service_
|| (decision
!= PROCEED
&& decision
!= DONT_PROCEED
))
101 scoped_ptr
<rappor::Sample
> sample
=
102 rappor_service_
->CreateSample(settings_
.rappor_report_type
);
104 // This will populate, for example, "intersitial.malware.domain" or
105 // "interstitial.ssl2.domain". |domain| will be empty for hosts w/o TLDs.
106 const std::string domain
=
107 rappor::GetDomainAndRegistrySampleFromGURL(request_url_
);
108 sample
->SetStringField("domain", domain
);
110 // Only report history and decision if we have history data.
111 if (num_visits_
>= 0) {
113 if (decision
== PROCEED
)
114 flags
|= 1 << InterstitialFlagBits::DID_PROCEED
;
116 flags
|= 1 << InterstitialFlagBits::IS_REPEAT_VISIT
;
117 // e.g. "interstitial.malware.flags"
118 sample
->SetFlagsField("flags", flags
,
119 InterstitialFlagBits::HIGHEST_USED_BIT
+ 1);
121 rappor_service_
->RecordSampleObj("interstitial." + settings_
.rappor_prefix
,
125 void MetricsHelper::RecordUserInteraction(Interaction interaction
) {
126 const std::string
histogram_name(
127 "interstitial." + settings_
.metric_prefix
+ ".interaction");
129 RecordSingleInteractionToMetrics(interaction
, histogram_name
);
130 if (!settings_
.extra_suffix
.empty()) {
131 RecordSingleInteractionToMetrics(
132 interaction
, histogram_name
+ "." + settings_
.extra_suffix
);
134 RecordExtraUserInteractionMetrics(interaction
);
137 void MetricsHelper::OnGotHistoryCount(bool success
,
139 base::Time
/*first_visit*/) {
141 num_visits_
= num_visits
;
144 } // namespace security_interstitials