| Index: chrome/browser/ssl/ssl_error_handler_unittest.cc
|
| diff --git a/chrome/browser/ssl/ssl_error_handler_unittest.cc b/chrome/browser/ssl/ssl_error_handler_unittest.cc
|
| index 0dfb7d1b918dbc6922cb0ac2d9528825ccbaf2df..f6693e229c7b0b1ee0f11ef8f00d30adad612a05 100644
|
| --- a/chrome/browser/ssl/ssl_error_handler_unittest.cc
|
| +++ b/chrome/browser/ssl/ssl_error_handler_unittest.cc
|
| @@ -8,6 +8,8 @@
|
| #include "base/macros.h"
|
| #include "base/metrics/field_trial.h"
|
| #include "base/run_loop.h"
|
| +#include "base/test/simple_test_clock.h"
|
| +#include "base/test/simple_test_tick_clock.h"
|
| #include "base/time/time.h"
|
| #include "chrome/browser/captive_portal/captive_portal_service.h"
|
| #include "chrome/browser/profiles/profile.h"
|
| @@ -16,13 +18,22 @@
|
| #include "chrome/test/base/chrome_render_view_host_test_harness.h"
|
| #include "chrome/test/base/testing_profile.h"
|
| #include "components/captive_portal/captive_portal_testing_utils.h"
|
| +#include "components/network_time/network_time_test_utils.h"
|
| +#include "components/network_time/network_time_tracker.h"
|
| +#include "components/prefs/testing_pref_service.h"
|
| +#include "content/public/browser/browser_thread.h"
|
| #include "content/public/browser/notification_service.h"
|
| #include "net/base/net_errors.h"
|
| +#include "net/cert/cert_status_flags.h"
|
| #include "net/cert/x509_certificate.h"
|
| +#include "net/http/http_response_headers.h"
|
| #include "net/ssl/ssl_info.h"
|
| #include "net/test/cert_test_util.h"
|
| +#include "net/test/embedded_test_server/embedded_test_server.h"
|
| +#include "net/test/embedded_test_server/http_response.h"
|
| #include "net/test/test_certificate_data.h"
|
| #include "net/test/test_data_directory.h"
|
| +#include "net/url_request/url_request_test_util.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
|
|
| class SSLErrorHandlerForTest : public SSLErrorHandler {
|
| @@ -32,7 +43,7 @@ class SSLErrorHandlerForTest : public SSLErrorHandler {
|
| const net::SSLInfo& ssl_info)
|
| : SSLErrorHandler(
|
| web_contents,
|
| - net::ERR_CERT_COMMON_NAME_INVALID,
|
| + net::MapCertStatusToNetError(ssl_info.cert_status),
|
| ssl_info,
|
| GURL(),
|
| 0,
|
| @@ -43,6 +54,7 @@ class SSLErrorHandlerForTest : public SSLErrorHandler {
|
| suggested_url_exists_(false),
|
| suggested_url_checked_(false),
|
| ssl_interstitial_shown_(false),
|
| + bad_clock_interstitial_shown_(false),
|
| captive_portal_interstitial_shown_(false),
|
| redirected_to_suggested_url_(false),
|
| is_overridable_error_(true) {}
|
| @@ -72,6 +84,9 @@ class SSLErrorHandlerForTest : public SSLErrorHandler {
|
| int captive_portal_interstitial_shown() const {
|
| return captive_portal_interstitial_shown_;
|
| }
|
| + bool bad_clock_interstitial_shown() const {
|
| + return bad_clock_interstitial_shown_;
|
| + }
|
| bool suggested_url_checked() const { return suggested_url_checked_; }
|
| bool redirected_to_suggested_url() const {
|
| return redirected_to_suggested_url_;
|
| @@ -85,6 +100,7 @@ class SSLErrorHandlerForTest : public SSLErrorHandler {
|
| suggested_url_exists_ = false;
|
| suggested_url_checked_ = false;
|
| ssl_interstitial_shown_ = false;
|
| + bad_clock_interstitial_shown_ = false;
|
| captive_portal_interstitial_shown_ = false;
|
| redirected_to_suggested_url_ = false;
|
| }
|
| @@ -104,6 +120,11 @@ class SSLErrorHandlerForTest : public SSLErrorHandler {
|
|
|
| void ShowSSLInterstitial() override { ssl_interstitial_shown_ = true; }
|
|
|
| + void ShowBadClockInterstitial(const base::Time& now,
|
| + ssl_errors::ClockState clock_state) override {
|
| + bad_clock_interstitial_shown_ = true;
|
| + }
|
| +
|
| void ShowCaptivePortalInterstitial(const GURL& landing_url) override {
|
| captive_portal_interstitial_shown_ = true;
|
| }
|
| @@ -123,6 +144,7 @@ class SSLErrorHandlerForTest : public SSLErrorHandler {
|
| bool suggested_url_exists_;
|
| bool suggested_url_checked_;
|
| bool ssl_interstitial_shown_;
|
| + bool bad_clock_interstitial_shown_;
|
| bool captive_portal_interstitial_shown_;
|
| bool redirected_to_suggested_url_;
|
| bool is_overridable_error_;
|
| @@ -130,9 +152,9 @@ class SSLErrorHandlerForTest : public SSLErrorHandler {
|
| DISALLOW_COPY_AND_ASSIGN(SSLErrorHandlerForTest);
|
| };
|
|
|
| -class SSLErrorHandlerTest : public ChromeRenderViewHostTestHarness {
|
| +class SSLErrorHandlerNameMismatchTest : public ChromeRenderViewHostTestHarness {
|
| public:
|
| - SSLErrorHandlerTest() : field_trial_list_(nullptr) {}
|
| + SSLErrorHandlerNameMismatchTest() : field_trial_list_(nullptr) {}
|
|
|
| void SetUp() override {
|
| ChromeRenderViewHostTestHarness::SetUp();
|
| @@ -162,11 +184,82 @@ class SSLErrorHandlerTest : public ChromeRenderViewHostTestHarness {
|
| net::SSLInfo ssl_info_;
|
| std::unique_ptr<SSLErrorHandlerForTest> error_handler_;
|
| base::FieldTrialList field_trial_list_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(SSLErrorHandlerNameMismatchTest);
|
| +};
|
| +
|
| +class SSLErrorHandlerDateInvalidTest : public ChromeRenderViewHostTestHarness {
|
| + public:
|
| + SSLErrorHandlerDateInvalidTest()
|
| + : field_trial_test_(network_time::FieldTrialTest::CreateForUnitTest()),
|
| + clock_(new base::SimpleTestClock),
|
| + tick_clock_(new base::SimpleTestTickClock),
|
| + test_server_(new net::EmbeddedTestServer) {
|
| + SetThreadBundleOptions(content::TestBrowserThreadBundle::REAL_IO_THREAD);
|
| + network_time::NetworkTimeTracker::RegisterPrefs(pref_service_.registry());
|
| + }
|
| +
|
| + void SetUp() override {
|
| + ChromeRenderViewHostTestHarness::SetUp();
|
| +
|
| + field_trial_test()->SetNetworkQueriesWithVariationsService(
|
| + false, 0.0, network_time::FieldTrialTest::FETCHES_IN_BACKGROUND_ONLY);
|
| + tracker_.reset(new network_time::NetworkTimeTracker(
|
| + std::unique_ptr<base::Clock>(clock_),
|
| + std::unique_ptr<base::TickClock>(tick_clock_), &pref_service_,
|
| + new net::TestURLRequestContextGetter(
|
| + content::BrowserThread::GetTaskRunnerForThread(
|
| + content::BrowserThread::IO))));
|
| +
|
| + // Do this to be sure that |is_null| returns false.
|
| + clock_->Advance(base::TimeDelta::FromDays(111));
|
| + tick_clock_->Advance(base::TimeDelta::FromDays(222));
|
| +
|
| + SSLErrorHandler::SetInterstitialDelayForTest(base::TimeDelta());
|
| + ssl_info_.cert =
|
| + net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
|
| + ssl_info_.cert_status = net::CERT_STATUS_DATE_INVALID;
|
| + error_handler_.reset(
|
| + new SSLErrorHandlerForTest(profile(), web_contents(), ssl_info_));
|
| + error_handler_->SetNetworkTimeTrackerForTest(tracker_.get());
|
| + }
|
| +
|
| + void TearDown() override {
|
| + if (error_handler()) {
|
| + EXPECT_FALSE(error_handler()->IsTimerRunning());
|
| + error_handler_.reset(nullptr);
|
| + }
|
| + ChromeRenderViewHostTestHarness::TearDown();
|
| + }
|
| +
|
| + SSLErrorHandlerForTest* error_handler() { return error_handler_.get(); }
|
| +
|
| + network_time::FieldTrialTest* field_trial_test() {
|
| + return field_trial_test_.get();
|
| + }
|
| +
|
| + network_time::NetworkTimeTracker* tracker() { return tracker_.get(); }
|
| +
|
| + net::EmbeddedTestServer* test_server() { return test_server_.get(); }
|
| +
|
| + void ClearErrorHandler() { error_handler_.reset(nullptr); }
|
| +
|
| + private:
|
| + net::SSLInfo ssl_info_;
|
| + std::unique_ptr<SSLErrorHandlerForTest> error_handler_;
|
| + std::unique_ptr<network_time::FieldTrialTest> field_trial_test_;
|
| + base::SimpleTestClock* clock_;
|
| + base::SimpleTestTickClock* tick_clock_;
|
| + TestingPrefServiceSimple pref_service_;
|
| + std::unique_ptr<network_time::NetworkTimeTracker> tracker_;
|
| + std::unique_ptr<net::EmbeddedTestServer> test_server_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(SSLErrorHandlerDateInvalidTest);
|
| };
|
|
|
| #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
|
|
|
| -TEST_F(SSLErrorHandlerTest,
|
| +TEST_F(SSLErrorHandlerNameMismatchTest,
|
| ShouldShowSSLInterstitialOnTimerExpired) {
|
| EXPECT_FALSE(error_handler()->IsTimerRunning());
|
| error_handler()->StartHandlingError();
|
| @@ -185,7 +278,7 @@ TEST_F(SSLErrorHandlerTest,
|
| EXPECT_FALSE(error_handler()->captive_portal_interstitial_shown());
|
| }
|
|
|
| -TEST_F(SSLErrorHandlerTest,
|
| +TEST_F(SSLErrorHandlerNameMismatchTest,
|
| ShouldShowCustomInterstitialOnCaptivePortalResult) {
|
| EXPECT_FALSE(error_handler()->IsTimerRunning());
|
| error_handler()->StartHandlingError();
|
| @@ -206,7 +299,7 @@ TEST_F(SSLErrorHandlerTest,
|
| EXPECT_TRUE(error_handler()->captive_portal_interstitial_shown());
|
| }
|
|
|
| -TEST_F(SSLErrorHandlerTest,
|
| +TEST_F(SSLErrorHandlerNameMismatchTest,
|
| ShouldShowSSLInterstitialOnNoCaptivePortalResult) {
|
| EXPECT_FALSE(error_handler()->IsTimerRunning());
|
| error_handler()->StartHandlingError();
|
| @@ -229,7 +322,8 @@ TEST_F(SSLErrorHandlerTest,
|
| EXPECT_FALSE(error_handler()->captive_portal_interstitial_shown());
|
| }
|
|
|
| -TEST_F(SSLErrorHandlerTest, ShouldNotCheckSuggestedUrlIfNoSuggestedUrl) {
|
| +TEST_F(SSLErrorHandlerNameMismatchTest,
|
| + ShouldNotCheckSuggestedUrlIfNoSuggestedUrl) {
|
| error_handler()->StartHandlingError();
|
|
|
| EXPECT_TRUE(error_handler()->captive_portal_checked());
|
| @@ -241,7 +335,8 @@ TEST_F(SSLErrorHandlerTest, ShouldNotCheckSuggestedUrlIfNoSuggestedUrl) {
|
| EXPECT_TRUE(error_handler()->ssl_interstitial_shown());
|
| }
|
|
|
| -TEST_F(SSLErrorHandlerTest, ShouldNotCheckCaptivePortalIfSuggestedUrlExists) {
|
| +TEST_F(SSLErrorHandlerNameMismatchTest,
|
| + ShouldNotCheckCaptivePortalIfSuggestedUrlExists) {
|
| EXPECT_FALSE(error_handler()->IsTimerRunning());
|
| error_handler()->set_suggested_url_exists();
|
| error_handler()->StartHandlingError();
|
| @@ -255,7 +350,8 @@ TEST_F(SSLErrorHandlerTest, ShouldNotCheckCaptivePortalIfSuggestedUrlExists) {
|
| EXPECT_TRUE(error_handler()->ssl_interstitial_shown());
|
| }
|
|
|
| -TEST_F(SSLErrorHandlerTest, ShouldNotHandleNameMismatchOnNonOverridableError) {
|
| +TEST_F(SSLErrorHandlerNameMismatchTest,
|
| + ShouldNotHandleNameMismatchOnNonOverridableError) {
|
| error_handler()->set_non_overridable_error();
|
| error_handler()->set_suggested_url_exists();
|
| error_handler()->StartHandlingError();
|
| @@ -271,7 +367,7 @@ TEST_F(SSLErrorHandlerTest, ShouldNotHandleNameMismatchOnNonOverridableError) {
|
|
|
| #else // #if !BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
|
|
|
| -TEST_F(SSLErrorHandlerTest,
|
| +TEST_F(SSLErrorHandlerNameMismatchTest,
|
| ShouldShowSSLInterstitialOnCaptivePortalDetectionDisabled) {
|
| EXPECT_FALSE(error_handler()->IsTimerRunning());
|
| error_handler()->StartHandlingError();
|
| @@ -283,7 +379,7 @@ TEST_F(SSLErrorHandlerTest,
|
|
|
| #endif // BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
|
|
|
| -TEST_F(SSLErrorHandlerTest,
|
| +TEST_F(SSLErrorHandlerNameMismatchTest,
|
| ShouldShowSSLInterstitialOnTimerExpiredWhenSuggestedUrlExists) {
|
| error_handler()->set_suggested_url_exists();
|
| error_handler()->StartHandlingError();
|
| @@ -300,7 +396,8 @@ TEST_F(SSLErrorHandlerTest,
|
| EXPECT_FALSE(error_handler()->redirected_to_suggested_url());
|
| }
|
|
|
| -TEST_F(SSLErrorHandlerTest, ShouldRedirectOnSuggestedUrlCheckResult) {
|
| +TEST_F(SSLErrorHandlerNameMismatchTest,
|
| + ShouldRedirectOnSuggestedUrlCheckResult) {
|
| error_handler()->set_suggested_url_exists();
|
| error_handler()->StartHandlingError();
|
|
|
| @@ -321,7 +418,8 @@ TEST_F(SSLErrorHandlerTest, ShouldRedirectOnSuggestedUrlCheckResult) {
|
| EXPECT_TRUE(error_handler()->redirected_to_suggested_url());
|
| }
|
|
|
| -TEST_F(SSLErrorHandlerTest, ShouldShowSSLInterstitialOnInvalidUrlCheckResult) {
|
| +TEST_F(SSLErrorHandlerNameMismatchTest,
|
| + ShouldShowSSLInterstitialOnInvalidUrlCheckResult) {
|
| error_handler()->set_suggested_url_exists();
|
| error_handler()->StartHandlingError();
|
|
|
| @@ -339,3 +437,90 @@ TEST_F(SSLErrorHandlerTest, ShouldShowSSLInterstitialOnInvalidUrlCheckResult) {
|
| EXPECT_TRUE(error_handler()->ssl_interstitial_shown());
|
| EXPECT_FALSE(error_handler()->redirected_to_suggested_url());
|
| }
|
| +
|
| +TEST_F(SSLErrorHandlerDateInvalidTest, TimeQueryStarted) {
|
| + base::Time network_time;
|
| + base::TimeDelta uncertainty;
|
| + EXPECT_EQ(network_time::NetworkTimeTracker::NETWORK_TIME_NO_SYNC_ATTEMPT,
|
| + tracker()->GetNetworkTime(&network_time, &uncertainty));
|
| +
|
| + // Enable network time queries and handle the error. A bad clock interstitial
|
| + // should be shown.
|
| + EXPECT_TRUE(test_server()->Start());
|
| + test_server()->RegisterRequestHandler(
|
| + base::Bind(&network_time::GoodTimeResponseHandler));
|
| + tracker()->SetTimeServerURLForTesting(test_server()->GetURL("/"));
|
| + field_trial_test()->SetNetworkQueriesWithVariationsService(
|
| + true, 0.0, network_time::FieldTrialTest::FETCHES_ON_DEMAND_ONLY);
|
| + error_handler()->StartHandlingError();
|
| +
|
| + EXPECT_TRUE(error_handler()->IsTimerRunning());
|
| + tracker()->WaitForFetchForTesting(123123123);
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + EXPECT_TRUE(error_handler()->bad_clock_interstitial_shown());
|
| + EXPECT_FALSE(error_handler()->IsTimerRunning());
|
| +}
|
| +
|
| +// Tests that an SSL interstitial is shown if the accuracy of the system
|
| +// clock can't be determined because network time is unavailable.
|
| +TEST_F(SSLErrorHandlerDateInvalidTest, NoTimeQueries) {
|
| + base::Time network_time;
|
| + base::TimeDelta uncertainty;
|
| + EXPECT_EQ(network_time::NetworkTimeTracker::NETWORK_TIME_NO_SYNC_ATTEMPT,
|
| + tracker()->GetNetworkTime(&network_time, &uncertainty));
|
| +
|
| + // Handle the error without enabling time queries. A bad clock interstitial
|
| + // should not be shown.
|
| + error_handler()->StartHandlingError();
|
| +
|
| + EXPECT_FALSE(error_handler()->IsTimerRunning());
|
| + EXPECT_FALSE(error_handler()->bad_clock_interstitial_shown());
|
| + EXPECT_TRUE(error_handler()->ssl_interstitial_shown());
|
| +}
|
| +
|
| +// Runs |quit_closure| on the UI thread once a URL request has been
|
| +// seen. Returns a request that hangs.
|
| +std::unique_ptr<net::test_server::HttpResponse> WaitForRequest(
|
| + const base::Closure& quit_closure,
|
| + const net::test_server::HttpRequest& request) {
|
| + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
|
| + quit_closure);
|
| + return base::MakeUnique<net::test_server::HungResponse>();
|
| +}
|
| +
|
| +// Tests that an SSL interstitial is shown if determing the accuracy of
|
| +// the system clock times out (e.g. because a network time query hangs).
|
| +TEST_F(SSLErrorHandlerDateInvalidTest, TimeQueryHangs) {
|
| + base::Time network_time;
|
| + base::TimeDelta uncertainty;
|
| + EXPECT_EQ(network_time::NetworkTimeTracker::NETWORK_TIME_NO_SYNC_ATTEMPT,
|
| + tracker()->GetNetworkTime(&network_time, &uncertainty));
|
| +
|
| + // Enable network time queries and handle the error. Because the
|
| + // network time cannot be determined before the timer elapses, an SSL
|
| + // interstitial should be shown.
|
| + EXPECT_TRUE(test_server()->Start());
|
| + base::RunLoop wait_for_time_query_loop;
|
| + test_server()->RegisterRequestHandler(
|
| + base::Bind(&WaitForRequest, wait_for_time_query_loop.QuitClosure()));
|
| + tracker()->SetTimeServerURLForTesting(test_server()->GetURL("/"));
|
| + field_trial_test()->SetNetworkQueriesWithVariationsService(
|
| + true, 0.0, network_time::FieldTrialTest::FETCHES_ON_DEMAND_ONLY);
|
| + error_handler()->StartHandlingError();
|
| + EXPECT_TRUE(error_handler()->IsTimerRunning());
|
| + wait_for_time_query_loop.Run();
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + EXPECT_FALSE(error_handler()->bad_clock_interstitial_shown());
|
| + EXPECT_TRUE(error_handler()->ssl_interstitial_shown());
|
| + EXPECT_FALSE(error_handler()->IsTimerRunning());
|
| +
|
| + // Clear the error handler to test that, when the request completes,
|
| + // it doesn't try to call a callback on a deleted SSLErrorHandler.
|
| + ClearErrorHandler();
|
| +
|
| + // Shut down the server to cancel the pending request.
|
| + ASSERT_TRUE(test_server()->ShutdownAndWaitUntilComplete());
|
| + tracker()->WaitForFetchForTesting(123123123);
|
| +}
|
|
|