Commit e6b54d26 authored by Emily Stark's avatar Emily Stark Committed by Commit Bot

Add HasSeenRecurrentErrors() to ChromeSSLHostStateDelegate

In a follow-up CL, this will be used to add a message to the interstitial when
users have seen multiple errors in a browsing session.

Bug: 839969
Change-Id: I6e7f9c7e73f93b29c73f8fafa504acbfdd182e4c
Reviewed-on: https://chromium-review.googlesource.com/1048173
Commit-Queue: Emily Stark <estark@chromium.org>
Reviewed-by: default avatarChristopher Thompson <cthomp@chromium.org>
Cr-Commit-Position: refs/heads/master@{#557081}
parent 5dc0baca
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "base/guid.h" #include "base/guid.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/metrics/field_trial.h" #include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h"
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "base/time/clock.h" #include "base/time/clock.h"
#include "base/time/default_clock.h" #include "base/time/default_clock.h"
...@@ -38,6 +39,9 @@ ...@@ -38,6 +39,9 @@
namespace { namespace {
const char kRecurrentInterstitialThresholdParam[] = "threshold";
const int kRecurrentInterstitialDefaultThreshold = 3;
// The default expiration is one week, unless overidden by a field trial group. // The default expiration is one week, unless overidden by a field trial group.
// See https://crbug.com/487270. // See https://crbug.com/487270.
const uint64_t kDeltaDefaultExpirationInSeconds = UINT64_C(604800); const uint64_t kDeltaDefaultExpirationInSeconds = UINT64_C(604800);
...@@ -154,6 +158,9 @@ bool HostFilterToPatternFilter( ...@@ -154,6 +158,9 @@ bool HostFilterToPatternFilter(
} // namespace } // namespace
const base::Feature kRecurrentInterstitialFeature{
"RecurrentInterstitialFeature", base::FEATURE_DISABLED_BY_DEFAULT};
// This helper function gets the dictionary of certificate fingerprints to // This helper function gets the dictionary of certificate fingerprints to
// errors of certificates that have been accepted by the user from the content // errors of certificates that have been accepted by the user from the content
// dictionary that has been passed in. The returned pointer is owned by the the // dictionary that has been passed in. The returned pointer is owned by the the
...@@ -488,6 +495,39 @@ bool ChromeSSLHostStateDelegate::DidHostRunInsecureContent( ...@@ -488,6 +495,39 @@ bool ChromeSSLHostStateDelegate::DidHostRunInsecureContent(
NOTREACHED(); NOTREACHED();
return false; return false;
} }
void ChromeSSLHostStateDelegate::SetClock(std::unique_ptr<base::Clock> clock) { void ChromeSSLHostStateDelegate::SetClock(std::unique_ptr<base::Clock> clock) {
clock_ = std::move(clock); clock_ = std::move(clock);
} }
void ChromeSSLHostStateDelegate::DidDisplayErrorPage(int error) {
if (error != net::ERR_CERT_SYMANTEC_LEGACY &&
error != net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED) {
return;
}
const auto count_it = recurrent_errors_.find(error);
if (count_it == recurrent_errors_.end()) {
recurrent_errors_[error] = 1;
return;
}
if (count_it->second >= base::GetFieldTrialParamByFeatureAsInt(
kRecurrentInterstitialFeature,
kRecurrentInterstitialThresholdParam,
kRecurrentInterstitialDefaultThreshold)) {
return;
}
recurrent_errors_[error] = count_it->second + 1;
}
bool ChromeSSLHostStateDelegate::HasSeenRecurrentErrors(int error) const {
if (!base::FeatureList::IsEnabled(kRecurrentInterstitialFeature)) {
return false;
}
const auto count = recurrent_errors_.find(error);
if (count == recurrent_errors_.end())
return false;
return count->second >= base::GetFieldTrialParamByFeatureAsInt(
kRecurrentInterstitialFeature,
kRecurrentInterstitialThresholdParam,
kRecurrentInterstitialDefaultThreshold);
}
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <memory> #include <memory>
#include <set> #include <set>
#include "base/feature_list.h"
#include "base/gtest_prod_util.h" #include "base/gtest_prod_util.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/time/time.h" #include "base/time/time.h"
...@@ -20,10 +21,13 @@ class Clock; ...@@ -20,10 +21,13 @@ class Clock;
class DictionaryValue; class DictionaryValue;
} // namespace base } // namespace base
// Tracks whether the user has allowed a certificate error exception for a extern const base::Feature kRecurrentInterstitialFeature;
// specific site, SSL fingerprint, and error. Based on command-line flags and
// experimental group, remembers this decision either until end-of-session or // Tracks state related to certificate and SSL errors. This state includes:
// for a particular length of time. // - certificate error exceptions (which are remembered for a particular length
// of time depending on experimental groups)
// - mixed content exceptions
// - when errors have recurred multiple times
class ChromeSSLHostStateDelegate : public content::SSLHostStateDelegate { class ChromeSSLHostStateDelegate : public content::SSLHostStateDelegate {
public: public:
explicit ChromeSSLHostStateDelegate(Profile* profile); explicit ChromeSSLHostStateDelegate(Profile* profile);
...@@ -63,6 +67,18 @@ class ChromeSSLHostStateDelegate : public content::SSLHostStateDelegate { ...@@ -63,6 +67,18 @@ class ChromeSSLHostStateDelegate : public content::SSLHostStateDelegate {
// error combination exception is allowed, use QueryPolicy(). // error combination exception is allowed, use QueryPolicy().
bool HasAllowException(const std::string& host) const override; bool HasAllowException(const std::string& host) const override;
// Called when an error page is displayed for a given error code |error|.
// Tracks whether an error of interest has recurred over a threshold number of
// times.
void DidDisplayErrorPage(int error);
// Returns true if DidDisplayErrorPage() has been called over a threshold
// number of times for a particular error. Always returns false if
// |kRecurrentInterstitialFeature| is not enabled. Only certain error codes of
// interest are tracked, so this may return false for an error code that has
// recurred.
bool HasSeenRecurrentErrors(int error) const;
protected: protected:
// SetClock takes ownership of the passed in clock. // SetClock takes ownership of the passed in clock.
void SetClock(std::unique_ptr<base::Clock> clock); void SetClock(std::unique_ptr<base::Clock> clock);
...@@ -148,6 +164,10 @@ class ChromeSSLHostStateDelegate : public content::SSLHostStateDelegate { ...@@ -148,6 +164,10 @@ class ChromeSSLHostStateDelegate : public content::SSLHostStateDelegate {
// https://crbug.com/418631 for more details. // https://crbug.com/418631 for more details.
const std::string current_expiration_guid_; const std::string current_expiration_guid_;
// Tracks how many times an error page has been shown for a given error, up
// to a certain threshold value.
std::map<int /* error code */, int /* count */> recurrent_errors_;
DISALLOW_COPY_AND_ASSIGN(ChromeSSLHostStateDelegate); DISALLOW_COPY_AND_ASSIGN(ChromeSSLHostStateDelegate);
}; };
......
...@@ -345,6 +345,30 @@ IN_PROC_BROWSER_TEST_F(ChromeSSLHostStateDelegateTest, Migrate) { ...@@ -345,6 +345,30 @@ IN_PROC_BROWSER_TEST_F(ChromeSSLHostStateDelegateTest, Migrate) {
EXPECT_EQ(ContentSettingsPattern::Wildcard(), settings[0].secondary_pattern); EXPECT_EQ(ContentSettingsPattern::Wildcard(), settings[0].secondary_pattern);
} }
// Tests that ChromeSSLHostStateDelegate::HasSeenRecurrentErrors returns true
// after seeing an error of interest multiple times.
IN_PROC_BROWSER_TEST_F(ChromeSSLHostStateDelegateTest, HasSeenRecurrentErrors) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeatureWithParameters(kRecurrentInterstitialFeature,
{{"threshold", "2"}});
content::WebContents* tab =
browser()->tab_strip_model()->GetActiveWebContents();
Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate();
ChromeSSLHostStateDelegate* chrome_state =
static_cast<ChromeSSLHostStateDelegate*>(state);
chrome_state->DidDisplayErrorPage(net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED);
EXPECT_FALSE(chrome_state->HasSeenRecurrentErrors(
net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED));
chrome_state->DidDisplayErrorPage(net::ERR_CERT_SYMANTEC_LEGACY);
EXPECT_FALSE(chrome_state->HasSeenRecurrentErrors(
net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED));
chrome_state->DidDisplayErrorPage(net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED);
EXPECT_TRUE(chrome_state->HasSeenRecurrentErrors(
net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED));
}
class ForgetAtSessionEndSSLHostStateDelegateTest class ForgetAtSessionEndSSLHostStateDelegateTest
: public ChromeSSLHostStateDelegateTest { : public ChromeSSLHostStateDelegateTest {
protected: protected:
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/renderer_preferences_util.h" #include "chrome/browser/renderer_preferences_util.h"
#include "chrome/browser/ssl/cert_report_helper.h" #include "chrome/browser/ssl/cert_report_helper.h"
#include "chrome/browser/ssl/chrome_ssl_host_state_delegate.h"
#include "chrome/browser/ssl/chrome_ssl_host_state_delegate_factory.h"
#include "chrome/browser/ssl/ssl_cert_reporter.h" #include "chrome/browser/ssl/ssl_cert_reporter.h"
#include "chrome/browser/ssl/ssl_error_controller_client.h" #include "chrome/browser/ssl/ssl_error_controller_client.h"
#include "chrome/common/chrome_switches.h" #include "chrome/common/chrome_switches.h"
...@@ -85,6 +87,11 @@ SSLBlockingPage* SSLBlockingPage::Create( ...@@ -85,6 +87,11 @@ SSLBlockingPage* SSLBlockingPage::Create(
overridable, is_superfish)); overridable, is_superfish));
metrics_helper.get()->StartRecordingCaptivePortalMetrics(overridable); metrics_helper.get()->StartRecordingCaptivePortalMetrics(overridable);
ChromeSSLHostStateDelegate* state =
ChromeSSLHostStateDelegateFactory::GetForProfile(
Profile::FromBrowserContext(web_contents->GetBrowserContext()));
state->DidDisplayErrorPage(cert_error);
return new SSLBlockingPage(web_contents, cert_error, ssl_info, request_url, return new SSLBlockingPage(web_contents, cert_error, ssl_info, request_url,
options_mask, time_triggered, support_url, options_mask, time_triggered, support_url,
std::move(ssl_cert_reporter), overridable, std::move(ssl_cert_reporter), overridable,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment