diff options
author | felt <felt@chromium.org> | 2015-07-29 09:00:00 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-07-29 16:00:39 +0000 |
commit | aafecea4940c28a2bc7af3d94f51a0c068582cd2 (patch) | |
tree | 6b715e36ab73aa839a409e6044f690eca99872d8 /components | |
parent | 56f81e32556d513af513eac0710f2e85877ffa3b (diff) | |
download | chromium_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.gn | 1 | ||||
-rw-r--r-- | components/components.gyp | 1 | ||||
-rw-r--r-- | components/security_interstitials.gypi | 26 | ||||
-rw-r--r-- | components/security_interstitials/BUILD.gn | 14 | ||||
-rw-r--r-- | components/security_interstitials/DEPS | 6 | ||||
-rw-r--r-- | components/security_interstitials/OWNERS | 6 | ||||
-rw-r--r-- | components/security_interstitials/metrics_helper.cc | 116 | ||||
-rw-r--r-- | components/security_interstitials/metrics_helper.h | 111 |
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_ |