summaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorfelt <felt@chromium.org>2015-07-29 09:00:00 -0700
committerCommit bot <commit-bot@chromium.org>2015-07-29 16:00:39 +0000
commitaafecea4940c28a2bc7af3d94f51a0c068582cd2 (patch)
tree6b715e36ab73aa839a409e6044f690eca99872d8 /components
parent56f81e32556d513af513eac0710f2e85877ffa3b (diff)
downloadchromium_src-aafecea4940c28a2bc7af3d94f51a0c068582cd2.zip
chromium_src-aafecea4940c28a2bc7af3d94f51a0c068582cd2.tar.gz
chromium_src-aafecea4940c28a2bc7af3d94f51a0c068582cd2.tar.bz2
Move the security interstitial metrics helper into a new component
(1) Create components/security_interstitials/ (2) Move the non-Chrome-specific portions of SecurityInterstitialMetricsHelper into the component, as security_interstitials::MetricsHelper (3) Keep the Chrome-specific parts in ChromeSecurityInterstitialMetricsHelper as a subclass (4) Add browser tests to check that UMA histograms are still being recorded BUG=488673,454945 Review URL: https://codereview.chromium.org/1256753002 Cr-Commit-Position: refs/heads/master@{#340894}
Diffstat (limited to 'components')
-rw-r--r--components/BUILD.gn1
-rw-r--r--components/components.gyp1
-rw-r--r--components/security_interstitials.gypi26
-rw-r--r--components/security_interstitials/BUILD.gn14
-rw-r--r--components/security_interstitials/DEPS6
-rw-r--r--components/security_interstitials/OWNERS6
-rw-r--r--components/security_interstitials/metrics_helper.cc116
-rw-r--r--components/security_interstitials/metrics_helper.h111
8 files changed, 281 insertions, 0 deletions
diff --git a/components/BUILD.gn b/components/BUILD.gn
index dc82d95..c22576c 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -93,6 +93,7 @@ group("all_components") {
"//components/search_engines",
"//components/search_provider_logos",
"//components/secure_display",
+ "//components/security_interstitials",
"//components/sessions",
"//components/signin/core/browser",
"//components/startup_metric_utils",
diff --git a/components/components.gyp b/components/components.gyp
index ff7bd7e0..464dfad 100644
--- a/components/components.gyp
+++ b/components/components.gyp
@@ -63,6 +63,7 @@
'search_engines.gypi',
'search_provider_logos.gypi',
'secure_display.gypi',
+ 'security_interstitials.gypi',
'sessions.gypi',
'signin.gypi',
'startup_metric_utils.gypi',
diff --git a/components/security_interstitials.gypi b/components/security_interstitials.gypi
new file mode 100644
index 0000000..e93c58f
--- /dev/null
+++ b/components/security_interstitials.gypi
@@ -0,0 +1,26 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'security_interstitials',
+ 'type': 'static_library',
+ 'dependencies': [
+ '../base/base.gyp:base',
+ '../net/net.gyp:net',
+ 'history_core_browser',
+ 'metrics',
+ 'rappor',
+ ],
+ 'include_dirs': [
+ '..',
+ ],
+ 'sources': [
+ 'security_interstitials/metrics_helper.cc',
+ 'security_interstitials/metrics_helper.h',
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/components/security_interstitials/BUILD.gn b/components/security_interstitials/BUILD.gn
new file mode 100644
index 0000000..30d2eda
--- /dev/null
+++ b/components/security_interstitials/BUILD.gn
@@ -0,0 +1,14 @@
+source_set("security_interstitials") {
+ sources = [
+ "metrics_helper.cc",
+ "metrics_helper.h",
+ ]
+
+ deps = [
+ "//base",
+ "//components/history/core/browser",
+ "//components/metrics",
+ "//components/rappor",
+ "//net",
+ ]
+}
diff --git a/components/security_interstitials/DEPS b/components/security_interstitials/DEPS
new file mode 100644
index 0000000..a32a580
--- /dev/null
+++ b/components/security_interstitials/DEPS
@@ -0,0 +1,6 @@
+include_rules = [
+ "+components/history/core/browser",
+ "+components/metrics",
+ "+components/rappor",
+ "+net/base"
+]
diff --git a/components/security_interstitials/OWNERS b/components/security_interstitials/OWNERS
new file mode 100644
index 0000000..d46fc3f
--- /dev/null
+++ b/components/security_interstitials/OWNERS
@@ -0,0 +1,6 @@
+estark@chromium.org
+felt@chromium.org
+mattm@chromium.org
+meacer@chromium.org
+nparker@chromium.org
+palmer@chromium.org \ No newline at end of file
diff --git a/components/security_interstitials/metrics_helper.cc b/components/security_interstitials/metrics_helper.cc
new file mode 100644
index 0000000..ae2444d
--- /dev/null
+++ b/components/security_interstitials/metrics_helper.cc
@@ -0,0 +1,116 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/security_interstitials/metrics_helper.h"
+
+#include "base/metrics/histogram.h"
+#include "components/history/core/browser/history_service.h"
+#include "components/rappor/rappor_service.h"
+#include "components/rappor/rappor_utils.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+
+namespace {
+// Used for setting bits in Rappor's "interstitial.*.flags"
+enum InterstitialFlagBits {
+ DID_PROCEED = 0,
+ IS_REPEAT_VISIT = 1,
+ HIGHEST_USED_BIT = 1
+};
+} // namespace
+
+namespace security_interstitials {
+
+MetricsHelper::MetricsHelper(const GURL& request_url,
+ const ReportDetails settings,
+ history::HistoryService* history_service,
+ rappor::RapporService* rappor_service)
+ : request_url_(request_url),
+ settings_(settings),
+ rappor_service_(rappor_service),
+ num_visits_(-1) {
+ DCHECK(!settings_.metric_prefix.empty());
+ if (settings_.rappor_report_type == rappor::NUM_RAPPOR_TYPES) // Default.
+ rappor_service = nullptr;
+ DCHECK(!rappor_service || !settings_.rappor_prefix.empty());
+ if (history_service) {
+ history_service->GetVisibleVisitCountToHost(
+ request_url_,
+ base::Bind(&MetricsHelper::OnGotHistoryCount, base::Unretained(this)),
+ &request_tracker_);
+ }
+}
+
+// Directly adds to the UMA histograms, using the same properties as
+// UMA_HISTOGRAM_ENUMERATION, because the macro doesn't allow non-constant
+// histogram names. Reports to Rappor for certain decisions.
+void MetricsHelper::RecordUserDecision(Decision decision) {
+ // UMA
+ const std::string decision_histogram_name(
+ "interstitial." + settings_.metric_prefix + ".decision");
+ base::HistogramBase* decision_histogram = base::LinearHistogram::FactoryGet(
+ decision_histogram_name, 1, MAX_DECISION, MAX_DECISION + 1,
+ base::HistogramBase::kUmaTargetedHistogramFlag);
+ decision_histogram->Add(decision);
+
+ // Rappor
+ if (rappor_service_ && (decision == PROCEED || decision == DONT_PROCEED)) {
+ scoped_ptr<rappor::Sample> sample =
+ rappor_service_->CreateSample(settings_.rappor_report_type);
+
+ // This will populate, for example, "intersitial.malware.domain" or
+ // "interstitial.ssl2.domain". |domain| will be empty for hosts w/o TLDs.
+ const std::string domain =
+ rappor::GetDomainAndRegistrySampleFromGURL(request_url_);
+ sample->SetStringField("domain", domain);
+
+ // Only report history and decision if we have history data.
+ if (num_visits_ >= 0) {
+ int flags = 0;
+ if (decision == PROCEED)
+ flags |= 1 << InterstitialFlagBits::DID_PROCEED;
+ if (num_visits_ > 0)
+ flags |= 1 << InterstitialFlagBits::IS_REPEAT_VISIT;
+ // e.g. "interstitial.malware.flags"
+ sample->SetFlagsField("flags", flags,
+ InterstitialFlagBits::HIGHEST_USED_BIT + 1);
+ }
+ rappor_service_->RecordSampleObj("interstitial." + settings_.rappor_prefix,
+ sample.Pass());
+ }
+
+ // Record additional information about sites that users have
+ // visited before.
+ if (num_visits_ < 1)
+ return;
+ std::string history_histogram_name("interstitial." + settings_.metric_prefix +
+ ".decision.repeat_visit");
+ base::HistogramBase* history_histogram = base::LinearHistogram::FactoryGet(
+ history_histogram_name, 1, MAX_DECISION, MAX_DECISION + 1,
+ base::HistogramBase::kUmaTargetedHistogramFlag);
+ history_histogram->Add(SHOW);
+ history_histogram->Add(decision);
+
+ RecordExtraUserDecisionMetrics(decision);
+}
+
+void MetricsHelper::RecordUserInteraction(Interaction interaction) {
+ const std::string interaction_histogram_name(
+ "interstitial." + settings_.metric_prefix + ".interaction");
+ base::HistogramBase* interaction_histogram =
+ base::LinearHistogram::FactoryGet(
+ interaction_histogram_name, 1, MAX_INTERACTION, MAX_INTERACTION + 1,
+ base::HistogramBase::kUmaTargetedHistogramFlag);
+ interaction_histogram->Add(interaction);
+
+ RecordExtraUserInteractionMetrics(interaction);
+}
+
+void MetricsHelper::OnGotHistoryCount(bool success,
+ int num_visits,
+ base::Time /*first_visit*/) {
+ if (success)
+ num_visits_ = num_visits;
+}
+
+} // namespace security_interstitials
diff --git a/components/security_interstitials/metrics_helper.h b/components/security_interstitials/metrics_helper.h
new file mode 100644
index 0000000..2e403bc
--- /dev/null
+++ b/components/security_interstitials/metrics_helper.h
@@ -0,0 +1,111 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SECURITY_INTERSTITIALS_METRICS_HELPER_H_
+#define COMPONENTS_SECURITY_INTERSTITIALS_METRICS_HELPER_H_
+
+#include <string>
+
+#include "base/task/cancelable_task_tracker.h"
+#include "base/time/time.h"
+#include "components/rappor/rappor_service.h"
+#include "url/gurl.h"
+
+namespace history {
+class HistoryService;
+}
+
+namespace security_interstitials {
+
+// MetricsHelper records user warning interactions in a
+// common way via METRICS histograms and, optionally, RAPPOR metrics. The
+// class will generate the following histograms:
+// METRICS: interstitial.uma_prefix.decision
+// METRICS: interstitial.uma_prefix.decision.repeat_visit
+// METRICS: interstitial.uma_prefix.interaction
+// METRICS: interstitial.uma_prefix.interaction.repeat_visit
+// RAPPOR: interstitial.rappor_prefix
+// wherein |uma_prefix| and |rappor_prefix| are specified via ReportDetails.
+class MetricsHelper {
+ public:
+ // These enums are used for histograms. Don't reorder, delete, or insert
+ // elements. New elements should be added at the end (right before the max).
+ enum Decision {
+ SHOW,
+ PROCEED,
+ DONT_PROCEED,
+ PROCEEDING_DISABLED,
+ MAX_DECISION
+ };
+ enum Interaction {
+ TOTAL_VISITS,
+ SHOW_ADVANCED,
+ SHOW_PRIVACY_POLICY,
+ SHOW_DIAGNOSTIC,
+ SHOW_LEARN_MORE,
+ RELOAD,
+ OPEN_TIME_SETTINGS,
+ SET_EXTENDED_REPORTING_ENABLED,
+ SET_EXTENDED_REPORTING_DISABLED,
+ EXTENDED_REPORTING_IS_ENABLED,
+ REPORT_PHISHING_ERROR,
+ MAX_INTERACTION
+ };
+
+ // uma_prefix: Histogram prefix for UMA.
+ // examples: "phishing", "ssl_overridable"
+ // rappor_prefix: Metric prefix for Rappor.
+ // examples: "phishing", "ssl2"
+ // rappor_report_type: Used to differentiate UMA and Safe Browsing statistics.
+ // The rappor preferences can be left blank if rappor_service is not set.
+ struct ReportDetails {
+ ReportDetails() : rappor_report_type(rappor::NUM_RAPPOR_TYPES) {}
+ std::string metric_prefix;
+ std::string rappor_prefix;
+ rappor::RapporType rappor_report_type;
+ };
+
+ // Args:
+ // url: URL of page that triggered the interstitial. Only origin is used.
+ // history_service: Set this to record metrics based on whether the user
+ // has visited this hostname before.
+ // rappor_service: If you want RAPPOR statistics, provide a service,
+ // settings.rappor_prefix, and settings.rappor_report_type.
+ // settings: Specify reporting details (prefixes and report types).
+ // sampling_event_name: Event name for Experience Sampling.
+ // e.g. "phishing_interstitial_"
+ MetricsHelper(const GURL& url,
+ const ReportDetails settings,
+ history::HistoryService* history_service,
+ rappor::RapporService* rappor_service);
+ virtual ~MetricsHelper() {}
+
+ // Records a user decision or interaction to the appropriate UMA histogram
+ // and potentially in a RAPPOR metric.
+ void RecordUserDecision(Decision decision);
+ void RecordUserInteraction(Interaction interaction);
+
+ protected:
+ // Subclasses should implement any embedder-specific recording logic in these
+ // methods. They'll be invoked from RecordUserDecision/Interaction.
+ virtual void RecordExtraUserDecisionMetrics(Decision decision) = 0;
+ virtual void RecordExtraUserInteractionMetrics(Interaction interaction) = 0;
+
+ private:
+ // Used to query the HistoryService to see if the URL is in history.
+ // It will only be invoked if the constructor received |history_service|.
+ void OnGotHistoryCount(bool success, int num_visits, base::Time first_visit);
+
+ const GURL request_url_;
+ const ReportDetails settings_;
+ rappor::RapporService* rappor_service_;
+ int num_visits_;
+ base::CancelableTaskTracker request_tracker_;
+
+ DISALLOW_COPY_AND_ASSIGN(MetricsHelper);
+};
+
+} // namespace security_interstitials
+
+#endif // COMPONENTS_SECURITY_INTERSTITIALS_METRICS_HELPER_H_