Commit a3b92cfc authored by felt's avatar felt Committed by Commit bot

Refactor captive portal code from SSLBlockingPage to SSLErrorClassification

A function is also added to check the type of the network the user is
connected to.

CL originally written by radhikabhar@ as 400323002, but not landed before
her internship ended.

BUG=395295
TBR=meacer@chromium.org, dcheng@chromium.org

Review URL: https://codereview.chromium.org/516373003

Cr-Commit-Position: refs/heads/master@{#292767}
parent d5e2bf5c
...@@ -47,11 +47,6 @@ ...@@ -47,11 +47,6 @@
#include "ui/base/webui/jstemplate_builder.h" #include "ui/base/webui/jstemplate_builder.h"
#include "ui/base/webui/web_ui_util.h" #include "ui/base/webui/web_ui_util.h"
#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
#include "chrome/browser/captive_portal/captive_portal_service.h"
#include "chrome/browser/captive_portal/captive_portal_service_factory.h"
#endif
#if defined(ENABLE_EXTENSIONS) #if defined(ENABLE_EXTENSIONS)
#include "chrome/browser/extensions/api/experience_sampling_private/experience_sampling.h" #include "chrome/browser/extensions/api/experience_sampling_private/experience_sampling.h"
#endif #endif
...@@ -110,14 +105,15 @@ enum SSLBlockingPageEvent { ...@@ -110,14 +105,15 @@ enum SSLBlockingPageEvent {
SHOW_NEW_SITE, SHOW_NEW_SITE,
PROCEED_NEW_SITE, PROCEED_NEW_SITE,
PROCEED_MANUAL_NONOVERRIDABLE, PROCEED_MANUAL_NONOVERRIDABLE,
CAPTIVE_PORTAL_DETECTION_ENABLED, // Captive Portal errors moved to ssl_error_classification.
CAPTIVE_PORTAL_DETECTION_ENABLED_OVERRIDABLE, DEPRECATED_CAPTIVE_PORTAL_DETECTION_ENABLED,
CAPTIVE_PORTAL_PROBE_COMPLETED, DEPRECATED_CAPTIVE_PORTAL_DETECTION_ENABLED_OVERRIDABLE,
CAPTIVE_PORTAL_PROBE_COMPLETED_OVERRIDABLE, DEPRECATED_CAPTIVE_PORTAL_PROBE_COMPLETED,
CAPTIVE_PORTAL_NO_RESPONSE, DEPRECATED_CAPTIVE_PORTAL_PROBE_COMPLETED_OVERRIDABLE,
CAPTIVE_PORTAL_NO_RESPONSE_OVERRIDABLE, DEPRECATED_CAPTIVE_PORTAL_NO_RESPONSE,
CAPTIVE_PORTAL_DETECTED, DEPRECATED_CAPTIVE_PORTAL_NO_RESPONSE_OVERRIDABLE,
CAPTIVE_PORTAL_DETECTED_OVERRIDABLE, DEPRECATED_CAPTIVE_PORTAL_DETECTED,
DEPRECATED_CAPTIVE_PORTAL_DETECTED_OVERRIDABLE,
UNUSED_BLOCKING_PAGE_EVENT, UNUSED_BLOCKING_PAGE_EVENT,
}; };
...@@ -167,38 +163,11 @@ void RecordSSLBlockingPageDetailedStats(bool proceed, ...@@ -167,38 +163,11 @@ void RecordSSLBlockingPageDetailedStats(bool proceed,
bool overridable, bool overridable,
bool internal, bool internal,
int num_visits, int num_visits,
bool captive_portal_detection_enabled,
bool captive_portal_probe_completed,
bool captive_portal_no_response,
bool captive_portal_detected,
bool expired_but_previously_allowed) { bool expired_but_previously_allowed) {
UMA_HISTOGRAM_ENUMERATION("interstitial.ssl_error_type", UMA_HISTOGRAM_ENUMERATION("interstitial.ssl_error_type",
SSLErrorInfo::NetErrorToErrorType(cert_error), SSLErrorInfo::END_OF_ENUM); SSLErrorInfo::NetErrorToErrorType(cert_error), SSLErrorInfo::END_OF_ENUM);
RecordSSLExpirationPageEventState( RecordSSLExpirationPageEventState(
expired_but_previously_allowed, proceed, overridable); expired_but_previously_allowed, proceed, overridable);
#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
if (captive_portal_detection_enabled)
RecordSSLBlockingPageEventStats(
overridable ?
CAPTIVE_PORTAL_DETECTION_ENABLED_OVERRIDABLE :
CAPTIVE_PORTAL_DETECTION_ENABLED);
if (captive_portal_probe_completed)
RecordSSLBlockingPageEventStats(
overridable ?
CAPTIVE_PORTAL_PROBE_COMPLETED_OVERRIDABLE :
CAPTIVE_PORTAL_PROBE_COMPLETED);
// Log only one of portal detected and no response results.
if (captive_portal_detected)
RecordSSLBlockingPageEventStats(
overridable ?
CAPTIVE_PORTAL_DETECTED_OVERRIDABLE :
CAPTIVE_PORTAL_DETECTED);
else if (captive_portal_no_response)
RecordSSLBlockingPageEventStats(
overridable ?
CAPTIVE_PORTAL_NO_RESPONSE_OVERRIDABLE :
CAPTIVE_PORTAL_NO_RESPONSE);
#endif
if (!overridable) { if (!overridable) {
if (proceed) { if (proceed) {
RecordSSLBlockingPageEventStats(PROCEED_MANUAL_NONOVERRIDABLE); RecordSSLBlockingPageEventStats(PROCEED_MANUAL_NONOVERRIDABLE);
...@@ -351,10 +320,6 @@ SSLBlockingPage::SSLBlockingPage(content::WebContents* web_contents, ...@@ -351,10 +320,6 @@ SSLBlockingPage::SSLBlockingPage(content::WebContents* web_contents,
interstitial_page_(NULL), interstitial_page_(NULL),
internal_(false), internal_(false),
num_visits_(-1), num_visits_(-1),
captive_portal_detection_enabled_(false),
captive_portal_probe_completed_(false),
captive_portal_no_response_(false),
captive_portal_detected_(false),
expired_but_previously_allowed_( expired_but_previously_allowed_(
(options_mask & EXPIRED_BUT_PREVIOUSLY_ALLOWED) != 0) { (options_mask & EXPIRED_BUT_PREVIOUSLY_ALLOWED) != 0) {
Profile* profile = Profile::FromBrowserContext( Profile* profile = Profile::FromBrowserContext(
...@@ -378,20 +343,16 @@ SSLBlockingPage::SSLBlockingPage(content::WebContents* web_contents, ...@@ -378,20 +343,16 @@ SSLBlockingPage::SSLBlockingPage(content::WebContents* web_contents,
} }
} }
SSLErrorClassification ssl_error_classification( ssl_error_classification_.reset(new SSLErrorClassification(
web_contents_,
base::Time::NowFromSystemTime(), base::Time::NowFromSystemTime(),
request_url_, request_url_,
*ssl_info_.cert.get()); cert_error_,
ssl_error_classification.RecordUMAStatistics(overridable_, cert_error_); *ssl_info_.cert.get()));
ssl_error_classification_->RecordUMAStatistics(overridable_);
#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
CaptivePortalService* captive_portal_service = ssl_error_classification_->RecordCaptivePortalUMAStatistics(overridable_);
CaptivePortalServiceFactory::GetForProfile(profile);
captive_portal_detection_enabled_ = captive_portal_service ->enabled();
captive_portal_service ->DetectCaptivePortal();
registrar_.Add(this,
chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT,
content::Source<Profile>(profile));
#endif #endif
#if defined(ENABLE_EXTENSIONS) #if defined(ENABLE_EXTENSIONS)
...@@ -414,16 +375,27 @@ SSLBlockingPage::SSLBlockingPage(content::WebContents* web_contents, ...@@ -414,16 +375,27 @@ SSLBlockingPage::SSLBlockingPage(content::WebContents* web_contents,
} }
SSLBlockingPage::~SSLBlockingPage() { SSLBlockingPage::~SSLBlockingPage() {
// InvalidCommonNameSeverityScore() and InvalidDateSeverityScore() are in the
// destructor because they depend on knowing whether captive portal detection
// happened before the user made a decision.
SSLErrorInfo::ErrorType type =
SSLErrorInfo::NetErrorToErrorType(cert_error_);
switch (type) {
case SSLErrorInfo::CERT_DATE_INVALID:
ssl_error_classification_->InvalidDateSeverityScore();
break;
case SSLErrorInfo::CERT_COMMON_NAME_INVALID:
ssl_error_classification_->InvalidCommonNameSeverityScore();
break;
default:
break;
}
if (!callback_.is_null()) { if (!callback_.is_null()) {
RecordSSLBlockingPageDetailedStats(false, RecordSSLBlockingPageDetailedStats(false,
cert_error_, cert_error_,
overridable_, overridable_,
internal_, internal_,
num_visits_, num_visits_,
captive_portal_detection_enabled_,
captive_portal_probe_completed_,
captive_portal_no_response_,
captive_portal_detected_,
expired_but_previously_allowed_); expired_but_previously_allowed_);
// The page is closed without the user having chosen what to do, default to // The page is closed without the user having chosen what to do, default to
// deny. // deny.
...@@ -621,16 +593,13 @@ void SSLBlockingPage::OnProceed() { ...@@ -621,16 +593,13 @@ void SSLBlockingPage::OnProceed() {
overridable_, overridable_,
internal_, internal_,
num_visits_, num_visits_,
captive_portal_detection_enabled_,
captive_portal_probe_completed_,
captive_portal_no_response_,
captive_portal_detected_,
expired_but_previously_allowed_); expired_but_previously_allowed_);
#if defined(ENABLE_EXTENSIONS) #if defined(ENABLE_EXTENSIONS)
// ExperienceSampling: Notify that user decided to proceed. // ExperienceSampling: Notify that user decided to proceed.
if (sampling_event_.get()) if (sampling_event_.get())
sampling_event_->CreateUserDecisionEvent(ExperienceSamplingEvent::kProceed); sampling_event_->CreateUserDecisionEvent(ExperienceSamplingEvent::kProceed);
#endif #endif
// Accepting the certificate resumes the loading of the page. // Accepting the certificate resumes the loading of the page.
NotifyAllowCertificate(); NotifyAllowCertificate();
} }
...@@ -641,10 +610,6 @@ void SSLBlockingPage::OnDontProceed() { ...@@ -641,10 +610,6 @@ void SSLBlockingPage::OnDontProceed() {
overridable_, overridable_,
internal_, internal_,
num_visits_, num_visits_,
captive_portal_detection_enabled_,
captive_portal_probe_completed_,
captive_portal_no_response_,
captive_portal_detected_,
expired_but_previously_allowed_); expired_but_previously_allowed_);
#if defined(ENABLE_EXTENSIONS) #if defined(ENABLE_EXTENSIONS)
// ExperienceSampling: Notify that user decided to not proceed. // ExperienceSampling: Notify that user decided to not proceed.
...@@ -695,35 +660,3 @@ void SSLBlockingPage::OnGotHistoryCount(bool success, ...@@ -695,35 +660,3 @@ void SSLBlockingPage::OnGotHistoryCount(bool success,
base::Time first_visit) { base::Time first_visit) {
num_visits_ = num_visits; num_visits_ = num_visits;
} }
void SSLBlockingPage::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
// When detection is disabled, captive portal service always sends
// RESULT_INTERNET_CONNECTED. Ignore any probe results in that case.
if (!captive_portal_detection_enabled_)
return;
if (type == chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT) {
captive_portal_probe_completed_ = true;
CaptivePortalService::Results* results =
content::Details<CaptivePortalService::Results>(
details).ptr();
// If a captive portal was detected at any point when the interstitial was
// displayed, assume that the interstitial was caused by a captive portal.
// Example scenario:
// 1- Interstitial displayed and captive portal detected, setting the flag.
// 2- Captive portal detection automatically opens portal login page.
// 3- User logs in on the portal login page.
// A notification will be received here for RESULT_INTERNET_CONNECTED. Make
// sure we don't clear the captive portal flag, since the interstitial was
// potentially caused by the captive portal.
captive_portal_detected_ = captive_portal_detected_ ||
(results->result == captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL);
// Also keep track of non-HTTP portals and error cases.
captive_portal_no_response_ = captive_portal_no_response_ ||
(results->result == captive_portal::RESULT_NO_RESPONSE);
}
#endif
}
...@@ -32,15 +32,12 @@ class ExperienceSamplingEvent; ...@@ -32,15 +32,12 @@ class ExperienceSamplingEvent;
} }
#endif #endif
class SSLErrorClassification;
// This class is responsible for showing/hiding the interstitial page that is // This class is responsible for showing/hiding the interstitial page that is
// shown when a certificate error happens. // shown when a certificate error happens.
// It deletes itself when the interstitial page is closed. // It deletes itself when the interstitial page is closed.
// class SSLBlockingPage : public content::InterstitialPageDelegate {
// This class should only be used on the UI thread because its implementation
// uses captive_portal::CaptivePortalService which can only be accessed on the
// UI thread.
class SSLBlockingPage : public content::InterstitialPageDelegate,
public content::NotificationObserver {
public: public:
// These represent the commands sent from the interstitial JavaScript. They // These represent the commands sent from the interstitial JavaScript. They
// are defined in chrome/browser/resources/ssl/ssl_errors_common.js. // are defined in chrome/browser/resources/ssl/ssl_errors_common.js.
...@@ -100,12 +97,6 @@ class SSLBlockingPage : public content::InterstitialPageDelegate, ...@@ -100,12 +97,6 @@ class SSLBlockingPage : public content::InterstitialPageDelegate,
// Used to query the HistoryService to see if the URL is in history. For UMA. // Used to query the HistoryService to see if the URL is in history. For UMA.
void OnGotHistoryCount(bool success, int num_visits, base::Time first_visit); void OnGotHistoryCount(bool success, int num_visits, base::Time first_visit);
// content::NotificationObserver:
virtual void Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
base::Callback<void(bool)> callback_; base::Callback<void(bool)> callback_;
content::WebContents* web_contents_; content::WebContents* web_contents_;
...@@ -124,20 +115,10 @@ class SSLBlockingPage : public content::InterstitialPageDelegate, ...@@ -124,20 +115,10 @@ class SSLBlockingPage : public content::InterstitialPageDelegate,
int num_visits_; int num_visits_;
// Used for getting num_visits_. // Used for getting num_visits_.
base::CancelableTaskTracker request_tracker_; base::CancelableTaskTracker request_tracker_;
// Is captive portal detection enabled?
bool captive_portal_detection_enabled_;
// Did the probe complete before the interstitial was closed?
bool captive_portal_probe_completed_;
// Did the captive portal probe receive an error or get a non-HTTP response?
bool captive_portal_no_response_;
// Was a captive portal detected?
bool captive_portal_detected_;
// Did the user previously allow a bad certificate but the decision has now // Did the user previously allow a bad certificate but the decision has now
// expired? // expired?
const bool expired_but_previously_allowed_; const bool expired_but_previously_allowed_;
scoped_ptr<SSLErrorClassification> ssl_error_classification_;
// For the FieldTrial: this contains the name of the condition.
std::string trial_condition_;
#if defined(ENABLE_EXTENSIONS) #if defined(ENABLE_EXTENSIONS)
// For Chrome Experience Sampling Platform: this maintains event state. // For Chrome Experience Sampling Platform: this maintains event state.
......
...@@ -9,17 +9,29 @@ ...@@ -9,17 +9,29 @@
#include <vector> #include <vector>
#include "base/time/time.h" #include "base/time/time.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "net/cert/x509_certificate.h" #include "net/cert/x509_certificate.h"
#include "url/gurl.h" #include "url/gurl.h"
// This class calculates the severity scores for the different type of SSL namespace content {
// errors. class WebContents;
class SSLErrorClassification { }
// This class classifies characteristics of SSL errors, including information
// about captive portal detection.
//
// This class should only be used on the UI thread because its
// implementation uses captive_portal::CaptivePortalService which can only be
// accessed on the UI thread.
class SSLErrorClassification : public content::NotificationObserver {
public: public:
SSLErrorClassification(const base::Time& current_time, SSLErrorClassification(content::WebContents* web_contents,
const base::Time& current_time,
const GURL& url, const GURL& url,
int cert_error,
const net::X509Certificate& cert); const net::X509Certificate& cert);
~SSLErrorClassification(); virtual ~SSLErrorClassification();
// Returns true if the system time is in the past. // Returns true if the system time is in the past.
static bool IsUserClockInThePast(const base::Time& time_now); static bool IsUserClockInThePast(const base::Time& time_now);
...@@ -31,18 +43,19 @@ class SSLErrorClassification { ...@@ -31,18 +43,19 @@ class SSLErrorClassification {
static bool IsWindowsVersionSP3OrLower(); static bool IsWindowsVersionSP3OrLower();
// A function which calculates the severity score when the ssl error is // A function which calculates the severity score when the ssl error is
// CERT_DATE_INVALID, returns a score between 0.0 and 1.0, higher values // |CERT_DATE_INVALID|. The calculated score is between 0.0 and 1.0, higher
// being more severe, indicating how severe the certificate's invalid // being more severe, indicating how severe the certificate's
// date error is. // date invalid error is.
float InvalidDateSeverityScore(int cert_error) const; void InvalidDateSeverityScore();
// A function which calculates the severity score when the ssl error is // A function which calculates the severity score when the ssl error is
// when the SSL error is |CERT_COMMON_NAME_INVALID|, returns a score between // |CERT_COMMON_NAME_INVALID|. The calculated score is between 0.0 and 1.0,
// between 0.0 and 1.0, higher values being more severe, indicating how // higher being more severe, indicating how severe the certificate's common
// severe the certificate's common name invalid error is. // name invalid error is.
float InvalidCommonNameSeverityScore(int cert_error) const; void InvalidCommonNameSeverityScore();
void RecordUMAStatistics(bool overridable, int cert_error); void RecordUMAStatistics(bool overridable) const;
void RecordCaptivePortalUMAStatistics(bool overridable) const;
base::TimeDelta TimePassedSinceExpiry() const; base::TimeDelta TimePassedSinceExpiry() const;
private: private:
...@@ -90,8 +103,6 @@ class SSLErrorClassification { ...@@ -90,8 +103,6 @@ class SSLErrorClassification {
// fields. // fields.
bool IsCertLikelyFromMultiTenantHosting() const; bool IsCertLikelyFromMultiTenantHosting() const;
float CalculateScoreTimePassedSinceExpiry() const;
static std::vector<Tokens> GetTokenizedDNSNames( static std::vector<Tokens> GetTokenizedDNSNames(
const std::vector<std::string>& dns_names); const std::vector<std::string>& dns_names);
...@@ -109,13 +120,32 @@ class SSLErrorClassification { ...@@ -109,13 +120,32 @@ class SSLErrorClassification {
static Tokens Tokenize(const std::string& name); static Tokens Tokenize(const std::string& name);
float CalculateScoreTimePassedSinceExpiry() const;
float CalculateScoreEnvironments() const;
// content::NotificationObserver:
virtual void Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
content::WebContents* web_contents_;
// This stores the current time. // This stores the current time.
base::Time current_time_; base::Time current_time_;
const GURL& request_url_; const GURL& request_url_;
int cert_error_;
// This stores the certificate. // This stores the certificate.
const net::X509Certificate& cert_; const net::X509Certificate& cert_;
// Is captive portal detection enabled?
bool captive_portal_detection_enabled_;
// Did the probe complete before the interstitial was closed?
bool captive_portal_probe_completed_;
// Did the captive portal probe receive an error or get a non-HTTP response?
bool captive_portal_no_response_;
// Was a captive portal detected?
bool captive_portal_detected_;
content::NotificationRegistrar registrar_;
}; };
#endif // CHROME_BROWSER_SSL_SSL_ERROR_CLASSIFICATION_H_ #endif // CHROME_BROWSER_SSL_SSL_ERROR_CLASSIFICATION_H_
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/strings/string_split.h" #include "base/strings/string_split.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "content/public/browser/web_contents.h"
#include "net/base/net_errors.h"
#include "net/base/test_data_directory.h" #include "net/base/test_data_directory.h"
#include "net/cert/x509_cert_types.h" #include "net/cert/x509_cert_types.h"
#include "net/cert/x509_certificate.h" #include "net/cert/x509_certificate.h"
...@@ -16,34 +19,56 @@ ...@@ -16,34 +19,56 @@
#include "url/gurl.h" #include "url/gurl.h"
using base::Time; using base::Time;
using content::WebContents;
TEST(SSLErrorClassificationTest, TestDateInvalidScore) { class SSLErrorClassificationTest : public ChromeRenderViewHostTestHarness {
public:
SSLErrorClassificationTest() {
SetThreadBundleOptions(content::TestBrowserThreadBundle::REAL_IO_THREAD);
}
};
TEST_F(SSLErrorClassificationTest, TestDateInvalidScore) {
base::FilePath certs_dir = net::GetTestCertsDirectory(); base::FilePath certs_dir = net::GetTestCertsDirectory();
scoped_refptr<net::X509Certificate> expired_cert = scoped_refptr<net::X509Certificate> expired_cert =
net::ImportCertFromFile(certs_dir, "expired_cert.pem"); net::ImportCertFromFile(certs_dir, "expired_cert.pem");
base::Time time; base::Time time;
GURL origin("https://example.com"); GURL origin("https://example.com");
int cert_error = net::ERR_CERT_DATE_INVALID;
WebContents* contents = web_contents();
{ {
EXPECT_TRUE(base::Time::FromString("Wed, 03 Jan 2007 12:00:00 GMT", &time)); EXPECT_TRUE(base::Time::FromString("Wed, 03 Jan 2007 12:00:00 GMT", &time));
SSLErrorClassification ssl_error(time, origin, *expired_cert); SSLErrorClassification ssl_error(contents,
time,
origin,
cert_error,
*expired_cert);
EXPECT_FLOAT_EQ(0.2f, ssl_error.CalculateScoreTimePassedSinceExpiry()); EXPECT_FLOAT_EQ(0.2f, ssl_error.CalculateScoreTimePassedSinceExpiry());
} }
{ {
EXPECT_TRUE(base::Time::FromString("Sat, 06 Jan 2007 12:00:00 GMT", &time)); EXPECT_TRUE(base::Time::FromString("Sat, 06 Jan 2007 12:00:00 GMT", &time));
SSLErrorClassification ssl_error(time, origin, *expired_cert); SSLErrorClassification ssl_error(contents,
time,
origin,
cert_error,
*expired_cert);
EXPECT_FLOAT_EQ(0.3f, ssl_error.CalculateScoreTimePassedSinceExpiry()); EXPECT_FLOAT_EQ(0.3f, ssl_error.CalculateScoreTimePassedSinceExpiry());
} }
{ {
EXPECT_TRUE(base::Time::FromString("Mon, 08 Jan 2007 12:00:00 GMT", &time)); EXPECT_TRUE(base::Time::FromString("Mon, 08 Jan 2007 12:00:00 GMT", &time));
SSLErrorClassification ssl_error(time, origin, *expired_cert); SSLErrorClassification ssl_error(contents,
time,
origin,
cert_error,
*expired_cert);
EXPECT_FLOAT_EQ(0.4f, ssl_error.CalculateScoreTimePassedSinceExpiry()); EXPECT_FLOAT_EQ(0.4f, ssl_error.CalculateScoreTimePassedSinceExpiry());
} }
} }
TEST(SSLErrorClassificationTest, TestNameMismatch) { TEST_F(SSLErrorClassificationTest, TestNameMismatch) {
scoped_refptr<net::X509Certificate> google_cert( scoped_refptr<net::X509Certificate> google_cert(
net::X509Certificate::CreateFromBytes( net::X509Certificate::CreateFromBytes(
reinterpret_cast<const char*>(google_der), sizeof(google_der))); reinterpret_cast<const char*>(google_der), sizeof(google_der)));
...@@ -55,12 +80,18 @@ TEST(SSLErrorClassificationTest, TestNameMismatch) { ...@@ -55,12 +80,18 @@ TEST(SSLErrorClassificationTest, TestNameMismatch) {
dns_names_google.push_back("com"); dns_names_google.push_back("com");
std::vector<std::vector<std::string>> dns_name_tokens_google; std::vector<std::vector<std::string>> dns_name_tokens_google;
dns_name_tokens_google.push_back(dns_names_google); dns_name_tokens_google.push_back(dns_names_google);
int cert_error = net::ERR_CERT_COMMON_NAME_INVALID;
WebContents* contents = web_contents();
{ {
GURL origin("https://google.com"); GURL origin("https://google.com");
std::string host_name = origin.host(); std::string host_name = origin.host();
std::vector<std::string> host_name_tokens; std::vector<std::string> host_name_tokens;
base::SplitStringDontTrim(host_name, '.', &host_name_tokens); base::SplitStringDontTrim(host_name, '.', &host_name_tokens);
SSLErrorClassification ssl_error(time, origin, *google_cert); SSLErrorClassification ssl_error(contents,
time,
origin,
cert_error,
*google_cert);
EXPECT_TRUE(ssl_error.IsWWWSubDomainMatch()); EXPECT_TRUE(ssl_error.IsWWWSubDomainMatch());
EXPECT_FALSE(ssl_error.NameUnderAnyNames(host_name_tokens, EXPECT_FALSE(ssl_error.NameUnderAnyNames(host_name_tokens,
dns_name_tokens_google)); dns_name_tokens_google));
...@@ -75,7 +106,11 @@ TEST(SSLErrorClassificationTest, TestNameMismatch) { ...@@ -75,7 +106,11 @@ TEST(SSLErrorClassificationTest, TestNameMismatch) {
std::string host_name = origin.host(); std::string host_name = origin.host();
std::vector<std::string> host_name_tokens; std::vector<std::string> host_name_tokens;
base::SplitStringDontTrim(host_name, '.', &host_name_tokens); base::SplitStringDontTrim(host_name, '.', &host_name_tokens);
SSLErrorClassification ssl_error(time, origin, *google_cert); SSLErrorClassification ssl_error(contents,
time,
origin,
cert_error,
*google_cert);
EXPECT_FALSE(ssl_error.IsWWWSubDomainMatch()); EXPECT_FALSE(ssl_error.IsWWWSubDomainMatch());
EXPECT_FALSE(ssl_error.NameUnderAnyNames(host_name_tokens, EXPECT_FALSE(ssl_error.NameUnderAnyNames(host_name_tokens,
dns_name_tokens_google)); dns_name_tokens_google));
...@@ -88,7 +123,11 @@ TEST(SSLErrorClassificationTest, TestNameMismatch) { ...@@ -88,7 +123,11 @@ TEST(SSLErrorClassificationTest, TestNameMismatch) {
std::string host_name = origin.host(); std::string host_name = origin.host();
std::vector<std::string> host_name_tokens; std::vector<std::string> host_name_tokens;
base::SplitStringDontTrim(host_name, '.', &host_name_tokens); base::SplitStringDontTrim(host_name, '.', &host_name_tokens);
SSLErrorClassification ssl_error(time, origin, *google_cert); SSLErrorClassification ssl_error(contents,
time,
origin,
cert_error,
*google_cert);
EXPECT_FALSE(ssl_error.IsWWWSubDomainMatch()); EXPECT_FALSE(ssl_error.IsWWWSubDomainMatch());
EXPECT_TRUE(ssl_error.NameUnderAnyNames(host_name_tokens, EXPECT_TRUE(ssl_error.NameUnderAnyNames(host_name_tokens,
dns_name_tokens_google)); dns_name_tokens_google));
...@@ -101,7 +140,11 @@ TEST(SSLErrorClassificationTest, TestNameMismatch) { ...@@ -101,7 +140,11 @@ TEST(SSLErrorClassificationTest, TestNameMismatch) {
std::string host_name = origin.host(); std::string host_name = origin.host();
std::vector<std::string> host_name_tokens; std::vector<std::string> host_name_tokens;
base::SplitStringDontTrim(host_name, '.', &host_name_tokens); base::SplitStringDontTrim(host_name, '.', &host_name_tokens);
SSLErrorClassification ssl_error(time, origin, *google_cert); SSLErrorClassification ssl_error(contents,
time,
origin,
cert_error,
*google_cert);
EXPECT_FALSE(ssl_error.IsWWWSubDomainMatch()); EXPECT_FALSE(ssl_error.IsWWWSubDomainMatch());
EXPECT_FALSE(ssl_error.NameUnderAnyNames(host_name_tokens, EXPECT_FALSE(ssl_error.NameUnderAnyNames(host_name_tokens,
dns_name_tokens_google)); dns_name_tokens_google));
...@@ -114,7 +157,11 @@ TEST(SSLErrorClassificationTest, TestNameMismatch) { ...@@ -114,7 +157,11 @@ TEST(SSLErrorClassificationTest, TestNameMismatch) {
std::string host_name = origin.host(); std::string host_name = origin.host();
std::vector<std::string> host_name_tokens; std::vector<std::string> host_name_tokens;
base::SplitStringDontTrim(host_name, '.', &host_name_tokens); base::SplitStringDontTrim(host_name, '.', &host_name_tokens);
SSLErrorClassification ssl_error(time, origin, *google_cert); SSLErrorClassification ssl_error(contents,
time,
origin,
cert_error,
*google_cert);
EXPECT_FALSE(ssl_error.IsWWWSubDomainMatch()); EXPECT_FALSE(ssl_error.IsWWWSubDomainMatch());
EXPECT_FALSE(ssl_error.NameUnderAnyNames(host_name_tokens, EXPECT_FALSE(ssl_error.NameUnderAnyNames(host_name_tokens,
dns_name_tokens_google)); dns_name_tokens_google));
...@@ -136,7 +183,11 @@ TEST(SSLErrorClassificationTest, TestNameMismatch) { ...@@ -136,7 +183,11 @@ TEST(SSLErrorClassificationTest, TestNameMismatch) {
std::string host_name = origin.host(); std::string host_name = origin.host();
std::vector<std::string> host_name_tokens; std::vector<std::string> host_name_tokens;
base::SplitStringDontTrim(host_name, '.', &host_name_tokens); base::SplitStringDontTrim(host_name, '.', &host_name_tokens);
SSLErrorClassification ssl_error(time, origin, *webkit_cert); SSLErrorClassification ssl_error(contents,
time,
origin,
cert_error,
*webkit_cert);
EXPECT_FALSE(ssl_error.IsWWWSubDomainMatch()); EXPECT_FALSE(ssl_error.IsWWWSubDomainMatch());
EXPECT_FALSE(ssl_error.NameUnderAnyNames(host_name_tokens, EXPECT_FALSE(ssl_error.NameUnderAnyNames(host_name_tokens,
dns_name_tokens_webkit)); dns_name_tokens_webkit));
...@@ -147,7 +198,7 @@ TEST(SSLErrorClassificationTest, TestNameMismatch) { ...@@ -147,7 +198,7 @@ TEST(SSLErrorClassificationTest, TestNameMismatch) {
} }
} }
TEST(SSLErrorClassificationTest, TestHostNameHasKnownTLD) { TEST_F(SSLErrorClassificationTest, TestHostNameHasKnownTLD) {
std::string url1 = "www.google.com"; std::string url1 = "www.google.com";
std::string url2 = "b.appspot.com"; std::string url2 = "b.appspot.com";
std::string url3 = "a.private"; std::string url3 = "a.private";
......
...@@ -10436,6 +10436,17 @@ Therefore, the affected-histogram name has to have at least one dot in it. ...@@ -10436,6 +10436,17 @@ Therefore, the affected-histogram name has to have at least one dot in it.
</summary> </summary>
</histogram> </histogram>
<histogram name="interstitial.ssl.captive_portal" enum="SSLCaptivePortal">
<owner>meacer@chromium.org</owner>
<summary>
Record possible states of captive portals. This histogram is emitted
(possibly multiple times to different buckets) whenever a ssl interstitial
page is displayed and captive portal detection is enabled. The captive
portal technique forces a client on a network to see a special web page
(usually for authentication purposes) before using the internet normally.
</summary>
</histogram>
<histogram name="interstitial.ssl.cause.nonoverridable" <histogram name="interstitial.ssl.cause.nonoverridable"
enum="SSLNonAttackCauses"> enum="SSLNonAttackCauses">
<owner>felt@chromium.org</owner> <owner>felt@chromium.org</owner>
...@@ -49871,6 +49882,44 @@ To add a new entry, add it with any value and run test to compute valid value. ...@@ -49871,6 +49882,44 @@ To add a new entry, add it with any value and run test to compute valid value.
<int value="5" label="DEPRECATION_RAZE_FAILED">Raze failed.</int> <int value="5" label="DEPRECATION_RAZE_FAILED">Raze failed.</int>
</enum> </enum>
<enum name="SSLCaptivePortal" type="int">
<int value="0"
label="Chrome captive portal detection enabled
(CAPTIVE_PORTAL_DETECTION_ENABLED)"/>
<int value="1"
label="Chrome captive portal detection enabled on an overridable SSL
error page (CAPTIVE_PORTAL_DETECTION_ENABLED_OVERRIDABLE)">
This is a subset of CAPTIVE_PORTAL_DETECTION_ENABLED (bucket 0), the only
difference is that it is for overridable errors.
</int>
<int value="2"
label="Received a captive portal probe result.
(CAPTIVE_PORTAL_PROBE_COMPLETED)">
Was the captive portal probe completed before the interstitial was closed?
Captive Portal won't be detected unless ::Observe is triggered which might
be a few seconds later.
</int>
<int value="3"
label="Received a captive portal result on an overridable SSL error page
(CAPTIVE_PORTAL_PROBE_COMPLETED_OVERRIDABLE)">
This is a subset of CAPTIVE_PORTAL_PROBE_COMPLETED (bucket 2), the only
difference is that it is for overridable errors.
</int>
<int value="4"
label="Received no response or Non-HTTP login page
(CAPTIVE_PORTAL_NO_RESPONSE)"/>
<int value="5"
label="Received no response or Non-HTTP login page on an overridable
SSL error page (CAPTIVE_PORTAL_NO_RESPONSE_OVERRIDABLE)"/>
<int value="6" label="Detected captive portal (CAPTIVE_PORTAL_DETECTED)"/>
<int value="7"
label="Detected captive portal on an overridable SSL error page
(CAPTIVE_PORTAL_DETECTED_OVERRIDABLE)">
This is a subset of CAPTIVE_PORTAL_DETECTED (bucket 6), the only difference
is that it is for overridable errors.
</int>
</enum>
<enum name="SSLCipherSuite" type="int"> <enum name="SSLCipherSuite" type="int">
<summary>SSL/TLS cipher suites from the IANA registry</summary> <summary>SSL/TLS cipher suites from the IANA registry</summary>
<int value="0" label="TLS_NULL_WITH_NULL_NULL"/> <int value="0" label="TLS_NULL_WITH_NULL_NULL"/>
...@@ -50274,26 +50323,28 @@ To add a new entry, add it with any value and run test to compute valid value. ...@@ -50274,26 +50323,28 @@ To add a new entry, add it with any value and run test to compute valid value.
label="User manually typed proceed (PROCEED_MANUAL_NONOVERRIDABLE)"/> label="User manually typed proceed (PROCEED_MANUAL_NONOVERRIDABLE)"/>
<int value="17" <int value="17"
label="Chrome captive portal detection enabled label="Chrome captive portal detection enabled
(CAPTIVE_PORTAL_DETECTION_ENABLED)"/> (DEPRECATED_CAPTIVE_PORTAL_DETECTION_ENABLED)"/>
<int value="18" <int value="18"
label="Chrome captive portal detection enabled on an overridable SSL label="Chrome captive portal detection enabled on an overridable SSL
error page (CAPTIVE_PORTAL_DETECTION_ENABLED_OVERRIDABLE)"/> error page
(DEPRECATED_CAPTIVE_PORTAL_DETECTION_ENABLED_OVERRIDABLE)"/>
<int value="19" <int value="19"
label="Received a captive portal result label="Received a captive portal result
(CAPTIVE_PORTAL_PROBE_COMPLETED)"/> (DEPRECATED_CAPTIVE_PORTAL_PROBE_COMPLETED)"/>
<int value="20" <int value="20"
label="Received a captive portal result on an overridable SSL error label="Received a captive portal result on an overridable SSL error
page (CAPTIVE_PORTAL_PROBE_COMPLETED_OVERRIDABLE)"/> page (DEPRECATED_CAPTIVE_PORTAL_PROBE_COMPLETED_OVERRIDABLE)"/>
<int value="21" <int value="21"
label="Received no response or Non-HTTP login page label="Received no response or Non-HTTP login page
(CAPTIVE_PORTAL_NO_RESPONSE)"/> (DEPRECATED_CAPTIVE_PORTAL_NO_RESPONSE)"/>
<int value="22" <int value="22"
label="Received no response or Non-HTTP login page on an overridable label="Received no response or Non-HTTP login page on an overridable
SSL error page (CAPTIVE_PORTAL_NO_RESPONSE_OVERRIDABLE)"/> SSL error page
(DEPRECATED_CAPTIVE_PORTAL_NO_RESPONSE_OVERRIDABLE)"/>
<int value="23" label="Detected captive portal (CAPTIVE_PORTAL_DETECTED)"/> <int value="23" label="Detected captive portal (CAPTIVE_PORTAL_DETECTED)"/>
<int value="24" <int value="24"
label="Detected captive portal on an overridable SSL error page label="Detected captive portal on an overridable SSL error page
(CAPTIVE_PORTAL_DETECTED_OVERRIDABLE)"/> (DEPRECATED_CAPTIVE_PORTAL_DETECTED_OVERRIDABLE)"/>
</enum> </enum>
<enum name="StartupURLsMigration" type="int"> <enum name="StartupURLsMigration" type="int">
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