| Index: chrome/browser/ssl/ssl_error_handler.cc
|
| diff --git a/chrome/browser/ssl/ssl_error_handler.cc b/chrome/browser/ssl/ssl_error_handler.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..4159aa73c23687390bb1a42a0131e49bd92ff467
|
| --- /dev/null
|
| +++ b/chrome/browser/ssl/ssl_error_handler.cc
|
| @@ -0,0 +1,178 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chrome/browser/ssl/ssl_error_handler.h"
|
| +
|
| +#include "base/metrics/histogram.h"
|
| +#include "base/time/time.h"
|
| +#include "chrome/browser/profiles/profile.h"
|
| +#include "chrome/browser/ssl/ssl_blocking_page.h"
|
| +#include "content/public/browser/notification_service.h"
|
| +#include "content/public/browser/notification_source.h"
|
| +#include "content/public/browser/web_contents.h"
|
| +
|
| +#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
|
| +#include "chrome/browser/captive_portal/captive_portal_service.h"
|
| +#include "chrome/browser/captive_portal/captive_portal_service_factory.h"
|
| +#include "chrome/browser/captive_portal/captive_portal_tab_helper.h"
|
| +#include "chrome/browser/ssl/captive_portal_blocking_page.h"
|
| +#endif
|
| +
|
| +namespace {
|
| +
|
| +// Events for UMA.
|
| +enum SSLErrorHandlerEvent {
|
| + HANDLE_ALL,
|
| + SHOW_CAPTIVE_PORTAL_INTERSTITIAL,
|
| + SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE,
|
| + SHOW_SSL_INTERSTITIAL,
|
| + SHOW_SSL_INTERSTITIAL_OVERRIDABLE,
|
| + SSL_ERROR_HANDLER_EVENT_COUNT
|
| +};
|
| +
|
| +void RecordUMA(SSLErrorHandlerEvent event) {
|
| + UMA_HISTOGRAM_ENUMERATION("interstitial.ssl_error_handler",
|
| + event,
|
| + SSL_ERROR_HANDLER_EVENT_COUNT);
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +SSLErrorHandler::SSLErrorHandler(content::WebContents* web_contents,
|
| + int cert_error,
|
| + const net::SSLInfo& ssl_info,
|
| + const GURL& request_url,
|
| + const int options_mask,
|
| + const base::TimeDelta ssl_error_delay,
|
| + const base::Callback<void(bool)>& callback)
|
| + : content::WebContentsObserver(web_contents),
|
| + cert_error_(cert_error),
|
| + ssl_info_(ssl_info),
|
| + request_url_(request_url),
|
| + options_mask_(options_mask),
|
| + callback_(callback),
|
| + ssl_interstitial_display_delay_(ssl_error_delay) {
|
| +#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
|
| + Profile* profile = Profile::FromBrowserContext(
|
| + web_contents->GetBrowserContext());
|
| + registrar_.Add(this,
|
| + chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT,
|
| + content::Source<Profile>(profile));
|
| +#endif
|
| +}
|
| +
|
| +SSLErrorHandler::~SSLErrorHandler() {
|
| +}
|
| +
|
| +void SSLErrorHandler::HandleSSLError(
|
| + content::WebContents* web_contents,
|
| + int cert_error,
|
| + const net::SSLInfo& ssl_info,
|
| + const GURL& request_url,
|
| + int options_mask,
|
| + const base::Callback<void(bool)>& callback) {
|
| + // SSL interstitials aren't delayed if captive portal detection is disabled.
|
| + base::TimeDelta ssl_error_delay;
|
| +#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
|
| + CaptivePortalTabHelper* captive_portal_tab_helper =
|
| + CaptivePortalTabHelper::FromWebContents(web_contents);
|
| + if (captive_portal_tab_helper) {
|
| + ssl_error_delay = captive_portal_tab_helper->GetSSLErrorDelay();
|
| + captive_portal_tab_helper->OnSSLCertError(ssl_info);
|
| + }
|
| +#endif
|
| + (new SSLErrorHandler(web_contents, cert_error, ssl_info, request_url,
|
| + options_mask, ssl_error_delay,
|
| + callback))->StartHandlingError();
|
| +}
|
| +
|
| +void SSLErrorHandler::StartHandlingError() {
|
| + RecordUMA(HANDLE_ALL);
|
| +
|
| +#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
|
| + CheckForCaptivePortal();
|
| + timer_.Start(FROM_HERE, ssl_interstitial_display_delay_,
|
| + base::Bind(&SSLErrorHandler::OnTimerExpired,
|
| + base::Unretained(this)));
|
| + content::NotificationService* service =
|
| + content::NotificationService::current();
|
| + service->Notify(chrome::NOTIFICATION_SSL_INTERSTITIAL_TIMER_FIRED,
|
| + content::Source<content::WebContents>(web_contents()),
|
| + content::NotificationService::NoDetails());
|
| + return;
|
| +#endif
|
| + // Display an SSL interstitial.
|
| + ShowSSLInterstitial();
|
| +}
|
| +
|
| +void SSLErrorHandler::OnTimerExpired() {
|
| + ShowSSLInterstitial();
|
| +}
|
| +
|
| +void SSLErrorHandler::CheckForCaptivePortal() {
|
| +#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
|
| + Profile* profile = Profile::FromBrowserContext(
|
| + web_contents()->GetBrowserContext());
|
| + CaptivePortalService* captive_portal_service =
|
| + CaptivePortalServiceFactory::GetForProfile(profile);
|
| + captive_portal_service->DetectCaptivePortal();
|
| +#else
|
| + NOTREACHED();
|
| +#endif
|
| +}
|
| +
|
| +void SSLErrorHandler::ShowCaptivePortalInterstitial() {
|
| +#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
|
| + // Show captive portal blocking page. The interstitial owns the blocking page.
|
| + RecordUMA(SSLBlockingPage::IsOverridable(options_mask_) ?
|
| + SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE :
|
| + SHOW_CAPTIVE_PORTAL_INTERSTITIAL);
|
| + (new CaptivePortalBlockingPage(web_contents(), request_url_))->Show();
|
| + delete this;
|
| +#else
|
| + NOTREACHED();
|
| +#endif
|
| +}
|
| +
|
| +void SSLErrorHandler::ShowSSLInterstitial() {
|
| + // Show SSL blocking page. The interstitial owns the blocking page.
|
| + RecordUMA(SSLBlockingPage::IsOverridable(options_mask_) ?
|
| + SHOW_SSL_INTERSTITIAL_OVERRIDABLE :
|
| + SHOW_SSL_INTERSTITIAL);
|
| + (new SSLBlockingPage(web_contents(), cert_error_, ssl_info_, request_url_,
|
| + options_mask_, callback_))->Show();
|
| + delete this;
|
| +}
|
| +
|
| +void SSLErrorHandler::Observe(
|
| + int type,
|
| + const content::NotificationSource& source,
|
| + const content::NotificationDetails& details) {
|
| +#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
|
| + if (type == chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT) {
|
| + timer_.Stop();
|
| + CaptivePortalService::Results* results =
|
| + content::Details<CaptivePortalService::Results>(details).ptr();
|
| + if (results->result == captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL)
|
| + ShowCaptivePortalInterstitial();
|
| + else
|
| + ShowSSLInterstitial();
|
| + }
|
| +#endif
|
| +}
|
| +
|
| +void SSLErrorHandler::DidStartNavigationToPendingEntry(
|
| + const GURL& url,
|
| + content::NavigationController::ReloadType reload_type) {
|
| + delete this;
|
| +}
|
| +
|
| +void SSLErrorHandler::DidStopLoading(
|
| + content::RenderViewHost* render_view_host) {
|
| + delete this;
|
| +}
|
| +
|
| +void SSLErrorHandler::WebContentsDestroyed() {
|
| + delete this;
|
| +}
|
|
|