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"
27 const char kDummyReport
[] = "foo.test";
28 const char kSecondDummyReport
[] = "foo2.test";
30 void MarkURLRequestDestroyed(bool* url_request_destroyed
) {
31 *url_request_destroyed
= true;
34 void SetUrlRequestMocksEnabled(bool enable
) {
35 URLRequestFilter::GetInstance()->ClearHandlers();
39 URLRequestFailedJob::AddUrlHandler();
40 URLRequestMockDataJob::AddUrlHandler();
43 // Check that data uploaded in the request matches the test report
44 // data. The sent reports will be erased from |expect_reports|.
45 void CheckUploadData(URLRequest
* request
,
46 std::set
<std::string
>* expect_reports
) {
47 const UploadDataStream
* upload
= request
->get_upload();
49 ASSERT_TRUE(upload
->GetElementReaders());
50 ASSERT_EQ(1u, upload
->GetElementReaders()->size());
52 const UploadBytesElementReader
* reader
=
53 (*upload
->GetElementReaders())[0]->AsBytesReader();
55 std::string
upload_data(reader
->bytes(), reader
->length());
57 EXPECT_EQ(1u, expect_reports
->erase(upload_data
));
60 // A network delegate that lets tests check that a certificate report
61 // was sent. It counts the number of requests and lets tests register a
62 // callback to run when the request is destroyed. It also checks that
63 // the uploaded data is as expected.
64 class TestCertificateReportSenderNetworkDelegate
: public NetworkDelegateImpl
{
66 TestCertificateReportSenderNetworkDelegate()
67 : url_request_destroyed_callback_(base::Bind(&base::DoNothing
)),
68 all_url_requests_destroyed_callback_(base::Bind(&base::DoNothing
)),
70 expect_cookies_(false) {}
72 ~TestCertificateReportSenderNetworkDelegate() override
{}
74 void ExpectReport(const std::string
& report
) {
75 expect_reports_
.insert(report
);
78 void set_all_url_requests_destroyed_callback(
79 const base::Closure
& all_url_requests_destroyed_callback
) {
80 all_url_requests_destroyed_callback_
= all_url_requests_destroyed_callback
;
83 void set_url_request_destroyed_callback(
84 const base::Closure
& url_request_destroyed_callback
) {
85 url_request_destroyed_callback_
= url_request_destroyed_callback
;
88 void set_expect_url(const GURL
& expect_url
) { expect_url_
= expect_url
; }
90 size_t num_requests() const { return num_requests_
; }
92 // Sets whether cookies are expected to be sent on requests.
93 void set_expect_cookies(bool expect_cookies
) {
94 expect_cookies_
= expect_cookies
;
97 // NetworkDelegateImpl implementation
98 int OnBeforeURLRequest(URLRequest
* request
,
99 const CompletionCallback
& callback
,
100 GURL
* new_url
) override
{
102 EXPECT_EQ(expect_url_
, request
->url());
103 EXPECT_STRCASEEQ("POST", request
->method().data());
105 if (expect_cookies_
) {
106 EXPECT_FALSE(request
->load_flags() & LOAD_DO_NOT_SEND_COOKIES
);
107 EXPECT_FALSE(request
->load_flags() & LOAD_DO_NOT_SAVE_COOKIES
);
109 EXPECT_TRUE(request
->load_flags() & LOAD_DO_NOT_SEND_COOKIES
);
110 EXPECT_TRUE(request
->load_flags() & LOAD_DO_NOT_SAVE_COOKIES
);
113 CheckUploadData(request
, &expect_reports_
);
117 void OnURLRequestDestroyed(URLRequest
* request
) override
{
118 url_request_destroyed_callback_
.Run();
119 if (expect_reports_
.empty())
120 all_url_requests_destroyed_callback_
.Run();
124 base::Closure url_request_destroyed_callback_
;
125 base::Closure all_url_requests_destroyed_callback_
;
126 size_t num_requests_
;
128 std::set
<std::string
> expect_reports_
;
129 bool expect_cookies_
;
131 DISALLOW_COPY_AND_ASSIGN(TestCertificateReportSenderNetworkDelegate
);
134 class CertificateReportSenderTest
: public ::testing::Test
{
136 CertificateReportSenderTest() : context_(true) {
137 SetUrlRequestMocksEnabled(true);
138 context_
.set_network_delegate(&network_delegate_
);
142 ~CertificateReportSenderTest() override
{ SetUrlRequestMocksEnabled(false); }
144 TestCertificateReportSenderNetworkDelegate
* network_delegate() {
145 return &network_delegate_
;
148 TestURLRequestContext
* context() { return &context_
; }
151 void SendReport(CertificateReportSender
* reporter
,
152 const std::string
& report
,
154 size_t request_sequence_number
) {
155 base::RunLoop run_loop
;
156 network_delegate_
.set_url_request_destroyed_callback(
157 run_loop
.QuitClosure());
159 network_delegate_
.set_expect_url(url
);
160 network_delegate_
.ExpectReport(report
);
162 EXPECT_EQ(request_sequence_number
, network_delegate_
.num_requests());
164 reporter
->Send(url
, report
);
166 // The report is sent asynchronously, so wait for the report's
167 // URLRequest to be destroyed before checking that the report was
171 EXPECT_EQ(request_sequence_number
+ 1, network_delegate_
.num_requests());
175 TestCertificateReportSenderNetworkDelegate network_delegate_
;
176 TestURLRequestContext context_
;
179 // Test that CertificateReportSender::Send creates a URLRequest for the
180 // endpoint and sends the expected data.
181 TEST_F(CertificateReportSenderTest
, SendsRequest
) {
182 GURL url
= URLRequestMockDataJob::GetMockHttpsUrl("dummy data", 1);
183 CertificateReportSender
reporter(
184 context(), CertificateReportSender::DO_NOT_SEND_COOKIES
);
185 SendReport(&reporter
, kDummyReport
, url
, 0);
188 TEST_F(CertificateReportSenderTest
, SendMultipleReportsSequentially
) {
189 GURL url
= URLRequestMockDataJob::GetMockHttpsUrl("dummy data", 1);
190 CertificateReportSender
reporter(
191 context(), CertificateReportSender::DO_NOT_SEND_COOKIES
);
192 SendReport(&reporter
, kDummyReport
, url
, 0);
193 SendReport(&reporter
, kDummyReport
, url
, 1);
196 TEST_F(CertificateReportSenderTest
, SendMultipleReportsSimultaneously
) {
197 base::RunLoop run_loop
;
198 network_delegate()->set_all_url_requests_destroyed_callback(
199 run_loop
.QuitClosure());
201 GURL url
= URLRequestMockDataJob::GetMockHttpsUrl("dummy data", 1);
202 network_delegate()->set_expect_url(url
);
203 network_delegate()->ExpectReport(kDummyReport
);
204 network_delegate()->ExpectReport(kSecondDummyReport
);
206 CertificateReportSender
reporter(
207 context(), CertificateReportSender::DO_NOT_SEND_COOKIES
);
209 EXPECT_EQ(0u, network_delegate()->num_requests());
211 reporter
.Send(url
, kDummyReport
);
212 reporter
.Send(url
, kSecondDummyReport
);
216 EXPECT_EQ(2u, network_delegate()->num_requests());
219 // Test that pending URLRequests get cleaned up when the report sender
221 TEST_F(CertificateReportSenderTest
, PendingRequestGetsDeleted
) {
222 bool url_request_destroyed
= false;
223 network_delegate()->set_url_request_destroyed_callback(base::Bind(
224 &MarkURLRequestDestroyed
, base::Unretained(&url_request_destroyed
)));
226 GURL url
= URLRequestFailedJob::GetMockHttpUrlWithFailurePhase(
227 URLRequestFailedJob::START
, ERR_IO_PENDING
);
228 network_delegate()->set_expect_url(url
);
229 network_delegate()->ExpectReport(kDummyReport
);
231 EXPECT_EQ(0u, network_delegate()->num_requests());
233 scoped_ptr
<CertificateReportSender
> reporter(new CertificateReportSender(
234 context(), CertificateReportSender::DO_NOT_SEND_COOKIES
));
235 reporter
->Send(url
, kDummyReport
);
238 EXPECT_EQ(1u, network_delegate()->num_requests());
239 EXPECT_TRUE(url_request_destroyed
);
242 // Test that a request that returns an error gets cleaned up.
243 TEST_F(CertificateReportSenderTest
, ErroredRequestGetsDeleted
) {
244 GURL url
= URLRequestFailedJob::GetMockHttpsUrl(ERR_FAILED
);
245 CertificateReportSender
reporter(
246 context(), CertificateReportSender::DO_NOT_SEND_COOKIES
);
247 // SendReport will block until the URLRequest is destroyed.
248 SendReport(&reporter
, kDummyReport
, url
, 0);
251 // Test that cookies are sent or not sent according to the error
252 // reporter's cookies preference.
254 TEST_F(CertificateReportSenderTest
, SendCookiesPreference
) {
255 GURL url
= URLRequestMockDataJob::GetMockHttpsUrl("dummy data", 1);
256 CertificateReportSender
reporter(context(),
257 CertificateReportSender::SEND_COOKIES
);
259 network_delegate()->set_expect_cookies(true);
260 SendReport(&reporter
, kDummyReport
, url
, 0);
263 TEST_F(CertificateReportSenderTest
, DoNotSendCookiesPreference
) {
264 GURL url
= URLRequestMockDataJob::GetMockHttpsUrl("dummy data", 1);
265 CertificateReportSender
reporter(
266 context(), CertificateReportSender::DO_NOT_SEND_COOKIES
);
268 network_delegate()->set_expect_cookies(false);
269 SendReport(&reporter
, kDummyReport
, url
, 0);