• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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