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

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: mmenke and rsleevi comments Created 6 years, 1 month 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/time/time.h"
8 #include "base/timer/timer.h"
9 #include "chrome/browser/profiles/profile.h"
10 #include "chrome/browser/ssl/ssl_blocking_page.h"
11 #include "chrome/common/chrome_version_info.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 // Events for UMA.
26 enum SSLErrorHandlerEvent {
27 HANDLE_ALL,
28 CAPTIVE_PORTAL_CHECK,
29 CAPTIVE_PORTAL_DETECTED_ALREADY_HANDLED,
30 CAPTIVE_PORTAL_DETECTED_BEFORE_TIMER_TRIGGERED,
31 CAPTIVE_PORTAL_DETECTED_AFTER_TIMER_EXPIRED,
32 SHOW_CAPTIVE_PORTAL_INTERSTITIAL,
33 SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE,
34 SHOW_SSL_INTERSTITIAL,
35 SHOW_SSL_INTERSTITIAL_OVERRIDABLE,
36 SSL_ERROR_HANDLER_EVENT_COUNT
37 };
38
39 void RecordUMA(SSLErrorHandlerEvent event) {
40 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl_error_handler",
41 event,
42 SSL_ERROR_HANDLER_EVENT_COUNT);
43 }
44
45 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
46 bool IsCaptivePortalInterstitialEnabled() {
47 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
48 return channel <= chrome::VersionInfo::CHANNEL_DEV;
49 }
50 #endif
51
52 } // namespace
53
54 SSLErrorHandler::SSLErrorHandler(content::WebContents* web_contents,
55 int cert_error,
56 const net::SSLInfo& ssl_info,
57 const GURL& request_url,
58 const int options_mask,
59 const base::TimeDelta ssl_error_delay,
60 const base::Callback<void(bool)>& callback)
61 : content::WebContentsObserver(web_contents),
62 web_contents_(web_contents),
63 cert_error_(cert_error),
64 ssl_info_(ssl_info),
65 request_url_(request_url),
66 options_mask_(options_mask),
67 callback_(callback),
68 handled_(false),
69 ssl_interstitial_display_delay_(ssl_error_delay),
70 timer_expired_(false) {
71 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
72 Profile* profile = Profile::FromBrowserContext(
73 web_contents_->GetBrowserContext());
74 registrar_.Add(this,
75 chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT,
76 content::Source<Profile>(profile));
77 #endif
78 }
79
80 SSLErrorHandler::~SSLErrorHandler() {
81 }
82
83 void SSLErrorHandler::HandleSSLError(
84 content::WebContents* web_contents,
85 int cert_error,
86 const net::SSLInfo& ssl_info,
87 const GURL& request_url,
88 int options_mask,
89 const base::Callback<void(bool)>& callback) {
90 // SSL interstitials aren't delayed if captive portal detection is disabled.
91 base::TimeDelta ssl_error_delay;
92 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
93 CaptivePortalTabHelper* captive_portal_tab_helper =
94 CaptivePortalTabHelper::FromWebContents(web_contents);
95 if (captive_portal_tab_helper) {
96 captive_portal_tab_helper->OnSSLCertError(ssl_info);
97 ssl_error_delay = captive_portal_tab_helper->GetSSLErrorDelay();
98 }
99 #endif
100 (new SSLErrorHandler(web_contents, cert_error, ssl_info, request_url,
101 options_mask, ssl_error_delay, callback))->Handle();
102 }
103
104 void SSLErrorHandler::Handle() {
105 RecordUMA(HANDLE_ALL);
106 if (handled_)
107 return;
mmenke 2014/11/07 15:45:30 Since this can't happen, we shouldn't check for it
meacer 2014/11/07 20:30:31 Done.
108
109 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
110 if (IsCaptivePortalInterstitialEnabled()) {
111 CheckForCaptivePortal();
112 timer_.Start(FROM_HERE, ssl_interstitial_display_delay_,
113 base::Bind(&SSLErrorHandler::OnTimerExpired,
114 base::Unretained(this)));
115 return;
116 }
117 #endif
118 // Display an SSL interstitial.
119 ShowSSLInterstitial();
120 handled_ = true;
mmenke 2014/11/07 15:45:30 I think it makes more sense to move this line into
meacer 2014/11/07 20:30:31 Done.
121 }
122
123 void SSLErrorHandler::CheckForCaptivePortal() {
124 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
125 RecordUMA(CAPTIVE_PORTAL_CHECK);
126 Profile* profile = Profile::FromBrowserContext(
127 web_contents_->GetBrowserContext());
128 CaptivePortalService* captive_portal_service =
129 CaptivePortalServiceFactory::GetForProfile(profile);
130 captive_portal_service->DetectCaptivePortal();
131 #endif
132 }
133
134 void SSLErrorHandler::ShowCaptivePortalInterstitial() {
mmenke 2014/11/07 15:45:30 DCHECK(!handled_);?
meacer 2014/11/07 20:30:31 Done.
135 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
136 // Show captive portal blocking page. The interstitial owns the blocking page.
137 RecordUMA(SSLBlockingPage::IsOverridable(options_mask_) ?
138 SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE :
139 SHOW_CAPTIVE_PORTAL_INTERSTITIAL);
140 (new CaptivePortalBlockingPage(web_contents_, request_url_))->Show();
141 #endif
142 }
143
144 void SSLErrorHandler::ShowSSLInterstitial() {
mmenke 2014/11/07 15:45:30 DCHECK(!handled_);?
meacer 2014/11/07 20:30:31 Done.
145 // Show SSL blocking page. The interstitial owns the blocking page.
146 RecordUMA(SSLBlockingPage::IsOverridable(options_mask_) ?
147 SHOW_SSL_INTERSTITIAL_OVERRIDABLE :
148 SHOW_SSL_INTERSTITIAL);
149 (new SSLBlockingPage(web_contents_, cert_error_, ssl_info_, request_url_,
150 options_mask_, callback_))->Show();
151 }
152
153 void SSLErrorHandler::OnTimerExpired() {
154 timer_expired_ = true;
155 if (handled_) {
156 return;
157 }
mmenke 2014/11/07 15:45:30 nit: Don't use braces when the condition and body
meacer 2014/11/07 20:30:31 Done.
158 ShowSSLInterstitial();
159 handled_ = true;
160 }
161
162 void SSLErrorHandler::Observe(
163 int type,
164 const content::NotificationSource& source,
165 const content::NotificationDetails& details) {
166 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
167 if (type == chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT) {
168 CaptivePortalService::Results* results =
169 content::Details<CaptivePortalService::Results>(details).ptr();
170 if (results->result != captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL)
171 return;
172 if (handled_) {
173 RecordUMA(CAPTIVE_PORTAL_DETECTED_ALREADY_HANDLED);
mmenke 2014/11/06 22:12:40 This histogram seems in need of improvement. If a
meacer 2014/11/06 23:23:19 I think I'm going to remove that histogram too. As
meacer 2014/11/07 20:30:31 Removed CAPTIVE_PORTAL_DETECTED_ALREADY_HANDLED
174 return;
175 }
176 if (!timer_.IsRunning()) {
177 RecordUMA(timer_expired_ ?
178 CAPTIVE_PORTAL_DETECTED_AFTER_TIMER_EXPIRED :
179 CAPTIVE_PORTAL_DETECTED_BEFORE_TIMER_TRIGGERED);
180 }
181 timer_.Stop();
182 ShowCaptivePortalInterstitial();
183 handled_ = true;
184 }
185 #endif
186 }
187
188 void SSLErrorHandler::DidStopLoading(
189 content::RenderViewHost* render_view_host) {
190 delete this;
191 }
192
193 void SSLErrorHandler::WebContentsDestroyed() {
194 delete this;
195 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698