Commit 109b7fed authored by John Abd-El-Malek's avatar John Abd-El-Malek Committed by Commit Bot

Convert certificate reporting service to use SimpleURLLoader.

With this change, CertificateReportingService now only lives on the UI thread.

Bug: 825242
TBR=rhalavati for test annotation removal

Cq-Include-Trybots: master.tryserver.chromium.linux:linux_mojo
Change-Id: I3945ab88a8d2f0507b4a2572df6c79edd7aab036
Reviewed-on: https://chromium-review.googlesource.com/996021
Commit-Queue: John Abd-El-Malek <jam@chromium.org>
Reviewed-by: default avatarJohn Abd-El-Malek <jam@chromium.org>
Reviewed-by: default avatarMustafa Emre Acer <meacer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#548473}
parent 39a0031c
......@@ -17,7 +17,7 @@ namespace net {
class CertVerifyProc;
}
class NET_EXPORT TrialComparisonCertVerifier : public net::CertVerifier {
class TrialComparisonCertVerifier : public net::CertVerifier {
public:
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
......
......@@ -181,22 +181,17 @@ class TrialComparisonCertVerifierTest : public testing::Test {
net::X509Certificate::FORMAT_AUTO);
ASSERT_TRUE(cert_chain_2_);
reporting_service_test_helper_.SetUpInterceptor();
reporting_service_test_helper_ =
base::MakeRefCounted<CertificateReportingServiceTestHelper>();
CertificateReportingServiceFactory::GetInstance()
->SetReportEncryptionParamsForTesting(
reporting_service_test_helper()->server_public_key(),
reporting_service_test_helper()->server_public_key_version());
CertificateReportingServiceFactory::GetInstance()
->SetURLLoaderFactoryForTesting(reporting_service_test_helper_);
reporting_service_test_helper()->SetFailureMode(
certificate_reporting_test_utils::REPORTS_SUCCESSFUL);
url_request_context_getter_ =
base::MakeRefCounted<net::TestURLRequestContextGetter>(
(content::BrowserThread::GetTaskRunnerForThread(
content::BrowserThread::IO)));
TestingBrowserProcess::GetGlobal()->SetSystemRequestContext(
url_request_context_getter_.get());
sb_service_ = base::MakeRefCounted<safe_browsing::TestSafeBrowsingService>(
// Doesn't matter, just need to choose one.
safe_browsing::V4FeatureList::V4UsageStatus::V4_DISABLED);
......@@ -236,7 +231,7 @@ class TrialComparisonCertVerifierTest : public testing::Test {
}
CertificateReportingServiceTestHelper* reporting_service_test_helper() {
return &reporting_service_test_helper_;
return reporting_service_test_helper_.get();
}
CertificateReportingService* service() const {
......@@ -252,12 +247,12 @@ class TrialComparisonCertVerifierTest : public testing::Test {
private:
content::TestBrowserThreadBundle thread_bundle_;
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
scoped_refptr<safe_browsing::SafeBrowsingService> sb_service_;
std::unique_ptr<TestingProfileManager> profile_manager_;
TestingProfile* profile_;
CertificateReportingServiceTestHelper reporting_service_test_helper_;
scoped_refptr<CertificateReportingServiceTestHelper>
reporting_service_test_helper_;
};
TEST_F(TrialComparisonCertVerifierTest, NotOptedIn) {
......
......@@ -14,7 +14,7 @@
#include "components/prefs/pref_service.h"
#include "components/safe_browsing/common/safe_browsing_prefs.h"
#include "content/public/browser/browser_thread.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace {
......@@ -44,11 +44,6 @@ void RecordUMAEvent(CertificateReportingService::ReportOutcome outcome) {
CertificateReportingService::ReportOutcome::EVENT_COUNT);
}
void CleanupOnIOThread(
std::unique_ptr<CertificateReportingService::Reporter> reporter) {
reporter.reset();
}
} // namespace
const char CertificateReportingService::kReportEventHistogram[] =
......@@ -110,12 +105,10 @@ CertificateReportingService::Reporter::~Reporter() {}
void CertificateReportingService::Reporter::Send(
const std::string& serialized_report) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
SendInternal(Report(current_report_id_++, clock_->Now(), serialized_report));
}
void CertificateReportingService::Reporter::SendPending() {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
if (!retries_enabled_) {
return;
}
......@@ -153,25 +146,27 @@ CertificateReportingService::Reporter::GetQueueForTesting() const {
return retry_list_.get();
}
void CertificateReportingService::Reporter::
SetClosureWhenNoInflightReportsForTesting(const base::Closure& closure) {
no_in_flight_reports_ = closure;
}
void CertificateReportingService::Reporter::SendInternal(
const CertificateReportingService::Report& report) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
inflight_reports_.insert(std::make_pair(report.report_id, report));
RecordUMAEvent(ReportOutcome::SUBMITTED);
error_reporter_->SendExtendedReportingReport(
report.serialized_report,
base::Bind(&CertificateReportingService::Reporter::SuccessCallback,
base::BindOnce(&CertificateReportingService::Reporter::SuccessCallback,
weak_factory_.GetWeakPtr(), report.report_id),
base::Bind(&CertificateReportingService::Reporter::ErrorCallback,
base::BindOnce(&CertificateReportingService::Reporter::ErrorCallback,
weak_factory_.GetWeakPtr(), report.report_id));
}
void CertificateReportingService::Reporter::ErrorCallback(
int report_id,
const GURL& url,
int net_error,
int http_response_code) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
RecordUMAOnFailure(net_error);
RecordUMAEvent(ReportOutcome::FAILED);
if (retries_enabled_) {
......@@ -180,17 +175,20 @@ void CertificateReportingService::Reporter::ErrorCallback(
retry_list_->Add(it->second);
}
CHECK_GT(inflight_reports_.erase(report_id), 0u);
if (inflight_reports_.empty() && no_in_flight_reports_)
no_in_flight_reports_.Run();
}
void CertificateReportingService::Reporter::SuccessCallback(int report_id) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
RecordUMAEvent(ReportOutcome::SUCCESSFUL);
CHECK_GT(inflight_reports_.erase(report_id), 0u);
if (inflight_reports_.empty() && no_in_flight_reports_)
no_in_flight_reports_.Run();
}
CertificateReportingService::CertificateReportingService(
safe_browsing::SafeBrowsingService* safe_browsing_service,
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
Profile* profile,
uint8_t server_public_key[/* 32 */],
uint32_t server_public_key_version,
......@@ -199,7 +197,7 @@ CertificateReportingService::CertificateReportingService(
base::Clock* clock,
const base::Callback<void()>& reset_callback)
: pref_service_(*profile->GetPrefs()),
url_request_context_(nullptr),
url_loader_factory_(url_loader_factory),
max_queued_report_count_(max_queued_report_count),
max_report_age_(max_report_age),
clock_(clock),
......@@ -208,10 +206,6 @@ CertificateReportingService::CertificateReportingService(
server_public_key_version_(server_public_key_version) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK(clock_);
// Subscribe to SafeBrowsing shutdown notifications.
safe_browsing_service_shutdown_subscription_ =
safe_browsing_service->RegisterShutdownCallback(base::Bind(
&CertificateReportingService::Shutdown, base::Unretained(this)));
// Subscribe to SafeBrowsing preference change notifications.
safe_browsing_state_subscription_ =
......@@ -219,13 +213,8 @@ CertificateReportingService::CertificateReportingService(
base::Bind(&CertificateReportingService::OnPreferenceChanged,
base::Unretained(this)));
content::BrowserThread::PostTaskAndReply(
content::BrowserThread::IO, FROM_HERE,
base::BindOnce(&CertificateReportingService::InitializeOnIOThread,
base::Unretained(this), true, url_request_context_getter,
max_queued_report_count_, max_report_age_, clock_,
server_public_key_, server_public_key_version_),
reset_callback_);
Reset(true);
reset_callback_.Run();
}
CertificateReportingService::~CertificateReportingService() {
......@@ -233,65 +222,25 @@ CertificateReportingService::~CertificateReportingService() {
}
void CertificateReportingService::Shutdown() {
// Shutdown will be called twice: Once after SafeBrowsing shuts down, and once
// when all KeyedServices shut down. All calls after the first one are no-op.
url_request_context_ = nullptr;
content::BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
base::BindOnce(&CleanupOnIOThread, std::move(reporter_)));
reporter_.reset();
}
void CertificateReportingService::Send(const std::string& serialized_report) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (!reporter_) {
return;
}
content::BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
base::BindOnce(&CertificateReportingService::Reporter::Send,
base::Unretained(reporter_.get()), serialized_report));
if (reporter_)
reporter_->Send(serialized_report);
}
void CertificateReportingService::SendPending() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (!reporter_) {
return;
}
content::BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
base::BindOnce(&CertificateReportingService::Reporter::SendPending,
base::Unretained(reporter_.get())));
}
void CertificateReportingService::InitializeOnIOThread(
bool enabled,
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
size_t max_queued_report_count,
base::TimeDelta max_report_age,
base::Clock* clock,
uint8_t* server_public_key,
uint32_t server_public_key_version) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
DCHECK(!url_request_context_);
url_request_context_ = url_request_context_getter->GetURLRequestContext();
ResetOnIOThread(enabled, url_request_context_, max_queued_report_count,
max_report_age, clock, server_public_key,
server_public_key_version);
if (reporter_)
reporter_->SendPending();
}
void CertificateReportingService::SetEnabled(bool enabled) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// Don't reset if the service is already shut down.
if (!url_request_context_)
return;
content::BrowserThread::PostTaskAndReply(
content::BrowserThread::IO, FROM_HERE,
base::BindOnce(&CertificateReportingService::ResetOnIOThread,
base::Unretained(this), enabled, url_request_context_,
max_queued_report_count_, max_report_age_, clock_,
server_public_key_, server_public_key_version_),
reset_callback_);
Reset(enabled);
reset_callback_.Run();
}
CertificateReportingService::Reporter*
......@@ -304,57 +253,26 @@ GURL CertificateReportingService::GetReportingURLForTesting() {
return GURL(kExtendedReportingUploadUrl);
}
void CertificateReportingService::ResetOnIOThread(
bool enabled,
net::URLRequestContext* url_request_context,
size_t max_queued_report_count,
base::TimeDelta max_report_age,
base::Clock* clock,
uint8_t* const server_public_key,
uint32_t server_public_key_version) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
// url_request_context_ is null during shutdown.
if (!enabled || !url_request_context) {
void CertificateReportingService::Reset(bool enabled) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (!enabled) {
reporter_.reset();
return;
}
std::unique_ptr<CertificateErrorReporter> error_reporter;
if (server_public_key) {
// Only used in tests.
net::NetworkTrafficAnnotationTag traffic_annotation =
net::DefineNetworkTrafficAnnotation(
"certificate_reporting_service_test", R"(
semantics {
sender: "Certificate Reporting Service Test"
description:
"This request is used for testing certificate reporting service."
trigger: "Upon request from testing API."
data:
"No user data."
destination: GOOGLE_OWNED_SERVICE
}
policy {
cookies_allowed: NO
setting:
"This feature is only used for testing."
policy_exception_justification:
"This feature is only used for testing."
}
)");
std::unique_ptr<net::ReportSender> report_sender(
new net::ReportSender(url_request_context, traffic_annotation));
if (server_public_key_) {
error_reporter.reset(new CertificateErrorReporter(
GURL(kExtendedReportingUploadUrl), server_public_key,
server_public_key_version, std::move(report_sender)));
url_loader_factory_, GURL(kExtendedReportingUploadUrl),
server_public_key_, server_public_key_version_));
} else {
error_reporter.reset(new CertificateErrorReporter(
url_request_context, GURL(kExtendedReportingUploadUrl)));
url_loader_factory_, GURL(kExtendedReportingUploadUrl)));
}
reporter_.reset(
new Reporter(std::move(error_reporter),
std::unique_ptr<BoundedReportList>(
new BoundedReportList(max_queued_report_count)),
clock, max_report_age, true /* retries_enabled */));
new BoundedReportList(max_queued_report_count_)),
clock_, max_report_age_, true /* retries_enabled */));
}
void CertificateReportingService::OnPreferenceChanged() {
......
......@@ -17,7 +17,7 @@
#include "base/time/time.h"
#include "chrome/browser/ssl/certificate_error_reporter.h"
#include "components/keyed_service/core/keyed_service.h"
#include "net/url_request/url_request_context_getter.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
class PrefService;
class Profile;
......@@ -26,8 +26,8 @@ namespace base {
class Clock;
}
namespace net {
class URLRequestContextGetter;
namespace network {
class SharedURLLoaderFactory;
}
namespace safe_browsing {
......@@ -41,16 +41,11 @@ class SafeBrowsingService;
//
// Lifetime and dependencies:
//
// CertificateReportingService uses the url request context from SafeBrowsing
// CertificateReportingService uses the URLLoaderFactory from SafeBrowsing
// service. SafeBrowsingService is created before CertificateReportingService,
// but is also shut down before any KeyedService is shut down. This means that
// CertificateReportingService cannot depend on SafeBrowsing's url request being
// available at all times, and it should know when SafeBrowsing shuts down. It
// does this by subscribing to SafeBrowsingService shut downs when it's
// created. When SafeBrowsingService shuts down, CertificateReportingService
// also shuts down.
// but is also shut down before any KeyedService is shut down.
//
// This class also observes SafeBrowsing preference changes to enable/disable
// This class observes SafeBrowsing preference changes to enable/disable
// reporting. It does this by subscribing to changes in SafeBrowsing and
// extended reporting preferences.
class CertificateReportingService : public KeyedService {
......@@ -142,6 +137,9 @@ class CertificateReportingService : public KeyedService {
// Getter and setters for testing:
size_t inflight_report_count_for_testing() const;
BoundedReportList* GetQueueForTesting() const;
// Sets a closure that is called when there are no more inflight reports.
void SetClosureWhenNoInflightReportsForTesting(
const base::Closure& closure);
private:
void SendInternal(const Report& report);
......@@ -149,7 +147,6 @@ class CertificateReportingService : public KeyedService {
// non-HTTP 200 response code. See
// TransportSecurityState::ReportSenderInterface for parameters.
void ErrorCallback(int report_id,
const GURL& url,
int net_error,
int http_response_code);
// Called when a report upload is successful.
......@@ -167,6 +164,8 @@ class CertificateReportingService : public KeyedService {
std::map<int, Report> inflight_reports_;
base::Closure no_in_flight_reports_;
base::WeakPtrFactory<Reporter> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(Reporter);
......@@ -177,7 +176,7 @@ class CertificateReportingService : public KeyedService {
CertificateReportingService(
safe_browsing::SafeBrowsingService* safe_browsing_service,
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
Profile* profile,
uint8_t server_public_key[/* 32 */],
uint32_t server_public_key_version,
......@@ -208,40 +207,18 @@ class CertificateReportingService : public KeyedService {
static GURL GetReportingURLForTesting();
private:
void InitializeOnIOThread(
bool enabled,
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
size_t max_queued_report_count,
base::TimeDelta max_report_age,
base::Clock* const clock,
uint8_t* server_public_key,
uint32_t server_public_key_version);
// Resets the reporter on the IO thread. Changes in SafeBrowsing or extended
// reporting enabled states cause the reporter to be reset.
// If |enabled| is false or |url_request_context_getter| is null, report is
// set to null, effectively cancelling all in flight uploads and clearing the
// Resets the reporter. Changes in SafeBrowsing or extended reporting enabled
// states cause the reporter to be reset. If |enabled| is false, report is set
// to null, effectively cancelling all in flight uploads and clearing the
// pending reports queue.
void ResetOnIOThread(bool enabled,
net::URLRequestContext* url_request_context,
size_t max_queued_report_count,
base::TimeDelta max_report_age,
base::Clock* const clock,
uint8_t* server_public_key,
uint32_t server_public_key_version);
void Reset(bool enabled);
void OnPreferenceChanged();
const PrefService& pref_service_;
net::URLRequestContext* url_request_context_;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
std::unique_ptr<Reporter> reporter_;
// Subscription for url request context shutdowns. When this subscription is
// notified, it means SafeBrowsingService is shutting down, and this service
// must also shut down.
std::unique_ptr<base::CallbackList<void(void)>::Subscription>
safe_browsing_service_shutdown_subscription_;
// Subscription for state changes. When this subscription is notified, it
// means SafeBrowsingService is enabled/disabled or one of the preferences
// related to it is changed.
......
......@@ -82,7 +82,8 @@ class CertificateReportingServiceBrowserTest
https_server_.ServeFilesFromSourceDirectory("chrome/test/data");
ASSERT_TRUE(https_server_.Start());
test_helper()->SetUpInterceptor();
test_helper_ =
base::MakeRefCounted<CertificateReportingServiceTestHelper>();
CertificateReportingServiceFactory::GetInstance()
->SetReportEncryptionParamsForTesting(
......@@ -92,6 +93,8 @@ class CertificateReportingServiceBrowserTest
->SetServiceResetCallbackForTesting(
base::Bind(&CertificateReportingServiceObserver::OnServiceReset,
base::Unretained(&service_observer_)));
CertificateReportingServiceFactory::GetInstance()
->SetURLLoaderFactoryForTesting(test_helper_);
event_histogram_tester_.reset(new EventHistogramTester());
InProcessBrowserTest::SetUpOnMainThread();
......@@ -126,7 +129,23 @@ class CertificateReportingServiceBrowserTest
}
}
CertificateReportingServiceTestHelper* test_helper() { return &test_helper_; }
CertificateReportingServiceTestHelper* test_helper() {
return test_helper_.get();
}
void WaitForNoReports() {
if (!service()->GetReporterForTesting() ||
!service()
->GetReporterForTesting()
->inflight_report_count_for_testing())
return;
base::RunLoop run_loop;
service()
->GetReporterForTesting()
->SetClosureWhenNoInflightReportsForTesting(run_loop.QuitClosure());
run_loop.Run();
}
protected:
CertificateReportingServiceFactory* factory() {
......@@ -157,7 +176,10 @@ class CertificateReportingServiceBrowserTest
content::WaitForInterstitialDetach(contents);
}
void SendPendingReports() { service()->SendPending(); }
void SendPendingReports() {
WaitForNoReports();
service()->SendPending();
}
// Changes opt-in status and waits for the cert reporting service to reset.
// Can only be used after the service is initialized. When changing the
......@@ -216,7 +238,7 @@ class CertificateReportingServiceBrowserTest
int num_expected_failed_report_ = -1;
CertificateReportingServiceTestHelper test_helper_;
scoped_refptr<CertificateReportingServiceTestHelper> test_helper_;
CertificateReportingServiceObserver service_observer_;
......@@ -434,6 +456,8 @@ IN_PROC_BROWSER_TEST_P(CertificateReportingServiceBrowserTest,
test_helper()->WaitForRequestsDestroyed(
ReportExpectation::Successful({{"report1", RetryStatus::RETRIED}}));
WaitForNoReports();
// report0 was submitted once, failed once, then cleared.
// report1 was submitted twice, failed once, succeeded once.
event_histogram_tester()->SetExpectedValues(
......@@ -512,6 +536,8 @@ IN_PROC_BROWSER_TEST_P(CertificateReportingServiceBrowserTest,
test_helper()->WaitForRequestsDestroyed(
ReportExpectation::Successful({{"report3", RetryStatus::NOT_RETRIED}}));
WaitForNoReports();
// report0 was submitted once, failed once, dropped once.
// report1 was submitted twice, failed twice, dropped once.
// report2 was submitted twice, failed twice, dropped once.
......@@ -593,6 +619,8 @@ IN_PROC_BROWSER_TEST_P(CertificateReportingServiceBrowserTest,
test_helper()->WaitForRequestsDestroyed(ReportExpectation::Successful(
{{"report2", RetryStatus::RETRIED}, {"report3", RetryStatus::RETRIED}}));
WaitForNoReports();
// report0 was submitted once, failed once, dropped once.
// report1 was submitted twice, failed twice, dropped once.
// report2 was submitted thrice, failed twice, succeeded once.
......@@ -623,6 +651,8 @@ IN_PROC_BROWSER_TEST_P(CertificateReportingServiceBrowserTest,
test_helper()->WaitForRequestsDestroyed(
ReportExpectation::Delayed({{"report0", RetryStatus::NOT_RETRIED}}));
WaitForNoReports();
// report0 was submitted once and succeeded once.
event_histogram_tester()->SetExpectedValues(
1 /* submitted */, 0 /* failed */, 1 /* successful */, 0 /* dropped */);
......@@ -674,6 +704,11 @@ IN_PROC_BROWSER_TEST_P(CertificateReportingServiceBrowserTest, Delayed_Reset) {
// Disable SafeBrowsing. This should clear all pending reports.
ToggleSafeBrowsingAndWaitForServiceReset(false);
// In production, the request would have already went out to the network. For
// this test, we manually resume it which will cause it to be cancelled.
test_helper()->ResumeDelayedRequest();
test_helper()->WaitForRequestsDestroyed(
ReportExpectation::Delayed({{"report0", RetryStatus::NOT_RETRIED}}));
......@@ -695,6 +730,8 @@ IN_PROC_BROWSER_TEST_P(CertificateReportingServiceBrowserTest, Delayed_Reset) {
test_helper()->WaitForRequestsDestroyed(
ReportExpectation::Delayed({{"report1", RetryStatus::NOT_RETRIED}}));
WaitForNoReports();
// report0 was submitted once and delayed, then cleared.
// report1 was submitted once and delayed, then succeeded.
event_histogram_tester()->SetExpectedValues(
......
......@@ -2,13 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/safe_browsing/certificate_reporting_service_factory.h"
#include "base/time/default_clock.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/safe_browsing/certificate_reporting_service.h"
#include "chrome/browser/safe_browsing/certificate_reporting_service_factory.h"
#include "chrome/browser/safe_browsing/safe_browsing_service.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace {
......@@ -65,6 +67,11 @@ void CertificateReportingServiceFactory::SetServiceResetCallbackForTesting(
service_reset_callback_ = service_reset_callback;
}
void CertificateReportingServiceFactory::SetURLLoaderFactoryForTesting(
scoped_refptr<network::SharedURLLoaderFactory> factory) {
url_loader_factory_ = factory;
}
CertificateReportingServiceFactory::CertificateReportingServiceFactory()
: BrowserContextKeyedServiceFactory(
"cert_reporting::Factory",
......@@ -83,7 +90,9 @@ KeyedService* CertificateReportingServiceFactory::BuildServiceInstanceFor(
safe_browsing::SafeBrowsingService* safe_browsing_service =
g_browser_process->safe_browsing_service();
return new CertificateReportingService(
safe_browsing_service, safe_browsing_service->url_request_context(),
safe_browsing_service,
url_loader_factory_.get() ? url_loader_factory_
: safe_browsing_service->GetURLLoaderFactory(),
static_cast<Profile*>(profile), server_public_key_,
server_public_key_version_, max_queued_report_count_, queued_report_ttl_,
clock_, service_reset_callback_);
......
......@@ -7,6 +7,7 @@
#include "base/memory/singleton.h"
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace base {
class Clock;
......@@ -36,6 +37,8 @@ class CertificateReportingServiceFactory
void SetMaxQueuedReportCountForTesting(size_t max_report_count);
void SetServiceResetCallbackForTesting(
const base::Callback<void()>& service_reset_callback);
void SetURLLoaderFactoryForTesting(
scoped_refptr<network::SharedURLLoaderFactory> factory);
private:
friend struct base::DefaultSingletonTraits<
......@@ -58,6 +61,7 @@ class CertificateReportingServiceFactory
base::TimeDelta queued_report_ttl_;
size_t max_queued_report_count_;
base::Callback<void()> service_reset_callback_;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
DISALLOW_COPY_AND_ASSIGN(CertificateReportingServiceFactory);
};
......
......@@ -23,26 +23,16 @@ namespace {
static const char kHkdfLabel[] = "certificate report";
const uint32_t kServerPublicKeyTestVersion = 16;
void SetUpURLHandlersOnIOThread(
std::unique_ptr<net::URLRequestInterceptor> url_request_interceptor) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance();
filter->AddUrlInterceptor(
CertificateReportingService::GetReportingURLForTesting(),
std::move(url_request_interceptor));
}
std::string GetUploadData(net::URLRequest* request) {
const net::UploadDataStream* stream = request->get_upload();
EXPECT_TRUE(stream);
EXPECT_TRUE(stream->GetElementReaders());
EXPECT_EQ(1u, stream->GetElementReaders()->size());
const net::UploadBytesElementReader* reader =
(*stream->GetElementReaders())[0]->AsBytesReader();
return std::string(reader->bytes(), reader->length());
std::string GetUploadData(const network::ResourceRequest& request) {
auto body = request.request_body;
CHECK(body.get());
CHECK_EQ(1u, body->elements()->size());
const auto& element = body->elements()->at(0);
CHECK_EQ(network::DataElement::TYPE_BYTES, element.type());
return std::string(element.bytes(), element.length());
}
std::string GetReportContents(net::URLRequest* request,
std::string GetReportContents(const network::ResourceRequest& request,
const uint8_t* server_private_key) {
std::string serialized_report(GetUploadData(request));
encrypted_messages::EncryptedMessage encrypted_message;
......@@ -235,108 +225,6 @@ void DelayableCertReportURLRequestJob::Resume() {
weak_factory_.GetWeakPtr()));
}
CertReportJobInterceptor::CertReportJobInterceptor(
ReportSendingResult expected_report_result,
const uint8_t* server_private_key)
: expected_report_result_(expected_report_result),
server_private_key_(server_private_key) {}
CertReportJobInterceptor::~CertReportJobInterceptor() {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
}
net::URLRequestJob* CertReportJobInterceptor::MaybeInterceptRequest(
net::URLRequest* request,
net::NetworkDelegate* network_delegate) const {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
const std::string serialized_report =
GetReportContents(request, server_private_key_);
RequestCreated(serialized_report, expected_report_result_);
if (expected_report_result_ == REPORTS_FAIL) {
return new DelayableCertReportURLRequestJob(
false, true, request, network_delegate,
base::Bind(&CertReportJobInterceptor::RequestDestructed,
base::Unretained(this), serialized_report,
expected_report_result_));
} else if (expected_report_result_ == REPORTS_DELAY) {
DCHECK(!delayed_request_) << "Supports only one delayed request at a time";
DelayableCertReportURLRequestJob* job =
new DelayableCertReportURLRequestJob(
true, false, request, network_delegate,
base::Bind(&CertReportJobInterceptor::RequestDestructed,
base::Unretained(this), serialized_report,
expected_report_result_));
delayed_request_ = job->GetWeakPtr();
return job;
}
// Successful url request job.
return new DelayableCertReportURLRequestJob(
false, false, request, network_delegate,
base::Bind(&CertReportJobInterceptor::RequestDestructed,
base::Unretained(this), serialized_report,
expected_report_result_));
}
void CertReportJobInterceptor::SetFailureMode(
ReportSendingResult expected_report_result) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
content::BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
base::BindOnce(&CertReportJobInterceptor::SetFailureModeOnIOThread,
base::Unretained(this), expected_report_result));
}
void CertReportJobInterceptor::Resume() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
content::BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
base::BindOnce(&CertReportJobInterceptor::ResumeOnIOThread,
base::Unretained(this)));
}
RequestObserver* CertReportJobInterceptor::request_created_observer() const {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
return &request_created_observer_;
}
RequestObserver* CertReportJobInterceptor::request_destroyed_observer() const {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
return &request_destroyed_observer_;
}
void CertReportJobInterceptor::SetFailureModeOnIOThread(
ReportSendingResult expected_report_result) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
expected_report_result_ = expected_report_result;
}
void CertReportJobInterceptor::ResumeOnIOThread() {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
EXPECT_EQ(REPORTS_DELAY, expected_report_result_);
if (delayed_request_)
delayed_request_->Resume();
}
void CertReportJobInterceptor::RequestCreated(
const std::string& serialized_report,
ReportSendingResult expected_report_result) const {
content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
base::BindOnce(&RequestObserver::OnRequest,
base::Unretained(&request_created_observer_),
serialized_report, expected_report_result));
}
void CertReportJobInterceptor::RequestDestructed(
const std::string& serialized_report,
ReportSendingResult expected_report_result) const {
request_destroyed_observer_.OnRequest(serialized_report,
expected_report_result);
}
ReportExpectation::ReportExpectation() {}
ReportExpectation::ReportExpectation(const ReportExpectation& other) = default;
......@@ -393,7 +281,8 @@ void CertificateReportingServiceObserver::OnServiceReset() {
run_loop_->Quit();
}
CertificateReportingServiceTestHelper::CertificateReportingServiceTestHelper() {
CertificateReportingServiceTestHelper::CertificateReportingServiceTestHelper()
: expected_report_result_(REPORTS_FAIL) {
memset(server_private_key_, 1, sizeof(server_private_key_));
X25519_public_from_private(server_public_key_, server_private_key_);
}
......@@ -401,26 +290,19 @@ CertificateReportingServiceTestHelper::CertificateReportingServiceTestHelper() {
CertificateReportingServiceTestHelper::
~CertificateReportingServiceTestHelper() {}
void CertificateReportingServiceTestHelper::SetUpInterceptor() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
url_request_interceptor_ =
new CertReportJobInterceptor(REPORTS_FAIL, server_private_key_);
content::BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
base::BindOnce(&SetUpURLHandlersOnIOThread,
std::unique_ptr<net::URLRequestInterceptor>(
url_request_interceptor_)));
}
void CertificateReportingServiceTestHelper::SetFailureMode(
ReportSendingResult expected_report_result) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
url_request_interceptor_->SetFailureMode(expected_report_result);
expected_report_result_ = expected_report_result;
}
void CertificateReportingServiceTestHelper::ResumeDelayedRequest() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
url_request_interceptor_->Resume();
EXPECT_EQ(REPORTS_DELAY, expected_report_result_);
if (delayed_client_) {
SendResponse(std::move(delayed_client_), delayed_result_ == REPORTS_FAIL);
request_destroyed_observer_.OnRequest(delayed_report_, delayed_result_);
}
}
uint8_t* CertificateReportingServiceTestHelper::server_public_key() {
......@@ -434,41 +316,33 @@ uint32_t CertificateReportingServiceTestHelper::server_public_key_version()
void CertificateReportingServiceTestHelper::WaitForRequestsCreated(
const ReportExpectation& expectation) {
WaitReports(interceptor()->request_created_observer(), expectation, nullptr);
WaitReports(&request_created_observer_, expectation, nullptr);
}
void CertificateReportingServiceTestHelper::WaitForRequestsCreated(
const ReportExpectation& expectation,
std::vector<std::string>* full_reports) {
WaitReports(interceptor()->request_created_observer(), expectation,
full_reports);
WaitReports(&request_created_observer_, expectation, full_reports);
}
void CertificateReportingServiceTestHelper::WaitForRequestsDestroyed(
const ReportExpectation& expectation) {
WaitReports(interceptor()->request_destroyed_observer(), expectation,
nullptr);
WaitReports(&request_destroyed_observer_, expectation, nullptr);
}
void CertificateReportingServiceTestHelper::WaitForRequestsDestroyed(
const ReportExpectation& expectation,
std::vector<std::string>* full_reports) {
WaitReports(interceptor()->request_destroyed_observer(), expectation,
full_reports);
WaitReports(&request_destroyed_observer_, expectation, full_reports);
}
void CertificateReportingServiceTestHelper::ExpectNoRequests(
CertificateReportingService* service) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// Check that all requests have been destroyed.
EXPECT_TRUE(interceptor()
->request_destroyed_observer()
->successful_reports()
.empty());
EXPECT_TRUE(
interceptor()->request_destroyed_observer()->failed_reports().empty());
EXPECT_TRUE(
interceptor()->request_destroyed_observer()->delayed_reports().empty());
EXPECT_TRUE(request_destroyed_observer_.successful_reports().empty());
EXPECT_TRUE(request_destroyed_observer_.failed_reports().empty());
EXPECT_TRUE(request_destroyed_observer_.delayed_reports().empty());
if (service->GetReporterForTesting()) {
// Reporter can be null if reporting is disabled.
......@@ -478,6 +352,62 @@ void CertificateReportingServiceTestHelper::ExpectNoRequests(
}
}
void CertificateReportingServiceTestHelper::SendResponse(
network::mojom::URLLoaderClientPtr client,
bool fail) {
if (fail) {
client->OnComplete(
network::URLLoaderCompletionStatus(net::ERR_SSL_PROTOCOL_ERROR));
return;
}
network::ResourceResponseHead head;
head.headers = new net::HttpResponseHeaders(
"HTTP/1.1 200 OK\nContent-type: text/html\n\n");
head.mime_type = "text/html";
client->OnReceiveResponse(head, nullptr);
client->OnComplete(network::URLLoaderCompletionStatus());
}
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
CertificateReportingServiceTestHelper::Clone() {
NOTREACHED();
return nullptr;
}
void CertificateReportingServiceTestHelper::CreateLoaderAndStart(
network::mojom::URLLoaderRequest request,
int32_t routing_id,
int32_t request_id,
uint32_t options,
const network::ResourceRequest& url_request,
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
const std::string serialized_report =
GetReportContents(url_request, server_private_key_);
request_created_observer_.OnRequest(serialized_report,
expected_report_result_);
if (expected_report_result_ == REPORTS_FAIL) {
SendResponse(std::move(client), true);
request_destroyed_observer_.OnRequest(serialized_report,
expected_report_result_);
return;
}
if (expected_report_result_ == REPORTS_DELAY) {
DCHECK(!delayed_client_) << "Supports only one delayed request at a time";
delayed_client_ = std::move(client);
delayed_report_ = serialized_report;
delayed_result_ = expected_report_result_;
return;
}
SendResponse(std::move(client), false);
request_destroyed_observer_.OnRequest(serialized_report,
expected_report_result_);
}
EventHistogramTester::EventHistogramTester() {}
EventHistogramTester::~EventHistogramTester() {
......
......@@ -17,6 +17,7 @@
#include "net/base/network_delegate_impl.h"
#include "net/url_request/url_request_interceptor.h"
#include "net/url_request/url_request_job.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace net {
class NetworkDelegate;
......@@ -139,51 +140,6 @@ class DelayableCertReportURLRequestJob : public net::URLRequestJob {
DISALLOW_COPY_AND_ASSIGN(DelayableCertReportURLRequestJob);
};
// A job interceptor that returns a failed, succesful or delayed request job.
// Used to simulate report uploads that fail, succeed or hang.
// The caller is responsible for guaranteeing that |this| is kept alive for
// all posted tasks and URLRequestJob objects.
class CertReportJobInterceptor : public net::URLRequestInterceptor {
public:
CertReportJobInterceptor(ReportSendingResult expected_report_result,
const uint8_t* server_private_key);
~CertReportJobInterceptor() override;
// net::URLRequestInterceptor method:
net::URLRequestJob* MaybeInterceptRequest(
net::URLRequest* request,
net::NetworkDelegate* network_delegate) const override;
// Sets the failure mode for reports. Must be called on the UI thread.
void SetFailureMode(ReportSendingResult expected_report_result);
// Resumes any hanging URL request and runs callback when the request
// is resumed (i.e. response starts). Must be called on the UI thread.
void Resume();
RequestObserver* request_created_observer() const;
RequestObserver* request_destroyed_observer() const;
private:
void SetFailureModeOnIOThread(ReportSendingResult expected_report_result);
void ResumeOnIOThread();
void RequestCreated(const std::string& serialized_report,
ReportSendingResult expected_report_result) const;
void RequestDestructed(const std::string& serialized_report,
ReportSendingResult expected_report_result) const;
ReportSendingResult expected_report_result_;
// Private key to decrypt certificate reports.
const uint8_t* server_private_key_;
mutable RequestObserver request_created_observer_;
mutable RequestObserver request_destroyed_observer_;
mutable base::WeakPtr<DelayableCertReportURLRequestJob> delayed_request_;
DISALLOW_COPY_AND_ASSIGN(CertReportJobInterceptor);
};
// Class to wait for the CertificateReportingService to reset.
class CertificateReportingServiceObserver {
public:
......@@ -204,14 +160,11 @@ class CertificateReportingServiceObserver {
std::unique_ptr<base::RunLoop> run_loop_;
};
// Base class for CertificateReportingService tests. Sets up an interceptor to
// keep track of reports that are being sent.
class CertificateReportingServiceTestHelper {
// Base class for CertificateReportingService tests.
class CertificateReportingServiceTestHelper
: public network::SharedURLLoaderFactory {
public:
CertificateReportingServiceTestHelper();
~CertificateReportingServiceTestHelper();
void SetUpInterceptor();
// Changes the behavior of report uploads to fail, succeed or hang.
void SetFailureMode(ReportSendingResult expected_report_result);
......@@ -235,10 +188,30 @@ class CertificateReportingServiceTestHelper {
uint32_t server_public_key_version() const;
private:
CertReportJobInterceptor* interceptor() { return url_request_interceptor_; }
void SetUpInterceptorOnIOThread();
friend class base::RefCounted<CertificateReportingServiceTestHelper>;
~CertificateReportingServiceTestHelper() override;
void SendResponse(network::mojom::URLLoaderClientPtr client, bool fail);
// network::SharedURLLoaderFactory
std::unique_ptr<network::SharedURLLoaderFactoryInfo> Clone() override;
void CreateLoaderAndStart(network::mojom::URLLoaderRequest request,
int32_t routing_id,
int32_t request_id,
uint32_t options,
const network::ResourceRequest& url_request,
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag&
traffic_annotation) override;
ReportSendingResult expected_report_result_;
network::mojom::URLLoaderClientPtr delayed_client_;
std::string delayed_report_;
ReportSendingResult delayed_result_;
CertReportJobInterceptor* url_request_interceptor_;
RequestObserver request_created_observer_;
RequestObserver request_destroyed_observer_;
uint8_t server_public_key_[32];
uint8_t server_private_key_[32];
......
......@@ -23,6 +23,7 @@
#include "chrome/browser/ssl/certificate_error_report.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/weak_wrapper_shared_url_loader_factory.h"
#include "content/public/test/test_browser_thread.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "crypto/rsa_private_key.h"
......@@ -33,6 +34,7 @@
#include "net/test/url_request/url_request_mock_data_job.h"
#include "net/url_request/url_request_filter.h"
#include "net/url_request/url_request_test_util.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
using certificate_reporting_test_utils::CertificateReportingServiceTestHelper;
......@@ -90,10 +92,6 @@ void CheckReport(const CertificateReportingService::Report& report,
EXPECT_EQ(expected_creation_time, report.creation_time);
}
void ClearURLHandlers() {
net::URLRequestFilter::GetInstance()->ClearHandlers();
}
// Class for histogram testing. The failed report histogram is checked once
// after teardown to ensure all in flight requests have completed.
class ReportHistogramTestHelper {
......@@ -167,19 +165,15 @@ class CertificateReportingServiceReporterOnIOThreadTest
: public ::testing::Test {
public:
void SetUp() override {
message_loop_.reset(new base::MessageLoopForIO());
io_thread_.reset(new content::TestBrowserThread(content::BrowserThread::IO,
message_loop_.get()));
url_request_context_getter_ =
new net::TestURLRequestContextGetter(message_loop_->task_runner());
net::URLRequestFailedJob::AddUrlHandler();
net::URLRequestMockDataJob::AddUrlHandler();
test_shared_loader_factory_ =
base::MakeRefCounted<content::WeakWrapperSharedURLLoaderFactory>(
&test_url_loader_factory_);
message_loop_.reset(new base::MessageLoopForIO());
event_histogram_tester_.reset(new EventHistogramTester());
}
void TearDown() override {
ClearURLHandlers();
// Check histograms as the last thing. This makes sure no in-flight report
// is missed.
histogram_test_helper_.CheckHistogram();
......@@ -187,8 +181,11 @@ class CertificateReportingServiceReporterOnIOThreadTest
}
protected:
net::URLRequestContextGetter* url_request_context_getter() {
return url_request_context_getter_.get();
network::TestURLLoaderFactory* test_url_loader_factory() {
return &test_url_loader_factory_;
}
scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory() {
return test_shared_loader_factory_;
}
void SetExpectedFailedReportCountOnTearDown(unsigned int count) {
......@@ -203,7 +200,8 @@ class CertificateReportingServiceReporterOnIOThreadTest
std::unique_ptr<base::MessageLoopForIO> message_loop_;
std::unique_ptr<content::TestBrowserThread> io_thread_;
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
network::TestURLLoaderFactory test_url_loader_factory_;
scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
ReportHistogramTestHelper histogram_test_helper_;
// Histogram tester for reporting events. This is a member instead of a local
// so that we can check the histogram after the test teardown. At that point
......@@ -220,11 +218,14 @@ TEST_F(CertificateReportingServiceReporterOnIOThreadTest,
const base::Time reference_time = base::Time::Now();
clock->SetNow(reference_time);
const GURL kFailureURL =
net::URLRequestFailedJob::GetMockHttpsUrl(net::ERR_SSL_PROTOCOL_ERROR);
const GURL kFailureURL("https://www.foo.com/");
test_url_loader_factory()->AddResponse(
kFailureURL, network::ResourceResponseHead(), std::string(),
network::URLLoaderCompletionStatus(net::ERR_SSL_PROTOCOL_ERROR));
CertificateErrorReporter* certificate_error_reporter =
new CertificateErrorReporter(
url_request_context_getter()->GetURLRequestContext(), kFailureURL);
new CertificateErrorReporter(test_shared_loader_factory(), kFailureURL);
CertificateReportingService::BoundedReportList* list =
new CertificateReportingService::BoundedReportList(2);
......@@ -290,8 +291,10 @@ TEST_F(CertificateReportingServiceReporterOnIOThreadTest,
// Send pending reports again, this time successfully. There should be no
// pending reports left.
const GURL kSuccessURL =
net::URLRequestMockDataJob::GetMockHttpsUrl("dummy data", 1);
const GURL kSuccessURL("https://www.bar.com/");
test_url_loader_factory()->AddResponse(kSuccessURL.spec(), "dummy data");
certificate_error_reporter->set_upload_url_for_testing(kSuccessURL);
clock->Advance(base::TimeDelta::FromSeconds(1));
reporter.SendPending();
......@@ -315,11 +318,14 @@ TEST_F(CertificateReportingServiceReporterOnIOThreadTest,
base::Time reference_time = base::Time::Now();
clock->SetNow(reference_time);
const GURL kFailureURL =
net::URLRequestFailedJob::GetMockHttpsUrl(net::ERR_SSL_PROTOCOL_ERROR);
const GURL kFailureURL("https://www.foo.com/");
test_url_loader_factory()->AddResponse(
kFailureURL, network::ResourceResponseHead(), std::string(),
network::URLLoaderCompletionStatus(net::ERR_SSL_PROTOCOL_ERROR));
CertificateErrorReporter* certificate_error_reporter =
new CertificateErrorReporter(
url_request_context_getter()->GetURLRequestContext(), kFailureURL);
new CertificateErrorReporter(test_shared_loader_factory(), kFailureURL);
CertificateReportingService::BoundedReportList* list =
new CertificateReportingService::BoundedReportList(2);
......@@ -369,24 +375,18 @@ class CertificateReportingServiceTest : public ::testing::Test {
void SetUp() override {
service_observer_.Clear();
test_helper_.SetUpInterceptor();
WaitForIOThread();
content::BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
base::BindOnce(
&CertificateReportingServiceTest::SetUpURLRequestContextOnIOThread,
base::Unretained(this)));
WaitForIOThread();
safe_browsing::SafeBrowsingService::RegisterFactory(&sb_service_factory);
sb_service_ = sb_service_factory.CreateSafeBrowsingService();
test_helper_ =
base::MakeRefCounted<CertificateReportingServiceTestHelper>();
clock_.reset(new base::SimpleTestClock());
service_.reset(new CertificateReportingService(
sb_service_.get(), url_request_context_getter(), &profile_,
test_helper_.server_public_key(),
test_helper_.server_public_key_version(), kMaxReportCountInQueue,
sb_service_.get(), test_helper_, &profile_,
test_helper_->server_public_key(),
test_helper_->server_public_key_version(), kMaxReportCountInQueue,
base::TimeDelta::FromHours(24), clock_.get(),
base::Bind(&CertificateReportingServiceObserver::OnServiceReset,
base::Unretained(&service_observer_))));
......@@ -396,36 +396,16 @@ class CertificateReportingServiceTest : public ::testing::Test {
}
void TearDown() override {
WaitForIOThread();
test_helper()->ExpectNoRequests(service());
service_->Shutdown();
WaitForIOThread();
service_.reset(nullptr);
content::BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
base::BindOnce(&CertificateReportingServiceTest::TearDownOnIOThread,
base::Unretained(this)));
content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
base::BindOnce(&ClearURLHandlers));
WaitForIOThread();
histogram_test_helper_.CheckHistogram();
event_histogram_tester_.reset();
}
protected:
net::URLRequestContextGetter* url_request_context_getter() {
return url_request_context_getter_.get();
}
void WaitForIOThread() {
scoped_refptr<base::ThreadTestHelper> io_helper(
new base::ThreadTestHelper(io_task_runner_));
ASSERT_TRUE(io_helper->Run());
}
CertificateReportingService* service() { return service_.get(); }
// Sets service enabled state and waits for a reset event.
......@@ -435,42 +415,33 @@ class CertificateReportingServiceTest : public ::testing::Test {
service_observer_.WaitForReset();
}
void AdvanceClock(base::TimeDelta delta) {
content::BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
base::BindOnce(&base::SimpleTestClock::Advance,
base::Unretained(clock_.get()), delta));
}
void AdvanceClock(base::TimeDelta delta) { clock_->Advance(delta); }
void SetNow(base::Time now) {
content::BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
base::BindOnce(&base::SimpleTestClock::SetNow,
base::Unretained(clock_.get()), now));
}
void SetNow(base::Time now) { clock_->SetNow(now); }
void SetExpectedFailedReportCountOnTearDown(unsigned int count) {
histogram_test_helper_.SetExpectedFailedReportCount(count);
}
CertificateReportingServiceTestHelper* test_helper() { return &test_helper_; }
CertificateReportingServiceTestHelper* test_helper() {
return test_helper_.get();
}
EventHistogramTester* event_histogram_tester() {
return event_histogram_tester_.get();
}
private:
void SetUpURLRequestContextOnIOThread() {
std::unique_ptr<net::TestURLRequestContext> url_request_context(
new net::TestURLRequestContext(false));
url_request_context_getter_ = new net::TestURLRequestContextGetter(
io_task_runner_, std::move(url_request_context));
}
void WaitForNoReports() {
if (!service_->GetReporterForTesting()->inflight_report_count_for_testing())
return;
void TearDownOnIOThread() {
url_request_context_getter_ = nullptr;
base::RunLoop run_loop;
service_->GetReporterForTesting()
->SetClosureWhenNoInflightReportsForTesting(run_loop.QuitClosure());
run_loop.Run();
}
private:
// Must be initialized before url_request_context_getter_
content::TestBrowserThreadBundle thread_bundle_;
......@@ -484,7 +455,7 @@ class CertificateReportingServiceTest : public ::testing::Test {
safe_browsing::TestSafeBrowsingServiceFactory sb_service_factory;
TestingProfile profile_;
CertificateReportingServiceTestHelper test_helper_;
scoped_refptr<CertificateReportingServiceTestHelper> test_helper_;
ReportHistogramTestHelper histogram_test_helper_;
CertificateReportingServiceObserver service_observer_;
......@@ -504,6 +475,7 @@ TEST_F(CertificateReportingServiceTest, SendSuccessful) {
ReportExpectation::Successful({{"report0", RetryStatus::NOT_RETRIED},
{"report1", RetryStatus::NOT_RETRIED}}));
WaitForNoReports();
// report0 and report1 were both submitted once, succeeded once.
event_histogram_tester()->SetExpectedValues(
2 /* submitted */, 0 /* failed */, 2 /* successful */, 0 /* dropped */);
......@@ -523,6 +495,9 @@ TEST_F(CertificateReportingServiceTest, SendFailure) {
ReportExpectation::Failed({{"report0", RetryStatus::NOT_RETRIED},
{"report1", RetryStatus::NOT_RETRIED}}));
// Need this to ensure the pending reports are queued.
WaitForNoReports();
// Send pending reports. Previously queued reports should be queued again.
service()->SendPending();
test_helper()->WaitForRequestsDestroyed(ReportExpectation::Failed(
......@@ -537,12 +512,16 @@ TEST_F(CertificateReportingServiceTest, SendFailure) {
test_helper()->WaitForRequestsDestroyed(
ReportExpectation::Successful({{"report2", RetryStatus::NOT_RETRIED}}));
// Need this to ensure the pending reports are queued.
WaitForNoReports();
// Send pending reports. Previously failed and queued two reports should be
// observed.
service()->SendPending();
test_helper()->WaitForRequestsDestroyed(ReportExpectation::Successful(
{{"report0", RetryStatus::RETRIED}, {"report1", RetryStatus::RETRIED}}));
WaitForNoReports();
// report0 and report1 were both submitted thrice, failed twice, succeeded
// once. report2 was submitted once, succeeded once.
event_histogram_tester()->SetExpectedValues(
......@@ -570,6 +549,7 @@ TEST_F(CertificateReportingServiceTest, Disabled_ShouldNotSend) {
test_helper()->WaitForRequestsDestroyed(
ReportExpectation::Successful({{"report1", RetryStatus::NOT_RETRIED}}));
WaitForNoReports();
// report0 was never sent. report1 was submitted once, succeeded once.
event_histogram_tester()->SetExpectedValues(
1 /* submitted */, 0 /* failed */, 1 /* successful */, 0 /* dropped */);
......@@ -586,6 +566,9 @@ TEST_F(CertificateReportingServiceTest, Disabled_ShouldClearPendingReports) {
test_helper()->WaitForRequestsDestroyed(
ReportExpectation::Failed({{"report0", RetryStatus::NOT_RETRIED}}));
// Need this to ensure the pending reports are queued.
WaitForNoReports();
// Disable the service.
SetServiceEnabledAndWait(false);
......@@ -599,6 +582,7 @@ TEST_F(CertificateReportingServiceTest, Disabled_ShouldClearPendingReports) {
// Sending with empty queue has no effect.
service()->SendPending();
WaitForNoReports();
// report0 was submitted once, failed once.
event_histogram_tester()->SetExpectedValues(
1 /* submitted */, 1 /* failed */, 0 /* successful */, 0 /* dropped */);
......@@ -624,6 +608,10 @@ TEST_F(CertificateReportingServiceTest, DontSendOldReports) {
// time. This makes the report0 older than max age (24 hours). The report1 is
// now 20 hours old.
AdvanceClock(base::TimeDelta::FromHours(20));
// Need this to ensure the pending reports are queued.
WaitForNoReports();
// Send pending reports. report0 should be discarded since it's too old.
// report1 should be queued again.
service()->SendPending();
......@@ -637,6 +625,10 @@ TEST_F(CertificateReportingServiceTest, DontSendOldReports) {
// Advance the clock 5 hours. The report1 will now be 25 hours old.
AdvanceClock(base::TimeDelta::FromHours(5));
// Need this to ensure the pending reports are queued.
WaitForNoReports();
// Send pending reports. report1 should be discarded since it's too old.
// report2 should be queued again.
service()->SendPending();
......@@ -646,10 +638,15 @@ TEST_F(CertificateReportingServiceTest, DontSendOldReports) {
// Advance the clock 20 hours again so that report2 is 25 hours old and is
// older than max age (24 hours)
AdvanceClock(base::TimeDelta::FromHours(20));
// Need this to ensure the pending reports are queued.
WaitForNoReports();
// Send pending reports. report2 should be discarded since it's too old. No
// other reports remain.
service()->SendPending();
WaitForNoReports();
// report0 was submitted once, failed once, dropped once.
// report1 was submitted twice, failed twice, dropped once.
// report2 was submitted twice, failed twice, dropped once.
......@@ -687,6 +684,9 @@ TEST_F(CertificateReportingServiceTest, DiscardOldReports) {
{"report2", RetryStatus::NOT_RETRIED},
{"report3", RetryStatus::NOT_RETRIED}}));
// Need this to ensure the pending reports are queued.
WaitForNoReports();
// 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.
......@@ -706,6 +706,10 @@ TEST_F(CertificateReportingServiceTest, DiscardOldReports) {
// report2 is 20 hours old.
// report3 is 15 hours old.
AdvanceClock(base::TimeDelta::FromHours(15));
// Need this to ensure the pending reports are queued.
WaitForNoReports();
// Send pending reports. Only report2 and report3 should be sent, report1
// should be ignored because it's too old.
service()->SendPending();
......@@ -715,6 +719,7 @@ TEST_F(CertificateReportingServiceTest, DiscardOldReports) {
// Do a final send. No reports should be sent.
service()->SendPending();
WaitForNoReports();
// report0 was submitted once, failed once, dropped once.
// report1 was submitted twice, failed twice, dropped once.
// report2 was submitted thrice, failed twice, succeeded once.
......@@ -740,6 +745,7 @@ TEST_F(CertificateReportingServiceTest, Delayed_Resumed) {
test_helper()->WaitForRequestsDestroyed(
ReportExpectation::Delayed({{"report0", RetryStatus::NOT_RETRIED}}));
WaitForNoReports();
// report0 was submitted once, succeeded once.
event_histogram_tester()->SetExpectedValues(
1 /* submitted */, 0 /* failed */, 1 /* successful */, 0 /* dropped */);
......@@ -779,6 +785,7 @@ TEST_F(CertificateReportingServiceTest, Delayed_Reset) {
ReportExpectation::Delayed({{"report0", RetryStatus::NOT_RETRIED},
{"report1", RetryStatus::NOT_RETRIED}}));
WaitForNoReports();
// report0 was submitted once, but neither failed nor succeeded because the
// report queue was cleared. report1 was submitted once, succeeded once.
event_histogram_tester()->SetExpectedValues(
......
......@@ -176,7 +176,6 @@ void SafeBrowsingService::Initialize() {
void SafeBrowsingService::ShutDown() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
shutdown_callback_list_.Notify();
// Remove Profile creation/destruction observers.
profiles_registrar_.RemoveAll();
......@@ -546,13 +545,6 @@ SafeBrowsingService::RegisterStateCallback(
return state_callback_list_.Add(callback);
}
std::unique_ptr<SafeBrowsingService::ShutdownSubscription>
SafeBrowsingService::RegisterShutdownCallback(
const base::Callback<void(void)>& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return shutdown_callback_list_.Add(callback);
}
void SafeBrowsingService::RefreshState() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Check if any profile requires the service to be active.
......
......@@ -210,12 +210,6 @@ class SafeBrowsingService : public base::RefCountedThreadSafe<
std::unique_ptr<StateSubscription> RegisterStateCallback(
const base::Callback<void(void)>& callback);
// Adds a listener for when SafeBrowsingService starts shutting down.
// The callbacks run on the UI thread, and give the subscribers an opportunity
// to clean up any references they hold to SafeBrowsingService.
std::unique_ptr<ShutdownSubscription> RegisterShutdownCallback(
const base::Callback<void(void)>& callback);
// Sends serialized download report to backend.
virtual void SendSerializedDownloadReport(const std::string& report);
......@@ -350,10 +344,6 @@ class SafeBrowsingService : public base::RefCountedThreadSafe<
// Should only be accessed on the UI thread.
base::CallbackList<void(void)> state_callback_list_;
// Callbacks when SafeBrowsing service starts shutting down.
// Should only be accessed on the UI thread.
base::CallbackList<void(void)> shutdown_callback_list_;
// The UI manager handles showing interstitials. Accessed on both UI and IO
// thread.
scoped_refptr<SafeBrowsingUIManager> ui_manager_;
......
......@@ -2,6 +2,7 @@ include_rules = [
"+components/captive_portal",
"+components/certificate_transparency",
"+components/wifi",
"+services/network/test",
]
specific_include_rules = {
......
......@@ -13,10 +13,12 @@
#include "base/logging.h"
#include "base/strings/string_piece.h"
#include "chrome/browser/net/chrome_report_sender.h"
#include "components/encrypted_messages/encrypted_message.pb.h"
#include "components/encrypted_messages/message_encrypter.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/report_sender.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace {
......@@ -72,26 +74,22 @@ constexpr net::NetworkTrafficAnnotationTag
} // namespace
CertificateErrorReporter::CertificateErrorReporter(
net::URLRequestContext* request_context,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
const GURL& upload_url)
: CertificateErrorReporter(
: CertificateErrorReporter(url_loader_factory,
upload_url,
kServerPublicKey,
kServerPublicKeyVersion,
std::make_unique<net::ReportSender>(
request_context,
kSafeBrowsingCertificateErrorReportingTrafficAnnotation)) {}
kServerPublicKeyVersion) {}
CertificateErrorReporter::CertificateErrorReporter(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
const GURL& upload_url,
const uint8_t server_public_key[/* 32 */],
const uint32_t server_public_key_version,
std::unique_ptr<net::ReportSender> certificate_report_sender)
: certificate_report_sender_(std::move(certificate_report_sender)),
const uint32_t server_public_key_version)
: url_loader_factory_(url_loader_factory),
upload_url_(upload_url),
server_public_key_(server_public_key),
server_public_key_version_(server_public_key_version) {
DCHECK(certificate_report_sender_);
DCHECK(!upload_url.is_empty());
}
......@@ -99,14 +97,11 @@ CertificateErrorReporter::~CertificateErrorReporter() {}
void CertificateErrorReporter::SendExtendedReportingReport(
const std::string& serialized_report,
const base::Callback<void()>& success_callback,
const base::Callback<void(const GURL&, int, int)>& error_callback) {
if (upload_url_.SchemeIsCryptographic()) {
certificate_report_sender_->Send(upload_url_, "application/octet-stream",
serialized_report, success_callback,
error_callback);
return;
}
base::OnceCallback<void()> success_callback,
base::OnceCallback<void(int, int)> error_callback) {
std::string serialized_encrypted_report;
const std::string* string_to_send = &serialized_report;
if (!upload_url_.SchemeIsCryptographic()) {
encrypted_messages::EncryptedMessage encrypted_report;
// By mistake, the HKDF label here ends up with an extra null byte on
// the end, due to using sizeof(kHkdfLabel) in the StringPiece
......@@ -121,9 +116,13 @@ void CertificateErrorReporter::SendExtendedReportingReport(
LOG(ERROR) << "Failed to encrypt serialized report.";
return;
}
std::string serialized_encrypted_report;
encrypted_report.SerializeToString(&serialized_encrypted_report);
certificate_report_sender_->Send(upload_url_, "application/octet-stream",
serialized_encrypted_report,
success_callback, error_callback);
string_to_send = &serialized_encrypted_report;
}
SendReport(url_loader_factory_,
kSafeBrowsingCertificateErrorReportingTrafficAnnotation,
upload_url_, "application/octet-stream", *string_to_send,
std::move(success_callback), std::move(error_callback));
}
......@@ -13,11 +13,11 @@
#include "base/callback.h"
#include "base/macros.h"
#include "net/url_request/report_sender.h"
#include "base/memory/ref_counted.h"
#include "url/gurl.h"
namespace net {
class URLRequestContext;
namespace network {
class SharedURLLoaderFactory;
}
// Provides functionality for sending reports about invalid SSL
......@@ -25,19 +25,19 @@ class URLRequestContext;
class CertificateErrorReporter {
public:
// Creates a certificate error reporter that will send certificate
// error reports to |upload_url|, using |request_context| as the
// error reports to |upload_url|, using |url_loader_factory| as the
// context for the reports.
CertificateErrorReporter(net::URLRequestContext* request_context,
CertificateErrorReporter(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
const GURL& upload_url);
// Allows tests to use a server public key with known private key and
// a mock ReportSender. |server_public_key| must outlive
// the ErrorReporter.
// Allows tests to use a server public key with known private key.
// |server_public_key| must outlive the ErrorReporter.
CertificateErrorReporter(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
const GURL& upload_url,
const uint8_t server_public_key[/* 32 */],
const uint32_t server_public_key_version,
std::unique_ptr<net::ReportSender> certificate_report_sender);
const uint32_t server_public_key_version);
virtual ~CertificateErrorReporter();
......@@ -63,16 +63,14 @@ class CertificateErrorReporter {
// net error and HTTP response code parameters.
virtual void SendExtendedReportingReport(
const std::string& serialized_report,
const base::Callback<void()>& success_callback,
const base::Callback<void(const GURL&,
int /* net_error */,
int /* http_response_code */)>& error_callback);
base::OnceCallback<void()> success_callback,
base::OnceCallback<void(int /* net_error */,
int /* http_response_code */)> error_callback);
void set_upload_url_for_testing(const GURL& url) { upload_url_ = url; }
private:
std::unique_ptr<net::ReportSender> certificate_report_sender_;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
GURL upload_url_;
const uint8_t* server_public_key_;
......
......@@ -17,14 +17,14 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/string_piece.h"
#include "base/test/bind_test_util.h"
#include "components/encrypted_messages/encrypted_message.pb.h"
#include "components/encrypted_messages/message_encrypter.h"
#include "content/public/common/weak_wrapper_shared_url_loader_factory.h"
#include "net/http/http_status_code.h"
#include "net/test/url_request/url_request_failed_job.h"
#include "net/test/url_request/url_request_mock_data_job.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/report_sender.h"
#include "net/url_request/url_request_test_util.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/boringssl/src/include/openssl/curve25519.h"
......@@ -36,79 +36,12 @@ const char kDummyHttpsReportUri[] = "https://example.test";
const char kDummyReport[] = "a dummy report";
const uint32_t kServerPublicKeyTestVersion = 16;
void ErrorCallback(bool* called,
const GURL& report_uri,
int net_error,
int http_response_code) {
EXPECT_NE(net::OK, net_error);
EXPECT_EQ(-1, http_response_code);
*called = true;
}
void SuccessCallback(bool* called) {
*called = true;
}
// A mock ReportSender that keeps track of the last report
// sent.
class MockCertificateReportSender : public net::ReportSender {
public:
MockCertificateReportSender()
: net::ReportSender(nullptr, TRAFFIC_ANNOTATION_FOR_TESTS) {}
~MockCertificateReportSender() override {}
void Send(const GURL& report_uri,
base::StringPiece content_type,
base::StringPiece report,
const base::Callback<void()>& success_callback,
const base::Callback<void(const GURL&, int, int)>& error_callback)
override {
latest_report_uri_ = report_uri;
report.CopyToString(&latest_report_);
content_type.CopyToString(&latest_content_type_);
}
const GURL& latest_report_uri() const { return latest_report_uri_; }
const std::string& latest_report() const { return latest_report_; }
const std::string& latest_content_type() const {
return latest_content_type_;
}
private:
GURL latest_report_uri_;
std::string latest_report_;
std::string latest_content_type_;
DISALLOW_COPY_AND_ASSIGN(MockCertificateReportSender);
};
// A test network delegate that allows the user to specify a callback to
// be run whenever a net::URLRequest is destroyed.
class TestCertificateReporterNetworkDelegate : public net::NetworkDelegateImpl {
public:
TestCertificateReporterNetworkDelegate()
: url_request_destroyed_callback_(base::DoNothing()) {}
void set_url_request_destroyed_callback(const base::Closure& callback) {
url_request_destroyed_callback_ = callback;
}
// net::NetworkDelegateImpl:
void OnURLRequestDestroyed(net::URLRequest* request) override {
url_request_destroyed_callback_.Run();
}
private:
base::Closure url_request_destroyed_callback_;
DISALLOW_COPY_AND_ASSIGN(TestCertificateReporterNetworkDelegate);
};
class ErrorReporterTest : public ::testing::Test {
public:
ErrorReporterTest() {
ErrorReporterTest()
: test_shared_loader_factory_(
base::MakeRefCounted<content::WeakWrapperSharedURLLoaderFactory>(
&test_url_loader_factory_)) {
memset(server_private_key_, 1, sizeof(server_private_key_));
X25519_public_from_private(server_public_key_, server_private_key_);
}
......@@ -120,44 +53,57 @@ class ErrorReporterTest : public ::testing::Test {
uint8_t server_public_key_[32];
uint8_t server_private_key_[32];
network::TestURLLoaderFactory test_url_loader_factory_;
scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
DISALLOW_COPY_AND_ASSIGN(ErrorReporterTest);
};
// Test that ErrorReporter::SendExtendedReportingReport sends
// an encrypted or plaintext extended reporting report as appropriate.
TEST_F(ErrorReporterTest, ExtendedReportingSendReport) {
GURL latest_report_uri;
std::string latest_report;
std::string latest_content_type;
test_url_loader_factory_.SetInterceptor(
base::BindLambdaForTesting([&](const network::ResourceRequest& request) {
latest_report_uri = request.url;
request.headers.GetHeader(net::HttpRequestHeaders::kContentType,
&latest_content_type);
auto body = request.request_body;
CHECK_EQ(1u, body->elements()->size());
auto& element = body->elements()->at(0);
CHECK_EQ(network::DataElement::TYPE_BYTES, element.type());
latest_report = std::string(element.bytes(), element.length());
}));
// Data should not be encrypted when sent to an HTTPS URL.
MockCertificateReportSender* mock_report_sender =
new MockCertificateReportSender();
GURL https_url(kDummyHttpsReportUri);
CertificateErrorReporter https_reporter(https_url, server_public_key_,
kServerPublicKeyTestVersion,
base::WrapUnique(mock_report_sender));
const GURL https_url(kDummyHttpsReportUri);
CertificateErrorReporter https_reporter(test_shared_loader_factory_,
https_url, server_public_key_,
kServerPublicKeyTestVersion);
https_reporter.SendExtendedReportingReport(
kDummyReport, base::Callback<void()>(),
base::Callback<void(const GURL&, int, int)>());
EXPECT_EQ(mock_report_sender->latest_report_uri(), https_url);
EXPECT_EQ(mock_report_sender->latest_report(), kDummyReport);
kDummyReport, base::OnceCallback<void()>(),
base::OnceCallback<void(int, int)>());
EXPECT_EQ(latest_report_uri, https_url);
EXPECT_EQ(latest_report, kDummyReport);
// Data should be encrypted when sent to an HTTP URL.
MockCertificateReportSender* http_mock_report_sender =
new MockCertificateReportSender();
const GURL http_url(kDummyHttpReportUri);
CertificateErrorReporter http_reporter(
http_url, server_public_key_, kServerPublicKeyTestVersion,
base::WrapUnique(http_mock_report_sender));
CertificateErrorReporter http_reporter(test_shared_loader_factory_, http_url,
server_public_key_,
kServerPublicKeyTestVersion);
http_reporter.SendExtendedReportingReport(
kDummyReport, base::Callback<void()>(),
base::Callback<void(const GURL&, int, int)>());
kDummyReport, base::OnceCallback<void()>(),
base::OnceCallback<void(int, int)>());
EXPECT_EQ(http_mock_report_sender->latest_report_uri(), http_url);
EXPECT_EQ("application/octet-stream",
http_mock_report_sender->latest_content_type());
EXPECT_EQ(latest_report_uri, http_url);
EXPECT_EQ("application/octet-stream", latest_content_type);
std::string uploaded_report;
encrypted_messages::EncryptedMessage encrypted_report;
ASSERT_TRUE(encrypted_report.ParseFromString(
http_mock_report_sender->latest_report()));
ASSERT_TRUE(encrypted_report.ParseFromString(latest_report));
EXPECT_EQ(kServerPublicKeyTestVersion,
encrypted_report.server_public_key_version());
EXPECT_EQ(
......@@ -177,54 +123,37 @@ TEST_F(ErrorReporterTest, ExtendedReportingSendReport) {
// Tests that an UMA histogram is recorded if a report fails to send.
TEST_F(ErrorReporterTest, ErroredRequestCallsCallback) {
net::URLRequestFailedJob::AddUrlHandler();
base::RunLoop run_loop;
net::TestURLRequestContext context(true);
TestCertificateReporterNetworkDelegate test_delegate;
test_delegate.set_url_request_destroyed_callback(run_loop.QuitClosure());
context.set_network_delegate(&test_delegate);
context.Init();
const GURL report_uri(
net::URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_FAILED));
CertificateErrorReporter reporter(&context, report_uri);
bool error_callback_called = false;
bool success_callback_called = false;
const GURL report_uri("http://foo.com/bar");
test_url_loader_factory_.AddResponse(
report_uri, network::ResourceResponseHead(), std::string(),
network::URLLoaderCompletionStatus(net::ERR_CONNECTION_FAILED));
CertificateErrorReporter reporter(test_shared_loader_factory_, report_uri);
reporter.SendExtendedReportingReport(
kDummyReport, base::Bind(&SuccessCallback, &success_callback_called),
base::Bind(&ErrorCallback, &error_callback_called));
kDummyReport, base::BindLambdaForTesting([&]() { FAIL(); }),
base::BindLambdaForTesting(
[&](int net_error, int http_response_code) { run_loop.Quit(); }));
run_loop.Run();
EXPECT_TRUE(error_callback_called);
EXPECT_FALSE(success_callback_called);
}
// Tests that an UMA histogram is recorded if a report is successfully sent.
TEST_F(ErrorReporterTest, SuccessfulRequestCallsCallback) {
net::URLRequestMockDataJob::AddUrlHandler();
base::RunLoop run_loop;
net::TestURLRequestContext context(true);
TestCertificateReporterNetworkDelegate test_delegate;
test_delegate.set_url_request_destroyed_callback(run_loop.QuitClosure());
context.set_network_delegate(&test_delegate);
context.Init();
const GURL report_uri(
net::URLRequestMockDataJob::GetMockHttpUrl("some data", 1));
CertificateErrorReporter reporter(&context, report_uri);
bool error_callback_called = false;
bool success_callback_called = false;
const GURL report_uri("http://foo.com/bar");
test_url_loader_factory_.AddResponse(report_uri.spec(), "some data");
CertificateErrorReporter reporter(test_shared_loader_factory_, report_uri);
reporter.SendExtendedReportingReport(
kDummyReport, base::Bind(&SuccessCallback, &success_callback_called),
base::Bind(&ErrorCallback, &error_callback_called));
kDummyReport, base::BindLambdaForTesting([&]() { run_loop.Quit(); }),
base::BindLambdaForTesting(
[&](int net_error, int http_response_code) { FAIL(); }));
run_loop.Run();
EXPECT_FALSE(error_callback_called);
EXPECT_TRUE(success_callback_called);
}
} // namespace
......@@ -96,6 +96,8 @@ bool TestURLLoaderFactory::CreateLoaderAndStartInternal(
return false;
CHECK(it->second.redirects.empty()) << "TODO(jam): handle redirects";
if (it->second.status.error_code == net::OK) {
client->OnReceiveResponse(it->second.head, nullptr);
mojo::DataPipe data_pipe(it->second.content.size());
uint32_t bytes_written = it->second.content.size();
......@@ -103,6 +105,7 @@ bool TestURLLoaderFactory::CreateLoaderAndStartInternal(
it->second.content.data(), &bytes_written,
MOJO_WRITE_DATA_FLAG_ALL_OR_NONE));
client->OnStartLoadingResponseBody(std::move(data_pipe.consumer_handle));
}
client->OnComplete(it->second.status);
return true;
}
......
......@@ -36,7 +36,6 @@ Refer to README.md for content description and update process.
<item id="cast_socket" hash_code="115192205" type="0" content_hash_code="63056899" os_list="linux,windows" file_path="components/cast_channel/cast_socket.cc"/>
<item id="cast_udp_socket" hash_code="22573197" type="0" content_hash_code="75328301" os_list="linux,windows" file_path="components/mirroring/service/udp_socket_client.cc"/>
<item id="cast_udp_transport" hash_code="5576536" type="0" content_hash_code="107643273" os_list="linux,windows" file_path="media/cast/net/udp_transport_impl.cc"/>
<item id="certificate_reporting_service_test" hash_code="98123372" type="0" content_hash_code="136253658" os_list="linux,windows" file_path="chrome/browser/safe_browsing/certificate_reporting_service.cc"/>
<item id="certificate_verifier" hash_code="113553577" type="0" content_hash_code="62346354" os_list="linux,windows" file_path="net/cert_net/cert_net_fetcher_impl.cc"/>
<item id="chrome_apps_socket_api" hash_code="8591273" type="0" content_hash_code="70868355" os_list="linux,windows" file_path="extensions/browser/api/socket/socket.cc"/>
<item id="chrome_cleaner" hash_code="27071967" type="0" content_hash_code="111240292" os_list="windows" file_path="chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_fetcher_win.cc"/>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment