| // 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. |
| |
| #include "chrome/browser/ssl/certificate_reporting_test_utils.h" |
| |
| #include "base/bind.h" |
| #include "base/bind_helpers.h" |
| #include "base/metrics/field_trial.h" |
| #include "base/prefs/pref_service.h" |
| #include "base/run_loop.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "chrome/browser/browser_process.h" |
| #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/cert_report_helper.h" |
| #include "chrome/browser/ssl/certificate_error_report.h" |
| #include "chrome/browser/ssl/ssl_cert_reporter.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/common/pref_names.h" |
| #include "components/variations/variations_associated_data.h" |
| #include "net/url_request/certificate_report_sender.h" |
| #include "net/url_request/url_request_context.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "url/gurl.h" |
| |
| using chrome_browser_net::CertificateErrorReporter; |
| |
| namespace { |
| |
| void SetMockReporter(SafeBrowsingService* safe_browsing_service, |
| scoped_ptr<CertificateErrorReporter> reporter) { |
| safe_browsing_service->ping_manager()->SetCertificateErrorReporterForTesting( |
| reporter.Pass()); |
| } |
| |
| } // namespace |
| |
| namespace CertificateReportingTestUtils { |
| |
| // This class is used to test invalid certificate chain reporting when |
| // 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 chrome_browser_net::CertificateErrorReporter { |
| public: |
| MockReporter( |
| net::URLRequestContext* request_context, |
| const GURL& upload_url, |
| net::CertificateReportSender::CookiesPreference cookies_preference); |
| |
| // CertificateErrorReporter implementation |
| void SendReport(CertificateErrorReporter::ReportType type, |
| const std::string& serialized_report) override; |
| |
| // Returns the hostname in the report for the last call to |
| // |SendReport|. |
| const std::string& latest_hostname_reported() { |
| return latest_hostname_reported_; |
| } |
| |
| private: |
| std::string latest_hostname_reported_; |
| |
| DISALLOW_COPY_AND_ASSIGN(MockReporter); |
| }; |
| |
| MockReporter::MockReporter( |
| net::URLRequestContext* request_context, |
| const GURL& upload_url, |
| net::CertificateReportSender::CookiesPreference cookies_preference) |
| : CertificateErrorReporter(request_context, |
| upload_url, |
| cookies_preference) {} |
| |
| void MockReporter::SendReport(CertificateErrorReporter::ReportType type, |
| const std::string& serialized_report) { |
| CertificateErrorReport report; |
| ASSERT_TRUE(report.InitializeFromString(serialized_report)); |
| EXPECT_EQ(CertificateErrorReporter::REPORT_TYPE_EXTENDED_REPORTING, type); |
| latest_hostname_reported_ = report.hostname(); |
| } |
| |
| void CertificateReportingTest::SetUpMockReporter() { |
| // Set up the mock reporter to track the hostnames that reports get |
| // sent for. The request_context argument is null here |
| // because the MockReporter doesn't actually use a |
| // request_context. (In order to pass a real request_context, the |
| // reporter would have to be constructed on the IO thread.) |
| reporter_ = |
| new MockReporter(nullptr, GURL("http://example.test"), |
| net::CertificateReportSender::DO_NOT_SEND_COOKIES); |
| |
| scoped_refptr<SafeBrowsingService> safe_browsing_service = |
| g_browser_process->safe_browsing_service(); |
| ASSERT_TRUE(safe_browsing_service); |
| |
| content::BrowserThread::PostTask( |
| content::BrowserThread::IO, FROM_HERE, |
| base::Bind( |
| SetMockReporter, safe_browsing_service, |
| base::Passed(scoped_ptr<CertificateErrorReporter>(reporter_)))); |
| } |
| |
| const std::string& CertificateReportingTest::GetLatestHostnameReported() const { |
| return reporter_->latest_hostname_reported(); |
| } |
| |
| // This is a test implementation of the interface that blocking pages |
| // use to send certificate reports. It checks that the blocking page |
| // calls or does not call the report method when a report should or |
| // should not be sent, respectively. |
| 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& serialized_report) override { |
| reported_ = true; |
| if (expect_report_) { |
| safe_browsing_ui_manager_->ReportInvalidCertificateChain( |
| serialized_report, 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_; |
| }; |
| |
| void SetCertReportingOptIn(Browser* browser, OptIn opt_in) { |
| browser->profile()->GetPrefs()->SetBoolean( |
| prefs::kSafeBrowsingExtendedReportingEnabled, |
| opt_in == EXTENDED_REPORTING_OPT_IN); |
| } |
| |
| scoped_ptr<SSLCertReporter> SetUpMockSSLCertReporter( |
| base::RunLoop* run_loop, |
| ExpectReport expect_report) { |
| // 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(); |
| EXPECT_TRUE(sb_service); |
| if (!sb_service) |
| return nullptr; |
| |
| scoped_ptr<MockSSLCertReporter> ssl_cert_reporter(new MockSSLCertReporter( |
| sb_service->ui_manager(), expect_report == CERT_REPORT_EXPECTED |
| ? run_loop->QuitClosure() |
| : base::Bind(&base::DoNothing))); |
| ssl_cert_reporter->set_expect_report(expect_report == CERT_REPORT_EXPECTED); |
| return ssl_cert_reporter.Pass(); |
| } |
| |
| ExpectReport GetReportExpectedFromFinch() { |
| const std::string group_name = base::FieldTrialList::FindFullName( |
| CertReportHelper::kFinchExperimentName); |
| |
| if (group_name == CertReportHelper::kFinchGroupShowPossiblySend) { |
| const std::string param = variations::GetVariationParamValue( |
| CertReportHelper::kFinchExperimentName, |
| CertReportHelper::kFinchParamName); |
| double sendingThreshold; |
| if (!base::StringToDouble(param, &sendingThreshold)) |
| return CERT_REPORT_NOT_EXPECTED; |
| |
| if (sendingThreshold == 1.0) |
| return CertificateReportingTestUtils::CERT_REPORT_EXPECTED; |
| } |
| return CertificateReportingTestUtils::CERT_REPORT_NOT_EXPECTED; |
| } |
| |
| } // namespace CertificateReportingTestUtils |