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

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 comments, add login scenario to browser tests and fix race. 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/histogram.h"
8 #include "base/time/time.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 SHOW_CAPTIVE_PORTAL_INTERSTITIAL,
29 SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE,
30 SHOW_SSL_INTERSTITIAL,
31 SHOW_SSL_INTERSTITIAL_OVERRIDABLE,
32 SSL_ERROR_HANDLER_EVENT_COUNT
33 };
34
35 void RecordUMA(SSLErrorHandlerEvent event) {
36 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl_error_handler",
37 event,
38 SSL_ERROR_HANDLER_EVENT_COUNT);
39 }
40
41 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
42 bool IsCaptivePortalInterstitialEnabled() {
43 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
44 return channel <= chrome::VersionInfo::CHANNEL_DEV;
mmenke 2014/11/26 18:57:49 Suggest using Finch instead - I think should avoid
meacer 2014/12/08 22:29:51 Enabled on all channels.
45 }
46 #endif
47
48 } // namespace
49
50 SSLErrorHandler::SSLErrorHandler(content::WebContents* web_contents,
51 int cert_error,
52 const net::SSLInfo& ssl_info,
53 const GURL& request_url,
54 const int options_mask,
55 const base::TimeDelta ssl_error_delay,
56 const base::Callback<void(bool)>& callback)
57 : content::WebContentsObserver(web_contents),
58 web_contents_(web_contents),
59 cert_error_(cert_error),
60 ssl_info_(ssl_info),
61 request_url_(request_url),
62 options_mask_(options_mask),
63 callback_(callback),
64 ssl_interstitial_display_delay_(ssl_error_delay) {
65 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
66 Profile* profile = Profile::FromBrowserContext(
67 web_contents_->GetBrowserContext());
68 registrar_.Add(this,
69 chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT,
70 content::Source<Profile>(profile));
71 #endif
72 }
73
74 SSLErrorHandler::~SSLErrorHandler() {
75 }
76
77 void SSLErrorHandler::HandleSSLError(
78 content::WebContents* web_contents,
79 int cert_error,
80 const net::SSLInfo& ssl_info,
81 const GURL& request_url,
82 int options_mask,
83 const base::Callback<void(bool)>& callback) {
84 // SSL interstitials aren't delayed if captive portal detection is disabled.
85 base::TimeDelta ssl_error_delay;
86 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
87 CaptivePortalTabHelper* captive_portal_tab_helper =
88 CaptivePortalTabHelper::FromWebContents(web_contents);
89 if (captive_portal_tab_helper) {
90 ssl_error_delay = captive_portal_tab_helper->GetSSLErrorDelay();
91 captive_portal_tab_helper->OnSSLCertError(ssl_info);
92 }
93 #endif
94 (new SSLErrorHandler(web_contents, cert_error, ssl_info, request_url,
95 options_mask, ssl_error_delay, callback))->Handle();
96 }
97
98 void SSLErrorHandler::Handle() {
99 RecordUMA(HANDLE_ALL);
100
101 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
102 if (IsCaptivePortalInterstitialEnabled()) {
103 CheckForCaptivePortal();
104 timer_.Start(FROM_HERE, ssl_interstitial_display_delay_,
105 base::Bind(&SSLErrorHandler::OnTimerExpired,
106 base::Unretained(this)));
107 return;
108 }
109 #endif
110 // Display an SSL interstitial.
111 ShowSSLInterstitial();
112 }
113
114 void SSLErrorHandler::OnTimerExpired() {
115 ShowSSLInterstitial();
116 }
117
118 void SSLErrorHandler::CheckForCaptivePortal() {
119 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
120 Profile* profile = Profile::FromBrowserContext(
121 web_contents_->GetBrowserContext());
122 CaptivePortalService* captive_portal_service =
123 CaptivePortalServiceFactory::GetForProfile(profile);
124 captive_portal_service->DetectCaptivePortal();
125 #endif
mmenke 2014/11/26 18:57:49 optional: Should this have an #else NOTREACHED, j
meacer 2014/12/08 22:29:51 Done.
126 }
127
128 void SSLErrorHandler::ShowCaptivePortalInterstitial() {
129 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
130 // Show captive portal blocking page. The interstitial owns the blocking page.
131 RecordUMA(SSLBlockingPage::IsOverridable(options_mask_) ?
132 SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE :
133 SHOW_CAPTIVE_PORTAL_INTERSTITIAL);
134 (new CaptivePortalBlockingPage(web_contents_, request_url_))->Show();
135 delete this;
136 #else
137 NOTREACHED();
138 #endif
139 }
140
141 void SSLErrorHandler::ShowSSLInterstitial() {
142 // Show SSL blocking page. The interstitial owns the blocking page.
143 RecordUMA(SSLBlockingPage::IsOverridable(options_mask_) ?
144 SHOW_SSL_INTERSTITIAL_OVERRIDABLE :
145 SHOW_SSL_INTERSTITIAL);
146 (new SSLBlockingPage(web_contents_, cert_error_, ssl_info_, request_url_,
147 options_mask_, callback_))->Show();
148 delete this;
149 }
150
151 void SSLErrorHandler::Observe(
152 int type,
153 const content::NotificationSource& source,
154 const content::NotificationDetails& details) {
155 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
156 if (type == chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT) {
157 timer_.Stop();
158 CaptivePortalService::Results* results =
159 content::Details<CaptivePortalService::Results>(details).ptr();
160 if (results->result == captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL)
161 ShowCaptivePortalInterstitial();
162 else
163 ShowSSLInterstitial();
164 }
165 #endif
166 }
167
168 void SSLErrorHandler::DidStartNavigationToPendingEntry(
169 const GURL& url,
170 content::NavigationController::ReloadType reload_type) {
171 delete this;
172 }
173
174 void SSLErrorHandler::DidStopLoading(
175 content::RenderViewHost* render_view_host) {
176 delete this;
177 }
178
179 void SSLErrorHandler::WebContentsDestroyed() {
180 delete this;
mmenke 2014/11/26 18:57:49 Should think about tests for these deletes. Just
meacer 2014/12/08 22:29:51 I added a check at the end of CaptivePortalBrowser
181 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698