Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(33)

Side by Side Diff: chrome/browser/safe_browsing/certificate_reporting_service_test_utils.cc

Issue 2543523002: Implement main CertificateReportingService code and add unit tests. (Closed)
Patch Set: estark comments Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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.
4
5 #include "chrome/browser/safe_browsing/certificate_reporting_service_test_utils. h"
6
7 #include "base/threading/thread_task_runner_handle.h"
8 #include "components/certificate_reporting/encrypted_cert_logger.pb.h"
9 #include "content/public/browser/browser_thread.h"
10 #include "content/public/test/test_utils.h"
11 #include "crypto/curve25519.h"
12 #include "net/base/upload_bytes_element_reader.h"
13 #include "net/base/upload_data_stream.h"
14 #include "net/test/url_request/url_request_failed_job.h"
15 #include "net/test/url_request/url_request_mock_data_job.h"
16 #include "net/url_request/url_request_filter.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 namespace {
20
21 const uint32_t kServerPublicKeyTestVersion = 16;
22
23 void SetUpURLHandlersOnIOThread(
24 std::unique_ptr<net::URLRequestInterceptor> url_request_interceptor) {
25 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
26 net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance();
27 filter->AddUrlInterceptor(
28 CertificateReportingService::GetReportingURLForTesting(),
29 std::move(url_request_interceptor));
30 }
31
32 std::string GetUploadData(net::URLRequest* request) {
33 const net::UploadDataStream* stream = request->get_upload();
34 EXPECT_TRUE(stream);
35 EXPECT_TRUE(stream->GetElementReaders());
36 EXPECT_EQ(1u, stream->GetElementReaders()->size());
37 const net::UploadBytesElementReader* reader =
38 (*stream->GetElementReaders())[0]->AsBytesReader();
39 return std::string(reader->bytes(), reader->length());
40 }
41
42 std::string GetReportContents(net::URLRequest* request,
43 const uint8_t* server_private_key) {
44 std::string serialized_report(GetUploadData(request));
45 certificate_reporting::EncryptedCertLoggerRequest encrypted_request;
46 EXPECT_TRUE(encrypted_request.ParseFromString(serialized_report));
47 EXPECT_EQ(kServerPublicKeyTestVersion,
48 encrypted_request.server_public_key_version());
49 EXPECT_EQ(certificate_reporting::EncryptedCertLoggerRequest::
50 AEAD_ECDH_AES_128_CTR_HMAC_SHA256,
51 encrypted_request.algorithm());
52 std::string decrypted_report;
53 certificate_reporting::ErrorReporter::DecryptErrorReport(
54 server_private_key, encrypted_request, &decrypted_report);
55 return decrypted_report;
56 }
57
58 } // namespace
59
60 namespace certificate_reporting_test_utils {
61
62 DelayableCertReportURLRequestJob::DelayableCertReportURLRequestJob(
63 net::URLRequest* request,
64 net::NetworkDelegate* network_delegate)
65 : net::URLRequestJob(request, network_delegate), weak_factory_(this) {}
66
67 DelayableCertReportURLRequestJob::~DelayableCertReportURLRequestJob() {}
68
69 base::WeakPtr<DelayableCertReportURLRequestJob>
70 DelayableCertReportURLRequestJob::GetWeakPtr() {
71 return weak_factory_.GetWeakPtr();
72 }
73
74 void DelayableCertReportURLRequestJob::Start() {
75 started_ = true;
76 if (delayed_) {
77 // Do nothing until Resume() is called.
78 return;
79 }
80 Resume();
81 }
82
83 int DelayableCertReportURLRequestJob::ReadRawData(net::IOBuffer* buf,
84 int buf_size) {
85 // Report sender ignores responses. Return empty response.
86 return 0;
87 }
88
89 int DelayableCertReportURLRequestJob::GetResponseCode() const {
90 // Report sender ignores responses. Return empty response.
91 return 200;
92 }
93
94 void DelayableCertReportURLRequestJob::GetResponseInfo(
95 net::HttpResponseInfo* info) {
96 // Report sender ignores responses. Return empty response.
97 }
98
99 void DelayableCertReportURLRequestJob::Resume() {
100 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
101 DCHECK(delayed_);
102 if (!started_) {
103 // If Start() hasn't been called yet, then unset |delayed_| so
104 // that when Start() is called, the request will begin
105 // immediately.
106 delayed_ = false;
107 return;
108 }
109 // Start reading asynchronously as would a normal network request.
110 base::ThreadTaskRunnerHandle::Get()->PostTask(
111 FROM_HERE,
112 base::Bind(&DelayableCertReportURLRequestJob::NotifyHeadersComplete,
113 weak_factory_.GetWeakPtr()));
114 }
115
116 CertReportJobInterceptor::CertReportJobInterceptor(
117 ReportSendingResult expected_report_result,
118 const uint8_t* server_private_key)
119 : expected_report_result_(expected_report_result),
120 server_private_key_(server_private_key),
121 weak_factory_(this) {}
122
123 CertReportJobInterceptor::~CertReportJobInterceptor() {}
124
125 net::URLRequestJob* CertReportJobInterceptor::MaybeInterceptRequest(
126 net::URLRequest* request,
127 net::NetworkDelegate* network_delegate) const {
128 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
129
130 const std::string uploaded_report =
131 GetReportContents(request, server_private_key_);
132 content::BrowserThread::PostTask(
133 content::BrowserThread::UI, FROM_HERE,
134 base::Bind(&CertReportJobInterceptor::RequestCreated,
135 weak_factory_.GetWeakPtr(), uploaded_report,
136 expected_report_result_));
137
138 if (expected_report_result_ == REPORTS_FAIL) {
139 return new net::URLRequestFailedJob(request, network_delegate,
140 net::ERR_SSL_PROTOCOL_ERROR);
141 } else if (expected_report_result_ == REPORTS_DELAY) {
142 DCHECK(!delayed_request_) << "Supports only one delayed request at a time";
143 DelayableCertReportURLRequestJob* job =
144 new DelayableCertReportURLRequestJob(request, network_delegate);
145 delayed_request_ = job->GetWeakPtr();
146 return job;
147 }
148 // Successful url request job.
149 return new net::URLRequestMockDataJob(request, network_delegate, "some data",
150 1, false);
151 }
152
153 void CertReportJobInterceptor::SetFailureMode(
154 ReportSendingResult expected_report_result) {
155 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
156 content::BrowserThread::PostTask(
157 content::BrowserThread::IO, FROM_HERE,
158 base::Bind(&CertReportJobInterceptor::SetFailureModeOnIOThread,
159 weak_factory_.GetWeakPtr(), expected_report_result));
160 }
161
162 void CertReportJobInterceptor::Resume() {
163 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
164 content::BrowserThread::PostTask(
165 content::BrowserThread::IO, FROM_HERE,
166 base::Bind(&CertReportJobInterceptor::ResumeOnIOThread,
167 base::Unretained(this)));
168 }
169
170 const std::set<std::string>& CertReportJobInterceptor::successful_reports()
171 const {
172 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
173 return successful_reports_;
174 }
175
176 const std::set<std::string>& CertReportJobInterceptor::failed_reports() const {
177 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
178 return failed_reports_;
179 }
180
181 const std::set<std::string>& CertReportJobInterceptor::delayed_reports() const {
182 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
183 return delayed_reports_;
184 }
185
186 void CertReportJobInterceptor::ClearObservedReports() {
187 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
188 successful_reports_.clear();
189 failed_reports_.clear();
190 delayed_reports_.clear();
191 }
192
193 void CertReportJobInterceptor::SetFailureModeOnIOThread(
194 ReportSendingResult expected_report_result) {
195 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
196 expected_report_result_ = expected_report_result;
197 }
198
199 void CertReportJobInterceptor::ResumeOnIOThread() {
200 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
201 EXPECT_EQ(REPORTS_DELAY, expected_report_result_);
202 if (delayed_request_)
203 delayed_request_->Resume();
204 }
205
206 void CertReportJobInterceptor::RequestCreated(
207 const std::string& uploaded_report,
208 ReportSendingResult expected_report_result) {
209 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
210 switch (expected_report_result) {
211 case REPORTS_SUCCESSFUL:
212 successful_reports_.insert(uploaded_report);
213 break;
214 case REPORTS_FAIL:
215 failed_reports_.insert(uploaded_report);
216 break;
217 case REPORTS_DELAY:
218 delayed_reports_.insert(uploaded_report);
219 break;
220 }
221 }
222
223 CertificateReportingServiceTestNetworkDelegate::
224 CertificateReportingServiceTestNetworkDelegate(
225 const base::Callback<void()>& url_request_destroyed_callback)
226 : url_request_destroyed_callback_(url_request_destroyed_callback) {}
227
228 CertificateReportingServiceTestNetworkDelegate::
229 ~CertificateReportingServiceTestNetworkDelegate() {}
230
231 void CertificateReportingServiceTestNetworkDelegate::OnURLRequestDestroyed(
232 net::URLRequest* request) {
233 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
234 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
235 url_request_destroyed_callback_);
236 }
237
238 CertificateReportingServiceTestBase::ReportExpectation::ReportExpectation() {}
239
240 CertificateReportingServiceTestBase::ReportExpectation::ReportExpectation(
241 const ReportExpectation& other) = default;
242
243 CertificateReportingServiceTestBase::ReportExpectation::~ReportExpectation() {}
244
245 // static
246 CertificateReportingServiceTestBase::ReportExpectation
247 CertificateReportingServiceTestBase::ReportExpectation::Successful(
248 const std::set<std::string>& reports) {
249 ReportExpectation expectation;
250 expectation.successful_reports = reports;
251 return expectation;
252 }
253
254 // static
255 CertificateReportingServiceTestBase::ReportExpectation
256 CertificateReportingServiceTestBase::ReportExpectation::Failed(
257 const std::set<std::string>& reports) {
258 ReportExpectation expectation;
259 expectation.failed_reports = reports;
260 return expectation;
261 }
262
263 // static
264 CertificateReportingServiceTestBase::ReportExpectation
265 CertificateReportingServiceTestBase::ReportExpectation::Delayed(
266 const std::set<std::string>& reports) {
267 ReportExpectation expectation;
268 expectation.delayed_reports = reports;
269 return expectation;
270 }
271
272 CertificateReportingServiceTestBase::CertificateReportingServiceTestBase()
273 : num_request_deletions_to_wait_for_(0), num_deleted_requests_(0) {
274 memset(server_private_key_, 1, sizeof(server_private_key_));
275 crypto::curve25519::ScalarBaseMult(server_private_key_, server_public_key_);
276 }
277
278 CertificateReportingServiceTestBase::~CertificateReportingServiceTestBase() {}
279
280 void CertificateReportingServiceTestBase::SetUpInterceptor() {
281 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
282 url_request_interceptor_ =
283 new CertReportJobInterceptor(REPORTS_FAIL, server_private_key_);
284 content::BrowserThread::PostTask(
285 content::BrowserThread::IO, FROM_HERE,
286 base::Bind(
287 &CertificateReportingServiceTestBase::SetUpInterceptorOnIOThread,
288 base::Unretained(this),
289 base::Passed(std::unique_ptr<net::URLRequestInterceptor>(
290 url_request_interceptor_))));
291 }
292
293 void CertificateReportingServiceTestBase::TearDownInterceptor() {
294 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
295 content::BrowserThread::PostTask(
296 content::BrowserThread::IO, FROM_HERE,
297 base::Bind(
298 &CertificateReportingServiceTestBase::TearDownInterceptorOnIOThread,
299 base::Unretained(this)));
300 }
301
302 // Changes the behavior of report uploads to fail or succeed.
303 void CertificateReportingServiceTestBase::SetFailureMode(
304 ReportSendingResult expected_report_result) {
305 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
306 url_request_interceptor_->SetFailureMode(expected_report_result);
307 }
308
309 void CertificateReportingServiceTestBase::ResumeDelayedRequest() {
310 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
311 url_request_interceptor_->Resume();
312 }
313
314 void CertificateReportingServiceTestBase::WaitForRequestsDestroyed(
315 const ReportExpectation& expectation) {
316 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
317 DCHECK(!run_loop_);
318
319 const int num_request_deletions_to_wait_for =
320 expectation.successful_reports.size() +
321 expectation.failed_reports.size() + expectation.delayed_reports.size();
322
323 ASSERT_LE(num_deleted_requests_, num_request_deletions_to_wait_for)
324 << "Observed unexpected report";
325 if (num_deleted_requests_ < num_request_deletions_to_wait_for) {
326 num_request_deletions_to_wait_for_ = num_request_deletions_to_wait_for;
327 run_loop_.reset(new base::RunLoop());
328 run_loop_->Run();
329 run_loop_.reset(nullptr);
330 EXPECT_EQ(0, num_deleted_requests_);
331 EXPECT_EQ(0, num_request_deletions_to_wait_for_);
332 } else if (num_deleted_requests_ == num_request_deletions_to_wait_for) {
333 num_deleted_requests_ = 0;
334 num_request_deletions_to_wait_for_ = 0;
335 }
336 EXPECT_EQ(expectation.successful_reports,
337 url_request_interceptor_->successful_reports());
338 EXPECT_EQ(expectation.failed_reports,
339 url_request_interceptor_->failed_reports());
340 EXPECT_EQ(expectation.delayed_reports,
341 url_request_interceptor_->delayed_reports());
342 url_request_interceptor_->ClearObservedReports();
343 }
344
345 uint8_t* CertificateReportingServiceTestBase::server_public_key() {
346 return server_public_key_;
347 }
348
349 uint32_t CertificateReportingServiceTestBase::server_public_key_version()
350 const {
351 return kServerPublicKeyTestVersion;
352 }
353
354 net::NetworkDelegate* CertificateReportingServiceTestBase::network_delegate() {
355 return network_delegate_.get();
356 }
357
358 void CertificateReportingServiceTestBase::SetUpInterceptorOnIOThread(
359 std::unique_ptr<net::URLRequestInterceptor> url_request_interceptor) {
360 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
361 network_delegate_.reset(new CertificateReportingServiceTestNetworkDelegate(
362 base::Bind(&CertificateReportingServiceTestBase::OnURLRequestDestroyed,
363 base::Unretained(this))));
364 SetUpURLHandlersOnIOThread(std::move(url_request_interceptor));
365 }
366
367 void CertificateReportingServiceTestBase::TearDownInterceptorOnIOThread() {
368 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
369 network_delegate_.reset(nullptr);
370 }
371
372 void CertificateReportingServiceTestBase::OnURLRequestDestroyed() {
373 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
374 num_deleted_requests_++;
375 if (!run_loop_) {
376 return;
377 }
378 EXPECT_LE(num_deleted_requests_, num_request_deletions_to_wait_for_);
379 if (num_deleted_requests_ == num_request_deletions_to_wait_for_) {
380 num_request_deletions_to_wait_for_ = 0;
381 num_deleted_requests_ = 0;
382 run_loop_->Quit();
383 }
384 }
385
386 } // namespace certificate_reporting_test_utils
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698