1 // Copyright 2017 The Chromium Authors
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 "net/reporting/reporting_delivery_agent.h"
6
7 #include <vector>
8
9 #include "base/json/json_reader.h"
10 #include "base/test/metrics/histogram_tester.h"
11 #include "base/test/scoped_feature_list.h"
12 #include "base/test/simple_test_tick_clock.h"
13 #include "base/test/values_test_util.h"
14 #include "base/time/time.h"
15 #include "base/timer/mock_timer.h"
16 #include "base/unguessable_token.h"
17 #include "base/values.h"
18 #include "net/base/backoff_entry.h"
19 #include "net/base/features.h"
20 #include "net/base/isolation_info.h"
21 #include "net/base/network_anonymization_key.h"
22 #include "net/base/schemeful_site.h"
23 #include "net/reporting/reporting_cache.h"
24 #include "net/reporting/reporting_report.h"
25 #include "net/reporting/reporting_test_util.h"
26 #include "net/reporting/reporting_uploader.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 #include "third_party/abseil-cpp/absl/types/optional.h"
29 #include "url/gurl.h"
30 #include "url/origin.h"
31
32 namespace net {
33 namespace {
34
35 constexpr char kReportingUploadHeaderTypeHistogram[] =
36 "Net.Reporting.UploadHeaderType";
37
38 class ReportingDeliveryAgentTest : public ReportingTestBase {
39 protected:
ReportingDeliveryAgentTest()40 ReportingDeliveryAgentTest() {
41 // This is a private API of the reporting service, so no need to test the
42 // case kPartitionNelAndReportingByNetworkIsolationKey is disabled - the
43 // feature is only applied at the entry points of the service.
44 feature_list_.InitAndEnableFeature(
45 features::kPartitionNelAndReportingByNetworkIsolationKey);
46
47 ReportingPolicy policy;
48 policy.endpoint_backoff_policy.num_errors_to_ignore = 0;
49 policy.endpoint_backoff_policy.initial_delay_ms = 60000;
50 policy.endpoint_backoff_policy.multiply_factor = 2.0;
51 policy.endpoint_backoff_policy.jitter_factor = 0.0;
52 policy.endpoint_backoff_policy.maximum_backoff_ms = -1;
53 policy.endpoint_backoff_policy.entry_lifetime_ms = 0;
54 policy.endpoint_backoff_policy.always_use_initial_delay = false;
55 UsePolicy(policy);
56 }
57
AddReport(const absl::optional<base::UnguessableToken> & reporting_source,const NetworkAnonymizationKey & network_anonymization_key,const GURL & url,const std::string & group)58 void AddReport(const absl::optional<base::UnguessableToken>& reporting_source,
59 const NetworkAnonymizationKey& network_anonymization_key,
60 const GURL& url,
61 const std::string& group) {
62 base::Value::Dict report_body;
63 report_body.Set("key", "value");
64 cache()->AddReport(reporting_source, network_anonymization_key, url,
65 kUserAgent_, group, kType_, std::move(report_body),
66 0 /* depth */, tick_clock()->NowTicks() /* queued */,
67 0 /* attempts */);
68 }
69
70 // The first report added to the cache is uploaded immediately, and a timer is
71 // started for all subsequent reports (which may then be batched). To test
72 // behavior involving batching multiple reports, we need to add, upload, and
73 // immediately resolve a dummy report to prime the delivery timer.
UploadFirstReportAndStartTimer()74 void UploadFirstReportAndStartTimer() {
75 ReportingEndpointGroupKey dummy_group(
76 NetworkAnonymizationKey(),
77 url::Origin::Create(GURL("https://dummy.test")), "dummy");
78 ASSERT_TRUE(SetEndpointInCache(
79 dummy_group, GURL("https://dummy.test/upload"), kExpires_));
80 AddReport(absl::nullopt, dummy_group.network_anonymization_key,
81 dummy_group.origin.GetURL(), dummy_group.group_name);
82
83 ASSERT_EQ(1u, pending_uploads().size());
84 pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
85 EXPECT_EQ(0u, pending_uploads().size());
86 EXPECT_TRUE(delivery_timer()->IsRunning());
87 }
88
89 // Prime delivery timer with a document report with a endpoint group that
90 // has matching reporting_source.
UploadFirstDocumentReportAndStartTimer()91 void UploadFirstDocumentReportAndStartTimer() {
92 ReportingEndpointGroupKey dummy_group(
93 kNik_, kDocumentReportingSource_,
94 url::Origin::Create(GURL("https://dummy.test")), "dummy");
95 SetV1EndpointInCache(dummy_group, kDocumentReportingSource_,
96 kIsolationInfo_, GURL("https://dummy.test/upload"));
97 AddReport(kDocumentReportingSource_, dummy_group.network_anonymization_key,
98 dummy_group.origin.GetURL(), dummy_group.group_name);
99
100 ASSERT_EQ(1u, pending_uploads().size());
101 pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
102 EXPECT_EQ(0u, pending_uploads().size());
103 EXPECT_TRUE(delivery_timer()->IsRunning());
104 }
105
SendReportsForSource(base::UnguessableToken reporting_source)106 void SendReportsForSource(base::UnguessableToken reporting_source) {
107 delivery_agent()->SendReportsForSource(reporting_source);
108 }
109
110 base::test::ScopedFeatureList feature_list_;
111
112 const GURL kUrl_ = GURL("https://origin/path");
113 const GURL kOtherUrl_ = GURL("https://other-origin/path");
114 const GURL kSubdomainUrl_ = GURL("https://sub.origin/path");
115 const url::Origin kOrigin_ = url::Origin::Create(GURL("https://origin/"));
116 const url::Origin kOtherOrigin_ =
117 url::Origin::Create(GURL("https://other-origin/"));
118 const absl::optional<base::UnguessableToken> kEmptyReportingSource_ =
119 absl::nullopt;
120 const base::UnguessableToken kDocumentReportingSource_ =
121 base::UnguessableToken::Create();
122 const NetworkAnonymizationKey kNik_ =
123 NetworkAnonymizationKey::CreateSameSite(SchemefulSite(kOrigin_));
124 const NetworkAnonymizationKey kOtherNik_ =
125 NetworkAnonymizationKey::CreateSameSite(SchemefulSite(kOtherOrigin_));
126 const IsolationInfo kIsolationInfo_ =
127 IsolationInfo::Create(IsolationInfo::RequestType::kOther,
128 kOrigin_,
129 kOrigin_,
130 SiteForCookies::FromOrigin(kOrigin_));
131 const IsolationInfo kOtherIsolationInfo_ =
132 IsolationInfo::Create(IsolationInfo::RequestType::kOther,
133 kOtherOrigin_,
134 kOtherOrigin_,
135 SiteForCookies::FromOrigin(kOtherOrigin_));
136 const GURL kEndpoint_ = GURL("https://endpoint/");
137 const std::string kUserAgent_ = "Mozilla/1.0";
138 const std::string kGroup_ = "group";
139 const std::string kType_ = "type";
140 const base::Time kExpires_ = base::Time::Now() + base::Days(7);
141 const ReportingEndpointGroupKey kGroupKey_ =
142 ReportingEndpointGroupKey(kNik_, kOrigin_, kGroup_);
143 const ReportingEndpointGroupKey kDocumentGroupKey_ =
144 ReportingEndpointGroupKey(kGroupKey_, kDocumentReportingSource_);
145 };
146
TEST_F(ReportingDeliveryAgentTest,SuccessfulImmediateUpload)147 TEST_F(ReportingDeliveryAgentTest, SuccessfulImmediateUpload) {
148 base::HistogramTester histograms;
149 ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
150 AddReport(kEmptyReportingSource_, kNik_, kUrl_, kGroup_);
151
152 // Upload is automatically started when cache is modified.
153
154 ASSERT_EQ(1u, pending_uploads().size());
155 EXPECT_EQ(kEndpoint_, pending_uploads()[0]->url());
156 {
157 auto value = pending_uploads()[0]->GetValue();
158
159 ASSERT_TRUE(value->is_list());
160 ASSERT_EQ(1u, value->GetList().size());
161
162 const base::Value& report = value->GetList()[0];
163 ASSERT_TRUE(report.is_dict());
164 const base::Value::Dict& report_dict = report.GetDict();
165 EXPECT_EQ(5u, report_dict.size());
166
167 ExpectDictIntegerValue(0, report_dict, "age");
168 ExpectDictStringValue(kType_, report_dict, "type");
169 ExpectDictStringValue(kUrl_.spec(), report_dict, "url");
170 ExpectDictStringValue(kUserAgent_, report_dict, "user_agent");
171 const base::Value::Dict* body = report_dict.FindDict("body");
172 EXPECT_EQ("value", *body->FindString("key"));
173 }
174 pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
175
176 // Successful upload should remove delivered reports.
177 std::vector<const ReportingReport*> reports;
178 cache()->GetReports(&reports);
179 EXPECT_TRUE(reports.empty());
180 histograms.ExpectBucketCount(
181 kReportingUploadHeaderTypeHistogram,
182 ReportingDeliveryAgent::ReportingUploadHeaderType::kReportTo, 1);
183 histograms.ExpectBucketCount(
184 kReportingUploadHeaderTypeHistogram,
185 ReportingDeliveryAgent::ReportingUploadHeaderType::kReportingEndpoints,
186 0);
187
188 {
189 ReportingEndpoint::Statistics stats =
190 GetEndpointStatistics(kGroupKey_, kEndpoint_);
191 EXPECT_EQ(1, stats.attempted_uploads);
192 EXPECT_EQ(1, stats.successful_uploads);
193 EXPECT_EQ(1, stats.attempted_reports);
194 EXPECT_EQ(1, stats.successful_reports);
195 }
196
197 // TODO(dcreager): Check that BackoffEntry was informed of success.
198 }
199
TEST_F(ReportingDeliveryAgentTest,ReportToHeaderCountedCorrectly)200 TEST_F(ReportingDeliveryAgentTest, ReportToHeaderCountedCorrectly) {
201 base::HistogramTester histograms;
202
203 // Set an endpoint with no reporting source (as if configured with the
204 // Report-To header).
205 ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
206
207 // Add and upload a report with an associated source.
208 AddReport(kDocumentReportingSource_, kNik_, kUrl_, kGroup_);
209 pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
210
211 // Successful upload should count this as a Report-To delivery, even though
212 // the report itself had a reporting source.
213 histograms.ExpectBucketCount(
214 kReportingUploadHeaderTypeHistogram,
215 ReportingDeliveryAgent::ReportingUploadHeaderType::kReportTo, 1);
216 histograms.ExpectBucketCount(
217 kReportingUploadHeaderTypeHistogram,
218 ReportingDeliveryAgent::ReportingUploadHeaderType::kReportingEndpoints,
219 0);
220 }
221
TEST_F(ReportingDeliveryAgentTest,SuccessfulImmediateUploadDocumentReport)222 TEST_F(ReportingDeliveryAgentTest, SuccessfulImmediateUploadDocumentReport) {
223 base::HistogramTester histograms;
224
225 SetV1EndpointInCache(kDocumentGroupKey_, kDocumentReportingSource_,
226 kIsolationInfo_, kEndpoint_);
227 AddReport(kDocumentReportingSource_, kNik_, kUrl_, kGroup_);
228
229 // Upload is automatically started when cache is modified.
230
231 ASSERT_EQ(1u, pending_uploads().size());
232 EXPECT_EQ(kEndpoint_, pending_uploads()[0]->url());
233 {
234 const auto value = pending_uploads()[0]->GetValue();
235
236 ASSERT_TRUE(value->is_list());
237 ASSERT_EQ(1u, value->GetList().size());
238
239 const base::Value& report = value->GetList()[0];
240 ASSERT_TRUE(report.is_dict());
241 const base::Value::Dict& report_dict = report.GetDict();
242
243 ExpectDictIntegerValue(0, report_dict, "age");
244 ExpectDictStringValue(kType_, report_dict, "type");
245 ExpectDictStringValue(kUrl_.spec(), report_dict, "url");
246 ExpectDictStringValue(kUserAgent_, report_dict, "user_agent");
247 const base::Value::Dict* body = report_dict.FindDict("body");
248 EXPECT_EQ("value", *body->FindString("key"));
249 }
250 pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
251
252 // Successful upload should remove delivered reports.
253 std::vector<const ReportingReport*> reports;
254 cache()->GetReports(&reports);
255 EXPECT_TRUE(reports.empty());
256 histograms.ExpectBucketCount(
257 kReportingUploadHeaderTypeHistogram,
258 ReportingDeliveryAgent::ReportingUploadHeaderType::kReportingEndpoints,
259 1);
260 histograms.ExpectBucketCount(
261 kReportingUploadHeaderTypeHistogram,
262 ReportingDeliveryAgent::ReportingUploadHeaderType::kReportTo, 0);
263
264 {
265 ReportingEndpoint::Statistics stats =
266 GetEndpointStatistics(kDocumentGroupKey_, kEndpoint_);
267 EXPECT_EQ(1, stats.attempted_uploads);
268 EXPECT_EQ(1, stats.successful_uploads);
269 EXPECT_EQ(1, stats.attempted_reports);
270 EXPECT_EQ(1, stats.successful_reports);
271 }
272 }
273
TEST_F(ReportingDeliveryAgentTest,UploadHeaderTypeEnumCountPerReport)274 TEST_F(ReportingDeliveryAgentTest, UploadHeaderTypeEnumCountPerReport) {
275 UploadFirstDocumentReportAndStartTimer();
276 base::HistogramTester histograms;
277
278 SetV1EndpointInCache(kDocumentGroupKey_, kDocumentReportingSource_,
279 kIsolationInfo_, kEndpoint_);
280 AddReport(kDocumentReportingSource_, kNik_, kUrl_, kGroup_);
281 AddReport(kDocumentReportingSource_, kNik_, kUrl_, kGroup_);
282
283 // There should be one upload per (NIK, origin, reporting source).
284 EXPECT_TRUE(delivery_timer()->IsRunning());
285 delivery_timer()->Fire();
286
287 ASSERT_EQ(1u, pending_uploads().size());
288 pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
289
290 // Successful upload should remove delivered reports.
291 std::vector<const ReportingReport*> reports;
292 cache()->GetReports(&reports);
293 EXPECT_TRUE(reports.empty());
294 histograms.ExpectBucketCount(
295 kReportingUploadHeaderTypeHistogram,
296 ReportingDeliveryAgent::ReportingUploadHeaderType::kReportingEndpoints,
297 2);
298 histograms.ExpectBucketCount(
299 kReportingUploadHeaderTypeHistogram,
300 ReportingDeliveryAgent::ReportingUploadHeaderType::kReportTo, 0);
301 }
302
TEST_F(ReportingDeliveryAgentTest,SuccessfulImmediateSubdomainUpload)303 TEST_F(ReportingDeliveryAgentTest, SuccessfulImmediateSubdomainUpload) {
304 ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_,
305 OriginSubdomains::INCLUDE));
306 AddReport(kEmptyReportingSource_, kNik_, kSubdomainUrl_, kGroup_);
307
308 // Upload is automatically started when cache is modified.
309
310 ASSERT_EQ(1u, pending_uploads().size());
311 EXPECT_EQ(kEndpoint_, pending_uploads()[0]->url());
312 {
313 auto value = pending_uploads()[0]->GetValue();
314
315 ASSERT_TRUE(value->is_list());
316 ASSERT_EQ(1u, value->GetList().size());
317
318 const base::Value& report = value->GetList()[0];
319 ASSERT_TRUE(report.is_dict());
320 const base::Value::Dict& report_dict = report.GetDict();
321 EXPECT_EQ(5u, report_dict.size());
322
323 ExpectDictIntegerValue(0, report_dict, "age");
324 ExpectDictStringValue(kType_, report_dict, "type");
325 ExpectDictStringValue(kSubdomainUrl_.spec(), report_dict, "url");
326 ExpectDictStringValue(kUserAgent_, report_dict, "user_agent");
327 const base::Value::Dict* body = report_dict.FindDict("body");
328 EXPECT_EQ("value", *body->FindString("key"));
329 }
330 pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
331
332 // Successful upload should remove delivered reports.
333 std::vector<const ReportingReport*> reports;
334 cache()->GetReports(&reports);
335 EXPECT_TRUE(reports.empty());
336
337 {
338 ReportingEndpoint::Statistics stats =
339 GetEndpointStatistics(kGroupKey_, kEndpoint_);
340 EXPECT_EQ(1, stats.attempted_uploads);
341 EXPECT_EQ(1, stats.successful_uploads);
342 EXPECT_EQ(1, stats.attempted_reports);
343 EXPECT_EQ(1, stats.successful_reports);
344 }
345
346 // TODO(dcreager): Check that BackoffEntry was informed of success.
347 }
348
TEST_F(ReportingDeliveryAgentTest,SuccessfulImmediateSubdomainUploadWithOverwrittenEndpoint)349 TEST_F(ReportingDeliveryAgentTest,
350 SuccessfulImmediateSubdomainUploadWithOverwrittenEndpoint) {
351 ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_,
352 OriginSubdomains::INCLUDE));
353 AddReport(kEmptyReportingSource_, kNik_, kSubdomainUrl_, kGroup_);
354
355 // Upload is automatically started when cache is modified.
356
357 ASSERT_EQ(1u, pending_uploads().size());
358 // Change the endpoint group to exclude subdomains.
359 ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_,
360 OriginSubdomains::EXCLUDE));
361 pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
362
363 {
364 ReportingEndpoint::Statistics stats =
365 GetEndpointStatistics(kGroupKey_, kEndpoint_);
366 EXPECT_EQ(1, stats.attempted_uploads);
367 EXPECT_EQ(1, stats.successful_uploads);
368 EXPECT_EQ(1, stats.attempted_reports);
369 EXPECT_EQ(1, stats.successful_reports);
370 }
371
372 // Successful upload should remove delivered reports.
373 std::vector<const ReportingReport*> reports;
374 cache()->GetReports(&reports);
375 EXPECT_TRUE(reports.empty());
376 }
377
TEST_F(ReportingDeliveryAgentTest,SuccessfulDelayedUpload)378 TEST_F(ReportingDeliveryAgentTest, SuccessfulDelayedUpload) {
379 // Trigger and complete an upload to start the delivery timer.
380 ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
381 AddReport(kEmptyReportingSource_, kNik_, kUrl_, kGroup_);
382 pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
383
384 // Add another report to upload after a delay.
385 AddReport(kEmptyReportingSource_, kNik_, kUrl_, kGroup_);
386
387 EXPECT_TRUE(delivery_timer()->IsRunning());
388 delivery_timer()->Fire();
389
390 ASSERT_EQ(1u, pending_uploads().size());
391 EXPECT_EQ(kEndpoint_, pending_uploads()[0]->url());
392 {
393 auto value = pending_uploads()[0]->GetValue();
394
395 ASSERT_TRUE(value->is_list());
396 ASSERT_EQ(1u, value->GetList().size());
397
398 const base::Value& report = value->GetList()[0];
399 ASSERT_TRUE(report.is_dict());
400 const base::Value::Dict& report_dict = report.GetDict();
401 EXPECT_EQ(5u, report_dict.size());
402
403 ExpectDictIntegerValue(0, report_dict, "age");
404 ExpectDictStringValue(kType_, report_dict, "type");
405 ExpectDictStringValue(kUrl_.spec(), report_dict, "url");
406 ExpectDictStringValue(kUserAgent_, report_dict, "user_agent");
407 const base::Value::Dict* body = report_dict.FindDict("body");
408 EXPECT_EQ("value", *body->FindString("key"));
409 }
410 pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
411
412 {
413 ReportingEndpoint::Statistics stats =
414 GetEndpointStatistics(kGroupKey_, kEndpoint_);
415 EXPECT_EQ(2, stats.attempted_uploads);
416 EXPECT_EQ(2, stats.successful_uploads);
417 EXPECT_EQ(2, stats.attempted_reports);
418 EXPECT_EQ(2, stats.successful_reports);
419 }
420
421 // Successful upload should remove delivered reports.
422 std::vector<const ReportingReport*> reports;
423 cache()->GetReports(&reports);
424 EXPECT_TRUE(reports.empty());
425
426 // TODO(juliatuttle): Check that BackoffEntry was informed of success.
427 }
428
TEST_F(ReportingDeliveryAgentTest,FailedUpload)429 TEST_F(ReportingDeliveryAgentTest, FailedUpload) {
430 ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
431 AddReport(kEmptyReportingSource_, kNik_, kUrl_, kGroup_);
432
433 EXPECT_TRUE(delivery_timer()->IsRunning());
434 delivery_timer()->Fire();
435
436 ASSERT_EQ(1u, pending_uploads().size());
437 pending_uploads()[0]->Complete(ReportingUploader::Outcome::FAILURE);
438
439 {
440 ReportingEndpoint::Statistics stats =
441 GetEndpointStatistics(kGroupKey_, kEndpoint_);
442 EXPECT_EQ(1, stats.attempted_uploads);
443 EXPECT_EQ(0, stats.successful_uploads);
444 EXPECT_EQ(1, stats.attempted_reports);
445 EXPECT_EQ(0, stats.successful_reports);
446 }
447
448 // Failed upload should increment reports' attempts.
449 std::vector<const ReportingReport*> reports;
450 cache()->GetReports(&reports);
451 ASSERT_EQ(1u, reports.size());
452 EXPECT_EQ(1, reports[0]->attempts);
453
454 // Since endpoint is now failing, an upload won't be started despite a pending
455 // report.
456 ASSERT_TRUE(pending_uploads().empty());
457 EXPECT_TRUE(delivery_timer()->IsRunning());
458 delivery_timer()->Fire();
459 EXPECT_TRUE(pending_uploads().empty());
460
461 {
462 ReportingEndpoint::Statistics stats =
463 GetEndpointStatistics(kGroupKey_, kEndpoint_);
464 EXPECT_EQ(1, stats.attempted_uploads);
465 EXPECT_EQ(0, stats.successful_uploads);
466 EXPECT_EQ(1, stats.attempted_reports);
467 EXPECT_EQ(0, stats.successful_reports);
468 }
469 }
470
TEST_F(ReportingDeliveryAgentTest,DisallowedUpload)471 TEST_F(ReportingDeliveryAgentTest, DisallowedUpload) {
472 // This mimics the check that is controlled by the BACKGROUND_SYNC permission
473 // in a real browser profile.
474 context()->test_delegate()->set_disallow_report_uploads(true);
475
476 static const int kAgeMillis = 12345;
477
478 ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
479 AddReport(kEmptyReportingSource_, kNik_, kUrl_, kGroup_);
480
481 tick_clock()->Advance(base::Milliseconds(kAgeMillis));
482
483 EXPECT_TRUE(delivery_timer()->IsRunning());
484 delivery_timer()->Fire();
485
486 // We should not try to upload the report, since we weren't given permission
487 // for this origin.
488 EXPECT_TRUE(pending_uploads().empty());
489
490 {
491 ReportingEndpoint::Statistics stats =
492 GetEndpointStatistics(kGroupKey_, kEndpoint_);
493 EXPECT_EQ(0, stats.attempted_uploads);
494 EXPECT_EQ(0, stats.successful_uploads);
495 EXPECT_EQ(0, stats.attempted_reports);
496 EXPECT_EQ(0, stats.successful_reports);
497 }
498
499 // Disallowed reports should NOT have been removed from the cache.
500 std::vector<const ReportingReport*> reports;
501 cache()->GetReports(&reports);
502 EXPECT_EQ(1u, reports.size());
503 }
504
TEST_F(ReportingDeliveryAgentTest,RemoveEndpointUpload)505 TEST_F(ReportingDeliveryAgentTest, RemoveEndpointUpload) {
506 static const ReportingEndpointGroupKey kOtherGroupKey(kNik_, kOtherOrigin_,
507 kGroup_);
508
509 ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
510 ASSERT_TRUE(SetEndpointInCache(kOtherGroupKey, kEndpoint_, kExpires_));
511
512 AddReport(kEmptyReportingSource_, kNik_, kUrl_, kGroup_);
513
514 EXPECT_TRUE(delivery_timer()->IsRunning());
515 delivery_timer()->Fire();
516
517 ASSERT_EQ(1u, pending_uploads().size());
518 pending_uploads()[0]->Complete(ReportingUploader::Outcome::REMOVE_ENDPOINT);
519
520 // "Remove endpoint" upload should remove endpoint from *all* origins and
521 // increment reports' attempts.
522 std::vector<const ReportingReport*> reports;
523 cache()->GetReports(&reports);
524 ASSERT_EQ(1u, reports.size());
525 EXPECT_EQ(1, reports[0]->attempts);
526
527 EXPECT_FALSE(FindEndpointInCache(kGroupKey_, kEndpoint_));
528 EXPECT_FALSE(FindEndpointInCache(kOtherGroupKey, kEndpoint_));
529
530 // Since endpoint is now failing, an upload won't be started despite a pending
531 // report.
532 EXPECT_TRUE(delivery_timer()->IsRunning());
533 delivery_timer()->Fire();
534 EXPECT_TRUE(pending_uploads().empty());
535 }
536
TEST_F(ReportingDeliveryAgentTest,ConcurrentRemove)537 TEST_F(ReportingDeliveryAgentTest, ConcurrentRemove) {
538 ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
539 AddReport(kEmptyReportingSource_, kNik_, kUrl_, kGroup_);
540
541 EXPECT_TRUE(delivery_timer()->IsRunning());
542 delivery_timer()->Fire();
543 ASSERT_EQ(1u, pending_uploads().size());
544
545 // Remove the report while the upload is running.
546 std::vector<const ReportingReport*> reports;
547 cache()->GetReports(&reports);
548 EXPECT_EQ(1u, reports.size());
549
550 const ReportingReport* report = reports[0];
551 EXPECT_FALSE(cache()->IsReportDoomedForTesting(report));
552
553 // Report should appear removed, even though the cache has doomed it.
554 cache()->RemoveReports(reports);
555 cache()->GetReports(&reports);
556 EXPECT_TRUE(reports.empty());
557 EXPECT_TRUE(cache()->IsReportDoomedForTesting(report));
558
559 // Completing upload shouldn't crash, and report should still be gone.
560 pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
561 cache()->GetReports(&reports);
562 EXPECT_TRUE(reports.empty());
563 }
564
TEST_F(ReportingDeliveryAgentTest,ConcurrentRemoveDuringPermissionsCheck)565 TEST_F(ReportingDeliveryAgentTest, ConcurrentRemoveDuringPermissionsCheck) {
566 // Pause the permissions check, so that we can try to remove some reports
567 // while we're in the middle of verifying that we can upload them. (This is
568 // similar to the previous test, but removes the reports during a different
569 // part of the upload process.)
570 context()->test_delegate()->set_pause_permissions_check(true);
571
572 ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
573 AddReport(kEmptyReportingSource_, kNik_, kUrl_, kGroup_);
574
575 ASSERT_TRUE(context()->test_delegate()->PermissionsCheckPaused());
576
577 // Remove the report while the upload is running.
578 std::vector<const ReportingReport*> reports;
579 cache()->GetReports(&reports);
580 EXPECT_EQ(1u, reports.size());
581
582 const ReportingReport* report = reports[0];
583 EXPECT_FALSE(cache()->IsReportDoomedForTesting(report));
584
585 // Report should appear removed, even though the cache has doomed it.
586 cache()->RemoveReports(reports);
587 cache()->GetReports(&reports);
588 EXPECT_TRUE(reports.empty());
589 EXPECT_TRUE(cache()->IsReportDoomedForTesting(report));
590
591 // Completing upload shouldn't crash, and report should still be gone.
592 context()->test_delegate()->ResumePermissionsCheck();
593 ASSERT_EQ(1u, pending_uploads().size());
594 pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
595 cache()->GetReports(&reports);
596 EXPECT_TRUE(reports.empty());
597 }
598
599 // Reports uploaded together must share a NIK and origin.
600 // Test that the agent will not combine reports destined for the same endpoint
601 // if the reports are from different origins or NIKs, but does combine all
602 // reports for the same (NIK, origin).
TEST_F(ReportingDeliveryAgentTest,OnlyBatchSameNikAndOrigin)603 TEST_F(ReportingDeliveryAgentTest, OnlyBatchSameNikAndOrigin) {
604 const ReportingEndpointGroupKey kGroupKeys[] = {
605 ReportingEndpointGroupKey(kNik_, kOrigin_, kGroup_),
606 ReportingEndpointGroupKey(kNik_, kOtherOrigin_, kGroup_),
607 ReportingEndpointGroupKey(kOtherNik_, kOrigin_, kGroup_),
608 ReportingEndpointGroupKey(kOtherNik_, kOtherOrigin_, kGroup_),
609 };
610 for (const ReportingEndpointGroupKey& group_key : kGroupKeys) {
611 ASSERT_TRUE(SetEndpointInCache(group_key, kEndpoint_, kExpires_));
612 }
613
614 // Trigger and complete an upload to start the delivery timer.
615 UploadFirstReportAndStartTimer();
616
617 // Now that the delivery timer is running, these reports won't be immediately
618 // uploaded.
619 AddReport(kEmptyReportingSource_, kNik_, kUrl_, kGroup_);
620 AddReport(kEmptyReportingSource_, kNik_, kOtherUrl_, kGroup_);
621 AddReport(kEmptyReportingSource_, kNik_, kOtherUrl_, kGroup_);
622 AddReport(kEmptyReportingSource_, kOtherNik_, kUrl_, kGroup_);
623 AddReport(kEmptyReportingSource_, kOtherNik_, kUrl_, kGroup_);
624 AddReport(kEmptyReportingSource_, kOtherNik_, kUrl_, kGroup_);
625 AddReport(kEmptyReportingSource_, kOtherNik_, kOtherUrl_, kGroup_);
626 AddReport(kEmptyReportingSource_, kOtherNik_, kOtherUrl_, kGroup_);
627 AddReport(kEmptyReportingSource_, kOtherNik_, kOtherUrl_, kGroup_);
628 AddReport(kEmptyReportingSource_, kOtherNik_, kOtherUrl_, kGroup_);
629 EXPECT_EQ(0u, pending_uploads().size());
630
631 // There should be one upload per (NIK, origin).
632 EXPECT_TRUE(delivery_timer()->IsRunning());
633 delivery_timer()->Fire();
634 ASSERT_EQ(4u, pending_uploads().size());
635
636 pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
637 pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
638 pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
639 pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
640 EXPECT_EQ(0u, pending_uploads().size());
641
642 for (int i = 0; i < 4; ++i) {
643 ReportingEndpoint::Statistics stats =
644 GetEndpointStatistics(kGroupKeys[i], kEndpoint_);
645 EXPECT_EQ(1, stats.attempted_uploads);
646 EXPECT_EQ(1, stats.successful_uploads);
647 EXPECT_EQ(i + 1, stats.attempted_reports);
648 EXPECT_EQ(i + 1, stats.successful_reports);
649 }
650 }
651
652 // Test that the agent won't start a second upload for a (NIK, origin, group)
653 // while one is pending, even if a different endpoint is available, but will
654 // once the original delivery is complete and the (NIK, origin, group) is no
655 // longer pending.
TEST_F(ReportingDeliveryAgentTest,SerializeUploadsToGroup)656 TEST_F(ReportingDeliveryAgentTest, SerializeUploadsToGroup) {
657 static const GURL kDifferentEndpoint("https://endpoint2/");
658
659 ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
660 ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kDifferentEndpoint, kExpires_));
661
662 // Trigger and complete an upload to start the delivery timer.
663 UploadFirstReportAndStartTimer();
664
665 // First upload causes this group key to become pending.
666 AddReport(kEmptyReportingSource_, kNik_, kUrl_, kGroup_);
667 EXPECT_EQ(0u, pending_uploads().size());
668 EXPECT_TRUE(delivery_timer()->IsRunning());
669 delivery_timer()->Fire();
670 EXPECT_EQ(1u, pending_uploads().size());
671
672 // Second upload isn't started because the group is pending.
673 AddReport(kEmptyReportingSource_, kNik_, kUrl_, kGroup_);
674 EXPECT_TRUE(delivery_timer()->IsRunning());
675 delivery_timer()->Fire();
676 ASSERT_EQ(1u, pending_uploads().size());
677
678 // Resolve the first upload.
679 pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
680 EXPECT_EQ(0u, pending_uploads().size());
681
682 // Now the other upload can happen.
683 EXPECT_TRUE(delivery_timer()->IsRunning());
684 delivery_timer()->Fire();
685 ASSERT_EQ(1u, pending_uploads().size());
686 pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
687 EXPECT_EQ(0u, pending_uploads().size());
688
689 // A total of 2 reports were uploaded.
690 {
691 ReportingEndpoint::Statistics stats =
692 GetEndpointStatistics(kGroupKey_, kEndpoint_);
693 ReportingEndpoint::Statistics different_stats =
694 GetEndpointStatistics(kGroupKey_, kDifferentEndpoint);
695 EXPECT_EQ(2, stats.attempted_uploads + different_stats.attempted_uploads);
696 EXPECT_EQ(2, stats.successful_uploads + different_stats.successful_uploads);
697 EXPECT_EQ(2, stats.attempted_reports + different_stats.attempted_reports);
698 EXPECT_EQ(2, stats.successful_reports + different_stats.successful_reports);
699 }
700 }
701
702 // Tests that the agent will start parallel uploads to different groups within
703 // the same (NIK, origin) to endpoints with different URLs.
TEST_F(ReportingDeliveryAgentTest,ParallelizeUploadsAcrossGroups)704 TEST_F(ReportingDeliveryAgentTest, ParallelizeUploadsAcrossGroups) {
705 static const GURL kDifferentEndpoint("https://endpoint2/");
706 static const std::string kDifferentGroup("group2");
707 const ReportingEndpointGroupKey kDifferentGroupKey(kNik_, kOrigin_,
708 kDifferentGroup);
709
710 ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
711 ASSERT_TRUE(
712 SetEndpointInCache(kDifferentGroupKey, kDifferentEndpoint, kExpires_));
713
714 // Trigger and complete an upload to start the delivery timer.
715 UploadFirstReportAndStartTimer();
716
717 AddReport(kEmptyReportingSource_, kNik_, kUrl_, kGroup_);
718 AddReport(kEmptyReportingSource_, kNik_, kUrl_, kDifferentGroup);
719
720 EXPECT_TRUE(delivery_timer()->IsRunning());
721 delivery_timer()->Fire();
722 ASSERT_EQ(2u, pending_uploads().size());
723
724 pending_uploads()[1]->Complete(ReportingUploader::Outcome::SUCCESS);
725 pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
726 EXPECT_EQ(0u, pending_uploads().size());
727
728 {
729 ReportingEndpoint::Statistics stats =
730 GetEndpointStatistics(kGroupKey_, kEndpoint_);
731 EXPECT_EQ(1, stats.attempted_uploads);
732 EXPECT_EQ(1, stats.successful_uploads);
733 EXPECT_EQ(1, stats.attempted_reports);
734 EXPECT_EQ(1, stats.successful_reports);
735 }
736 {
737 ReportingEndpoint::Statistics stats =
738 GetEndpointStatistics(kDifferentGroupKey, kDifferentEndpoint);
739 EXPECT_EQ(1, stats.attempted_uploads);
740 EXPECT_EQ(1, stats.successful_uploads);
741 EXPECT_EQ(1, stats.attempted_reports);
742 EXPECT_EQ(1, stats.successful_reports);
743 }
744 }
745
746 // Tests that the agent will include reports for different groups for the same
747 // (NIK, origin) in the same upload if they are destined for the same endpoint
748 // URL.
TEST_F(ReportingDeliveryAgentTest,BatchReportsAcrossGroups)749 TEST_F(ReportingDeliveryAgentTest, BatchReportsAcrossGroups) {
750 static const std::string kDifferentGroup("group2");
751 const ReportingEndpointGroupKey kDifferentGroupKey(kNik_, kOrigin_,
752 kDifferentGroup);
753
754 ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
755 ASSERT_TRUE(SetEndpointInCache(kDifferentGroupKey, kEndpoint_, kExpires_));
756
757 UploadFirstReportAndStartTimer();
758
759 AddReport(kEmptyReportingSource_, kNik_, kUrl_, kGroup_);
760 AddReport(kEmptyReportingSource_, kNik_, kUrl_, kDifferentGroup);
761
762 EXPECT_TRUE(delivery_timer()->IsRunning());
763 delivery_timer()->Fire();
764 ASSERT_EQ(1u, pending_uploads().size());
765 pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
766 EXPECT_EQ(0u, pending_uploads().size());
767
768 {
769 ReportingEndpoint::Statistics stats =
770 GetEndpointStatistics(kGroupKey_, kEndpoint_);
771 EXPECT_EQ(1, stats.attempted_uploads);
772 EXPECT_EQ(1, stats.successful_uploads);
773 EXPECT_EQ(1, stats.attempted_reports);
774 EXPECT_EQ(1, stats.successful_reports);
775 }
776 {
777 ReportingEndpoint::Statistics stats =
778 GetEndpointStatistics(kDifferentGroupKey, kEndpoint_);
779 EXPECT_EQ(1, stats.attempted_uploads);
780 EXPECT_EQ(1, stats.successful_uploads);
781 EXPECT_EQ(1, stats.attempted_reports);
782 EXPECT_EQ(1, stats.successful_reports);
783 }
784 }
785
786 // Tests that the agent can send all outstanding reports for a single source
787 // when necessary. This test queues two reports for the same reporting source,
788 // for different endpoints, another for a different source at the same URL, and
789 // another for a different source on a different origin.
TEST_F(ReportingDeliveryAgentTest,SendReportsForSource)790 TEST_F(ReportingDeliveryAgentTest, SendReportsForSource) {
791 static const std::string kGroup2("group2");
792
793 // Two other reporting sources; kReportingSource2 will enqueue reports for the
794 // same URL as kReportingSource_, while kReportingSource3 will be a separate
795 // origin.
796 const base::UnguessableToken kReportingSource1 =
797 base::UnguessableToken::Create();
798 const base::UnguessableToken kReportingSource2 =
799 base::UnguessableToken::Create();
800 const base::UnguessableToken kReportingSource3 =
801 base::UnguessableToken::Create();
802
803 const IsolationInfo kIsolationInfo1 =
804 IsolationInfo::Create(IsolationInfo::RequestType::kOther, kOrigin_,
805 kOrigin_, SiteForCookies::FromOrigin(kOrigin_));
806 const IsolationInfo kIsolationInfo2 =
807 IsolationInfo::Create(IsolationInfo::RequestType::kOther, kOrigin_,
808 kOrigin_, SiteForCookies::FromOrigin(kOrigin_));
809 const IsolationInfo kIsolationInfo3 = IsolationInfo::Create(
810 IsolationInfo::RequestType::kOther, kOtherOrigin_, kOtherOrigin_,
811 SiteForCookies::FromOrigin(kOtherOrigin_));
812
813 // Set up identical endpoint configuration for kReportingSource1 and
814 // kReportingSource2. kReportingSource3 is independent.
815 const ReportingEndpointGroupKey kGroup1Key1(kNik_, kReportingSource1,
816 kOrigin_, kGroup_);
817 const ReportingEndpointGroupKey kGroup2Key1(kNik_, kReportingSource1,
818 kOrigin_, kGroup2);
819 const ReportingEndpointGroupKey kGroup1Key2(kNik_, kReportingSource2,
820 kOrigin_, kGroup_);
821 const ReportingEndpointGroupKey kGroup2Key2(kNik_, kReportingSource2,
822 kOrigin_, kGroup2);
823 const ReportingEndpointGroupKey kOtherGroupKey(kOtherNik_, kReportingSource3,
824 kOtherOrigin_, kGroup_);
825
826 SetV1EndpointInCache(kGroup1Key1, kReportingSource1, kIsolationInfo1, kUrl_);
827 SetV1EndpointInCache(kGroup2Key1, kReportingSource1, kIsolationInfo1, kUrl_);
828 SetV1EndpointInCache(kGroup1Key2, kReportingSource2, kIsolationInfo2, kUrl_);
829 SetV1EndpointInCache(kGroup2Key2, kReportingSource2, kIsolationInfo2, kUrl_);
830 SetV1EndpointInCache(kOtherGroupKey, kReportingSource3, kIsolationInfo3,
831 kOtherUrl_);
832
833 UploadFirstReportAndStartTimer();
834
835 AddReport(kReportingSource1, kNik_, kUrl_, kGroup_);
836 AddReport(kReportingSource1, kNik_, kUrl_, kGroup2);
837 AddReport(kReportingSource2, kNik_, kUrl_, kGroup_);
838 AddReport(kReportingSource3, kOtherNik_, kUrl_, kGroup_);
839
840 // There should be four queued reports at this point.
841 EXPECT_EQ(4u, cache()->GetReportCountWithStatusForTesting(
842 ReportingReport::Status::QUEUED));
843 EXPECT_EQ(0u, pending_uploads().size());
844 SendReportsForSource(kReportingSource1);
845 // Sending all reports for the source should only queue two, despite the fact
846 // that there are other reports queued for the same origin and endpoint.
847 EXPECT_EQ(2u, cache()->GetReportCountWithStatusForTesting(
848 ReportingReport::Status::QUEUED));
849 EXPECT_EQ(2u, cache()->GetReportCountWithStatusForTesting(
850 ReportingReport::Status::PENDING));
851 // All pending reports for the same source should be batched into a single
852 // upload.
853 ASSERT_EQ(1u, pending_uploads().size());
854 pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
855 EXPECT_EQ(0u, pending_uploads().size());
856 }
857
858 // Tests that the agent can send all outstanding V1 reports for multiple sources
859 // and that these are not batched together.
TEST_F(ReportingDeliveryAgentTest,SendReportsForMultipleSources)860 TEST_F(ReportingDeliveryAgentTest, SendReportsForMultipleSources) {
861 static const std::string kGroup2("group2");
862
863 // Two other reporting sources; kReportingSource2 will enqueue reports for the
864 // same URL as kReportingSource_, while kReportingSource3 will be a separate
865 // origin.
866 const base::UnguessableToken kReportingSource1 =
867 base::UnguessableToken::Create();
868 const base::UnguessableToken kReportingSource2 =
869 base::UnguessableToken::Create();
870 const base::UnguessableToken kReportingSource3 =
871 base::UnguessableToken::Create();
872
873 const IsolationInfo kIsolationInfo1 =
874 IsolationInfo::Create(IsolationInfo::RequestType::kOther, kOrigin_,
875 kOrigin_, SiteForCookies::FromOrigin(kOrigin_));
876 const IsolationInfo kIsolationInfo2 =
877 IsolationInfo::Create(IsolationInfo::RequestType::kOther, kOrigin_,
878 kOrigin_, SiteForCookies::FromOrigin(kOrigin_));
879 const IsolationInfo kIsolationInfo3 = IsolationInfo::Create(
880 IsolationInfo::RequestType::kOther, kOtherOrigin_, kOtherOrigin_,
881 SiteForCookies::FromOrigin(kOtherOrigin_));
882
883 // Set up identical endpoint configuration for kReportingSource1 and
884 // kReportingSource2. kReportingSource3 is independent.
885 const ReportingEndpointGroupKey kGroup1Key1(kNik_, kReportingSource1,
886 kOrigin_, kGroup_);
887 const ReportingEndpointGroupKey kGroup2Key1(kNik_, kReportingSource1,
888 kOrigin_, kGroup2);
889 const ReportingEndpointGroupKey kGroup1Key2(kNik_, kReportingSource2,
890 kOrigin_, kGroup_);
891 const ReportingEndpointGroupKey kGroup2Key2(kNik_, kReportingSource2,
892 kOrigin_, kGroup2);
893 const ReportingEndpointGroupKey kOtherGroupKey(kOtherNik_, kReportingSource3,
894 kOtherOrigin_, kGroup_);
895
896 SetV1EndpointInCache(kGroup1Key1, kReportingSource1, kIsolationInfo1, kUrl_);
897 SetV1EndpointInCache(kGroup2Key1, kReportingSource1, kIsolationInfo1, kUrl_);
898 SetV1EndpointInCache(kGroup1Key2, kReportingSource2, kIsolationInfo2, kUrl_);
899 SetV1EndpointInCache(kGroup2Key2, kReportingSource2, kIsolationInfo2, kUrl_);
900 SetV1EndpointInCache(kOtherGroupKey, kReportingSource3, kIsolationInfo3,
901 kOtherUrl_);
902
903 UploadFirstReportAndStartTimer();
904
905 AddReport(kReportingSource1, kNik_, kUrl_, kGroup_);
906 AddReport(kReportingSource1, kNik_, kUrl_, kGroup2);
907 AddReport(kReportingSource2, kNik_, kUrl_, kGroup_);
908 AddReport(kReportingSource3, kOtherNik_, kUrl_, kGroup_);
909
910 // There should be four queued reports at this point.
911 EXPECT_EQ(4u, cache()->GetReportCountWithStatusForTesting(
912 ReportingReport::Status::QUEUED));
913 EXPECT_EQ(0u, pending_uploads().size());
914
915 // Send reports for both ReportingSource 1 and 2 at the same time. These
916 // should be sent to the same endpoint, but should still not be batched
917 // together.
918 SendReportsForSource(kReportingSource1);
919 SendReportsForSource(kReportingSource2);
920
921 // We expect to see three pending reports, and one still queued. The pending
922 // reports should be divided into two uploads.
923 EXPECT_EQ(1u, cache()->GetReportCountWithStatusForTesting(
924 ReportingReport::Status::QUEUED));
925 EXPECT_EQ(3u, cache()->GetReportCountWithStatusForTesting(
926 ReportingReport::Status::PENDING));
927 ASSERT_EQ(2u, pending_uploads().size());
928 }
929
930 } // namespace
931 } // namespace net
932