blob: b0f152ee227a1f84ea8b8e8387708bfd65d8fb11 [file] [log] [blame]
meacer4ef065e2015-01-09 03:21:351// 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
avi664c07b2015-12-26 02:18:317#include <stdint.h>
dchenge73d8520c2015-12-27 01:19:098#include <utility>
avi664c07b2015-12-26 02:18:319
meacerd2c91b42015-03-20 18:34:4010#include "base/callback_helpers.h"
meacer80166852016-12-08 01:51:3611#include "base/feature_list.h"
avi664c07b2015-12-26 02:18:3112#include "base/macros.h"
meacer4ef065e2015-01-09 03:21:3513#include "base/metrics/field_trial.h"
asvitkineaa060312016-09-01 22:44:1314#include "base/metrics/histogram_macros.h"
bhanudevd6bd7782015-08-21 00:01:5415#include "base/strings/stringprintf.h"
felt534cc9e72015-09-01 20:38:5916#include "base/time/clock.h"
meacer4ef065e2015-01-09 03:21:3517#include "base/time/time.h"
mab740b02b2016-03-17 23:44:2118#include "chrome/browser/browser_process.h"
meacer4ef065e2015-01-09 03:21:3519#include "chrome/browser/profiles/profile.h"
felt534cc9e72015-09-01 20:38:5920#include "chrome/browser/ssl/bad_clock_blocking_page.h"
meacer4ef065e2015-01-09 03:21:3521#include "chrome/browser/ssl/ssl_blocking_page.h"
estark3ba11132015-04-10 01:38:3322#include "chrome/browser/ssl/ssl_cert_reporter.h"
brettwab78fef2016-10-12 02:56:0523#include "chrome/common/features.h"
estark5057f822016-11-08 21:34:5424#include "components/network_time/network_time_tracker.h"
felt70127b42015-11-10 21:57:2325#include "components/ssl_errors/error_classification.h"
felt2493b4452015-09-17 20:33:5926#include "components/ssl_errors/error_info.h"
meacer4ef065e2015-01-09 03:21:3527#include "content/public/browser/notification_service.h"
28#include "content/public/browser/notification_source.h"
bhanudevd6bd7782015-08-21 00:01:5429#include "content/public/browser/render_frame_host.h"
meacer4ef065e2015-01-09 03:21:3530#include "content/public/browser/web_contents.h"
bhanudev3999e372015-08-21 07:23:1031#include "net/base/net_errors.h"
meacer4ef065e2015-01-09 03:21:3532
brettwab78fef2016-10-12 02:56:0533#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
meacer4ef065e2015-01-09 03:21:3534#include "chrome/browser/captive_portal/captive_portal_service.h"
35#include "chrome/browser/captive_portal/captive_portal_service_factory.h"
36#include "chrome/browser/captive_portal/captive_portal_tab_helper.h"
37#include "chrome/browser/ssl/captive_portal_blocking_page.h"
38#endif
39
mab740b02b2016-03-17 23:44:2140namespace network_time {
41class NetworkTimeTracker;
42}
43
meacer4ef065e2015-01-09 03:21:3544namespace {
45
meacer80166852016-12-08 01:51:3646#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
47const base::Feature kCaptivePortalInterstitial{
48 "CaptivePortalInterstitial", base::FEATURE_ENABLED_BY_DEFAULT};
49#endif
50
meacer8b4cea22015-08-28 02:02:5551// The delay in milliseconds before displaying the SSL interstitial.
52// This can be changed in tests.
53// - If there is a name mismatch and a suggested URL available result arrives
54// during this time, the user is redirected to the suggester URL.
55// - If a "captive portal detected" result arrives during this time,
56// a captive portal interstitial is displayed.
57// - Otherwise, an SSL interstitial is displayed.
meacerf940d5d2016-04-05 19:36:3858int64_t g_interstitial_delay_in_milliseconds = 3000;
meacer4ef065e2015-01-09 03:21:3559
60// Callback to call when the interstitial timer is started. Used for testing.
61SSLErrorHandler::TimerStartedCallback* g_timer_started_callback = nullptr;
62
felt534cc9e72015-09-01 20:38:5963// The clock to use when deciding which error type to display. Used for testing.
64base::Clock* g_testing_clock = nullptr;
65
estark5057f822016-11-08 21:34:5466network_time::NetworkTimeTracker* g_network_time_tracker = nullptr;
67
meacer4ef065e2015-01-09 03:21:3568// Events for UMA.
69enum SSLErrorHandlerEvent {
70 HANDLE_ALL,
71 SHOW_CAPTIVE_PORTAL_INTERSTITIAL_NONOVERRIDABLE,
72 SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE,
73 SHOW_SSL_INTERSTITIAL_NONOVERRIDABLE,
74 SHOW_SSL_INTERSTITIAL_OVERRIDABLE,
bhanudev45d9a432015-08-20 02:38:5175 WWW_MISMATCH_FOUND,
76 WWW_MISMATCH_URL_AVAILABLE,
77 WWW_MISMATCH_URL_NOT_AVAILABLE,
felt534cc9e72015-09-01 20:38:5978 SHOW_BAD_CLOCK,
meacer4ef065e2015-01-09 03:21:3579 SSL_ERROR_HANDLER_EVENT_COUNT
80};
81
meacer8b4cea22015-08-28 02:02:5582// Adds a message to console after navigation commits and then, deletes itself.
83// Also deletes itself if the navigation is stopped.
84class CommonNameMismatchRedirectObserver
85 : public content::WebContentsObserver,
86 public content::WebContentsUserData<CommonNameMismatchRedirectObserver> {
87 public:
88 static void AddToConsoleAfterNavigation(
89 content::WebContents* web_contents,
90 const std::string& request_url_hostname,
91 const std::string& suggested_url_hostname) {
92 web_contents->SetUserData(
93 UserDataKey(),
94 new CommonNameMismatchRedirectObserver(
95 web_contents, request_url_hostname, suggested_url_hostname));
meacer4ef065e2015-01-09 03:21:3596 }
meacer8b4cea22015-08-28 02:02:5597
98 private:
99 CommonNameMismatchRedirectObserver(content::WebContents* web_contents,
100 const std::string& request_url_hostname,
101 const std::string& suggested_url_hostname)
102 : WebContentsObserver(web_contents),
103 web_contents_(web_contents),
104 request_url_hostname_(request_url_hostname),
105 suggested_url_hostname_(suggested_url_hostname) {}
106 ~CommonNameMismatchRedirectObserver() override {}
107
108 // WebContentsObserver:
109 void NavigationStopped() override {
110 // Deletes |this|.
111 web_contents_->RemoveUserData(UserDataKey());
112 }
113
114 void NavigationEntryCommitted(
115 const content::LoadCommittedDetails& /* load_details */) override {
116 web_contents_->GetMainFrame()->AddMessageToConsole(
117 content::CONSOLE_MESSAGE_LEVEL_LOG,
118 base::StringPrintf(
119 "Redirecting navigation %s -> %s because the server presented a "
meaceree63a4e2016-03-30 23:03:19120 "certificate valid for %s but not for %s. To disable such "
121 "redirects launch Chrome with the following flag: "
122 "--force-fieldtrials=SSLCommonNameMismatchHandling/Disabled/",
meacer8b4cea22015-08-28 02:02:55123 request_url_hostname_.c_str(), suggested_url_hostname_.c_str(),
124 suggested_url_hostname_.c_str(), request_url_hostname_.c_str()));
125 web_contents_->RemoveUserData(UserDataKey());
126 }
127
128 void WebContentsDestroyed() override {
129 web_contents_->RemoveUserData(UserDataKey());
130 }
131
132 content::WebContents* web_contents_;
133 const std::string request_url_hostname_;
134 const std::string suggested_url_hostname_;
135
136 DISALLOW_COPY_AND_ASSIGN(CommonNameMismatchRedirectObserver);
137};
138
139void RecordUMA(SSLErrorHandlerEvent event) {
140 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl_error_handler", event,
141 SSL_ERROR_HANDLER_EVENT_COUNT);
meacer4ef065e2015-01-09 03:21:35142}
meacer5c777682015-01-09 06:54:53143
brettwab78fef2016-10-12 02:56:05144#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
meacer5c777682015-01-09 06:54:53145bool IsCaptivePortalInterstitialEnabled() {
meacer80166852016-12-08 01:51:36146 return base::FeatureList::IsEnabled(kCaptivePortalInterstitial);
meacer5c777682015-01-09 06:54:53147}
meacer4ef065e2015-01-09 03:21:35148#endif
149
bhanudev4b280dc2015-08-20 20:43:00150bool IsSSLCommonNameMismatchHandlingEnabled() {
151 return base::FieldTrialList::FindFullName("SSLCommonNameMismatchHandling") ==
152 "Enabled";
153}
154
meacer4ef065e2015-01-09 03:21:35155} // namespace
156
157DEFINE_WEB_CONTENTS_USER_DATA_KEY(SSLErrorHandler);
meacer8b4cea22015-08-28 02:02:55158DEFINE_WEB_CONTENTS_USER_DATA_KEY(CommonNameMismatchRedirectObserver);
meacer4ef065e2015-01-09 03:21:35159
160void SSLErrorHandler::HandleSSLError(
161 content::WebContents* web_contents,
162 int cert_error,
163 const net::SSLInfo& ssl_info,
164 const GURL& request_url,
165 int options_mask,
dcheng4af48582016-04-19 00:29:35166 std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
estark719dde52016-08-09 03:14:27167 const base::Callback<void(content::CertificateRequestResultType)>&
168 callback) {
meacer4ef065e2015-01-09 03:21:35169 DCHECK(!FromWebContents(web_contents));
meacer4ef065e2015-01-09 03:21:35170 SSLErrorHandler* error_handler =
meacer8b4cea22015-08-28 02:02:55171 new SSLErrorHandler(web_contents, cert_error, ssl_info, request_url,
dchenge73d8520c2015-12-27 01:19:09172 options_mask, std::move(ssl_cert_reporter), callback);
meacer8b4cea22015-08-28 02:02:55173 web_contents->SetUserData(UserDataKey(), error_handler);
meacer4ef065e2015-01-09 03:21:35174 error_handler->StartHandlingError();
175}
176
177// static
meacer8b4cea22015-08-28 02:02:55178void SSLErrorHandler::SetInterstitialDelayForTest(base::TimeDelta delay) {
179 g_interstitial_delay_in_milliseconds = delay.InMilliseconds();
meacer4ef065e2015-01-09 03:21:35180}
181
182// static
183void SSLErrorHandler::SetInterstitialTimerStartedCallbackForTest(
184 TimerStartedCallback* callback) {
185 DCHECK(!callback || !callback->is_null());
186 g_timer_started_callback = callback;
187}
188
felt534cc9e72015-09-01 20:38:59189// static
190void SSLErrorHandler::SetClockForTest(base::Clock* testing_clock) {
191 g_testing_clock = testing_clock;
192}
193
estark5057f822016-11-08 21:34:54194// static
195void SSLErrorHandler::SetNetworkTimeTrackerForTest(
196 network_time::NetworkTimeTracker* tracker) {
197 g_network_time_tracker = tracker;
198}
199
dcheng4af48582016-04-19 00:29:35200SSLErrorHandler::SSLErrorHandler(
201 content::WebContents* web_contents,
202 int cert_error,
203 const net::SSLInfo& ssl_info,
204 const GURL& request_url,
205 int options_mask,
206 std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
estark719dde52016-08-09 03:14:27207 const base::Callback<void(content::CertificateRequestResultType)>& callback)
meacerd2c91b42015-03-20 18:34:40208 : content::WebContentsObserver(web_contents),
209 web_contents_(web_contents),
meacer4ef065e2015-01-09 03:21:35210 cert_error_(cert_error),
211 ssl_info_(ssl_info),
212 request_url_(request_url),
213 options_mask_(options_mask),
estark93272ab2015-03-25 23:54:01214 callback_(callback),
bhanudev2051ce72015-08-18 22:21:18215 profile_(Profile::FromBrowserContext(web_contents->GetBrowserContext())),
estark5057f822016-11-08 21:34:54216 ssl_cert_reporter_(std::move(ssl_cert_reporter)),
217 weak_ptr_factory_(this) {}
meacer4ef065e2015-01-09 03:21:35218
219SSLErrorHandler::~SSLErrorHandler() {
220}
221
222void SSLErrorHandler::StartHandlingError() {
223 RecordUMA(HANDLE_ALL);
224
mab740b02b2016-03-17 23:44:21225 if (ssl_errors::ErrorInfo::NetErrorToErrorType(cert_error_) ==
226 ssl_errors::ErrorInfo::CERT_DATE_INVALID) {
estark5057f822016-11-08 21:34:54227 HandleCertDateInvalidError();
228 return;
felt534cc9e72015-09-01 20:38:59229 }
230
bhanudev2051ce72015-08-18 22:21:18231 std::vector<std::string> dns_names;
232 ssl_info_.cert->GetDNSNames(&dns_names);
233 DCHECK(!dns_names.empty());
234 GURL suggested_url;
bhanudev4b280dc2015-08-20 20:43:00235 if (IsSSLCommonNameMismatchHandlingEnabled() &&
bhanudev3999e372015-08-21 07:23:10236 cert_error_ == net::ERR_CERT_COMMON_NAME_INVALID &&
237 IsErrorOverridable() && GetSuggestedUrl(dns_names, &suggested_url)) {
bhanudev45d9a432015-08-20 02:38:51238 RecordUMA(WWW_MISMATCH_FOUND);
bhanudev2051ce72015-08-18 22:21:18239 net::CertStatus extra_cert_errors =
240 ssl_info_.cert_status ^ net::CERT_STATUS_COMMON_NAME_INVALID;
241
242 // Show the SSL intersitial if |CERT_STATUS_COMMON_NAME_INVALID| is not
243 // the only error. Need not check for captive portal in this case.
244 // (See the comment below).
245 if (net::IsCertStatusError(extra_cert_errors) &&
246 !net::IsCertStatusMinorError(ssl_info_.cert_status)) {
247 ShowSSLInterstitial();
248 return;
249 }
250 CheckSuggestedUrl(suggested_url);
meacer8b4cea22015-08-28 02:02:55251 timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(
252 g_interstitial_delay_in_milliseconds),
253 this, &SSLErrorHandler::ShowSSLInterstitial);
bhanudev2051ce72015-08-18 22:21:18254 if (g_timer_started_callback)
255 g_timer_started_callback->Run(web_contents_);
256
257 // Do not check for a captive portal in this case, because a captive
258 // portal most likely cannot serve a valid certificate which passes the
259 // similarity check.
260 return;
261 }
262
brettwab78fef2016-10-12 02:56:05263#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
bhanudev2051ce72015-08-18 22:21:18264 CaptivePortalTabHelper* captive_portal_tab_helper =
265 CaptivePortalTabHelper::FromWebContents(web_contents_);
266 if (captive_portal_tab_helper) {
267 captive_portal_tab_helper->OnSSLCertError(ssl_info_);
268 }
269
270 registrar_.Add(this, chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT,
271 content::Source<Profile>(profile_));
272
meacer5c777682015-01-09 06:54:53273 if (IsCaptivePortalInterstitialEnabled()) {
274 CheckForCaptivePortal();
meacer8b4cea22015-08-28 02:02:55275 timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(
276 g_interstitial_delay_in_milliseconds),
277 this, &SSLErrorHandler::ShowSSLInterstitial);
meacer5c777682015-01-09 06:54:53278 if (g_timer_started_callback)
279 g_timer_started_callback->Run(web_contents_);
280 return;
281 }
282#endif
meacer4ef065e2015-01-09 03:21:35283 // Display an SSL interstitial.
284 ShowSSLInterstitial();
meacer4ef065e2015-01-09 03:21:35285}
286
meacer8b4cea22015-08-28 02:02:55287void SSLErrorHandler::CheckForCaptivePortal() {
brettwab78fef2016-10-12 02:56:05288#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
meacer8b4cea22015-08-28 02:02:55289 CaptivePortalService* captive_portal_service =
290 CaptivePortalServiceFactory::GetForProfile(profile_);
291 captive_portal_service->DetectCaptivePortal();
292#else
293 NOTREACHED();
294#endif
meacer4ef065e2015-01-09 03:21:35295}
296
bhanudev2051ce72015-08-18 22:21:18297bool SSLErrorHandler::GetSuggestedUrl(const std::vector<std::string>& dns_names,
298 GURL* suggested_url) const {
299 return CommonNameMismatchHandler::GetSuggestedUrl(request_url_, dns_names,
300 suggested_url);
301}
302
303void SSLErrorHandler::CheckSuggestedUrl(const GURL& suggested_url) {
304 scoped_refptr<net::URLRequestContextGetter> request_context(
305 profile_->GetRequestContext());
306 common_name_mismatch_handler_.reset(
307 new CommonNameMismatchHandler(request_url_, request_context));
308
309 common_name_mismatch_handler_->CheckSuggestedUrl(
310 suggested_url,
311 base::Bind(&SSLErrorHandler::CommonNameMismatchHandlerCallback,
312 base::Unretained(this)));
313}
314
315void SSLErrorHandler::NavigateToSuggestedURL(const GURL& suggested_url) {
316 content::NavigationController::LoadURLParams load_params(suggested_url);
317 load_params.transition_type = ui::PAGE_TRANSITION_TYPED;
318 web_contents()->GetController().LoadURLWithParams(load_params);
319}
320
bhanudev3999e372015-08-21 07:23:10321bool SSLErrorHandler::IsErrorOverridable() const {
322 return SSLBlockingPage::IsOverridable(options_mask_, profile_);
323}
324
meacerca64d98192015-01-23 21:34:30325void SSLErrorHandler::ShowCaptivePortalInterstitial(const GURL& landing_url) {
brettwab78fef2016-10-12 02:56:05326#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
meacer4ef065e2015-01-09 03:21:35327 // Show captive portal blocking page. The interstitial owns the blocking page.
bhanudev3999e372015-08-21 07:23:10328 RecordUMA(IsErrorOverridable()
fahle66e7ff2015-04-23 19:38:30329 ? SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE
330 : SHOW_CAPTIVE_PORTAL_INTERSTITIAL_NONOVERRIDABLE);
meacerca64d98192015-01-23 21:34:30331 (new CaptivePortalBlockingPage(web_contents_, request_url_, landing_url,
dchenge73d8520c2015-12-27 01:19:09332 std::move(ssl_cert_reporter_), ssl_info_,
333 callback_))
334 ->Show();
meacer4ef065e2015-01-09 03:21:35335 // Once an interstitial is displayed, no need to keep the handler around.
meacer8b4cea22015-08-28 02:02:55336 // This is the equivalent of "delete this". It also destroys the timer.
meacer4ef065e2015-01-09 03:21:35337 web_contents_->RemoveUserData(UserDataKey());
338#else
339 NOTREACHED();
340#endif
341}
342
343void SSLErrorHandler::ShowSSLInterstitial() {
344 // Show SSL blocking page. The interstitial owns the blocking page.
bhanudev3999e372015-08-21 07:23:10345 RecordUMA(IsErrorOverridable() ? SHOW_SSL_INTERSTITIAL_OVERRIDABLE
346 : SHOW_SSL_INTERSTITIAL_NONOVERRIDABLE);
bhanudev2051ce72015-08-18 22:21:18347
meacerd19deef2016-09-29 02:08:16348 (SSLBlockingPage::Create(web_contents_, cert_error_, ssl_info_, request_url_,
349 options_mask_, base::Time::NowFromSystemTime(),
350 std::move(ssl_cert_reporter_), callback_))
bhanudev2051ce72015-08-18 22:21:18351 ->Show();
meacer4ef065e2015-01-09 03:21:35352 // Once an interstitial is displayed, no need to keep the handler around.
353 // This is the equivalent of "delete this".
354 web_contents_->RemoveUserData(UserDataKey());
355}
356
mab740b02b2016-03-17 23:44:21357void SSLErrorHandler::ShowBadClockInterstitial(
358 const base::Time& now,
359 ssl_errors::ClockState clock_state) {
felt534cc9e72015-09-01 20:38:59360 RecordUMA(SHOW_BAD_CLOCK);
361 (new BadClockBlockingPage(web_contents_, cert_error_, ssl_info_, request_url_,
mab740b02b2016-03-17 23:44:21362 now, clock_state, std::move(ssl_cert_reporter_),
363 callback_))
felt534cc9e72015-09-01 20:38:59364 ->Show();
365 // Once an interstitial is displayed, no need to keep the handler around.
366 // This is the equivalent of "delete this".
367 web_contents_->RemoveUserData(UserDataKey());
368}
369
meacer8b4cea22015-08-28 02:02:55370void SSLErrorHandler::CommonNameMismatchHandlerCallback(
371 const CommonNameMismatchHandler::SuggestedUrlCheckResult& result,
372 const GURL& suggested_url) {
373 timer_.Stop();
374 if (result == CommonNameMismatchHandler::SuggestedUrlCheckResult::
375 SUGGESTED_URL_AVAILABLE) {
376 RecordUMA(WWW_MISMATCH_URL_AVAILABLE);
377 CommonNameMismatchRedirectObserver::AddToConsoleAfterNavigation(
378 web_contents(), request_url_.host(), suggested_url.host());
379 NavigateToSuggestedURL(suggested_url);
380 } else {
381 RecordUMA(WWW_MISMATCH_URL_NOT_AVAILABLE);
382 ShowSSLInterstitial();
383 }
384}
385
meacer4ef065e2015-01-09 03:21:35386void SSLErrorHandler::Observe(
387 int type,
388 const content::NotificationSource& source,
389 const content::NotificationDetails& details) {
brettwab78fef2016-10-12 02:56:05390#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
thestig52835792016-06-13 21:08:09391 DCHECK_EQ(chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT, type);
392
393 timer_.Stop();
394 CaptivePortalService::Results* results =
395 content::Details<CaptivePortalService::Results>(details).ptr();
396 if (results->result == captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL)
397 ShowCaptivePortalInterstitial(results->landing_url);
398 else
399 ShowSSLInterstitial();
meacer4ef065e2015-01-09 03:21:35400#endif
401}
meacerd2c91b42015-03-20 18:34:40402
bhanudev85c5b8b52015-07-31 02:00:37403void SSLErrorHandler::DidStartNavigationToPendingEntry(
404 const GURL& /* url */,
toyoshim0df1d3a2016-09-09 09:52:48405 content::ReloadType /* reload_type */) {
406 // Destroy the error handler on all new navigations. This ensures that the
407 // handler is properly recreated when a hanging page is navigated to an SSL
408 // error, even when the tab's WebContents doesn't change.
bhanudev85c5b8b52015-07-31 02:00:37409 DeleteSSLErrorHandler();
410}
411
412void SSLErrorHandler::NavigationStopped() {
413// Destroy the error handler when the page load is stopped.
414 DeleteSSLErrorHandler();
415}
416
417void SSLErrorHandler::DeleteSSLErrorHandler() {
meacerd2c91b42015-03-20 18:34:40418 // Need to explicity deny the certificate via the callback, otherwise memory
419 // is leaked.
420 if (!callback_.is_null()) {
estark719dde52016-08-09 03:14:27421 base::ResetAndReturn(&callback_)
422 .Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY);
meacerd2c91b42015-03-20 18:34:40423 }
bhanudev2051ce72015-08-18 22:21:18424 if (common_name_mismatch_handler_) {
425 common_name_mismatch_handler_->Cancel();
426 common_name_mismatch_handler_.reset();
427 }
meacer8b4cea22015-08-28 02:02:55428 // Deletes |this| and also destroys the timer.
meacerd2c91b42015-03-20 18:34:40429 web_contents_->RemoveUserData(UserDataKey());
430}
estark5057f822016-11-08 21:34:54431
432void SSLErrorHandler::HandleCertDateInvalidError() {
433 network_time::NetworkTimeTracker* tracker =
434 g_network_time_tracker ? g_network_time_tracker
435 : g_browser_process->network_time_tracker();
436 timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(
437 g_interstitial_delay_in_milliseconds),
438 base::Bind(&SSLErrorHandler::HandleCertDateInvalidErrorImpl,
439 base::Unretained(this)));
440 // Try kicking off a time fetch to get an up-to-date estimate of the
441 // true time. This will only have an effect if network time is
442 // unavailable or if there is not already a query in progress.
443 //
444 // Pass a weak pointer as the callback; if the timer fires before the
445 // fetch completes and shows an interstitial, this SSLErrorHandler
446 // will be deleted.
447 if (!tracker->StartTimeFetch(
448 base::Bind(&SSLErrorHandler::HandleCertDateInvalidErrorImpl,
449 weak_ptr_factory_.GetWeakPtr()))) {
450 HandleCertDateInvalidErrorImpl();
451 return;
452 }
453
454 if (g_timer_started_callback)
455 g_timer_started_callback->Run(web_contents_);
456}
457
458void SSLErrorHandler::HandleCertDateInvalidErrorImpl() {
459 network_time::NetworkTimeTracker* tracker =
460 g_network_time_tracker ? g_network_time_tracker
461 : g_browser_process->network_time_tracker();
462 timer_.Stop();
463 const base::Time now = g_testing_clock == nullptr
464 ? base::Time::NowFromSystemTime()
465 : g_testing_clock->Now();
466 ssl_errors::ClockState clock_state = ssl_errors::GetClockState(now, tracker);
467 if (clock_state == ssl_errors::CLOCK_STATE_FUTURE ||
468 clock_state == ssl_errors::CLOCK_STATE_PAST) {
469 ShowBadClockInterstitial(now, clock_state);
470 return; // |this| is deleted after showing the interstitial.
471 }
472 ShowSSLInterstitial();
473}