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

Side by Side Diff: chrome/browser/ssl/ssl_error_handler.cc

Issue 318213002: Add custom interstitial for captive portals. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix Android builds Created 5 years, 11 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.
4
5 #include "chrome/browser/ssl/ssl_error_handler.h"
6
7 #include "base/metrics/field_trial.h"
8 #include "base/metrics/histogram.h"
9 #include "base/time/time.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/ssl/ssl_blocking_page.h"
12 #include "content/public/browser/notification_service.h"
13 #include "content/public/browser/notification_source.h"
14 #include "content/public/browser/web_contents.h"
15
16 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
17 #include "chrome/browser/captive_portal/captive_portal_service.h"
18 #include "chrome/browser/captive_portal/captive_portal_service_factory.h"
19 #include "chrome/browser/captive_portal/captive_portal_tab_helper.h"
20 #include "chrome/browser/ssl/captive_portal_blocking_page.h"
21 #endif
22
23 namespace {
24
25 // The type of the delay before displaying the SSL interstitial. This can be
26 // changed in tests.
27 SSLErrorHandler::InterstitialDelayType g_interstitial_delay_type =
28 SSLErrorHandler::NORMAL;
29
30 // Callback to call when the interstitial timer is started. Used for testing.
31 SSLErrorHandler::TimerStartedCallback* g_timer_started_callback = nullptr;
32
33 // Events for UMA.
34 enum SSLErrorHandlerEvent {
35 HANDLE_ALL,
36 SHOW_CAPTIVE_PORTAL_INTERSTITIAL_NONOVERRIDABLE,
37 SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE,
38 SHOW_SSL_INTERSTITIAL_NONOVERRIDABLE,
39 SHOW_SSL_INTERSTITIAL_OVERRIDABLE,
40 SSL_ERROR_HANDLER_EVENT_COUNT
41 };
42
43 void RecordUMA(SSLErrorHandlerEvent event) {
44 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl_error_handler",
45 event,
46 SSL_ERROR_HANDLER_EVENT_COUNT);
47 }
48
49 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
50 // The delay before displaying the SSL interstitial for cert errors.
51 // - If a "captive portal detected" result arrives in this many seconds,
52 // a captive portal interstitial is displayed.
53 // - Otherwise, an SSL interstitial is displayed.
54 const int kDefaultInterstitialDisplayDelayInSeconds = 2;
55
56 base::TimeDelta GetInterstitialDisplayDelay(
57 SSLErrorHandler::InterstitialDelayType delay) {
58 switch (delay) {
59 case SSLErrorHandler::LONG:
60 return base::TimeDelta::FromHours(1);
61
62 case SSLErrorHandler::NONE:
63 return base::TimeDelta();
64
65 case SSLErrorHandler::NORMAL:
66 return base::TimeDelta::FromSeconds(
67 kDefaultInterstitialDisplayDelayInSeconds);
68
69 default:
70 NOTREACHED();
71 }
72 return base::TimeDelta();
73 }
74 #endif
75
76 } // namespace
77
78 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SSLErrorHandler);
79
80 void SSLErrorHandler::HandleSSLError(
81 content::WebContents* web_contents,
82 int cert_error,
83 const net::SSLInfo& ssl_info,
84 const GURL& request_url,
85 int options_mask,
86 const base::Callback<void(bool)>& callback) {
87 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
88 CaptivePortalTabHelper* captive_portal_tab_helper =
89 CaptivePortalTabHelper::FromWebContents(web_contents);
90 if (captive_portal_tab_helper) {
91 captive_portal_tab_helper->OnSSLCertError(ssl_info);
92 }
93 #endif
94 DCHECK(!FromWebContents(web_contents));
95 web_contents->SetUserData(UserDataKey(),
96 new SSLErrorHandler(web_contents, cert_error,
97 ssl_info, request_url,
98 options_mask, callback));
99
100 SSLErrorHandler* error_handler =
101 SSLErrorHandler::FromWebContents(web_contents);
102 error_handler->StartHandlingError();
103 }
104
105 // static
106 void SSLErrorHandler::SetInterstitialDelayTypeForTest(
107 SSLErrorHandler::InterstitialDelayType delay) {
108 g_interstitial_delay_type = delay;
109 }
110
111 // static
112 void SSLErrorHandler::SetInterstitialTimerStartedCallbackForTest(
113 TimerStartedCallback* callback) {
114 DCHECK(!callback || !callback->is_null());
115 g_timer_started_callback = callback;
116 }
117
118 SSLErrorHandler::SSLErrorHandler(content::WebContents* web_contents,
119 int cert_error,
120 const net::SSLInfo& ssl_info,
121 const GURL& request_url,
122 int options_mask,
123 const base::Callback<void(bool)>& callback)
124 : web_contents_(web_contents),
125 cert_error_(cert_error),
126 ssl_info_(ssl_info),
127 request_url_(request_url),
128 options_mask_(options_mask),
129 callback_(callback) {
130 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
131 Profile* profile = Profile::FromBrowserContext(
132 web_contents->GetBrowserContext());
133 registrar_.Add(this,
134 chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT,
135 content::Source<Profile>(profile));
136 #endif
137 }
138
139 SSLErrorHandler::~SSLErrorHandler() {
140 }
141
142 void SSLErrorHandler::StartHandlingError() {
143 RecordUMA(HANDLE_ALL);
144
145 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
146 CheckForCaptivePortal();
147 timer_.Start(FROM_HERE,
148 GetInterstitialDisplayDelay(g_interstitial_delay_type),
149 this, &SSLErrorHandler::OnTimerExpired);
150 if (g_timer_started_callback)
151 g_timer_started_callback->Run(web_contents_);
152 #else
153 // Display an SSL interstitial.
154 ShowSSLInterstitial();
155 #endif
156 }
157
158 void SSLErrorHandler::OnTimerExpired() {
159 ShowSSLInterstitial();
160 }
161
162 void SSLErrorHandler::CheckForCaptivePortal() {
163 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
164 Profile* profile = Profile::FromBrowserContext(
165 web_contents_->GetBrowserContext());
166 CaptivePortalService* captive_portal_service =
167 CaptivePortalServiceFactory::GetForProfile(profile);
168 captive_portal_service->DetectCaptivePortal();
169 #else
170 NOTREACHED();
171 #endif
172 }
173
174 void SSLErrorHandler::ShowCaptivePortalInterstitial() {
175 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
176 // Show captive portal blocking page. The interstitial owns the blocking page.
177 RecordUMA(SSLBlockingPage::IsOptionsOverridable(options_mask_) ?
178 SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE :
179 SHOW_CAPTIVE_PORTAL_INTERSTITIAL_NONOVERRIDABLE);
180 (new CaptivePortalBlockingPage(web_contents_, request_url_,
181 callback_))->Show();
182 // Once an interstitial is displayed, no need to keep the handler around.
183 // This is the equivalent of "delete this".
184 web_contents_->RemoveUserData(UserDataKey());
185 #else
186 NOTREACHED();
187 #endif
188 }
189
190 void SSLErrorHandler::ShowSSLInterstitial() {
191 // Show SSL blocking page. The interstitial owns the blocking page.
192 RecordUMA(SSLBlockingPage::IsOptionsOverridable(options_mask_) ?
193 SHOW_SSL_INTERSTITIAL_OVERRIDABLE :
194 SHOW_SSL_INTERSTITIAL_NONOVERRIDABLE);
195 (new SSLBlockingPage(web_contents_, cert_error_, ssl_info_, request_url_,
196 options_mask_, callback_))->Show();
197 // Once an interstitial is displayed, no need to keep the handler around.
198 // This is the equivalent of "delete this".
199 web_contents_->RemoveUserData(UserDataKey());
200 }
201
202 void SSLErrorHandler::Observe(
203 int type,
204 const content::NotificationSource& source,
205 const content::NotificationDetails& details) {
206 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
207 if (type == chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT) {
208 timer_.Stop();
209 CaptivePortalService::Results* results =
210 content::Details<CaptivePortalService::Results>(details).ptr();
211 if (results->result == captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL)
212 ShowCaptivePortalInterstitial();
213 else
214 ShowSSLInterstitial();
215 }
216 #endif
217 }
OLDNEW
« no previous file with comments | « chrome/browser/ssl/ssl_error_handler.h ('k') | chrome/browser/ssl/ssl_error_handler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698