1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/url_request/certificate_report_sender.h"
8 #include "base/bind_helpers.h"
9 #include "base/macros.h"
10 #include "base/run_loop.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "net/base/load_flags.h"
13 #include "net/base/network_delegate_impl.h"
14 #include "net/base/upload_bytes_element_reader.h"
15 #include "net/base/upload_data_stream.h"
16 #include "net/base/upload_element_reader.h"
17 #include "net/test/url_request/url_request_failed_job.h"
18 #include "net/test/url_request/url_request_mock_data_job.h"
19 #include "net/url_request/url_request_filter.h"
20 #include "net/url_request/url_request_test_util.h"
21 #include "testing/gtest/include/gtest/gtest.h"
26 const char kDummyReport
[] = "foo.test";
27 const char kSecondDummyReport
[] = "foo2.test";
29 void MarkURLRequestDestroyed(bool* url_request_destroyed
) {
30 *url_request_destroyed
= true;
33 // Checks that data uploaded in the request matches the test report
34 // data. Erases the sent reports from |expect_reports|.
35 void CheckUploadData(const URLRequest
& request
,
36 std::set
<std::string
>* expect_reports
) {
37 const UploadDataStream
* upload
= request
.get_upload();
39 ASSERT_TRUE(upload
->GetElementReaders());
40 ASSERT_EQ(1u, upload
->GetElementReaders()->size());
42 const UploadBytesElementReader
* reader
=
43 (*upload
->GetElementReaders())[0]->AsBytesReader();
45 std::string
upload_data(reader
->bytes(), reader
->length());
47 EXPECT_EQ(1u, expect_reports
->erase(upload_data
));
50 // A network delegate that lets tests check that a certificate report
51 // was sent. It counts the number of requests and lets tests register a
52 // callback to run when the request is destroyed. It also checks that
53 // the uploaded data is as expected.
54 class TestCertificateReportSenderNetworkDelegate
: public NetworkDelegateImpl
{
56 TestCertificateReportSenderNetworkDelegate()
57 : url_request_destroyed_callback_(base::Bind(&base::DoNothing
)),
58 all_url_requests_destroyed_callback_(base::Bind(&base::DoNothing
)),
60 expect_cookies_(false) {}
62 void ExpectReport(const std::string
& report
) {
63 expect_reports_
.insert(report
);
66 void set_all_url_requests_destroyed_callback(const base::Closure
& callback
) {
67 all_url_requests_destroyed_callback_
= callback
;
70 void set_url_request_destroyed_callback(const base::Closure
& callback
) {
71 url_request_destroyed_callback_
= callback
;
74 void set_expect_url(const GURL
& expect_url
) { expect_url_
= expect_url
; }
76 size_t num_requests() const { return num_requests_
; }
78 // Sets whether cookies are expected to be sent on requests.
79 void set_expect_cookies(bool expect_cookies
) {
80 expect_cookies_
= expect_cookies
;
83 // NetworkDelegateImpl implementation.
84 int OnBeforeURLRequest(URLRequest
* request
,
85 const CompletionCallback
& callback
,
86 GURL
* new_url
) override
{
88 EXPECT_EQ(expect_url_
, request
->url());
89 EXPECT_STRCASEEQ("POST", request
->method().data());
91 if (expect_cookies_
) {
92 EXPECT_FALSE(request
->load_flags() & LOAD_DO_NOT_SEND_COOKIES
);
93 EXPECT_FALSE(request
->load_flags() & LOAD_DO_NOT_SAVE_COOKIES
);
95 EXPECT_TRUE(request
->load_flags() & LOAD_DO_NOT_SEND_COOKIES
);
96 EXPECT_TRUE(request
->load_flags() & LOAD_DO_NOT_SAVE_COOKIES
);
99 CheckUploadData(*request
, &expect_reports_
);
101 // Unconditionally return OK, since the sender ignores the results
106 void OnURLRequestDestroyed(URLRequest
* request
) override
{
107 url_request_destroyed_callback_
.Run();
108 if (expect_reports_
.empty())
109 all_url_requests_destroyed_callback_
.Run();
113 base::Closure url_request_destroyed_callback_
;
114 base::Closure all_url_requests_destroyed_callback_
;
115 size_t num_requests_
;
117 std::set
<std::string
> expect_reports_
;
118 bool expect_cookies_
;
120 DISALLOW_COPY_AND_ASSIGN(TestCertificateReportSenderNetworkDelegate
);
123 class CertificateReportSenderTest
: public ::testing::Test
{
125 CertificateReportSenderTest() : context_(true) {
126 context_
.set_network_delegate(&network_delegate_
);
130 void SetUp() override
{
131 URLRequestFailedJob::AddUrlHandler();
132 URLRequestMockDataJob::AddUrlHandler();
135 void TearDown() override
{ URLRequestFilter::GetInstance()->ClearHandlers(); }
137 TestURLRequestContext
* context() { return &context_
; }
140 void SendReport(CertificateReportSender
* reporter
,
141 const std::string
& report
,
143 size_t request_sequence_number
) {
144 base::RunLoop run_loop
;
145 network_delegate_
.set_url_request_destroyed_callback(
146 run_loop
.QuitClosure());
148 network_delegate_
.set_expect_url(url
);
149 network_delegate_
.ExpectReport(report
);
151 EXPECT_EQ(request_sequence_number
, network_delegate_
.num_requests());
153 reporter
->Send(url
, report
);
155 // The report is sent asynchronously, so wait for the report's
156 // URLRequest to be destroyed before checking that the report was
160 EXPECT_EQ(request_sequence_number
+ 1, network_delegate_
.num_requests());
163 TestCertificateReportSenderNetworkDelegate network_delegate_
;
166 TestURLRequestContext context_
;
169 // Test that CertificateReportSender::Send creates a URLRequest for the
170 // endpoint and sends the expected data.
171 TEST_F(CertificateReportSenderTest
, SendsRequest
) {
172 GURL url
= URLRequestMockDataJob::GetMockHttpsUrl("dummy data", 1);
173 CertificateReportSender
reporter(
174 context(), CertificateReportSender::DO_NOT_SEND_COOKIES
);
175 SendReport(&reporter
, kDummyReport
, url
, 0);
178 TEST_F(CertificateReportSenderTest
, SendMultipleReportsSequentially
) {
179 GURL url
= URLRequestMockDataJob::GetMockHttpsUrl("dummy data", 1);
180 CertificateReportSender
reporter(
181 context(), CertificateReportSender::DO_NOT_SEND_COOKIES
);
182 SendReport(&reporter
, kDummyReport
, url
, 0);
183 SendReport(&reporter
, kDummyReport
, url
, 1);
186 TEST_F(CertificateReportSenderTest
, SendMultipleReportsSimultaneously
) {
187 base::RunLoop run_loop
;
188 network_delegate_
.set_all_url_requests_destroyed_callback(
189 run_loop
.QuitClosure());
191 GURL url
= URLRequestMockDataJob::GetMockHttpsUrl("dummy data", 1);
192 network_delegate_
.set_expect_url(url
);
193 network_delegate_
.ExpectReport(kDummyReport
);
194 network_delegate_
.ExpectReport(kSecondDummyReport
);
196 CertificateReportSender
reporter(
197 context(), CertificateReportSender::DO_NOT_SEND_COOKIES
);
199 EXPECT_EQ(0u, network_delegate_
.num_requests());
201 reporter
.Send(url
, kDummyReport
);
202 reporter
.Send(url
, kSecondDummyReport
);
206 EXPECT_EQ(2u, network_delegate_
.num_requests());
209 // Test that pending URLRequests get cleaned up when the report sender
211 TEST_F(CertificateReportSenderTest
, PendingRequestGetsDeleted
) {
212 bool url_request_destroyed
= false;
213 network_delegate_
.set_url_request_destroyed_callback(base::Bind(
214 &MarkURLRequestDestroyed
, base::Unretained(&url_request_destroyed
)));
216 GURL url
= URLRequestFailedJob::GetMockHttpUrlWithFailurePhase(
217 URLRequestFailedJob::START
, ERR_IO_PENDING
);
218 network_delegate_
.set_expect_url(url
);
219 network_delegate_
.ExpectReport(kDummyReport
);
221 EXPECT_EQ(0u, network_delegate_
.num_requests());
223 scoped_ptr
<CertificateReportSender
> reporter(new CertificateReportSender(
224 context(), CertificateReportSender::DO_NOT_SEND_COOKIES
));
225 reporter
->Send(url
, kDummyReport
);
228 EXPECT_EQ(1u, network_delegate_
.num_requests());
229 EXPECT_TRUE(url_request_destroyed
);
232 // Test that a request that returns an error gets cleaned up.
233 TEST_F(CertificateReportSenderTest
, ErroredRequestGetsDeleted
) {
234 GURL url
= URLRequestFailedJob::GetMockHttpsUrl(ERR_FAILED
);
235 CertificateReportSender
reporter(
236 context(), CertificateReportSender::DO_NOT_SEND_COOKIES
);
237 // SendReport will block until the URLRequest is destroyed.
238 SendReport(&reporter
, kDummyReport
, url
, 0);
241 // Test that cookies are sent or not sent according to the error
242 // reporter's cookies preference.
244 TEST_F(CertificateReportSenderTest
, SendCookiesPreference
) {
245 GURL url
= URLRequestMockDataJob::GetMockHttpsUrl("dummy data", 1);
246 CertificateReportSender
reporter(context(),
247 CertificateReportSender::SEND_COOKIES
);
249 network_delegate_
.set_expect_cookies(true);
250 SendReport(&reporter
, kDummyReport
, url
, 0);
253 TEST_F(CertificateReportSenderTest
, DoNotSendCookiesPreference
) {
254 GURL url
= URLRequestMockDataJob::GetMockHttpsUrl("dummy data", 1);
255 CertificateReportSender
reporter(
256 context(), CertificateReportSender::DO_NOT_SEND_COOKIES
);
258 network_delegate_
.set_expect_cookies(false);
259 SendReport(&reporter
, kDummyReport
, url
, 0);