Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ssl/ssl_error_handler.h" | 5 #include "chrome/browser/ssl/ssl_error_handler.h" |
| 6 | 6 |
| 7 #include "base/callback_helpers.h" | 7 #include "base/callback_helpers.h" |
| 8 #include "base/metrics/field_trial.h" | 8 #include "base/metrics/field_trial.h" |
| 9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 10 #include "base/time/time.h" | 10 #include "base/time/time.h" |
| 11 #include "chrome/browser/profiles/profile.h" | 11 #include "chrome/browser/profiles/profile.h" |
| 12 #include "chrome/browser/ssl/ssl_blocking_page.h" | 12 #include "chrome/browser/ssl/ssl_blocking_page.h" |
| 13 #include "chrome/browser/ssl/ssl_cert_reporter.h" | 13 #include "chrome/browser/ssl/ssl_cert_reporter.h" |
| 14 #include "chrome/browser/ssl/ssl_error_classification.h" | |
| 14 #include "content/public/browser/notification_service.h" | 15 #include "content/public/browser/notification_service.h" |
| 15 #include "content/public/browser/notification_source.h" | 16 #include "content/public/browser/notification_source.h" |
| 16 #include "content/public/browser/web_contents.h" | 17 #include "content/public/browser/web_contents.h" |
| 17 | 18 |
| 18 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) | 19 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) |
| 19 #include "chrome/browser/captive_portal/captive_portal_service.h" | 20 #include "chrome/browser/captive_portal/captive_portal_service.h" |
| 20 #include "chrome/browser/captive_portal/captive_portal_service_factory.h" | 21 #include "chrome/browser/captive_portal/captive_portal_service_factory.h" |
| 21 #include "chrome/browser/captive_portal/captive_portal_tab_helper.h" | 22 #include "chrome/browser/captive_portal/captive_portal_tab_helper.h" |
| 22 #include "chrome/browser/ssl/captive_portal_blocking_page.h" | 23 #include "chrome/browser/ssl/captive_portal_blocking_page.h" |
| 23 #endif | 24 #endif |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 143 web_contents->GetBrowserContext()); | 144 web_contents->GetBrowserContext()); |
| 144 registrar_.Add(this, | 145 registrar_.Add(this, |
| 145 chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT, | 146 chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT, |
| 146 content::Source<Profile>(profile)); | 147 content::Source<Profile>(profile)); |
| 147 #endif | 148 #endif |
| 148 } | 149 } |
| 149 | 150 |
| 150 SSLErrorHandler::~SSLErrorHandler() { | 151 SSLErrorHandler::~SSLErrorHandler() { |
| 151 } | 152 } |
| 152 | 153 |
| 154 bool IsCommonNameMismatchHandlerEnabled() { | |
| 155 // Add finch trail later. | |
| 156 return 1; | |
|
meacer
2015/07/09 17:58:56
|return true| instead of 1. Actually, just remove
Bhanu Dev
2015/07/11 04:00:43
Done.
| |
| 157 } | |
| 158 | |
| 153 void SSLErrorHandler::StartHandlingError() { | 159 void SSLErrorHandler::StartHandlingError() { |
| 154 RecordUMA(HANDLE_ALL); | 160 RecordUMA(HANDLE_ALL); |
| 155 | 161 |
| 162 if (IsCommonNameMismatchHandlerEnabled()) { | |
| 163 std::vector<std::string> dns_names; | |
| 164 ssl_info_.cert->GetDNSNames(&dns_names); | |
| 165 DCHECK(!dns_names.empty()); | |
|
meacer
2015/07/09 17:58:56
I feel that dns_names can actually be empty, so no
Bhanu Dev
2015/07/11 04:00:43
|dns_names| contains the DNS names in SAN field or
| |
| 166 GURL suggested_url; | |
| 167 if (CommonNameMismatchHandler::GetSuggestedUrl(request_url_, dns_names, | |
| 168 suggested_url)) { | |
| 169 Profile* profile = | |
| 170 Profile::FromBrowserContext(web_contents_->GetBrowserContext()); | |
| 171 scoped_refptr<net::URLRequestContextGetter> request_context( | |
| 172 profile->GetRequestContext()); | |
| 173 common_name_mismatch_handler_.reset( | |
| 174 new CommonNameMismatchHandler(request_context)); | |
| 175 common_name_mismatch_handler_->CheckSuggestedUrl( | |
| 176 suggested_url, | |
| 177 base::Bind(&SSLErrorHandler::CommonNameMismatchHandlerCallback, | |
| 178 base::Unretained(this))); | |
| 179 timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds( | |
| 180 common_name_handler_delay_in_seconds), | |
| 181 this, &SSLErrorHandler::OnTimerExpired); | |
| 182 if (g_timer_started_callback) | |
| 183 g_timer_started_callback->Run(web_contents_); | |
| 184 return; | |
| 185 } | |
| 186 } | |
| 187 | |
| 156 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) | 188 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) |
| 157 if (IsCaptivePortalInterstitialEnabled()) { | 189 if (IsCaptivePortalInterstitialEnabled()) { |
| 158 CheckForCaptivePortal(); | 190 CheckForCaptivePortal(); |
| 159 timer_.Start(FROM_HERE, | 191 timer_.Start(FROM_HERE, |
| 160 GetInterstitialDisplayDelay(g_interstitial_delay_type), | 192 GetInterstitialDisplayDelay(g_interstitial_delay_type), |
| 161 this, &SSLErrorHandler::OnTimerExpired); | 193 this, &SSLErrorHandler::OnTimerExpired); |
| 162 if (g_timer_started_callback) | 194 if (g_timer_started_callback) |
| 163 g_timer_started_callback->Run(web_contents_); | 195 g_timer_started_callback->Run(web_contents_); |
| 164 return; | 196 return; |
| 165 } | 197 } |
| 166 #endif | 198 #endif |
| 167 // Display an SSL interstitial. | 199 // Display an SSL interstitial. |
| 168 ShowSSLInterstitial(); | 200 ShowSSLInterstitial(GURL()); |
| 169 } | 201 } |
| 170 | 202 |
| 171 void SSLErrorHandler::OnTimerExpired() { | 203 void SSLErrorHandler::OnTimerExpired() { |
| 172 ShowSSLInterstitial(); | 204 ShowSSLInterstitial(GURL()); |
| 173 } | 205 } |
| 174 | 206 |
| 175 void SSLErrorHandler::CheckForCaptivePortal() { | 207 void SSLErrorHandler::CheckForCaptivePortal() { |
| 176 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) | 208 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) |
| 177 Profile* profile = Profile::FromBrowserContext( | 209 Profile* profile = Profile::FromBrowserContext( |
| 178 web_contents_->GetBrowserContext()); | 210 web_contents_->GetBrowserContext()); |
| 179 CaptivePortalService* captive_portal_service = | 211 CaptivePortalService* captive_portal_service = |
| 180 CaptivePortalServiceFactory::GetForProfile(profile); | 212 CaptivePortalServiceFactory::GetForProfile(profile); |
| 181 captive_portal_service->DetectCaptivePortal(); | 213 captive_portal_service->DetectCaptivePortal(); |
| 182 #else | 214 #else |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 196 ssl_cert_reporter_.Pass(), ssl_info_, | 228 ssl_cert_reporter_.Pass(), ssl_info_, |
| 197 callback_))->Show(); | 229 callback_))->Show(); |
| 198 // Once an interstitial is displayed, no need to keep the handler around. | 230 // Once an interstitial is displayed, no need to keep the handler around. |
| 199 // This is the equivalent of "delete this". | 231 // This is the equivalent of "delete this". |
| 200 web_contents_->RemoveUserData(UserDataKey()); | 232 web_contents_->RemoveUserData(UserDataKey()); |
| 201 #else | 233 #else |
| 202 NOTREACHED(); | 234 NOTREACHED(); |
| 203 #endif | 235 #endif |
| 204 } | 236 } |
| 205 | 237 |
| 206 void SSLErrorHandler::ShowSSLInterstitial() { | 238 void SSLErrorHandler::ShowSSLInterstitial(const GURL& suggested_url) { |
| 207 // Show SSL blocking page. The interstitial owns the blocking page. | 239 // Show SSL blocking page. The interstitial owns the blocking page. |
| 208 const Profile* const profile = | 240 const Profile* const profile = |
| 209 Profile::FromBrowserContext(web_contents_->GetBrowserContext()); | 241 Profile::FromBrowserContext(web_contents_->GetBrowserContext()); |
| 210 RecordUMA(SSLBlockingPage::IsOverridable(options_mask_, profile) | 242 RecordUMA(SSLBlockingPage::IsOverridable(options_mask_, profile) |
| 211 ? SHOW_SSL_INTERSTITIAL_OVERRIDABLE | 243 ? SHOW_SSL_INTERSTITIAL_OVERRIDABLE |
| 212 : SHOW_SSL_INTERSTITIAL_NONOVERRIDABLE); | 244 : SHOW_SSL_INTERSTITIAL_NONOVERRIDABLE); |
| 213 (new SSLBlockingPage(web_contents_, cert_error_, ssl_info_, request_url_, | 245 (new SSLBlockingPage(web_contents_, cert_error_, ssl_info_, request_url_, |
| 214 options_mask_, base::Time::NowFromSystemTime(), | 246 options_mask_, base::Time::NowFromSystemTime(), |
| 215 ssl_cert_reporter_.Pass(), callback_))->Show(); | 247 ssl_cert_reporter_.Pass(), callback_, suggested_url)) |
| 248 ->Show(); | |
| 216 // Once an interstitial is displayed, no need to keep the handler around. | 249 // Once an interstitial is displayed, no need to keep the handler around. |
| 217 // This is the equivalent of "delete this". | 250 // This is the equivalent of "delete this". |
| 218 web_contents_->RemoveUserData(UserDataKey()); | 251 web_contents_->RemoveUserData(UserDataKey()); |
| 219 } | 252 } |
| 220 | 253 |
| 221 void SSLErrorHandler::Observe( | 254 void SSLErrorHandler::Observe( |
| 222 int type, | 255 int type, |
| 223 const content::NotificationSource& source, | 256 const content::NotificationSource& source, |
| 224 const content::NotificationDetails& details) { | 257 const content::NotificationDetails& details) { |
| 225 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) | 258 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) |
| 226 if (type == chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT) { | 259 if (type == chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT) { |
| 227 timer_.Stop(); | 260 timer_.Stop(); |
| 228 CaptivePortalService::Results* results = | 261 CaptivePortalService::Results* results = |
| 229 content::Details<CaptivePortalService::Results>(details).ptr(); | 262 content::Details<CaptivePortalService::Results>(details).ptr(); |
| 230 if (results->result == captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL) | 263 if (results->result == captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL) |
| 231 ShowCaptivePortalInterstitial(results->landing_url); | 264 ShowCaptivePortalInterstitial(results->landing_url); |
| 232 else | 265 else |
| 233 ShowSSLInterstitial(); | 266 ShowSSLInterstitial(GURL()); |
| 234 } | 267 } |
| 235 #endif | 268 #endif |
| 236 } | 269 } |
| 237 | 270 |
| 238 // Destroy the error handler on all new navigations. This ensures that the | 271 // Destroy the error handler on all new navigations. This ensures that the |
| 239 // handler is properly recreated when a hanging page is navigated to an SSL | 272 // handler is properly recreated when a hanging page is navigated to an SSL |
| 240 // error, even when the tab's WebContents doesn't change. | 273 // error, even when the tab's WebContents doesn't change. |
| 241 void SSLErrorHandler::DidStartNavigationToPendingEntry( | 274 void SSLErrorHandler::DidStartNavigationToPendingEntry( |
| 242 const GURL& url, | 275 const GURL& url, |
| 243 content::NavigationController::ReloadType reload_type) { | 276 content::NavigationController::ReloadType reload_type) { |
| 244 // Need to explicity deny the certificate via the callback, otherwise memory | 277 // Need to explicity deny the certificate via the callback, otherwise memory |
| 245 // is leaked. | 278 // is leaked. |
| 246 if (!callback_.is_null()) { | 279 if (!callback_.is_null()) { |
| 247 base::ResetAndReturn(&callback_).Run(false); | 280 base::ResetAndReturn(&callback_).Run(false); |
| 248 } | 281 } |
| 249 web_contents_->RemoveUserData(UserDataKey()); | 282 web_contents_->RemoveUserData(UserDataKey()); |
| 250 } | 283 } |
| 284 | |
| 285 void SSLErrorHandler::CommonNameMismatchHandlerCallback( | |
| 286 const CommonNameMismatchHandler::Results& results) { | |
| 287 timer_.Stop(); | |
| 288 if (results.result == CommonNameMismatchHandler::SuggestedUrlCheckResult:: | |
| 289 RESULT_SUGGESTED_URL_VALID) { | |
| 290 ShowSSLInterstitial(results.new_url); | |
|
meacer
2015/07/09 17:58:56
For this CL, let's just record the result in a his
Bhanu Dev
2015/07/11 04:00:43
Acknowledged.
| |
| 291 } else { | |
| 292 ShowSSLInterstitial(GURL()); | |
| 293 } | |
| 294 } | |
| OLD | NEW |