blob: 55aa0e206702ac38c547c21f9f6384732ebe85a8 [file] [log] [blame]
// 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 <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/macros.h"
#include "base/metrics/field_trial.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/ssl_cert_reporter.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/pref_names.h"
#include "components/certificate_reporting/error_report.h"
#include "components/certificate_reporting/error_reporter.h"
#include "components/prefs/pref_service.h"
#include "components/variations/variations_associated_data.h"
#include "net/url_request/report_sender.h"
#include "net/url_request/url_request_context.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
using safe_browsing::SafeBrowsingService;
using safe_browsing::SafeBrowsingUIManager;
namespace {
void SetMockReporter(
SafeBrowsingService* safe_browsing_service,
std::unique_ptr<certificate_reporting::ErrorReporter> reporter) {
safe_browsing_service->ping_manager()->SetCertificateErrorReporterForTesting(
std::move(reporter));
}
// 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_;
};
} // namespace
namespace certificate_reporting_test_utils {
// 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 an extended reporting report would
// have been sent over the network.
class CertificateReportingTest::MockReporter
: public certificate_reporting::ErrorReporter {
public:
MockReporter(net::URLRequestContext* request_context,
const GURL& upload_url,
net::ReportSender::CookiesPreference cookies_preference);
// ErrorReporter implementation.
void SendExtendedReportingReport(
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);
};
CertificateReportingTest::MockReporter::MockReporter(
net::URLRequestContext* request_context,
const GURL& upload_url,
net::ReportSender::CookiesPreference cookies_preference)
: certificate_reporting::ErrorReporter(request_context,
upload_url,
cookies_preference) {}
void CertificateReportingTest::MockReporter::SendExtendedReportingReport(
const std::string& serialized_report) {
certificate_reporting::ErrorReport report;
ASSERT_TRUE(report.InitializeFromString(serialized_report));
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 CertificateReportingTest::MockReporter(
nullptr, GURL("http://example.test"),
net::ReportSender::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, base::RetainedRef(safe_browsing_service),
base::Passed(std::unique_ptr<certificate_reporting::ErrorReporter>(
reporter_))));
}
const std::string& CertificateReportingTest::GetLatestHostnameReported() const {
return reporter_->latest_hostname_reported();
}
void SetCertReportingOptIn(Browser* browser, OptIn opt_in) {
browser->profile()->GetPrefs()->SetBoolean(
prefs::kSafeBrowsingExtendedReportingEnabled,
opt_in == EXTENDED_REPORTING_OPT_IN);
}
std::unique_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;
std::unique_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 std::move(ssl_cert_reporter);
}
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 certificate_reporting_test_utils::CERT_REPORT_EXPECTED;
}
return certificate_reporting_test_utils::CERT_REPORT_NOT_EXPECTED;
}
} // namespace certificate_reporting_test_utils