Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4737)

Unified Diff: chrome/browser/ssl/ssl_browser_tests.cc

Issue 2449193002: Attempt an on-demand time fetch when encountering a date invalid error (Closed)
Patch Set: cleanup Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ssl/ssl_browser_tests.cc
diff --git a/chrome/browser/ssl/ssl_browser_tests.cc b/chrome/browser/ssl/ssl_browser_tests.cc
index d8f3a8f5d574adf6e028103b2bcd36c15c9544ea..047c8bba9888256743a9222d50faedbcfd227320 100644
--- a/chrome/browser/ssl/ssl_browser_tests.cc
+++ b/chrome/browser/ssl/ssl_browser_tests.cc
@@ -20,6 +20,8 @@
#include "base/test/histogram_tester.h"
#include "base/test/simple_test_clock.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/default_clock.h"
+#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "chrome/app/chrome_command_ids.h"
@@ -50,8 +52,9 @@
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/network_time/network_time_test_utils.h"
#include "components/network_time/network_time_tracker.h"
-#include "components/prefs/pref_service.h"
+#include "components/prefs/testing_pref_service.h"
#include "components/security_interstitials/core/controller_client.h"
#include "components/security_interstitials/core/metrics_helper.h"
#include "components/security_state/security_state_model.h"
@@ -2853,6 +2856,281 @@ IN_PROC_BROWSER_TEST_F(SSLUITest,
after_interstitial_ssl_status.Equals(clock_interstitial_ssl_status));
}
+// A fixture for testing on-demand network time queries on SSL
+// certificate date errors.
meacer 2016/11/01 22:20:18 nit: Can you also document the capabilities of thi
estark 2016/11/02 19:58:12 Done.
+class SSLNetworkTimeBrowserTest : public SSLUITest {
+ public:
+ SSLNetworkTimeBrowserTest()
+ : SSLUITest(),
+ field_trial_test_(
+ network_time::FieldTrialTest::CreateForBrowserTest()) {}
+ ~SSLNetworkTimeBrowserTest() override {}
+
+ protected:
+ enum TimeServerBehavior {
+ TIME_SERVER_GOOD_RESPONSE,
+ TIME_SERVER_HANG,
+ };
+
+ network_time::FieldTrialTest* field_trial_test() {
meacer 2016/11/01 22:20:17 const method
estark 2016/11/02 19:58:13 Done.
+ return field_trial_test_.get();
+ }
+
+ // Returns a response that hangs.
+ static std::unique_ptr<net::test_server::HttpResponse> HangingResponseHandler(
+ const net::test_server::HttpRequest& request) {
+ return base::MakeUnique<net::test_server::HungResponse>();
+ }
+
+ // Returns a valid time response when |run_loop| quits.
+ static std::unique_ptr<net::test_server::HttpResponse>
+ WaitingGoodTimeResponseHandler(base::RunLoop* run_loop,
meacer 2016/11/01 22:20:18 nit: Waiting -> Delayed? (I don't feel strongly ab
estark 2016/11/02 19:58:12 Done.
+ const net::test_server::HttpRequest& request) {
+ run_loop->Run();
+ return network_time::GoodTimeResponseHandler(request);
+ }
+
+ void SetUpNetworkTimeServer(TimeServerBehavior behavior) {
+ field_trial_test()->SetNetworkQueriesWithVariationsService(
+ true, 0.0, network_time::FieldTrialTest::FETCHES_ON_DEMAND_ONLY);
+
+ switch (behavior) {
+ case TIME_SERVER_GOOD_RESPONSE:
+ embedded_test_server()->RegisterRequestHandler(base::Bind(
+ &SSLNetworkTimeBrowserTest::WaitingGoodTimeResponseHandler,
+ &waiting_good_time_run_loop_));
+ break;
+ case TIME_SERVER_HANG:
+ embedded_test_server()->RegisterRequestHandler(
+ base::Bind(&SSLNetworkTimeBrowserTest::HangingResponseHandler));
+ break;
+ }
+ ASSERT_TRUE(embedded_test_server()->Start());
+ g_browser_process->network_time_tracker()->SetTimeServerURLForTesting(
+ embedded_test_server()->GetURL("/"));
+ }
+
+ void TriggerGoodTimeResponse() {
+ waiting_good_time_run_loop_.QuitClosure().Run();
+ }
+
+ private:
+ std::unique_ptr<network_time::FieldTrialTest> field_trial_test_;
+ base::RunLoop waiting_good_time_run_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLNetworkTimeBrowserTest);
+};
+
+// Tests that if an on-demand network time fetch returns that the clock
+// is okay, a normal SSL interstitial is shown.
+IN_PROC_BROWSER_TEST_F(SSLNetworkTimeBrowserTest, OnDemandFetchClockOk) {
+ ASSERT_TRUE(https_server_expired_.Start());
+ SetUpNetworkTimeServer(TIME_SERVER_GOOD_RESPONSE);
+ // Use a testing clock set to the time that GoodTimeResponseHandler
+ // returns, to simulate the system clock matching the network time.
+ base::SimpleTestClock testing_clock;
+ SSLErrorHandler::SetClockForTest(&testing_clock);
+ testing_clock.SetNow(
+ base::Time::FromJsTime(network_time::kGoodTimeResponseHandlerTime));
+
+ // Set a long timeout to ensure that the on-demand time fetch completes.
+ SSLErrorHandler::SetInterstitialDelayForTest(base::TimeDelta::FromHours(1));
+
+ WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
+ ASSERT_TRUE(contents);
+ SSLInterstitialTimerObserver interstitial_timer_observer(contents);
+
+ content::WindowedNotificationObserver observer(
+ content::NOTIFICATION_LOAD_STOP,
+ content::NotificationService::AllSources());
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(), https_server_expired_.GetURL("/"),
+ WindowOpenDisposition::CURRENT_TAB, ui_test_utils::BROWSER_TEST_NONE);
+
+ // Once |interstitial_timer_observer| has fired, the request has been
+ // sent. Override the nonce that NetworkTimeTracker expects so that
+ // when the response comes back, it will validate. The nonce can only
+ // be overriden for the current in-flight request, so the test must
+ // call OverrideNonceForTesting() after the request has been sent and
+ // before the response has been received.
+ interstitial_timer_observer.WaitForTimerStarted();
+ g_browser_process->network_time_tracker()->OverrideNonceForTesting(123123123);
+ TriggerGoodTimeResponse();
+
+ EXPECT_TRUE(contents->IsLoading());
+ observer.Wait();
+
+ EXPECT_TRUE(contents->ShowingInterstitialPage());
+ InterstitialPage* interstitial_page = contents->GetInterstitialPage();
+ ASSERT_TRUE(interstitial_page);
+ ASSERT_EQ(SSLBlockingPage::kTypeForTesting,
+ interstitial_page->GetDelegateForTesting()->GetTypeForTesting());
+}
+
+// Tests that if an on-demand network time fetch returns that the clock
+// is wrong, a bad clock interstitial is shown.
+IN_PROC_BROWSER_TEST_F(SSLNetworkTimeBrowserTest, OnDemandFetchClockWrong) {
meacer 2016/11/01 22:20:18 My understanding is that this test sets the clock
estark 2016/11/02 19:58:13 The purpose of setting the test clock is actually
+ ASSERT_TRUE(https_server_expired_.Start());
+ SetUpNetworkTimeServer(TIME_SERVER_GOOD_RESPONSE);
+ // Use a testing clock set to a time that is different from what
+ // GoodTimeResponseHandler returns, simulating a system clock that is
+ // 30 days ahead of the network time.
+ base::SimpleTestClock testing_clock;
+ SSLErrorHandler::SetClockForTest(&testing_clock);
+ testing_clock.SetNow(
+ base::Time::FromJsTime(network_time::kGoodTimeResponseHandlerTime));
meacer 2016/11/01 22:20:17 Is there a particular reason to use JS time and ma
estark 2016/11/02 19:58:12 My thinking here is that it should be relatively e
meacer 2016/11/02 22:43:22 Ah, okay. Would it help to rename kGoodTimeRespons
+ testing_clock.Advance(base::TimeDelta::FromDays(30));
+
+ // Set a long timeout to ensure that the on-demand time fetch completes.
+ SSLErrorHandler::SetInterstitialDelayForTest(base::TimeDelta::FromHours(1));
+
+ WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
+ ASSERT_TRUE(contents);
+ SSLInterstitialTimerObserver interstitial_timer_observer(contents);
+
+ content::WindowedNotificationObserver observer(
+ content::NOTIFICATION_LOAD_STOP,
+ content::NotificationService::AllSources());
+
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(), https_server_expired_.GetURL("/"),
+ WindowOpenDisposition::CURRENT_TAB, ui_test_utils::BROWSER_TEST_NONE);
+
+ // Once |interstitial_timer_observer| has fired, the request has been
+ // sent. Override the nonce that NetworkTimeTracker expects so that
+ // when the response comes back, it will validate. The nonce can only
+ // be overriden for the current in-flight request, so the test must
+ // call OverrideNonceForTesting() after the request has been sent and
+ // before the response has been received.
+ interstitial_timer_observer.WaitForTimerStarted();
+ g_browser_process->network_time_tracker()->OverrideNonceForTesting(123123123);
+ TriggerGoodTimeResponse();
+
+ EXPECT_TRUE(contents->IsLoading());
+ observer.Wait();
meacer 2016/11/01 22:20:18 You might also want to put a WaitForInterstitialAt
estark 2016/11/02 19:58:12 Done.
+
+ EXPECT_TRUE(contents->ShowingInterstitialPage());
+ InterstitialPage* interstitial_page = contents->GetInterstitialPage();
+ ASSERT_TRUE(interstitial_page);
+ ASSERT_EQ(BadClockBlockingPage::kTypeForTesting,
+ interstitial_page->GetDelegateForTesting()->GetTypeForTesting());
+}
+
+// Tests that if the timeout expires before the network time fetch
+// returns, then a normal SSL intersitial is shown.
+IN_PROC_BROWSER_TEST_F(SSLNetworkTimeBrowserTest,
+ TimeoutExpiresBeforeFetchCompletes) {
+ ASSERT_TRUE(https_server_expired_.Start());
+ SetUpNetworkTimeServer(TIME_SERVER_HANG);
+ // Set the timer to fire immediately.
+ SSLErrorHandler::SetInterstitialDelayForTest(base::TimeDelta());
+
+ ui_test_utils::NavigateToURL(browser(), https_server_expired_.GetURL("/"));
+
+ WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
+ ASSERT_TRUE(contents);
+ EXPECT_TRUE(contents->ShowingInterstitialPage());
+ InterstitialPage* interstitial_page = contents->GetInterstitialPage();
+ ASSERT_TRUE(interstitial_page);
+ ASSERT_EQ(SSLBlockingPage::kTypeForTesting,
+ interstitial_page->GetDelegateForTesting()->GetTypeForTesting());
+}
+
+// Tests that if the user stops the page load before either the network
+// time fetch completes or the timeout expires, then there is no interstitial.
+IN_PROC_BROWSER_TEST_F(SSLNetworkTimeBrowserTest, StopBeforeTimeoutExpires) {
+ ASSERT_TRUE(https_server_expired_.Start());
+ SetUpNetworkTimeServer(TIME_SERVER_HANG);
+ // Set the timer to a long delay.
+ SSLErrorHandler::SetInterstitialDelayForTest(base::TimeDelta::FromHours(1));
+
+ WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
+ ASSERT_TRUE(contents);
+ SSLInterstitialTimerObserver interstitial_timer_observer(contents);
+
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(), https_server_expired_.GetURL("/"),
+ WindowOpenDisposition::CURRENT_TAB, ui_test_utils::BROWSER_TEST_NONE);
meacer 2016/11/01 22:20:17 Is there a reason not to use ui_test_utils::Naviga
estark 2016/11/02 19:58:12 This is based on CommonNameMismatchBrowserTest.Int
meacer 2016/11/02 22:43:22 Hmm, the documentation of this method says that th
+ interstitial_timer_observer.WaitForTimerStarted();
+
+ EXPECT_TRUE(contents->IsLoading());
+ content::WindowedNotificationObserver observer(
+ content::NOTIFICATION_LOAD_STOP,
+ content::NotificationService::AllSources());
+ contents->Stop();
+ observer.Wait();
+
+ SSLErrorHandler* ssl_error_handler =
+ SSLErrorHandler::FromWebContents(contents);
+ // Make sure that the |SSLErrorHandler| is deleted.
+ EXPECT_FALSE(ssl_error_handler);
meacer 2016/11/01 22:20:17 Nit: single line? EXPECT_FALSE(SSLErrorHandler::Fr
estark 2016/11/02 19:58:12 Done.
+ EXPECT_FALSE(contents->ShowingInterstitialPage());
+ EXPECT_FALSE(contents->IsLoading());
+}
+
+// Tests that if the user reloads the page before either the network
+// time fetch completes or the timeout expires, then there is no interstitial.
+IN_PROC_BROWSER_TEST_F(SSLNetworkTimeBrowserTest, ReloadBeforeTimeoutExpires) {
+ ASSERT_TRUE(https_server_expired_.Start());
+ SetUpNetworkTimeServer(TIME_SERVER_HANG);
+ // Set the timer to a long delay.
+ SSLErrorHandler::SetInterstitialDelayForTest(base::TimeDelta::FromHours(1));
+
+ WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
+ SSLInterstitialTimerObserver interstitial_timer_observer(contents);
+
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(), https_server_expired_.GetURL("/"),
+ WindowOpenDisposition::CURRENT_TAB, ui_test_utils::BROWSER_TEST_NONE);
meacer 2016/11/01 22:20:18 Same as above: ui_test_utils::NavigateToURL?
estark 2016/11/02 19:58:13 See above
+ interstitial_timer_observer.WaitForTimerStarted();
+
+ EXPECT_TRUE(contents->IsLoading());
+ content::TestNavigationObserver observer(contents, 1);
+ chrome::Reload(browser(), WindowOpenDisposition::CURRENT_TAB);
+ observer.Wait();
+
+ SSLErrorHandler* ssl_error_handler =
+ SSLErrorHandler::FromWebContents(contents);
meacer 2016/11/01 22:20:17 Same as above: single line?
estark 2016/11/02 19:58:13 Done.
+ // Make sure that the |SSLErrorHandler| is deleted.
+ EXPECT_FALSE(ssl_error_handler);
+ EXPECT_FALSE(contents->ShowingInterstitialPage());
+ EXPECT_FALSE(contents->IsLoading());
+}
+
+// Tests that if the user navigates away before either the network time
+// fetch completes or the timeout expires, then there is no
meacer 2016/11/01 22:20:18 I think we can improve test and the ones above. We
estark 2016/11/02 19:58:13 Done. This turns out to be a nice simplification b
+// interstitial.
+IN_PROC_BROWSER_TEST_F(SSLNetworkTimeBrowserTest,
+ NavigateAwayBeforeTimeoutExpires) {
+ ASSERT_TRUE(https_server_expired_.Start());
+ ASSERT_TRUE(https_server_.Start());
+ SetUpNetworkTimeServer(TIME_SERVER_HANG);
+ // Set the timer to a long delay.
+ SSLErrorHandler::SetInterstitialDelayForTest(base::TimeDelta::FromHours(1));
+
+ WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
+ SSLInterstitialTimerObserver interstitial_timer_observer(contents);
+
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(), https_server_expired_.GetURL("/"),
+ WindowOpenDisposition::CURRENT_TAB, ui_test_utils::BROWSER_TEST_NONE);
+ interstitial_timer_observer.WaitForTimerStarted();
+
+ EXPECT_TRUE(contents->IsLoading());
+ content::TestNavigationObserver observer(contents, 1);
+ browser()->OpenURL(content::OpenURLParams(
+ https_server_.GetURL("/"), content::Referrer(),
+ WindowOpenDisposition::CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false));
+ observer.Wait();
+
+ SSLErrorHandler* ssl_error_handler =
+ SSLErrorHandler::FromWebContents(contents);
+ // Make sure that the |SSLErrorHandler| is deleted.
+ EXPECT_FALSE(ssl_error_handler);
+ EXPECT_FALSE(contents->ShowingInterstitialPage());
+ EXPECT_FALSE(contents->IsLoading());
+}
+
meacer 2016/11/01 22:20:17 Maybe add another test where the tab is closed? Yo
estark 2016/11/02 19:58:13 Done.
class CommonNameMismatchBrowserTest : public CertVerifierBrowserTest {
public:
CommonNameMismatchBrowserTest() : CertVerifierBrowserTest() {}
« no previous file with comments | « no previous file | chrome/browser/ssl/ssl_error_handler.h » ('j') | components/network_time/network_time_test_utils.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698