// 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. #ifndef CHROME_BROWSER_SSL_SSL_ERROR_HANDLER_H_ #define CHROME_BROWSER_SSL_SSL_ERROR_HANDLER_H_ #include <string> #include "base/callback_forward.h" #include "base/macros.h" #include "base/timer/timer.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ssl/common_name_mismatch_handler.h" #include "chrome/browser/ssl/ssl_cert_reporter.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" #include "net/ssl/ssl_info.h" #include "url/gurl.h" class CommonNameMismatchHandler; class Profile; namespace base { class Clock; } namespace content { class RenderViewHost; class WebContents; } // This class is responsible for deciding what type of interstitial to show for // an SSL validation error. The display of the interstitial might be delayed by // a few seconds (2 by default) while trying to determine the cause of the // error. During this window, the class will: check for a clock error, wait for // a name-mismatch suggested URL, or wait for a captive portal result to arrive. // If there is a name mismatch error and a corresponding suggested URL // result arrives in this window, the user is redirected to the suggested URL. // Failing that, if a captive portal detected result arrives in the time window, // a captive portal error page is shown. If none of these potential error // causes match, an SSL interstitial is shown. // // This class should only be used on the UI thread because its implementation // uses captive_portal::CaptivePortalService which can only be accessed on the // UI thread. class SSLErrorHandler : public content::WebContentsUserData<SSLErrorHandler>, public content::WebContentsObserver, public content::NotificationObserver { public: typedef base::Callback<void(content::WebContents*)> TimerStartedCallback; // Entry point for the class. The parameters are the same as SSLBlockingPage // constructor. static void HandleSSLError(content::WebContents* web_contents, int cert_error, const net::SSLInfo& ssl_info, const GURL& request_url, int options_mask, scoped_ptr<SSLCertReporter> ssl_cert_reporter, const base::Callback<void(bool)>& callback); // Testing methods. static void SetInterstitialDelayForTest(base::TimeDelta delay); // The callback pointer must remain valid for the duration of error handling. static void SetInterstitialTimerStartedCallbackForTest( TimerStartedCallback* callback); static void SetClockForTest(base::Clock* testing_clock); protected: // The parameters are the same as SSLBlockingPage's constructor. SSLErrorHandler(content::WebContents* web_contents, int cert_error, const net::SSLInfo& ssl_info, const GURL& request_url, int options_mask, scoped_ptr<SSLCertReporter> ssl_cert_reporter, const base::Callback<void(bool)>& callback); ~SSLErrorHandler() override; // Called when an SSL cert error is encountered. Triggers a captive portal // check and fires a one shot timer to wait for a "captive portal detected" // result to arrive. void StartHandlingError(); const base::OneShotTimer& get_timer() const { return timer_; } // These are virtual for tests: virtual void CheckForCaptivePortal(); virtual bool GetSuggestedUrl(const std::vector<std::string>& dns_names, GURL* suggested_url) const; virtual void CheckSuggestedUrl(const GURL& suggested_url); virtual void NavigateToSuggestedURL(const GURL& suggested_url); virtual bool IsErrorOverridable() const; virtual void ShowCaptivePortalInterstitial(const GURL& landing_url); virtual void ShowSSLInterstitial(); void ShowBadClockInterstitial(const base::Time& now); // Gets the result of whether the suggested URL is valid. Displays // common name mismatch interstitial or ssl interstitial accordingly. void CommonNameMismatchHandlerCallback( const CommonNameMismatchHandler::SuggestedUrlCheckResult& result, const GURL& suggested_url); private: // content::NotificationObserver: void Observe( int type, const content::NotificationSource& source, const content::NotificationDetails& details) override; // content::WebContentsObserver: void DidStartNavigationToPendingEntry( const GURL& url, content::NavigationController::ReloadType reload_type) override; // content::WebContentsObserver: void NavigationStopped() override; // Deletes the SSLErrorHandler. This method is called when the page // load stops or when there is a new navigation. void DeleteSSLErrorHandler(); content::WebContents* web_contents_; const int cert_error_; const net::SSLInfo ssl_info_; const GURL request_url_; const int options_mask_; base::Callback<void(bool)> callback_; Profile* const profile_; content::NotificationRegistrar registrar_; base::OneShotTimer timer_; scoped_ptr<CommonNameMismatchHandler> common_name_mismatch_handler_; scoped_ptr<SSLCertReporter> ssl_cert_reporter_; DISALLOW_COPY_AND_ASSIGN(SSLErrorHandler); }; #endif // CHROME_BROWSER_SSL_SSL_ERROR_HANDLER_H_