| Index: chrome/browser/safe_browsing/certificate_reporting_service_unittest.cc
|
| diff --git a/chrome/browser/safe_browsing/certificate_reporting_service_unittest.cc b/chrome/browser/safe_browsing/certificate_reporting_service_unittest.cc
|
| index 8ef06293dfdb0372268a7cf9763e1cc964ee36f4..e9a6e026e5c828e7e794e606a45c7465639e611d 100644
|
| --- a/chrome/browser/safe_browsing/certificate_reporting_service_unittest.cc
|
| +++ b/chrome/browser/safe_browsing/certificate_reporting_service_unittest.cc
|
| @@ -6,6 +6,7 @@
|
|
|
| #include <string>
|
|
|
| +#include "base/atomic_sequence_num.h"
|
| #include "base/bind.h"
|
| #include "base/bind_helpers.h"
|
| #include "base/run_loop.h"
|
| @@ -19,10 +20,14 @@
|
| #include "chrome/browser/safe_browsing/safe_browsing_service.h"
|
| #include "chrome/browser/safe_browsing/test_safe_browsing_service.h"
|
| #include "chrome/test/base/testing_profile.h"
|
| +#include "components/certificate_reporting/error_report.h"
|
| #include "content/public/browser/browser_thread.h"
|
| #include "content/public/test/test_browser_thread.h"
|
| #include "content/public/test/test_browser_thread_bundle.h"
|
| -#include "net/base/network_delegate_impl.h"
|
| +#include "crypto/rsa_private_key.h"
|
| +#include "net/cert/x509_certificate.h"
|
| +#include "net/cert/x509_util.h"
|
| +#include "net/ssl/ssl_info.h"
|
| #include "net/test/url_request/url_request_failed_job.h"
|
| #include "net/test/url_request/url_request_mock_data_job.h"
|
| #include "net/url_request/url_request_filter.h"
|
| @@ -30,6 +35,7 @@
|
| #include "testing/gtest/include/gtest/gtest.h"
|
|
|
| using certificate_reporting_test_utils::CertificateReportingServiceTestHelper;
|
| +using certificate_reporting_test_utils::CertificateReportingServiceObserver;
|
| using certificate_reporting_test_utils::ReportExpectation;
|
|
|
| namespace {
|
| @@ -40,32 +46,41 @@ const size_t kMaxReportCountInQueue = 3;
|
|
|
| const char* kFailedReportHistogram = "SSL.CertificateErrorReportFailure";
|
|
|
| -void ClearURLHandlers() {
|
| - net::URLRequestFilter::GetInstance()->ClearHandlers();
|
| +// NSS requires that serial numbers be unique even for the same issuer;
|
| +// as all fake certificates will contain the same issuer name, it's
|
| +// necessary to ensure the serial number is unique, as otherwise
|
| +// NSS will fail to parse.
|
| +base::StaticAtomicSequenceNumber g_serial_number;
|
| +
|
| +scoped_refptr<net::X509Certificate> CreateFakeCert() {
|
| + std::unique_ptr<crypto::RSAPrivateKey> unused_key;
|
| + std::string cert_der;
|
| + if (!net::x509_util::CreateKeyAndSelfSignedCert(
|
| + "CN=Error", static_cast<uint32_t>(g_serial_number.GetNext()),
|
| + base::Time::Now() - base::TimeDelta::FromMinutes(5),
|
| + base::Time::Now() + base::TimeDelta::FromMinutes(5), &unused_key,
|
| + &cert_der)) {
|
| + return nullptr;
|
| + }
|
| + return net::X509Certificate::CreateFromBytes(cert_der.data(),
|
| + cert_der.size());
|
| }
|
|
|
| -// A network delegate used to observe URL request destructions. The tests check
|
| -// that no outstanding URL request is present during tear down.
|
| -class TestNetworkDelegate : public net::NetworkDelegateImpl {
|
| - public:
|
| - TestNetworkDelegate(
|
| - const base::Callback<void()>& url_request_destroyed_callback)
|
| - : url_request_destroyed_callback_(url_request_destroyed_callback) {}
|
| +std::string MakeReport(const std::string& hostname) {
|
| + net::SSLInfo ssl_info;
|
| + ssl_info.cert = ssl_info.unverified_cert = CreateFakeCert();
|
|
|
| - ~TestNetworkDelegate() override {}
|
| -
|
| - // net::NetworkDelegate method:
|
| - void OnURLRequestDestroyed(net::URLRequest* request) override {
|
| - DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
| - content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
|
| - url_request_destroyed_callback_);
|
| - }
|
| + certificate_reporting::ErrorReport report(hostname, ssl_info);
|
| + std::string serialized_report;
|
| + EXPECT_TRUE(report.Serialize(&serialized_report));
|
| + return serialized_report;
|
| +}
|
|
|
| - private:
|
| - base::Callback<void()> url_request_destroyed_callback_;
|
| -};
|
| +void ClearURLHandlers() {
|
| + net::URLRequestFilter::GetInstance()->ClearHandlers();
|
| +}
|
|
|
| -// Base class for histogram testing. The failed report histogram is checked once
|
| +// Class for histogram testing. The failed report histogram is checked once
|
| // after teardown to ensure all in flight requests have completed.
|
| class ReportHistogramTestHelper {
|
| public:
|
| @@ -122,8 +137,7 @@ TEST(CertificateReportingServiceReportListTest, BoundedReportList) {
|
| // Adding a report older than the oldest report in the list (report2) is
|
| // a no-op.
|
| list.Add(CertificateReportingService::Report(
|
| - 0, base::Time::Now() - base::TimeDelta::FromMinutes(
|
| - 10) /* 5 minutes older than report2 */,
|
| + 0, base::Time::Now() - base::TimeDelta::FromMinutes(10),
|
| std::string("report0_ten_minutes_old")));
|
| EXPECT_EQ(2u, list.items().size());
|
| EXPECT_EQ("report3_zero_minutes_old", list.items()[0].serialized_report);
|
| @@ -325,6 +339,7 @@ class CertificateReportingServiceTest : public ::testing::Test {
|
| ~CertificateReportingServiceTest() override {}
|
|
|
| void SetUp() override {
|
| + service_observer_.Clear();
|
| test_helper_.SetUpInterceptor();
|
| WaitForIOThread();
|
|
|
| @@ -343,19 +358,15 @@ class CertificateReportingServiceTest : public ::testing::Test {
|
| sb_service_.get(), url_request_context_getter(), &profile_,
|
| test_helper_.server_public_key(),
|
| test_helper_.server_public_key_version(), kMaxReportCountInQueue,
|
| - base::TimeDelta::FromHours(24), clock_.get()));
|
| - // Wait for service reset.
|
| - WaitForIOThread();
|
| + base::TimeDelta::FromHours(24), clock_.get(),
|
| + base::Bind(&CertificateReportingServiceObserver::OnServiceReset,
|
| + base::Unretained(&service_observer_))));
|
| + service_observer_.WaitForReset();
|
| }
|
|
|
| void TearDown() override {
|
| WaitForIOThread();
|
| - EXPECT_TRUE(test_helper_.interceptor()->successful_reports().empty());
|
| - EXPECT_TRUE(test_helper_.interceptor()->failed_reports().empty());
|
| - EXPECT_TRUE(test_helper_.interceptor()->delayed_reports().empty());
|
| - EXPECT_EQ(0u, service()
|
| - ->GetReporterForTesting()
|
| - ->inflight_report_count_for_testing());
|
| + test_helper()->ExpectNoRequests(service());
|
|
|
| service_->Shutdown();
|
| WaitForIOThread();
|
| @@ -373,17 +384,6 @@ class CertificateReportingServiceTest : public ::testing::Test {
|
| }
|
|
|
| protected:
|
| - void WaitForRequestsDestroyed(const ReportExpectation& expectation) {
|
| - wait_helper_.Wait(expectation.num_reports());
|
| - EXPECT_EQ(expectation.successful_reports,
|
| - test_helper_.interceptor()->successful_reports());
|
| - EXPECT_EQ(expectation.failed_reports,
|
| - test_helper_.interceptor()->failed_reports());
|
| - EXPECT_EQ(expectation.delayed_reports,
|
| - test_helper_.interceptor()->delayed_reports());
|
| - test_helper_.interceptor()->ClearObservedReports();
|
| - }
|
| -
|
| net::URLRequestContextGetter* url_request_context_getter() {
|
| return url_request_context_getter_.get();
|
| }
|
| @@ -398,8 +398,9 @@ class CertificateReportingServiceTest : public ::testing::Test {
|
|
|
| // Sets service enabled state and waits for a reset event.
|
| void SetServiceEnabledAndWait(bool enabled) {
|
| + service_observer_.Clear();
|
| service()->SetEnabled(enabled);
|
| - WaitForIOThread();
|
| + service_observer_.WaitForReset();
|
| }
|
|
|
| void AdvanceClock(base::TimeDelta delta) {
|
| @@ -424,34 +425,19 @@ class CertificateReportingServiceTest : public ::testing::Test {
|
|
|
| private:
|
| void SetUpURLRequestContextOnIOThread() {
|
| - network_delegate_.reset(new TestNetworkDelegate(
|
| - base::Bind(&CertificateReportingServiceTest::OnURLRequestDestroyed,
|
| - base::Unretained(this))));
|
| -
|
| std::unique_ptr<net::TestURLRequestContext> url_request_context(
|
| - new net::TestURLRequestContext(true));
|
| - url_request_context->set_network_delegate(network_delegate_.get());
|
| - url_request_context->Init();
|
| + new net::TestURLRequestContext(false));
|
| url_request_context_getter_ = new net::TestURLRequestContextGetter(
|
| io_task_runner_, std::move(url_request_context));
|
| }
|
|
|
| void TearDownOnIOThread() {
|
| url_request_context_getter_ = nullptr;
|
| - network_delegate_.reset(nullptr);
|
| - }
|
| -
|
| - void OnURLRequestDestroyed() {
|
| - DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| - wait_helper_.OnEvent();
|
| }
|
|
|
| // Must be initialized before url_request_context_getter_
|
| content::TestBrowserThreadBundle thread_bundle_;
|
|
|
| - std::unique_ptr<TestNetworkDelegate> network_delegate_;
|
| - certificate_reporting_test_utils::ReportWaitHelper wait_helper_;
|
| -
|
| scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
|
| scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
|
|
|
| @@ -464,6 +450,7 @@ class CertificateReportingServiceTest : public ::testing::Test {
|
|
|
| CertificateReportingServiceTestHelper test_helper_;
|
| ReportHistogramTestHelper histogram_test_helper_;
|
| + CertificateReportingServiceObserver service_observer_;
|
| };
|
|
|
| TEST_F(CertificateReportingServiceTest, Send) {
|
| @@ -474,29 +461,29 @@ TEST_F(CertificateReportingServiceTest, Send) {
|
| certificate_reporting_test_utils::ReportSendingResult::REPORTS_FAIL);
|
|
|
| // Send two reports. Both should fail and get queued.
|
| - service()->Send("report0");
|
| - WaitForRequestsDestroyed(ReportExpectation::Failed({"report0"}));
|
| + service()->Send(MakeReport("report0"));
|
| + service()->Send(MakeReport("report1"));
|
| + test_helper()->WaitForRequestsDestroyed(
|
| + ReportExpectation::Failed({"report0", "report1"}));
|
|
|
| - service()->Send("report1");
|
| - WaitForRequestsDestroyed(ReportExpectation::Failed({"report1"}));
|
| -
|
| - // Send pending reports. Previously queued reports should be observed. They
|
| - // will also be queued again.
|
| + // Send pending reports. Previously queued reports should be queued again.
|
| service()->SendPending();
|
| - WaitForRequestsDestroyed(ReportExpectation::Failed({"report0", "report1"}));
|
| + test_helper()->WaitForRequestsDestroyed(
|
| + ReportExpectation::Failed({"report0", "report1"}));
|
|
|
| // Let all reports succeed.
|
| test_helper()->SetFailureMode(certificate_reporting_test_utils::
|
| ReportSendingResult::REPORTS_SUCCESSFUL);
|
|
|
| // Send a third report. This should not be queued.
|
| - service()->Send("report2");
|
| - WaitForRequestsDestroyed(ReportExpectation::Successful({"report2"}));
|
| + service()->Send(MakeReport("report2"));
|
| + test_helper()->WaitForRequestsDestroyed(
|
| + ReportExpectation::Successful({"report2"}));
|
|
|
| // Send pending reports. Previously failed and queued two reports should be
|
| // observed.
|
| service()->SendPending();
|
| - WaitForRequestsDestroyed(
|
| + test_helper()->WaitForRequestsDestroyed(
|
| ReportExpectation::Successful({"report0", "report1"}));
|
| }
|
|
|
| @@ -512,13 +499,14 @@ TEST_F(CertificateReportingServiceTest, Disabled_ShouldNotSend) {
|
|
|
| // Send a report. Report attempt should be cancelled and no sent reports
|
| // should be observed.
|
| - service()->Send("report0");
|
| + service()->Send(MakeReport("report0"));
|
|
|
| // Enable the service and send a report again. It should be sent successfully.
|
| SetServiceEnabledAndWait(true);
|
|
|
| - service()->Send("report1");
|
| - WaitForRequestsDestroyed(ReportExpectation::Successful({"report1"}));
|
| + service()->Send(MakeReport("report1"));
|
| + test_helper()->WaitForRequestsDestroyed(
|
| + ReportExpectation::Successful({"report1"}));
|
| }
|
|
|
| TEST_F(CertificateReportingServiceTest, Disabled_ShouldClearPendingReports) {
|
| @@ -528,8 +516,9 @@ TEST_F(CertificateReportingServiceTest, Disabled_ShouldClearPendingReports) {
|
| test_helper()->SetFailureMode(
|
| certificate_reporting_test_utils::ReportSendingResult::REPORTS_FAIL);
|
|
|
| - service()->Send("report0");
|
| - WaitForRequestsDestroyed(ReportExpectation::Failed({"report0"}));
|
| + service()->Send(MakeReport("report0"));
|
| + test_helper()->WaitForRequestsDestroyed(
|
| + ReportExpectation::Failed({"report0"}));
|
|
|
| // Disable the service.
|
| SetServiceEnabledAndWait(false);
|
| @@ -553,15 +542,12 @@ TEST_F(CertificateReportingServiceTest, DontSendOldReports) {
|
| test_helper()->SetFailureMode(
|
| certificate_reporting_test_utils::ReportSendingResult::REPORTS_FAIL);
|
|
|
| - // Send a report.
|
| - service()->Send("report0");
|
| - WaitForRequestsDestroyed(ReportExpectation::Failed({"report0"}));
|
| -
|
| - // Advance the clock a bit and trigger another report.
|
| + // Send a report, then advance the clock and send another report.
|
| + service()->Send(MakeReport("report0"));
|
| AdvanceClock(base::TimeDelta::FromHours(5));
|
| -
|
| - service()->Send("report1");
|
| - WaitForRequestsDestroyed(ReportExpectation::Failed({"report1"}));
|
| + service()->Send(MakeReport("report1"));
|
| + test_helper()->WaitForRequestsDestroyed(
|
| + ReportExpectation::Failed({"report0", "report1"}));
|
|
|
| // Advance the clock to 20 hours, putting it 25 hours ahead of the reference
|
| // time. This makes the report0 older than max age (24 hours). The report1 is
|
| @@ -570,18 +556,21 @@ TEST_F(CertificateReportingServiceTest, DontSendOldReports) {
|
| // Send pending reports. report0 should be discarded since it's too old.
|
| // report1 should be queued again.
|
| service()->SendPending();
|
| - WaitForRequestsDestroyed(ReportExpectation::Failed({"report1"}));
|
| + test_helper()->WaitForRequestsDestroyed(
|
| + ReportExpectation::Failed({"report1"}));
|
|
|
| // Send a third report.
|
| - service()->Send("report2");
|
| - WaitForRequestsDestroyed(ReportExpectation::Failed({"report2"}));
|
| + service()->Send(MakeReport("report2"));
|
| + test_helper()->WaitForRequestsDestroyed(
|
| + ReportExpectation::Failed({"report2"}));
|
|
|
| // Advance the clock 5 hours. The report1 will now be 25 hours old.
|
| AdvanceClock(base::TimeDelta::FromHours(5));
|
| // Send pending reports. report1 should be discarded since it's too old.
|
| // report2 should be queued again.
|
| service()->SendPending();
|
| - WaitForRequestsDestroyed(ReportExpectation::Failed({"report2"}));
|
| + test_helper()->WaitForRequestsDestroyed(
|
| + ReportExpectation::Failed({"report2"}));
|
|
|
| // Advance the clock 20 hours again so that report2 is 25 hours old and is
|
| // older than max age (24 hours)
|
| @@ -599,31 +588,29 @@ TEST_F(CertificateReportingServiceTest, DiscardOldReports) {
|
| test_helper()->SetFailureMode(
|
| certificate_reporting_test_utils::ReportSendingResult::REPORTS_FAIL);
|
|
|
| - // Send a failed report.
|
| - service()->Send("report0");
|
| - WaitForRequestsDestroyed(ReportExpectation::Failed({"report0"}));
|
| -
|
| // Send three more reports within five hours of each other. After this:
|
| // report0 is 0 hours after reference time (15 hours old).
|
| // report1 is 5 hours after reference time (10 hours old).
|
| // report2 is 10 hours after reference time (5 hours old).
|
| // report3 is 15 hours after reference time (0 hours old).
|
| + service()->Send(MakeReport("report0"));
|
| +
|
| AdvanceClock(base::TimeDelta::FromHours(5));
|
| - service()->Send("report1");
|
| + service()->Send(MakeReport("report1"));
|
|
|
| AdvanceClock(base::TimeDelta::FromHours(5));
|
| - service()->Send("report2");
|
| + service()->Send(MakeReport("report2"));
|
|
|
| AdvanceClock(base::TimeDelta::FromHours(5));
|
| - service()->Send("report3");
|
| - WaitForRequestsDestroyed(
|
| - ReportExpectation::Failed({"report1", "report2", "report3"}));
|
| + service()->Send(MakeReport("report3"));
|
| + test_helper()->WaitForRequestsDestroyed(
|
| + ReportExpectation::Failed({"report0", "report1", "report2", "report3"}));
|
|
|
| // Send pending reports. Four reports were generated above, but the service
|
| // only queues three reports, so the very first one should be dropped since
|
| // it's the oldest.
|
| service()->SendPending();
|
| - WaitForRequestsDestroyed(
|
| + test_helper()->WaitForRequestsDestroyed(
|
| ReportExpectation::Failed({"report1", "report2", "report3"}));
|
|
|
| // Let all reports succeed.
|
| @@ -639,7 +626,7 @@ TEST_F(CertificateReportingServiceTest, DiscardOldReports) {
|
| // Send pending reports. Only report2 and report3 should be sent, report1
|
| // should be ignored because it's too old.
|
| service()->SendPending();
|
| - WaitForRequestsDestroyed(
|
| + test_helper()->WaitForRequestsDestroyed(
|
| ReportExpectation::Successful({"report2", "report3"}));
|
|
|
| // Do a final send. No reports should be sent.
|
| @@ -655,12 +642,13 @@ TEST_F(CertificateReportingServiceTest, Delayed_Resumed) {
|
| certificate_reporting_test_utils::ReportSendingResult::REPORTS_DELAY);
|
| // Send a report. The report upload hangs, so no error or success callbacks
|
| // should be called.
|
| - service()->Send("report0");
|
| + service()->Send(MakeReport("report0"));
|
|
|
| // Resume the report upload and run the callbacks. The report should be
|
| // successfully sent.
|
| - test_helper()->ResumeDelayedRequest(base::Bind(&base::DoNothing));
|
| - WaitForRequestsDestroyed(ReportExpectation::Delayed({"report0"}));
|
| + test_helper()->ResumeDelayedRequest();
|
| + test_helper()->WaitForRequestsDestroyed(
|
| + ReportExpectation::Delayed({"report0"}));
|
| }
|
|
|
| // Delayed reports should cleaned when the service is reset.
|
| @@ -672,7 +660,7 @@ TEST_F(CertificateReportingServiceTest, Delayed_Reset) {
|
| certificate_reporting_test_utils::ReportSendingResult::REPORTS_DELAY);
|
| // Send a report. The report is triggered but hangs, so no error or success
|
| // callbacks should be called.
|
| - service()->Send("report0");
|
| + service()->Send(MakeReport("report0"));
|
|
|
| // Disable the service. This should reset the reporting service and
|
| // clear all pending reports.
|
| @@ -680,8 +668,8 @@ TEST_F(CertificateReportingServiceTest, Delayed_Reset) {
|
|
|
| // Resume delayed report. No report should be observed since the service
|
| // should have reset and all pending reports should be cleared. If any report
|
| - // is observed, the next WaitForRequestsDestroyed() will fail.
|
| - test_helper()->ResumeDelayedRequest(base::Bind(&base::DoNothing));
|
| + // is observed, the next test_helper()->WaitForRequestsDestroyed() will fail.
|
| + test_helper()->ResumeDelayedRequest();
|
|
|
| // Enable the service.
|
| SetServiceEnabledAndWait(true);
|
| @@ -689,9 +677,10 @@ TEST_F(CertificateReportingServiceTest, Delayed_Reset) {
|
| // Send a report. The report is triggered but hangs, so no error or success
|
| // callbacks should be called. The report id is again 0 since the pending
|
| // report queue has been cleared above.
|
| - service()->Send("report1");
|
| + service()->Send(MakeReport("report1"));
|
|
|
| // Resume delayed report. Two reports are successfully sent.
|
| - test_helper()->ResumeDelayedRequest(base::Bind(&base::DoNothing));
|
| - WaitForRequestsDestroyed(ReportExpectation::Delayed({"report0", "report1"}));
|
| + test_helper()->ResumeDelayedRequest();
|
| + test_helper()->WaitForRequestsDestroyed(
|
| + ReportExpectation::Delayed({"report0", "report1"}));
|
| }
|
|
|