diff options
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/chrome_content_browser_client.cc | 39 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_blocking_page.cc | 36 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_blocking_page.h | 22 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_browser_tests.cc | 64 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_cert_reporter.h | 27 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_error_handler.cc | 25 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_error_handler.h | 9 |
7 files changed, 153 insertions, 69 deletions
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index ecac531..39f2fcd 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc @@ -9,6 +9,7 @@ #include <vector> #include "base/bind.h" +#include "base/bind_helpers.h" #include "base/command_line.h" #include "base/files/scoped_file.h" #include "base/i18n/icu_util.h" @@ -53,6 +54,7 @@ #include "chrome/browser/renderer_host/chrome_render_message_filter.h" #include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" +#include "chrome/browser/safe_browsing/ui_manager.h" #include "chrome/browser/search/instant_service.h" #include "chrome/browser/search/instant_service_factory.h" #include "chrome/browser/search/search.h" @@ -62,6 +64,7 @@ #include "chrome/browser/speech/tts_message_filter.h" #include "chrome/browser/ssl/ssl_add_certificate.h" #include "chrome/browser/ssl/ssl_blocking_page.h" +#include "chrome/browser/ssl/ssl_cert_reporter.h" #include "chrome/browser/ssl/ssl_client_certificate_selector.h" #include "chrome/browser/ssl/ssl_error_handler.h" #include "chrome/browser/sync_file_system/local/sync_file_system_backend.h" @@ -518,6 +521,29 @@ void HandleBlockedPopupOnUIThread(const BlockedWindowParams& params) { popup_helper->AddBlockedPopup(params); } +// An implementation of the SSLCertReporter interface used by +// SSLErrorHandler. Uses the SafeBrowsing UI manager to send invalid +// certificate reports. +class SafeBrowsingSSLCertReporter : public SSLCertReporter { + public: + explicit SafeBrowsingSSLCertReporter( + const scoped_refptr<SafeBrowsingUIManager>& safe_browsing_ui_manager) + : safe_browsing_ui_manager_(safe_browsing_ui_manager) {} + ~SafeBrowsingSSLCertReporter() override {} + + // SSLCertReporter implementation + void ReportInvalidCertificateChain(const std::string& hostname, + const net::SSLInfo& ssl_info) override { + if (safe_browsing_ui_manager_) { + safe_browsing_ui_manager_->ReportInvalidCertificateChain( + hostname, ssl_info, base::Bind(&base::DoNothing)); + } + } + + private: + const scoped_refptr<SafeBrowsingUIManager> safe_browsing_ui_manager_; +}; + #if defined(OS_ANDROID) void HandleSingleTabModeBlockOnUIThread(const BlockedWindowParams& params) { @@ -571,7 +597,7 @@ void GetGuestViewDefaultContentSettingRules( std::string(), incognito)); } -#endif // defined(ENALBE_EXTENSIONS) +#endif // defined(ENABLE_EXTENSIONS) } // namespace @@ -1711,11 +1737,12 @@ void ChromeContentBrowserClient::AllowCertificateError( SafeBrowsingService* safe_browsing_service = g_browser_process->safe_browsing_service(); - SSLErrorHandler::HandleSSLError( - tab, cert_error, ssl_info, request_url, options_mask, - safe_browsing_service ? safe_browsing_service->ui_manager().get() - : nullptr, - callback); + scoped_ptr<SafeBrowsingSSLCertReporter> cert_reporter( + new SafeBrowsingSSLCertReporter(safe_browsing_service + ? safe_browsing_service->ui_manager() + : nullptr)); + SSLErrorHandler::HandleSSLError(tab, cert_error, ssl_info, request_url, + options_mask, cert_reporter.Pass(), callback); } void ChromeContentBrowserClient::SelectClientCertificate( diff --git a/chrome/browser/ssl/ssl_blocking_page.cc b/chrome/browser/ssl/ssl_blocking_page.cc index d5f256e..717d138 100644 --- a/chrome/browser/ssl/ssl_blocking_page.cc +++ b/chrome/browser/ssl/ssl_blocking_page.cc @@ -28,7 +28,7 @@ #include "chrome/browser/interstitials/security_interstitial_metrics_helper.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/renderer_preferences_util.h" -#include "chrome/browser/safe_browsing/ui_manager.h" +#include "chrome/browser/ssl/ssl_cert_reporter.h" #include "chrome/browser/ssl/ssl_error_classification.h" #include "chrome/browser/ssl/ssl_error_info.h" #include "chrome/common/chrome_switches.h" @@ -236,15 +236,14 @@ InterstitialPageDelegate::TypeID SSLBlockingPage::kTypeForTesting = // Note that we always create a navigation entry with SSL errors. // No error happening loading a sub-resource triggers an interstitial so far. -SSLBlockingPage::SSLBlockingPage( - content::WebContents* web_contents, - int cert_error, - const net::SSLInfo& ssl_info, - const GURL& request_url, - int options_mask, - const base::Time& time_triggered, - SafeBrowsingUIManager* safe_browsing_ui_manager, - const base::Callback<void(bool)>& callback) +SSLBlockingPage::SSLBlockingPage(content::WebContents* web_contents, + int cert_error, + const net::SSLInfo& ssl_info, + const GURL& request_url, + int options_mask, + const base::Time& time_triggered, + scoped_ptr<SSLCertReporter> ssl_cert_reporter, + const base::Callback<void(bool)>& callback) : SecurityInterstitialPage(web_contents, request_url), callback_(callback), cert_error_(cert_error), @@ -255,7 +254,7 @@ SSLBlockingPage::SSLBlockingPage( expired_but_previously_allowed_( (options_mask & EXPIRED_BUT_PREVIOUSLY_ALLOWED) != 0), time_triggered_(time_triggered), - safe_browsing_ui_manager_(safe_browsing_ui_manager) { + ssl_cert_reporter_(ssl_cert_reporter.Pass()) { interstitial_reason_ = IsErrorDueToBadClock(time_triggered_, cert_error_) ? SSL_REASON_BAD_CLOCK : SSL_REASON_SSL; @@ -498,9 +497,9 @@ void SSLBlockingPage::OverrideEntry(NavigationEntry* entry) { entry->GetSSL().security_bits = ssl_info_.security_bits; } -void SSLBlockingPage::SetCertificateReportCallbackForTesting( - const base::Closure& callback) { - certificate_report_callback_for_testing_ = callback; +void SSLBlockingPage::SetSSLCertReporterForTesting( + scoped_ptr<SSLCertReporter> ssl_cert_reporter) { + ssl_cert_reporter_ = ssl_cert_reporter.Pass(); } // This handles the commands sent from the interstitial JavaScript. @@ -649,9 +648,6 @@ std::string SSLBlockingPage::GetSamplingEventName() const { } void SSLBlockingPage::FinishCertCollection() { - base::ScopedClosureRunner scoped_callback( - certificate_report_callback_for_testing_); - if (!ShouldShowCertificateReporterCheckbox()) return; @@ -665,10 +661,8 @@ void SSLBlockingPage::FinishCertCollection() { SecurityInterstitialMetricsHelper::EXTENDED_REPORTING_IS_ENABLED); if (ShouldReportCertificateError()) { - if (certificate_report_callback_for_testing_.is_null()) - scoped_callback.Reset(base::Bind(&base::DoNothing)); - safe_browsing_ui_manager_->ReportInvalidCertificateChain( - request_url().host(), ssl_info_, scoped_callback.Release()); + ssl_cert_reporter_->ReportInvalidCertificateChain(request_url().host(), + ssl_info_); } } diff --git a/chrome/browser/ssl/ssl_blocking_page.h b/chrome/browser/ssl/ssl_blocking_page.h index 6e63f54..ce694f80 100644 --- a/chrome/browser/ssl/ssl_blocking_page.h +++ b/chrome/browser/ssl/ssl_blocking_page.h @@ -13,6 +13,7 @@ #include "base/task/cancelable_task_tracker.h" #include "base/time/time.h" #include "chrome/browser/interstitials/security_interstitial_page.h" +#include "chrome/browser/ssl/ssl_cert_reporter.h" #include "net/ssl/ssl_info.h" #include "url/gurl.h" @@ -28,7 +29,6 @@ class ExperienceSamplingEvent; } #endif -class SafeBrowsingUIManager; class SSLErrorClassification; // This class is responsible for showing/hiding the interstitial page that is @@ -65,7 +65,7 @@ class SSLBlockingPage : public SecurityInterstitialPage { const GURL& request_url, int options_mask, const base::Time& time_triggered, - SafeBrowsingUIManager* safe_browsing_ui_manager, + scoped_ptr<SSLCertReporter> ssl_cert_reporter, const base::Callback<void(bool)>& callback); // InterstitialPageDelegate method: @@ -74,9 +74,8 @@ class SSLBlockingPage : public SecurityInterstitialPage { // Returns true if |options_mask| refers to an overridable SSL error. static bool IsOptionsOverridable(int options_mask); - // Allows tests to be notified when an invalid cert chain report has - // been sent (or not sent). - void SetCertificateReportCallbackForTesting(const base::Closure& callback); + void SetSSLCertReporterForTesting( + scoped_ptr<SSLCertReporter> ssl_cert_reporter); protected: // InterstitialPageDelegate implementation. @@ -100,8 +99,7 @@ class SSLBlockingPage : public SecurityInterstitialPage { std::string GetUmaHistogramPrefix() const; std::string GetSamplingEventName() const; - // Send a report about an invalid certificate to the server. Takes - // care of calling certificate_report_callback_for_testing_. + // Send a report about an invalid certificate to the server. void FinishCertCollection(); // Check whether a checkbox should be shown on the page that allows @@ -136,14 +134,8 @@ class SSLBlockingPage : public SecurityInterstitialPage { // calculates all times relative to this. const base::Time time_triggered_; - // For reporting invalid SSL certificates as part of Safe Browsing - // Extended Reporting. - SafeBrowsingUIManager* safe_browsing_ui_manager_; - - // This callback is run when an extended reporting certificate chain - // report has been sent, or when it is decided that it should not be - // sent (for example, when in incognito mode). - base::Closure certificate_report_callback_for_testing_; + // Handles reports of invalid SSL certificates. + scoped_ptr<SSLCertReporter> ssl_cert_reporter_; // Which type of interstitial this is. enum SSLInterstitialReason { diff --git a/chrome/browser/ssl/ssl_browser_tests.cc b/chrome/browser/ssl/ssl_browser_tests.cc index 83aa42b..d6eb171 100644 --- a/chrome/browser/ssl/ssl_browser_tests.cc +++ b/chrome/browser/ssl/ssl_browser_tests.cc @@ -20,6 +20,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/safe_browsing/ping_manager.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" +#include "chrome/browser/safe_browsing/ui_manager.h" #include "chrome/browser/ssl/ssl_blocking_page.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" @@ -195,7 +196,9 @@ enum Proceed { SSL_INTERSTITIAL_PROCEED, SSL_INTERSTITIAL_DO_NOT_PROCEED }; enum ExpectReport { CERT_REPORT_EXPECTED, CERT_REPORT_NOT_EXPECTED }; // This class is used to test invalid certificate chain reporting when -// the user opts in to do so on the interstitial. +// the user opts in to do so on the interstitial. It keeps track of the +// most recent hostname for which a report would have been sent over the +// network. class MockReporter : public CertificateErrorReporter { public: explicit MockReporter(net::URLRequestContext* request_context, @@ -226,6 +229,40 @@ void SetUpMockReporter(SafeBrowsingService* safe_browsing_service, scoped_ptr<CertificateErrorReporter>(reporter)); } +// This is a test implementation of the interface that blocking pages +// use to send certificate reports. It checks that the blocking page +// calls the report method when a report should be sent. +class MockSSLCertReporter : public SSLCertReporter { + public: + MockSSLCertReporter( + const scoped_refptr<SafeBrowsingUIManager>& safe_browsing_ui_manager, + const base::Closure& report_sent_callback) + : safe_browsing_ui_manager_(safe_browsing_ui_manager), + reported_(false), + expect_report_(false), + report_sent_callback_(report_sent_callback) {} + + ~MockSSLCertReporter() override { EXPECT_EQ(expect_report_, reported_); } + + // SSLCertReporter implementation + void ReportInvalidCertificateChain(const std::string& hostname, + const net::SSLInfo& ssl_info) override { + reported_ = true; + if (expect_report_) { + safe_browsing_ui_manager_->ReportInvalidCertificateChain( + hostname, ssl_info, report_sent_callback_); + } + } + + void set_expect_report(bool expect_report) { expect_report_ = expect_report; } + + private: + const scoped_refptr<SafeBrowsingUIManager> safe_browsing_ui_manager_; + bool reported_; + bool expect_report_; + base::Closure report_sent_callback_; +}; + } // namespace CertificateReporting } // namespace @@ -434,6 +471,9 @@ class SSLUITest : public InProcessBrowserTest { CertificateReporting::Proceed proceed, CertificateReporting::ExpectReport expect_report, Browser* browser) { + base::RunLoop run_loop; + bool report_expected = + expect_report == CertificateReporting::CERT_REPORT_EXPECTED; ASSERT_TRUE(https_server_expired_.Start()); // Opt in to sending reports for invalid certificate chains. @@ -447,13 +487,21 @@ class SSLUITest : public InProcessBrowserTest { CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, AuthState::SHOWING_INTERSTITIAL); - // Set up a callback so that the test is notified when the report - // has been sent on the IO thread (or not sent). - base::RunLoop report_run_loop; - base::Closure report_callback = report_run_loop.QuitClosure(); + // Set up a MockSSLCertReporter to keep track of when the blocking + // page invokes the cert reporter. + SafeBrowsingService* sb_service = + g_browser_process->safe_browsing_service(); + ASSERT_TRUE(sb_service); + scoped_ptr<CertificateReporting::MockSSLCertReporter> ssl_cert_reporter( + new CertificateReporting::MockSSLCertReporter( + sb_service->ui_manager(), report_expected + ? run_loop.QuitClosure() + : base::Bind(&base::DoNothing))); + ssl_cert_reporter->set_expect_report(report_expected); + SSLBlockingPage* interstitial_page = static_cast<SSLBlockingPage*>( tab->GetInterstitialPage()->GetDelegateForTesting()); - interstitial_page->SetCertificateReportCallbackForTesting(report_callback); + interstitial_page->SetSSLCertReporterForTesting(ssl_cert_reporter.Pass()); EXPECT_EQ(std::string(), reporter_->latest_hostname_reported()); @@ -467,11 +515,9 @@ class SSLUITest : public InProcessBrowserTest { interstitial_page->DontProceed(); } - // Wait until the report has been sent on the IO thread. - report_run_loop.Run(); - if (expect_report == CertificateReporting::CERT_REPORT_EXPECTED) { // Check that the mock reporter received a request to send a report. + run_loop.Run(); EXPECT_EQ(https_server_expired_.GetURL("/").host(), reporter_->latest_hostname_reported()); } else { diff --git a/chrome/browser/ssl/ssl_cert_reporter.h b/chrome/browser/ssl/ssl_cert_reporter.h new file mode 100644 index 0000000..d31c080 --- /dev/null +++ b/chrome/browser/ssl/ssl_cert_reporter.h @@ -0,0 +1,27 @@ +// Copyright 2015 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_CERT_REPORTER_H_ +#define CHROME_BROWSER_SSL_SSL_CERT_REPORTER_H_ + +#include <string> + +namespace net { +class SSLInfo; +} // namespace net + +// An interface used by interstitial pages to send reports of invalid +// certificate chains. +class SSLCertReporter { + public: + virtual ~SSLCertReporter() {} + + // Send a report for |hostname| with the given |ssl_info| to the + // report collection endpoint. |callback| will be run when the report has + // been sent off (not necessarily after a response has been received). + virtual void ReportInvalidCertificateChain(const std::string& hostname, + const net::SSLInfo& ssl_info) = 0; +}; + +#endif // CHROME_BROWSER_SSL_SSL_CERT_REPORTER_H_ diff --git a/chrome/browser/ssl/ssl_error_handler.cc b/chrome/browser/ssl/ssl_error_handler.cc index 6e0cd4d..25e4b6a 100644 --- a/chrome/browser/ssl/ssl_error_handler.cc +++ b/chrome/browser/ssl/ssl_error_handler.cc @@ -9,8 +9,8 @@ #include "base/metrics/histogram.h" #include "base/time/time.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/safe_browsing/ui_manager.h" #include "chrome/browser/ssl/ssl_blocking_page.h" +#include "chrome/browser/ssl/ssl_cert_reporter.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_source.h" #include "content/public/browser/web_contents.h" @@ -90,7 +90,7 @@ void SSLErrorHandler::HandleSSLError( const net::SSLInfo& ssl_info, const GURL& request_url, int options_mask, - SafeBrowsingUIManager* safe_browsing_ui_manager, + scoped_ptr<SSLCertReporter> ssl_cert_reporter, const base::Callback<void(bool)>& callback) { #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) CaptivePortalTabHelper* captive_portal_tab_helper = @@ -103,7 +103,7 @@ void SSLErrorHandler::HandleSSLError( web_contents->SetUserData( UserDataKey(), new SSLErrorHandler(web_contents, cert_error, ssl_info, request_url, - options_mask, safe_browsing_ui_manager, callback)); + options_mask, ssl_cert_reporter.Pass(), callback)); SSLErrorHandler* error_handler = SSLErrorHandler::FromWebContents(web_contents); @@ -123,14 +123,13 @@ void SSLErrorHandler::SetInterstitialTimerStartedCallbackForTest( g_timer_started_callback = callback; } -SSLErrorHandler::SSLErrorHandler( - content::WebContents* web_contents, - int cert_error, - const net::SSLInfo& ssl_info, - const GURL& request_url, - int options_mask, - SafeBrowsingUIManager* safe_browsing_ui_manager, - const base::Callback<void(bool)>& callback) +SSLErrorHandler::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) : content::WebContentsObserver(web_contents), web_contents_(web_contents), cert_error_(cert_error), @@ -138,7 +137,7 @@ SSLErrorHandler::SSLErrorHandler( request_url_(request_url), options_mask_(options_mask), callback_(callback), - safe_browsing_ui_manager_(safe_browsing_ui_manager) { + ssl_cert_reporter_(ssl_cert_reporter.Pass()) { #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) Profile* profile = Profile::FromBrowserContext( web_contents->GetBrowserContext()); @@ -208,7 +207,7 @@ void SSLErrorHandler::ShowSSLInterstitial() { SHOW_SSL_INTERSTITIAL_NONOVERRIDABLE); (new SSLBlockingPage(web_contents_, cert_error_, ssl_info_, request_url_, options_mask_, base::Time::NowFromSystemTime(), - safe_browsing_ui_manager_, callback_))->Show(); + ssl_cert_reporter_.Pass(), callback_))->Show(); // Once an interstitial is displayed, no need to keep the handler around. // This is the equivalent of "delete this". web_contents_->RemoveUserData(UserDataKey()); diff --git a/chrome/browser/ssl/ssl_error_handler.h b/chrome/browser/ssl/ssl_error_handler.h index c069b47..49f0c35 100644 --- a/chrome/browser/ssl/ssl_error_handler.h +++ b/chrome/browser/ssl/ssl_error_handler.h @@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/timer/timer.h" #include "chrome/browser/chrome_notification_types.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" @@ -23,8 +24,6 @@ class RenderViewHost; class WebContents; } -class SafeBrowsingUIManager; - // This class is responsible for deciding whether to show an SSL warning or a // captive portal error page. It makes this decision by delaying the display of // SSL interstitial for a few seconds (2 by default), and waiting for a captive @@ -53,7 +52,7 @@ class SSLErrorHandler : public content::WebContentsUserData<SSLErrorHandler>, const net::SSLInfo& ssl_info, const GURL& request_url, int options_mask, - SafeBrowsingUIManager* safe_browsing_ui_manager, + scoped_ptr<SSLCertReporter> ssl_cert_reporter, const base::Callback<void(bool)>& callback); static void SetInterstitialDelayTypeForTest(InterstitialDelayType delay); @@ -68,7 +67,7 @@ class SSLErrorHandler : public content::WebContentsUserData<SSLErrorHandler>, const net::SSLInfo& ssl_info, const GURL& request_url, int options_mask, - SafeBrowsingUIManager* safe_browsing_ui_manager, + scoped_ptr<SSLCertReporter> ssl_cert_reporter, const base::Callback<void(bool)>& callback); ~SSLErrorHandler() override; @@ -112,7 +111,7 @@ class SSLErrorHandler : public content::WebContentsUserData<SSLErrorHandler>, content::NotificationRegistrar registrar_; base::OneShotTimer<SSLErrorHandler> timer_; - SafeBrowsingUIManager* safe_browsing_ui_manager_; + scoped_ptr<SSLCertReporter> ssl_cert_reporter_; DISALLOW_COPY_AND_ASSIGN(SSLErrorHandler); }; |