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

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: bauerb comments Created 6 years 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 delay before displaying the SSL interstitial for cert errors.
26 // - If a "captive portal detected" result arrives in this many seconds,
27 // a captive portal interstitial is displayed.
28 // - Otherwise, an SSL interstitial is displayed.
29 const int kDefaultInterstitialDisplayDelayInSeconds = 2;
30
31 // The type of the delay before displaying the SSL interstitial. This can be
32 // changed in tests.
33 SSLErrorHandler::InterstitialDelayType g_interstitial_delay_type =
34 SSLErrorHandler::NORMAL;
35
36 // Callback to call when the interstitial timer is fired. Used for testing.
37 SSLErrorHandler::TimerFiredCallback* g_timer_fired_callback = nullptr;
38
39 // Events for UMA.
40 enum SSLErrorHandlerEvent {
41 HANDLE_ALL,
42 SHOW_CAPTIVE_PORTAL_INTERSTITIAL,
43 SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE,
44 SHOW_SSL_INTERSTITIAL,
45 SHOW_SSL_INTERSTITIAL_OVERRIDABLE,
46 SSL_ERROR_HANDLER_EVENT_COUNT
47 };
48
49 void RecordUMA(SSLErrorHandlerEvent event) {
50 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl_error_handler",
51 event,
52 SSL_ERROR_HANDLER_EVENT_COUNT);
53 }
54
55 base::TimeDelta GetInterstitialDisplayDelay(
56 SSLErrorHandler::InterstitialDelayType delay) {
57 if (delay == SSLErrorHandler::LONG)
58 return base::TimeDelta::FromHours(1);
59 else if (delay == SSLErrorHandler::SHORT)
60 return base::TimeDelta();
61 return base::TimeDelta::FromSeconds(
62 kDefaultInterstitialDisplayDelayInSeconds);
63 }
64
65 } // namespace
66
67 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SSLErrorHandler);
68
69 SSLErrorHandler::~SSLErrorHandler() {
70 }
71
72 void SSLErrorHandler::HandleSSLError(
73 content::WebContents* web_contents,
74 int cert_error,
75 const net::SSLInfo& ssl_info,
76 const GURL& request_url,
77 int options_mask,
78 const base::Callback<void(bool)>& callback) {
79 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
80 CaptivePortalTabHelper* captive_portal_tab_helper =
81 CaptivePortalTabHelper::FromWebContents(web_contents);
82 if (captive_portal_tab_helper) {
83 captive_portal_tab_helper->OnSSLCertError(ssl_info);
84 }
85 #endif
86 DCHECK(!FromWebContents(web_contents));
87 web_contents->SetUserData(UserDataKey(),
88 new SSLErrorHandler(web_contents, cert_error,
89 ssl_info, request_url,
90 options_mask, callback));
91
92 SSLErrorHandler* error_handler =
93 SSLErrorHandler::FromWebContents(web_contents);
94 error_handler->StartHandlingError();
95 }
96
97 // static
98 void SSLErrorHandler::SetInterstitialDelayTypeForTest(
99 SSLErrorHandler::InterstitialDelayType delay) {
100 g_interstitial_delay_type = delay;
101 }
102
103 // static
104 void SSLErrorHandler::SetInterstitialTimerFiredCallbackForTest(
105 TimerFiredCallback* callback) {
106 if (callback)
107 DCHECK(!callback->is_null());
108 g_timer_fired_callback = callback;
mmenke 2014/12/19 19:07:51 I think this is misnamed. A timer is fired when t
109 }
110
111 SSLErrorHandler::SSLErrorHandler(content::WebContents* web_contents,
112 int cert_error,
113 const net::SSLInfo& ssl_info,
114 const GURL& request_url,
115 int options_mask,
116 const base::Callback<void(bool)>& callback)
117 : web_contents_(web_contents),
118 cert_error_(cert_error),
119 ssl_info_(ssl_info),
120 request_url_(request_url),
121 options_mask_(options_mask),
122 callback_(callback) {
123 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
124 Profile* profile = Profile::FromBrowserContext(
125 web_contents->GetBrowserContext());
126 registrar_.Add(this,
127 chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT,
128 content::Source<Profile>(profile));
129 #endif
130 }
131
132 void SSLErrorHandler::StartHandlingError() {
133 RecordUMA(HANDLE_ALL);
134
135 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
136 CheckForCaptivePortal();
137 timer_.Start(FROM_HERE,
138 GetInterstitialDisplayDelay(g_interstitial_delay_type),
139 base::Bind(&SSLErrorHandler::OnTimerExpired,
140 base::Unretained(this)));
141 if (g_timer_fired_callback)
142 g_timer_fired_callback->Run(web_contents_);
143 #else
144 // Display an SSL interstitial.
145 ShowSSLInterstitial();
146 #endif
147 }
148
149 void SSLErrorHandler::OnTimerExpired() {
150 ShowSSLInterstitial();
151 }
152
153 void SSLErrorHandler::CheckForCaptivePortal() {
154 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
155 Profile* profile = Profile::FromBrowserContext(
156 web_contents_->GetBrowserContext());
157 CaptivePortalService* captive_portal_service =
158 CaptivePortalServiceFactory::GetForProfile(profile);
159 captive_portal_service->DetectCaptivePortal();
160 #else
161 NOTREACHED();
162 #endif
163 }
164
165 void SSLErrorHandler::ShowCaptivePortalInterstitial() {
166 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
167 // Show captive portal blocking page. The interstitial owns the blocking page.
168 RecordUMA(SSLBlockingPage::IsOverridable(options_mask_) ?
169 SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE :
170 SHOW_CAPTIVE_PORTAL_INTERSTITIAL);
171 (new CaptivePortalBlockingPage(web_contents_, request_url_))->Show();
172 // Once an interstitial is displayed, no need to keep the handler around.
173 // This is the equivalent of "delete this".
174 web_contents_->RemoveUserData(UserDataKey());
175 #else
176 NOTREACHED();
177 #endif
178 }
179
180 void SSLErrorHandler::ShowSSLInterstitial() {
181 // Show SSL blocking page. The interstitial owns the blocking page.
182 RecordUMA(SSLBlockingPage::IsOverridable(options_mask_) ?
183 SHOW_SSL_INTERSTITIAL_OVERRIDABLE :
184 SHOW_SSL_INTERSTITIAL);
185 (new SSLBlockingPage(web_contents_, cert_error_, ssl_info_, request_url_,
186 options_mask_, callback_))->Show();
187 // Once an interstitial is displayed, no need to keep the handler around.
188 // This is the equivalent of "delete this".
189 web_contents_->RemoveUserData(UserDataKey());
190 }
191
192 void SSLErrorHandler::Observe(
193 int type,
194 const content::NotificationSource& source,
195 const content::NotificationDetails& details) {
196 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
197 if (type == chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT) {
198 timer_.Stop();
199 CaptivePortalService::Results* results =
200 content::Details<CaptivePortalService::Results>(details).ptr();
201 if (results->result == captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL)
202 ShowCaptivePortalInterstitial();
203 else
204 ShowSSLInterstitial();
205 }
206 #endif
207 }
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