blob: a00a4b1421676ee18fe182ac8ceaa40626974f65 [file] [log] [blame]
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/security_interstitials/core/metrics_helper.h"
#include <memory>
#include <utility>
#include "base/functional/bind.h"
#include "base/metrics/histogram.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/user_metrics.h"
#include "base/metrics/user_metrics_action.h"
#include "base/time/time.h"
#include "components/history/core/browser/history_service.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
using base::RecordAction;
using base::UserMetricsAction;
namespace security_interstitials {
namespace {
void RecordSingleDecisionToMetrics(MetricsHelper::Decision decision,
const std::string& histogram_name) {
base::UmaHistogramExactLinear(histogram_name, decision,
MetricsHelper::MAX_DECISION);
}
void RecordSingleInteractionToMetrics(MetricsHelper::Interaction interaction,
const std::string& histogram_name) {
base::UmaHistogramExactLinear(histogram_name, interaction,
MetricsHelper::MAX_INTERACTION);
}
void MaybeRecordDecisionAsAction(MetricsHelper::Decision decision,
const std::string& metric_name) {
if (decision == MetricsHelper::PROCEED) {
if (metric_name == "malware" || metric_name == "malware_subresource")
RecordAction(UserMetricsAction("MalwareInterstitial.Proceed"));
else if (metric_name == "harmful" || metric_name == "harmful_subresource")
RecordAction(UserMetricsAction("HarmfulInterstitial.Proceed"));
else if (metric_name == "ssl_overridable")
RecordAction(UserMetricsAction("SSLOverridableInterstitial.Proceed"));
else if (metric_name == "phishing" || metric_name == "phishing_subresource")
RecordAction(UserMetricsAction("PhishingInterstitial.Proceed"));
else if (metric_name == "billing" || metric_name == "billing_subresource")
RecordAction(UserMetricsAction("BillingInterstitial.Proceed"));
} else if (decision == MetricsHelper::DONT_PROCEED) {
if (metric_name == "malware" || metric_name == "malware_subresource")
RecordAction(UserMetricsAction("MalwareInterstitial.Back"));
else if (metric_name == "harmful" || metric_name == "harmful_subresource")
RecordAction(UserMetricsAction("HarmfulInterstitial.Back"));
else if (metric_name == "ssl_overridable")
RecordAction(UserMetricsAction("SSLOverridableInterstitial.Back"));
else if (metric_name == "ssl_nonoverridable")
RecordAction(UserMetricsAction("SSLNonOverridableInsterstitial.Back"));
else if (metric_name == "bad_clock")
RecordAction(UserMetricsAction("BadClockInterstitial.Back"));
else if (metric_name == "phishing" || metric_name == "phishing_subresource")
RecordAction(UserMetricsAction("PhishingInterstitial.Back"));
else if (metric_name == "billing" || metric_name == "billing_subresource")
RecordAction(UserMetricsAction("BillingInterstitial.Back"));
}
}
void MaybeRecordInteractionAsAction(MetricsHelper::Interaction interaction,
const std::string& metric_name) {
if (interaction == MetricsHelper::TOTAL_VISITS) {
if (metric_name == "malware" || metric_name == "malware_subresource")
RecordAction(UserMetricsAction("MalwareInterstitial.Show"));
else if (metric_name == "harmful" || metric_name == "harmful_subresource")
RecordAction(UserMetricsAction("HarmfulInterstitial.Show"));
else if (metric_name == "ssl_overridable")
RecordAction(UserMetricsAction("SSLOverridableInterstitial.Show"));
else if (metric_name == "ssl_nonoverridable")
RecordAction(UserMetricsAction("SSLNonOverridableInterstitial.Show"));
else if (metric_name == "bad_clock")
RecordAction(UserMetricsAction("BadClockInterstitial.Show"));
else if (metric_name == "phishing" || metric_name == "phishing_subresource")
RecordAction(UserMetricsAction("PhishingInterstitial.Show"));
else if (metric_name == "billing" || metric_name == "billing_subresource")
RecordAction(UserMetricsAction("BillingInterstitial.Show"));
} else if (interaction == MetricsHelper::SHOW_ADVANCED) {
if (metric_name == "malware" || metric_name == "malware_subresource") {
RecordAction(UserMetricsAction("MalwareInterstitial.Advanced"));
} else if (metric_name == "harmful" ||
metric_name == "harmful_subresource") {
RecordAction(UserMetricsAction("HarmfulInterstitial.Advanced"));
} else if (metric_name == "ssl_overridable" ||
metric_name == "ssl_nonoverridable") {
RecordAction(UserMetricsAction("SSLInterstitial.Advanced"));
} else if (metric_name == "phishing" ||
metric_name == "phishing_subresource")
RecordAction(UserMetricsAction("PhishingInterstitial.Advanced"));
else if (metric_name == "billing" || metric_name == "billing_subresource")
RecordAction(UserMetricsAction("BillingInterstitial.Advanced"));
} else if (interaction == MetricsHelper::RELOAD) {
if (metric_name == "ssl_nonoverridable")
RecordAction(UserMetricsAction("SSLInterstitial.Reload"));
} else if (interaction == MetricsHelper::OPEN_TIME_SETTINGS) {
if (metric_name == "bad_clock")
RecordAction(UserMetricsAction("BadClockInterstitial.Settings"));
} else if (metric_name == "phishing" ||
metric_name == "phishing_subresource") {
if (interaction == MetricsHelper::SHOW_PRIVACY_POLICY) {
RecordAction(UserMetricsAction("PhishingInterstitial.PrivacyPolicy"));
} else if (interaction == MetricsHelper::SHOW_DIAGNOSTIC) {
RecordAction(UserMetricsAction("PhishingInterstitial.Diagnostic"));
} else if (interaction == MetricsHelper::SHOW_LEARN_MORE) {
RecordAction(UserMetricsAction("PhishingInterstitial.LearnMore"));
} else if (interaction == MetricsHelper::SET_EXTENDED_REPORTING_ENABLED) {
RecordAction(UserMetricsAction(
"PhishingInterstitial.SetExtendedReportingEnabled"));
} else if (interaction == MetricsHelper::SET_EXTENDED_REPORTING_DISABLED) {
RecordAction(UserMetricsAction(
"PhishingInterstitial.SetExtendedReportingDisabled"));
} else if (interaction == MetricsHelper::REPORT_PHISHING_ERROR) {
RecordAction(
UserMetricsAction("PhishingInterstitial.ReportPhishingError"));
} else if (interaction == MetricsHelper::SHOW_WHITEPAPER) {
RecordAction(UserMetricsAction("PhishingInterstitial.WhitePaper"));
} else if (interaction == MetricsHelper::SHOW_ENHANCED_PROTECTION) {
RecordAction(
UserMetricsAction("PhishingInterstitial.EnhancedProtectionMessage"));
} else if (interaction == MetricsHelper::OPEN_ENHANCED_PROTECTION) {
RecordAction(
UserMetricsAction("PhishingInterstitial.EnhancedProtectionSettings"));
} else if (interaction == MetricsHelper::CLOSE_INTERSTITIAL_WITHOUT_UI) {
RecordAction(
UserMetricsAction("PhishingInterstitial.CloseInterstitialWithoutUI"));
}
}
}
} // namespace
MetricsHelper::~MetricsHelper() {}
MetricsHelper::ReportDetails::ReportDetails() {}
MetricsHelper::ReportDetails::ReportDetails(const ReportDetails& other) =
default;
MetricsHelper::ReportDetails::~ReportDetails() {}
MetricsHelper::MetricsHelper(const GURL& request_url,
const ReportDetails settings,
history::HistoryService* history_service)
: request_url_(request_url), settings_(settings), num_visits_(-1) {
DCHECK(!settings_.metric_prefix.empty());
if (history_service) {
history_service->GetVisibleVisitCountToHost(
request_url_,
base::BindOnce(&MetricsHelper::OnGotHistoryCount,
base::Unretained(this)),
&request_tracker_);
}
}
void MetricsHelper::RecordUserDecision(Decision decision) {
const std::string histogram_name(
"interstitial." + settings_.metric_prefix + ".decision");
RecordUserDecisionToMetrics(decision, histogram_name);
// Record additional information about sites that users have visited before.
// Report |decision| and SHOW together, filtered by the same history state
// so they they are paired regardless of when if num_visits_ is populated.
if (num_visits_ > 0 && (decision == PROCEED || decision == DONT_PROCEED)) {
RecordUserDecisionToMetrics(SHOW, histogram_name + ".repeat_visit");
RecordUserDecisionToMetrics(decision, histogram_name + ".repeat_visit");
}
MaybeRecordDecisionAsAction(decision, settings_.metric_prefix);
}
void MetricsHelper::RecordUserDecisionToMetrics(
Decision decision,
const std::string& histogram_name) {
// Record the decision, and additionally |with extra_suffix|.
RecordSingleDecisionToMetrics(decision, histogram_name);
if (!settings_.extra_suffix.empty()) {
RecordSingleDecisionToMetrics(
decision, histogram_name + "." + settings_.extra_suffix);
}
std::string has_page_shown_suffix =
settings_.blocked_page_shown_timestamp.has_value() ? "after_page_shown"
: "before_page_shown";
RecordSingleDecisionToMetrics(decision,
histogram_name + "." + has_page_shown_suffix);
}
void MetricsHelper::RecordUserInteraction(Interaction interaction) {
const std::string histogram_name(
"interstitial." + settings_.metric_prefix + ".interaction");
RecordSingleInteractionToMetrics(interaction, histogram_name);
if (!settings_.extra_suffix.empty()) {
RecordSingleInteractionToMetrics(
interaction, histogram_name + "." + settings_.extra_suffix);
}
std::string has_page_shown_suffix =
settings_.blocked_page_shown_timestamp.has_value() ? "after_page_shown"
: "before_page_shown";
RecordSingleInteractionToMetrics(
interaction, histogram_name + "." + has_page_shown_suffix);
MaybeRecordInteractionAsAction(interaction, settings_.metric_prefix);
}
void MetricsHelper::RecordShutdownMetrics() {
RecordExtraShutdownMetrics();
}
void MetricsHelper::RecordInterstitialShowDelay() {
const std::string histogram_name("interstitial." + settings_.metric_prefix +
".show_delay");
base::TimeDelta delay =
settings_.blocked_page_shown_timestamp.has_value()
? base::TimeTicks::Now() -
settings_.blocked_page_shown_timestamp.value()
: base::TimeDelta::Min();
base::UmaHistogramTimes(histogram_name, delay);
if (!settings_.extra_suffix.empty()) {
base::UmaHistogramTimes(histogram_name + "." + settings_.extra_suffix,
delay);
}
}
int MetricsHelper::NumVisits() {
return num_visits_;
}
void MetricsHelper::RecordExtraUserDecisionMetrics(Decision decision) {}
void MetricsHelper::RecordExtraUserInteractionMetrics(Interaction interaction) {
}
void MetricsHelper::RecordExtraShutdownMetrics() {}
void MetricsHelper::OnGotHistoryCount(
history::VisibleVisitCountToHostResult result) {
if (result.success)
num_visits_ = result.count;
}
} // namespace security_interstitials