1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ssl/ssl_error_handler.h"
7 #include "base/callback.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/metrics/field_trial.h"
10 #include "base/run_loop.h"
11 #include "base/time/time.h"
12 #include "chrome/browser/captive_portal/captive_portal_service.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
15 #include "chrome/test/base/testing_profile.h"
16 #include "components/captive_portal/captive_portal_testing_utils.h"
17 #include "content/public/browser/notification_service.h"
18 #include "net/base/net_errors.h"
19 #include "net/ssl/ssl_info.h"
20 #include "testing/gtest/include/gtest/gtest.h"
22 class TestSSLErrorHandler
: public SSLErrorHandler
{
24 TestSSLErrorHandler(Profile
* profile
,
25 content::WebContents
* web_contents
,
26 const net::SSLInfo
& ssl_info
)
27 : SSLErrorHandler(web_contents
,
28 net::ERR_CERT_COMMON_NAME_INVALID
,
33 base::Callback
<void(bool)>()),
35 captive_portal_checked_(false),
36 ssl_interstitial_shown_(false),
37 captive_portal_interstitial_shown_(false) {}
39 ~TestSSLErrorHandler() override
{
42 using SSLErrorHandler::StartHandlingError
;
44 void SendCaptivePortalNotification(
45 captive_portal::CaptivePortalResult result
) {
46 CaptivePortalService::Results results
;
47 results
.previous_result
= captive_portal::RESULT_INTERNET_CONNECTED
;
48 results
.result
= result
;
49 content::NotificationService::current()->Notify(
50 chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT
,
51 content::Source
<Profile
>(profile_
),
52 content::Details
<CaptivePortalService::Results
>(&results
));
55 bool IsTimerRunning() const {
56 return get_timer().IsRunning();
59 int captive_portal_checked() const {
60 return captive_portal_checked_
;
63 int ssl_interstitial_shown() const {
64 return ssl_interstitial_shown_
;
67 int captive_portal_interstitial_shown() const {
68 return captive_portal_interstitial_shown_
;
72 captive_portal_checked_
= false;
73 ssl_interstitial_shown_
= false;
74 captive_portal_interstitial_shown_
= false;
78 void CheckForCaptivePortal() override
{
79 captive_portal_checked_
= true;
82 void ShowSSLInterstitial() override
{
83 ssl_interstitial_shown_
= true;
86 void ShowCaptivePortalInterstitial(const GURL
& landing_url
) override
{
87 captive_portal_interstitial_shown_
= true;
91 bool captive_portal_checked_
;
92 bool ssl_interstitial_shown_
;
93 bool captive_portal_interstitial_shown_
;
95 DISALLOW_COPY_AND_ASSIGN(TestSSLErrorHandler
);
98 class SSLErrorHandlerTest
: public ChromeRenderViewHostTestHarness
{
100 SSLErrorHandlerTest()
101 : field_trial_list_(NULL
) {
104 void SetUp() override
{
105 ChromeRenderViewHostTestHarness::SetUp();
106 SSLErrorHandler::SetInterstitialDelayTypeForTest(SSLErrorHandler::NONE
);
107 error_handler_
.reset(new TestSSLErrorHandler(profile(),
110 // Enable finch experiment for captive portal interstitials.
111 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
112 "CaptivePortalInterstitial", "Enabled"));
115 void TearDown() override
{
116 EXPECT_FALSE(error_handler()->IsTimerRunning());
117 error_handler_
.reset(NULL
);
118 ChromeRenderViewHostTestHarness::TearDown();
121 TestSSLErrorHandler
* error_handler() { return error_handler_
.get(); }
124 net::SSLInfo ssl_info_
;
125 scoped_ptr
<TestSSLErrorHandler
> error_handler_
;
126 base::FieldTrialList field_trial_list_
;
129 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
131 TEST_F(SSLErrorHandlerTest
,
132 ShouldShowSSLInterstitialOnTimerExpired
) {
133 EXPECT_FALSE(error_handler()->IsTimerRunning());
134 error_handler()->StartHandlingError();
136 EXPECT_TRUE(error_handler()->IsTimerRunning());
137 EXPECT_TRUE(error_handler()->captive_portal_checked());
138 EXPECT_FALSE(error_handler()->ssl_interstitial_shown());
139 EXPECT_FALSE(error_handler()->captive_portal_interstitial_shown());
141 error_handler()->Reset();
142 base::MessageLoop::current()->RunUntilIdle();
144 EXPECT_FALSE(error_handler()->IsTimerRunning());
145 EXPECT_FALSE(error_handler()->captive_portal_checked());
146 EXPECT_TRUE(error_handler()->ssl_interstitial_shown());
147 EXPECT_FALSE(error_handler()->captive_portal_interstitial_shown());
150 TEST_F(SSLErrorHandlerTest
,
151 ShouldShowCustomInterstitialOnCaptivePortalResult
) {
152 EXPECT_FALSE(error_handler()->IsTimerRunning());
153 error_handler()->StartHandlingError();
155 EXPECT_TRUE(error_handler()->IsTimerRunning());
156 EXPECT_TRUE(error_handler()->captive_portal_checked());
157 EXPECT_FALSE(error_handler()->ssl_interstitial_shown());
158 EXPECT_FALSE(error_handler()->captive_portal_interstitial_shown());
159 // Fake a captive portal result.
160 error_handler()->Reset();
161 error_handler()->SendCaptivePortalNotification(
162 captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL
);
163 base::MessageLoop::current()->RunUntilIdle();
165 EXPECT_FALSE(error_handler()->IsTimerRunning());
166 EXPECT_FALSE(error_handler()->captive_portal_checked());
167 EXPECT_FALSE(error_handler()->ssl_interstitial_shown());
168 EXPECT_TRUE(error_handler()->captive_portal_interstitial_shown());
171 TEST_F(SSLErrorHandlerTest
,
172 ShouldShowSSLInterstitialOnNoCaptivePortalResult
) {
173 EXPECT_FALSE(error_handler()->IsTimerRunning());
174 error_handler()->StartHandlingError();
176 EXPECT_TRUE(error_handler()->IsTimerRunning());
177 EXPECT_TRUE(error_handler()->captive_portal_checked());
178 EXPECT_FALSE(error_handler()->ssl_interstitial_shown());
179 EXPECT_FALSE(error_handler()->captive_portal_interstitial_shown());
180 // Fake a "connected to internet" result for the captive portal check.
181 // This should immediately trigger an SSL interstitial without waiting for
182 // the timer to expire.
183 error_handler()->Reset();
184 error_handler()->SendCaptivePortalNotification(
185 captive_portal::RESULT_INTERNET_CONNECTED
);
186 base::MessageLoop::current()->RunUntilIdle();
188 EXPECT_FALSE(error_handler()->IsTimerRunning());
189 EXPECT_FALSE(error_handler()->captive_portal_checked());
190 EXPECT_TRUE(error_handler()->ssl_interstitial_shown());
191 EXPECT_FALSE(error_handler()->captive_portal_interstitial_shown());
194 #else // #if !defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
196 TEST_F(SSLErrorHandlerTest
,
197 ShouldShowSSLInterstitialOnCaptivePortalDetectionDisabled
) {
198 EXPECT_FALSE(error_handler()->IsTimerRunning());
199 error_handler()->StartHandlingError();
200 EXPECT_FALSE(error_handler()->IsTimerRunning());
201 EXPECT_FALSE(error_handler()->captive_portal_checked());
202 EXPECT_TRUE(error_handler()->ssl_interstitial_shown());
203 EXPECT_FALSE(error_handler()->captive_portal_interstitial_shown());
206 #endif // defined(ENABLE_CAPTIVE_PORTAL_DETECTION)