| 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 |
| 24 | 25 |
| 25 namespace { | 26 namespace { |
| 26 | 27 |
| 27 // The type of the delay before displaying the SSL interstitial. This can be | 28 // The type of the delay before displaying the SSL interstitial. This can be |
| 28 // changed in tests. | 29 // changed in tests. |
| 29 SSLErrorHandler::InterstitialDelayType g_interstitial_delay_type = | 30 SSLErrorHandler::InterstitialDelayType g_interstitial_delay_type = |
| 30 SSLErrorHandler::NORMAL; | 31 SSLErrorHandler::NORMAL; |
| 31 | 32 |
| 32 // Callback to call when the interstitial timer is started. Used for testing. | 33 // Callback to call when the interstitial timer is started. Used for testing. |
| 33 SSLErrorHandler::TimerStartedCallback* g_timer_started_callback = nullptr; | 34 SSLErrorHandler::TimerStartedCallback* g_timer_started_callback = nullptr; |
| 34 | 35 |
| 35 // Events for UMA. | 36 // Events for UMA. |
| 36 enum SSLErrorHandlerEvent { | 37 enum SSLErrorHandlerEvent { |
| 37 HANDLE_ALL, | 38 HANDLE_ALL, |
| 38 SHOW_CAPTIVE_PORTAL_INTERSTITIAL_NONOVERRIDABLE, | 39 SHOW_CAPTIVE_PORTAL_INTERSTITIAL_NONOVERRIDABLE, |
| 39 SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE, | 40 SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE, |
| 40 SHOW_SSL_INTERSTITIAL_NONOVERRIDABLE, | 41 SHOW_SSL_INTERSTITIAL_NONOVERRIDABLE, |
| 41 SHOW_SSL_INTERSTITIAL_OVERRIDABLE, | 42 SHOW_SSL_INTERSTITIAL_OVERRIDABLE, |
| 43 SHOW_COMMON_NAME_MISMATCH_INTERSTITIAL_NONOVERRIDABLE, |
| 44 SHOW_COMMON_NAME_MISMATCH_INTERSTITIAL_OVERRIDABLE, |
| 42 SSL_ERROR_HANDLER_EVENT_COUNT | 45 SSL_ERROR_HANDLER_EVENT_COUNT |
| 43 }; | 46 }; |
| 44 | 47 |
| 45 void RecordUMA(SSLErrorHandlerEvent event) { | 48 void RecordUMA(SSLErrorHandlerEvent event) { |
| 46 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl_error_handler", | 49 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl_error_handler", |
| 47 event, | 50 event, |
| 48 SSL_ERROR_HANDLER_EVENT_COUNT); | 51 SSL_ERROR_HANDLER_EVENT_COUNT); |
| 49 } | 52 } |
| 50 | 53 |
| 51 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) | |
| 52 // The delay before displaying the SSL interstitial for cert errors. | 54 // The delay before displaying the SSL interstitial for cert errors. |
| 53 // - If a "captive portal detected" result arrives in this many seconds, | 55 // - If a "captive portal detected" or "suggested URL valid" result |
| 54 // a captive portal interstitial is displayed. | 56 // arrives in this many seconds, then a captive portal interstitial |
| 57 // or a common name mismatch interstitial is displayed. |
| 55 // - Otherwise, an SSL interstitial is displayed. | 58 // - Otherwise, an SSL interstitial is displayed. |
| 56 const int kDefaultInterstitialDisplayDelayInSeconds = 2; | 59 const int kDefaultInterstitialDisplayDelayInSeconds = 2; |
| 57 | 60 |
| 58 base::TimeDelta GetInterstitialDisplayDelay( | 61 base::TimeDelta GetInterstitialDisplayDelay( |
| 59 SSLErrorHandler::InterstitialDelayType delay) { | 62 SSLErrorHandler::InterstitialDelayType delay) { |
| 60 switch (delay) { | 63 switch (delay) { |
| 61 case SSLErrorHandler::LONG: | 64 case SSLErrorHandler::LONG: |
| 62 return base::TimeDelta::FromHours(1); | 65 return base::TimeDelta::FromHours(1); |
| 63 | 66 |
| 64 case SSLErrorHandler::NONE: | 67 case SSLErrorHandler::NONE: |
| 65 return base::TimeDelta(); | 68 return base::TimeDelta(); |
| 66 | 69 |
| 67 case SSLErrorHandler::NORMAL: | 70 case SSLErrorHandler::NORMAL: |
| 68 return base::TimeDelta::FromSeconds( | 71 return base::TimeDelta::FromSeconds( |
| 69 kDefaultInterstitialDisplayDelayInSeconds); | 72 kDefaultInterstitialDisplayDelayInSeconds); |
| 70 | 73 |
| 71 default: | 74 default: |
| 72 NOTREACHED(); | 75 NOTREACHED(); |
| 73 } | 76 } |
| 74 return base::TimeDelta(); | 77 return base::TimeDelta(); |
| 75 } | 78 } |
| 76 | 79 |
| 80 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) |
| 77 bool IsCaptivePortalInterstitialEnabled() { | 81 bool IsCaptivePortalInterstitialEnabled() { |
| 78 return base::FieldTrialList::FindFullName("CaptivePortalInterstitial") == | 82 return base::FieldTrialList::FindFullName("CaptivePortalInterstitial") == |
| 79 "Enabled"; | 83 "Enabled"; |
| 80 } | 84 } |
| 81 #endif | 85 #endif |
| 82 | 86 |
| 83 } // namespace | 87 } // namespace |
| 84 | 88 |
| 85 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SSLErrorHandler); | 89 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SSLErrorHandler); |
| 86 | 90 |
| 87 void SSLErrorHandler::HandleSSLError( | 91 void SSLErrorHandler::HandleSSLError( |
| 88 content::WebContents* web_contents, | 92 content::WebContents* web_contents, |
| 89 int cert_error, | 93 int cert_error, |
| 90 const net::SSLInfo& ssl_info, | 94 const net::SSLInfo& ssl_info, |
| 91 const GURL& request_url, | 95 const GURL& request_url, |
| 92 int options_mask, | 96 int options_mask, |
| 93 scoped_ptr<SSLCertReporter> ssl_cert_reporter, | 97 scoped_ptr<SSLCertReporter> ssl_cert_reporter, |
| 94 const base::Callback<void(bool)>& callback) { | 98 const base::Callback<void(bool)>& callback) { |
| 95 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) | |
| 96 CaptivePortalTabHelper* captive_portal_tab_helper = | |
| 97 CaptivePortalTabHelper::FromWebContents(web_contents); | |
| 98 if (captive_portal_tab_helper) { | |
| 99 captive_portal_tab_helper->OnSSLCertError(ssl_info); | |
| 100 } | |
| 101 #endif | |
| 102 DCHECK(!FromWebContents(web_contents)); | 99 DCHECK(!FromWebContents(web_contents)); |
| 103 web_contents->SetUserData( | 100 web_contents->SetUserData( |
| 104 UserDataKey(), | 101 UserDataKey(), |
| 105 new SSLErrorHandler(web_contents, cert_error, ssl_info, request_url, | 102 new SSLErrorHandler(web_contents, cert_error, ssl_info, request_url, |
| 106 options_mask, ssl_cert_reporter.Pass(), callback)); | 103 options_mask, ssl_cert_reporter.Pass(), callback)); |
| 107 | 104 |
| 108 SSLErrorHandler* error_handler = | 105 SSLErrorHandler* error_handler = |
| 109 SSLErrorHandler::FromWebContents(web_contents); | 106 SSLErrorHandler::FromWebContents(web_contents); |
| 110 error_handler->StartHandlingError(); | 107 error_handler->StartHandlingError(); |
| 111 } | 108 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 130 int options_mask, | 127 int options_mask, |
| 131 scoped_ptr<SSLCertReporter> ssl_cert_reporter, | 128 scoped_ptr<SSLCertReporter> ssl_cert_reporter, |
| 132 const base::Callback<void(bool)>& callback) | 129 const base::Callback<void(bool)>& callback) |
| 133 : content::WebContentsObserver(web_contents), | 130 : content::WebContentsObserver(web_contents), |
| 134 web_contents_(web_contents), | 131 web_contents_(web_contents), |
| 135 cert_error_(cert_error), | 132 cert_error_(cert_error), |
| 136 ssl_info_(ssl_info), | 133 ssl_info_(ssl_info), |
| 137 request_url_(request_url), | 134 request_url_(request_url), |
| 138 options_mask_(options_mask), | 135 options_mask_(options_mask), |
| 139 callback_(callback), | 136 callback_(callback), |
| 140 ssl_cert_reporter_(ssl_cert_reporter.Pass()) { | 137 profile_(Profile::FromBrowserContext(web_contents->GetBrowserContext())), |
| 141 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) | 138 ssl_cert_reporter_(ssl_cert_reporter.Pass()) {} |
| 142 Profile* profile = Profile::FromBrowserContext( | |
| 143 web_contents->GetBrowserContext()); | |
| 144 registrar_.Add(this, | |
| 145 chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT, | |
| 146 content::Source<Profile>(profile)); | |
| 147 #endif | |
| 148 } | |
| 149 | 139 |
| 150 SSLErrorHandler::~SSLErrorHandler() { | 140 SSLErrorHandler::~SSLErrorHandler() { |
| 151 } | 141 } |
| 152 | 142 |
| 153 void SSLErrorHandler::StartHandlingError() { | 143 void SSLErrorHandler::StartHandlingError() { |
| 154 RecordUMA(HANDLE_ALL); | 144 RecordUMA(HANDLE_ALL); |
| 155 | 145 |
| 146 std::vector<std::string> dns_names; |
| 147 ssl_info_.cert->GetDNSNames(&dns_names); |
| 148 DCHECK(!dns_names.empty()); |
| 149 GURL suggested_url; |
| 150 if (ssl_info_.cert_status == net::CERT_STATUS_COMMON_NAME_INVALID && |
| 151 GetSuggestedUrl(dns_names, &suggested_url)) { |
| 152 net::CertStatus extra_cert_errors = |
| 153 ssl_info_.cert_status ^ net::CERT_STATUS_COMMON_NAME_INVALID; |
| 154 |
| 155 // Show the SSL intersitial if |CERT_STATUS_COMMON_NAME_INVALID| is not |
| 156 // the only error. Need not check for captive portal in this case. |
| 157 // (See the comment below). |
| 158 if (net::IsCertStatusError(extra_cert_errors) && |
| 159 !net::IsCertStatusMinorError(ssl_info_.cert_status)) { |
| 160 ShowSSLInterstitial(); |
| 161 return; |
| 162 } |
| 163 CheckSuggestedUrl(suggested_url); |
| 164 timer_.Start(FROM_HERE, |
| 165 GetInterstitialDisplayDelay(g_interstitial_delay_type), this, |
| 166 &SSLErrorHandler::OnTimerExpired); |
| 167 if (g_timer_started_callback) |
| 168 g_timer_started_callback->Run(web_contents_); |
| 169 |
| 170 // Do not check for a captive portal in this case, because a captive |
| 171 // portal most likely cannot serve a valid certificate which passes the |
| 172 // similarity check. |
| 173 return; |
| 174 } |
| 175 |
| 156 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) | 176 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) |
| 177 CaptivePortalTabHelper* captive_portal_tab_helper = |
| 178 CaptivePortalTabHelper::FromWebContents(web_contents_); |
| 179 if (captive_portal_tab_helper) { |
| 180 captive_portal_tab_helper->OnSSLCertError(ssl_info_); |
| 181 } |
| 182 |
| 183 registrar_.Add(this, chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT, |
| 184 content::Source<Profile>(profile_)); |
| 185 |
| 157 if (IsCaptivePortalInterstitialEnabled()) { | 186 if (IsCaptivePortalInterstitialEnabled()) { |
| 158 CheckForCaptivePortal(); | 187 CheckForCaptivePortal(); |
| 159 timer_.Start(FROM_HERE, | 188 timer_.Start(FROM_HERE, |
| 160 GetInterstitialDisplayDelay(g_interstitial_delay_type), | 189 GetInterstitialDisplayDelay(g_interstitial_delay_type), |
| 161 this, &SSLErrorHandler::OnTimerExpired); | 190 this, &SSLErrorHandler::OnTimerExpired); |
| 162 if (g_timer_started_callback) | 191 if (g_timer_started_callback) |
| 163 g_timer_started_callback->Run(web_contents_); | 192 g_timer_started_callback->Run(web_contents_); |
| 164 return; | 193 return; |
| 165 } | 194 } |
| 166 #endif | 195 #endif |
| 167 // Display an SSL interstitial. | 196 // Display an SSL interstitial. |
| 168 ShowSSLInterstitial(); | 197 ShowSSLInterstitial(); |
| 169 } | 198 } |
| 170 | 199 |
| 171 void SSLErrorHandler::OnTimerExpired() { | 200 void SSLErrorHandler::OnTimerExpired() { |
| 172 ShowSSLInterstitial(); | 201 ShowSSLInterstitial(); |
| 173 } | 202 } |
| 174 | 203 |
| 204 bool SSLErrorHandler::GetSuggestedUrl(const std::vector<std::string>& dns_names, |
| 205 GURL* suggested_url) const { |
| 206 return CommonNameMismatchHandler::GetSuggestedUrl(request_url_, dns_names, |
| 207 suggested_url); |
| 208 } |
| 209 |
| 210 void SSLErrorHandler::CheckSuggestedUrl(const GURL& suggested_url) { |
| 211 scoped_refptr<net::URLRequestContextGetter> request_context( |
| 212 profile_->GetRequestContext()); |
| 213 common_name_mismatch_handler_.reset( |
| 214 new CommonNameMismatchHandler(request_url_, request_context)); |
| 215 |
| 216 common_name_mismatch_handler_->CheckSuggestedUrl( |
| 217 suggested_url, |
| 218 base::Bind(&SSLErrorHandler::CommonNameMismatchHandlerCallback, |
| 219 base::Unretained(this))); |
| 220 } |
| 221 |
| 222 void SSLErrorHandler::NavigateToSuggestedURL(const GURL& suggested_url) { |
| 223 content::NavigationController::LoadURLParams load_params(suggested_url); |
| 224 load_params.transition_type = ui::PAGE_TRANSITION_TYPED; |
| 225 web_contents()->GetController().LoadURLWithParams(load_params); |
| 226 } |
| 227 |
| 175 void SSLErrorHandler::CheckForCaptivePortal() { | 228 void SSLErrorHandler::CheckForCaptivePortal() { |
| 176 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) | 229 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) |
| 177 Profile* profile = Profile::FromBrowserContext( | |
| 178 web_contents_->GetBrowserContext()); | |
| 179 CaptivePortalService* captive_portal_service = | 230 CaptivePortalService* captive_portal_service = |
| 180 CaptivePortalServiceFactory::GetForProfile(profile); | 231 CaptivePortalServiceFactory::GetForProfile(profile_); |
| 181 captive_portal_service->DetectCaptivePortal(); | 232 captive_portal_service->DetectCaptivePortal(); |
| 182 #else | 233 #else |
| 183 NOTREACHED(); | 234 NOTREACHED(); |
| 184 #endif | 235 #endif |
| 185 } | 236 } |
| 186 | 237 |
| 187 void SSLErrorHandler::ShowCaptivePortalInterstitial(const GURL& landing_url) { | 238 void SSLErrorHandler::ShowCaptivePortalInterstitial(const GURL& landing_url) { |
| 188 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) | 239 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) |
| 189 // Show captive portal blocking page. The interstitial owns the blocking page. | 240 // Show captive portal blocking page. The interstitial owns the blocking page. |
| 190 const Profile* const profile = | 241 RecordUMA(SSLBlockingPage::IsOverridable(options_mask_, profile_) |
| 191 Profile::FromBrowserContext(web_contents_->GetBrowserContext()); | |
| 192 RecordUMA(SSLBlockingPage::IsOverridable(options_mask_, profile) | |
| 193 ? SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE | 242 ? SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE |
| 194 : SHOW_CAPTIVE_PORTAL_INTERSTITIAL_NONOVERRIDABLE); | 243 : SHOW_CAPTIVE_PORTAL_INTERSTITIAL_NONOVERRIDABLE); |
| 195 (new CaptivePortalBlockingPage(web_contents_, request_url_, landing_url, | 244 (new CaptivePortalBlockingPage(web_contents_, request_url_, landing_url, |
| 196 ssl_cert_reporter_.Pass(), ssl_info_, | 245 ssl_cert_reporter_.Pass(), ssl_info_, |
| 197 callback_))->Show(); | 246 callback_))->Show(); |
| 198 // Once an interstitial is displayed, no need to keep the handler around. | 247 // Once an interstitial is displayed, no need to keep the handler around. |
| 199 // This is the equivalent of "delete this". | 248 // This is the equivalent of "delete this". |
| 200 web_contents_->RemoveUserData(UserDataKey()); | 249 web_contents_->RemoveUserData(UserDataKey()); |
| 201 #else | 250 #else |
| 202 NOTREACHED(); | 251 NOTREACHED(); |
| 203 #endif | 252 #endif |
| 204 } | 253 } |
| 205 | 254 |
| 206 void SSLErrorHandler::ShowSSLInterstitial() { | 255 void SSLErrorHandler::ShowSSLInterstitial() { |
| 207 // Show SSL blocking page. The interstitial owns the blocking page. | 256 // Show SSL blocking page. The interstitial owns the blocking page. |
| 208 const Profile* const profile = | 257 RecordUMA(SSLBlockingPage::IsOverridable(options_mask_, profile_) |
| 209 Profile::FromBrowserContext(web_contents_->GetBrowserContext()); | |
| 210 RecordUMA(SSLBlockingPage::IsOverridable(options_mask_, profile) | |
| 211 ? SHOW_SSL_INTERSTITIAL_OVERRIDABLE | 258 ? SHOW_SSL_INTERSTITIAL_OVERRIDABLE |
| 212 : SHOW_SSL_INTERSTITIAL_NONOVERRIDABLE); | 259 : SHOW_SSL_INTERSTITIAL_NONOVERRIDABLE); |
| 260 |
| 213 (new SSLBlockingPage(web_contents_, cert_error_, ssl_info_, request_url_, | 261 (new SSLBlockingPage(web_contents_, cert_error_, ssl_info_, request_url_, |
| 214 options_mask_, base::Time::NowFromSystemTime(), | 262 options_mask_, base::Time::NowFromSystemTime(), |
| 215 ssl_cert_reporter_.Pass(), callback_))->Show(); | 263 ssl_cert_reporter_.Pass(), callback_)) |
| 264 ->Show(); |
| 216 // Once an interstitial is displayed, no need to keep the handler around. | 265 // Once an interstitial is displayed, no need to keep the handler around. |
| 217 // This is the equivalent of "delete this". | 266 // This is the equivalent of "delete this". |
| 218 web_contents_->RemoveUserData(UserDataKey()); | 267 web_contents_->RemoveUserData(UserDataKey()); |
| 219 } | 268 } |
| 220 | 269 |
| 221 void SSLErrorHandler::Observe( | 270 void SSLErrorHandler::Observe( |
| 222 int type, | 271 int type, |
| 223 const content::NotificationSource& source, | 272 const content::NotificationSource& source, |
| 224 const content::NotificationDetails& details) { | 273 const content::NotificationDetails& details) { |
| 225 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) | 274 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) |
| (...skipping 22 matching lines...) Expand all Loading... |
| 248 // Destroy the error handler when the page load is stopped. | 297 // Destroy the error handler when the page load is stopped. |
| 249 DeleteSSLErrorHandler(); | 298 DeleteSSLErrorHandler(); |
| 250 } | 299 } |
| 251 | 300 |
| 252 void SSLErrorHandler::DeleteSSLErrorHandler() { | 301 void SSLErrorHandler::DeleteSSLErrorHandler() { |
| 253 // Need to explicity deny the certificate via the callback, otherwise memory | 302 // Need to explicity deny the certificate via the callback, otherwise memory |
| 254 // is leaked. | 303 // is leaked. |
| 255 if (!callback_.is_null()) { | 304 if (!callback_.is_null()) { |
| 256 base::ResetAndReturn(&callback_).Run(false); | 305 base::ResetAndReturn(&callback_).Run(false); |
| 257 } | 306 } |
| 307 if (common_name_mismatch_handler_) { |
| 308 common_name_mismatch_handler_->Cancel(); |
| 309 common_name_mismatch_handler_.reset(); |
| 310 } |
| 258 web_contents_->RemoveUserData(UserDataKey()); | 311 web_contents_->RemoveUserData(UserDataKey()); |
| 259 } | 312 } |
| 313 |
| 314 void SSLErrorHandler::CommonNameMismatchHandlerCallback( |
| 315 const CommonNameMismatchHandler::SuggestedUrlCheckResult& result, |
| 316 const GURL& suggested_url) { |
| 317 timer_.Stop(); |
| 318 if (result == CommonNameMismatchHandler::SuggestedUrlCheckResult:: |
| 319 SUGGESTED_URL_AVAILABLE) { |
| 320 NavigateToSuggestedURL(suggested_url); |
| 321 } else { |
| 322 ShowSSLInterstitial(); |
| 323 } |
| 324 } |
| OLD | NEW |