Add reporting_source to IPC calls to reporting service.

Send the reporting source token to the network service when configuring
the per-resource endpoints with the Reporting-Endpoints header, and when
queuing reports, and pass that token into the reporting service.

This token is currently unused, but the follow-up CL will use it to
isolate reports from different sources.

This is part of a series of CLs implementing V1 reporting isolation.
A summary of the architectural changes introduced can be found at
https://docs.google.com/document/d/1RmEz17pGSUQITPoRKV4s3IBgbyHjv-HLZqtVYYZ4lMg/edit

CLs in this series:
https://crrev.com/c/2878175 Update NEL browser tests to require Report-To
https://crrev.com/c/2878376 Separate parsing from processing Reporting-Endpoints
https://crrev.com/c/2889833 Add reporting source to worker objects
https://crrev.com/c/2889975 Add reporting source to COOP/COEP reporters
https://crrev.com/c/3039579 Add source token to reports
https://crrev.com/c/3041880 (This CL) Add source token to IPC calls
https://crrev.com/c/3042463 Isolate v1 reports from each other
https://crrev.com/c/3042465 Allow document source token to change
https://crrev.com/c/3042521 Clean up when docs/workers are destroyed

Bug: 1062359
Change-Id: I080d3d9e3c81c0891e2ebb630ebe9f1718add0ec
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3041880
Reviewed-by: Joshua Bell <[email protected]>
Reviewed-by: Lily Chen <[email protected]>
Reviewed-by: Ken Buchanan <[email protected]>
Reviewed-by: Matt Menke <[email protected]>
Commit-Queue: Ian Clelland <[email protected]>
Cr-Commit-Position: refs/heads/main@{#914373}
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
index 3df7498..8636111 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -178,10 +178,12 @@
 
 #if BUILDFLAG(ENABLE_REPORTING)
 #include "base/containers/flat_map.h"
+#include "base/unguessable_token.h"
 #include "net/network_error_logging/network_error_logging_service.h"
 #include "net/reporting/reporting_browsing_data_remover.h"
 #include "net/reporting/reporting_policy.h"
 #include "net/reporting/reporting_service.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #endif  // BUILDFLAG(ENABLE_REPORTING)
 
 using content::BrowsingDataFilterBuilder;
@@ -901,19 +903,22 @@
   // net::ReportingService implementation:
 
   void SetDocumentReportingEndpoints(
+      const base::UnguessableToken& reporting_source,
       const url::Origin& origin,
       const net::NetworkIsolationKey& network_isolation_key,
       const base::flat_map<std::string, std::string>& endpoints) override {
     NOTREACHED();
   }
 
-  void QueueReport(const GURL& url,
-                   const net::NetworkIsolationKey& network_isolation_key,
-                   const std::string& user_agent,
-                   const std::string& group,
-                   const std::string& type,
-                   std::unique_ptr<const base::Value> body,
-                   int depth) override {
+  void QueueReport(
+      const GURL& url,
+      const absl::optional<base::UnguessableToken>& reporting_source,
+      const net::NetworkIsolationKey& network_isolation_key,
+      const std::string& user_agent,
+      const std::string& group,
+      const std::string& type,
+      std::unique_ptr<const base::Value> body,
+      int depth) override {
     NOTREACHED();
   }
 
diff --git a/content/browser/net/cross_origin_embedder_policy_reporter.cc b/content/browser/net/cross_origin_embedder_policy_reporter.cc
index 4efe4bc..cded18c6 100644
--- a/content/browser/net/cross_origin_embedder_policy_reporter.cc
+++ b/content/browser/net/cross_origin_embedder_policy_reporter.cc
@@ -114,7 +114,8 @@
     body_to_pass.SetString("disposition", disposition);
 
     storage_partition_->GetNetworkContext()->QueueReport(
-        kType, *endpoint, context_url_, network_isolation_key_,
+        kType, *endpoint, context_url_, reporting_source_,
+        network_isolation_key_,
         /*user_agent=*/absl::nullopt, std::move(body_to_pass));
   }
 }
diff --git a/content/browser/net/cross_origin_embedder_policy_reporter_unittest.cc b/content/browser/net/cross_origin_embedder_policy_reporter_unittest.cc
index ad409769..100cc187 100644
--- a/content/browser/net/cross_origin_embedder_policy_reporter_unittest.cc
+++ b/content/browser/net/cross_origin_embedder_policy_reporter_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "base/strings/string_piece.h"
 #include "base/test/task_environment.h"
+#include "base/unguessable_token.h"
 #include "base/values.h"
 #include "content/public/test/test_storage_partition.h"
 #include "mojo/public/cpp/bindings/remote.h"
@@ -15,6 +16,7 @@
 #include "services/network/public/cpp/request_destination.h"
 #include "services/network/test/test_network_context.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/mojom/frame/reporting_observer.mojom.h"
 
 namespace content {
@@ -44,12 +46,14 @@
     base::Value body;
   };
 
-  void QueueReport(const std::string& type,
-                   const std::string& group,
-                   const GURL& url,
-                   const net::NetworkIsolationKey& network_isolation_key,
-                   const absl::optional<std::string>& user_agent,
-                   base::Value body) override {
+  void QueueReport(
+      const std::string& type,
+      const std::string& group,
+      const GURL& url,
+      const absl::optional<base::UnguessableToken>& reporting_source,
+      const net::NetworkIsolationKey& network_isolation_key,
+      const absl::optional<std::string>& user_agent,
+      base::Value body) override {
     DCHECK(!user_agent);
     reports_.emplace_back(
         Report(type, group, url, network_isolation_key, std::move(body)));
diff --git a/content/browser/net/cross_origin_opener_policy_reporter.cc b/content/browser/net/cross_origin_opener_policy_reporter.cc
index 454c2edf..44476756 100644
--- a/content/browser/net/cross_origin_opener_policy_reporter.cc
+++ b/content/browser/net/cross_origin_opener_policy_reporter.cc
@@ -244,8 +244,8 @@
   }
 
   storage_partition_->GetNetworkContext()->QueueReport(
-      "coop", endpoint, context_url_, network_isolation_key_, absl::nullopt,
-      std::move(body));
+      "coop", endpoint, context_url_, reporting_source_, network_isolation_key_,
+      absl::nullopt, std::move(body));
 }
 
 // static
@@ -395,7 +395,7 @@
       kEffectivePolicy,
       ToString(is_report_only ? coop_.report_only_value : coop_.value));
   storage_partition_->GetNetworkContext()->QueueReport(
-      "coop", endpoint, context_url_, network_isolation_key_,
+      "coop", endpoint, context_url_, reporting_source_, network_isolation_key_,
       /*user_agent=*/absl::nullopt, std::move(body));
 }
 
diff --git a/content/browser/net/cross_origin_opener_policy_reporter_unittest.cc b/content/browser/net/cross_origin_opener_policy_reporter_unittest.cc
index 6d4c1dc..c5bf836 100644
--- a/content/browser/net/cross_origin_opener_policy_reporter_unittest.cc
+++ b/content/browser/net/cross_origin_opener_policy_reporter_unittest.cc
@@ -8,12 +8,14 @@
 #include <vector>
 
 #include "base/test/task_environment.h"
+#include "base/unguessable_token.h"
 #include "base/values.h"
 #include "content/public/test/test_storage_partition.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "net/base/network_isolation_key.h"
 #include "services/network/test/test_network_context.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace content {
 namespace {
@@ -39,12 +41,14 @@
     base::Value body;
   };
 
-  void QueueReport(const std::string& type,
-                   const std::string& group,
-                   const GURL& url,
-                   const net::NetworkIsolationKey& network_isolation_key,
-                   const absl::optional<std::string>& user_agent,
-                   base::Value body) override {
+  void QueueReport(
+      const std::string& type,
+      const std::string& group,
+      const GURL& url,
+      const absl::optional<base::UnguessableToken>& reporting_source,
+      const net::NetworkIsolationKey& network_isolation_key,
+      const absl::optional<std::string>& user_agent,
+      base::Value body) override {
     DCHECK(!user_agent);
     reports_.emplace_back(
         Report(type, group, url, network_isolation_key, std::move(body)));
diff --git a/content/browser/net/reporting_service_proxy.cc b/content/browser/net/reporting_service_proxy.cc
index 74dd306..6e7f2a63 100644
--- a/content/browser/net/reporting_service_proxy.cc
+++ b/content/browser/net/reporting_service_proxy.cc
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "base/memory/ref_counted.h"
+#include "base/unguessable_token.h"
 #include "base/values.h"
 #include "content/browser/service_worker/service_worker_host.h"
 #include "content/browser/worker_host/dedicated_worker_host.h"
@@ -35,9 +36,13 @@
  public:
   ReportingServiceProxyImpl(
       int render_process_id,
+      const base::UnguessableToken& reporting_source,
       const net::NetworkIsolationKey& network_isolation_key)
       : render_process_id_(render_process_id),
-        network_isolation_key_(network_isolation_key) {}
+        reporting_source_(reporting_source),
+        network_isolation_key_(network_isolation_key) {
+    DCHECK(!reporting_source.is_empty());
+  }
 
   ReportingServiceProxyImpl(const ReportingServiceProxyImpl&) = delete;
   ReportingServiceProxyImpl& operator=(const ReportingServiceProxyImpl&) =
@@ -177,12 +182,13 @@
       return;
 
     rph->GetStoragePartition()->GetNetworkContext()->QueueReport(
-        type, group, url, network_isolation_key_,
+        type, group, url, reporting_source_, network_isolation_key_,
         /*user_agent=*/absl::nullopt,
         base::Value::FromUniquePtrValue(std::move(body)));
   }
 
   const int render_process_id_;
+  const base::UnguessableToken reporting_source_;
   const net::NetworkIsolationKey network_isolation_key_;
 };
 
@@ -194,6 +200,7 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   mojo::MakeSelfOwnedReceiver(std::make_unique<ReportingServiceProxyImpl>(
                                   render_frame_host->GetProcess()->GetID(),
+                                  render_frame_host->GetFrameToken().value(),
                                   render_frame_host->GetNetworkIsolationKey()),
                               std::move(receiver));
 }
@@ -205,6 +212,7 @@
   mojo::MakeSelfOwnedReceiver(
       std::make_unique<ReportingServiceProxyImpl>(
           service_worker_host->worker_process_id(),
+          service_worker_host->GetReportingSource(),
           service_worker_host->GetNetworkIsolationKey()),
       std::move(receiver));
 }
@@ -215,6 +223,7 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   mojo::MakeSelfOwnedReceiver(std::make_unique<ReportingServiceProxyImpl>(
                                   shared_worker_host->GetProcessHost()->GetID(),
+                                  shared_worker_host->GetReportingSource(),
                                   shared_worker_host->GetNetworkIsolationKey()),
                               std::move(receiver));
 }
@@ -226,6 +235,7 @@
   mojo::MakeSelfOwnedReceiver(
       std::make_unique<ReportingServiceProxyImpl>(
           dedicated_worker_host->GetProcessHost()->GetID(),
+          dedicated_worker_host->GetReportingSource(),
           dedicated_worker_host->GetNetworkIsolationKey()),
       std::move(receiver));
 }
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index a173ec1..3ca740f 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -3480,8 +3480,8 @@
   DCHECK(frame_token_.value());
   if (!reporting_endpoints_.empty()) {
     GetStoragePartition()->GetNetworkContext()->SetDocumentReportingEndpoints(
-        params.origin, isolation_info_.network_isolation_key(),
-        reporting_endpoints_);
+        frame_token_.value(), params.origin,
+        isolation_info_.network_isolation_key(), reporting_endpoints_);
   }
 
   // When the frame hosts a different document, its state must be replicated
@@ -10495,7 +10495,9 @@
   // Send the crash report to the Reporting API.
   GetProcess()->GetStoragePartition()->GetNetworkContext()->QueueReport(
       /*type=*/"crash", /*group=*/"default", last_committed_url_,
-      isolation_info_.network_isolation_key(), absl::nullopt, std::move(body));
+      frame_token_.value() /* reporting_source */,
+      isolation_info_.network_isolation_key(), absl::nullopt /* user_agent */,
+      std::move(body));
 }
 
 void RenderFrameHostImpl::SendCommitNavigation(
diff --git a/net/network_error_logging/network_error_logging_service.cc b/net/network_error_logging/network_error_logging_service.cc
index afc7869..a47ebbed 100644
--- a/net/network_error_logging/network_error_logging_service.cc
+++ b/net/network_error_logging/network_error_logging_service.cc
@@ -489,9 +489,11 @@
              << ", depth=" << details.reporting_upload_depth << ") for "
              << details.uri;
 
+    // A null reporting source token is used since this report is not associated
+    // with any particular document.
     reporting_service_->QueueReport(
-        details.uri, details.network_isolation_key, details.user_agent,
-        policy->report_to, kReportType,
+        details.uri, absl::nullopt, details.network_isolation_key,
+        details.user_agent, policy->report_to, kReportType,
         CreateReportBody(phase_string, type_string, sampling_fraction.value(),
                          details),
         details.reporting_upload_depth);
@@ -537,9 +539,11 @@
       return;
     }
 
+    // A null reporting source token is used since this report is not associated
+    // with any particular document.
     reporting_service_->QueueReport(
-        details.outer_url, details.network_isolation_key, details.user_agent,
-        policy->report_to, kReportType,
+        details.outer_url, absl::nullopt, details.network_isolation_key,
+        details.user_agent, policy->report_to, kReportType,
         CreateSignedExchangeReportBody(details, sampling_fraction.value()),
         0 /* depth */);
     RecordSignedExchangeRequestOutcome(RequestOutcome::kQueued);
diff --git a/net/reporting/reporting_browsing_data_remover_unittest.cc b/net/reporting/reporting_browsing_data_remover_unittest.cc
index 687bf5a..a340d102 100644
--- a/net/reporting/reporting_browsing_data_remover_unittest.cc
+++ b/net/reporting/reporting_browsing_data_remover_unittest.cc
@@ -43,7 +43,8 @@
 
   // TODO(chlily): Take NIK.
   void AddReport(const GURL& url) {
-    cache()->AddReport(NetworkIsolationKey(), url, kUserAgent_, kGroup_, kType_,
+    cache()->AddReport(absl::nullopt, NetworkIsolationKey(), url, kUserAgent_,
+                       kGroup_, kType_,
                        std::make_unique<base::DictionaryValue>(), 0,
                        tick_clock()->NowTicks(), 0);
   }
diff --git a/net/reporting/reporting_cache.h b/net/reporting/reporting_cache.h
index 6c5411e8..6e5bc17d 100644
--- a/net/reporting/reporting_cache.h
+++ b/net/reporting/reporting_cache.h
@@ -13,11 +13,13 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/time/time.h"
+#include "base/unguessable_token.h"
 #include "base/values.h"
 #include "net/base/net_export.h"
 #include "net/reporting/reporting_endpoint.h"
 #include "net/reporting/reporting_header_parser.h"
 #include "net/reporting/reporting_report.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 #include "url/origin.h"
 
@@ -55,17 +57,23 @@
 
   // Adds a report to the cache.
   //
-  // All parameters correspond to the desired values for the relevant fields in
-  // ReportingReport.
-  virtual void AddReport(const NetworkIsolationKey& network_isolation_key,
-                         const GURL& url,
-                         const std::string& user_agent,
-                         const std::string& group_name,
-                         const std::string& type,
-                         std::unique_ptr<const base::Value> body,
-                         int depth,
-                         base::TimeTicks queued,
-                         int attempts) = 0;
+  // |reporting_source| and |network_isolation_key| will be used when the
+  // report is delivered, to determine which endpoints are eligible to receive
+  // this report, and which other reports this report can be batched with.
+  //
+  // All other parameters correspond to the desired values for the relevant
+  // fields in ReportingReport.
+  virtual void AddReport(
+      const absl::optional<base::UnguessableToken>& reporting_source,
+      const NetworkIsolationKey& network_isolation_key,
+      const GURL& url,
+      const std::string& user_agent,
+      const std::string& group_name,
+      const std::string& type,
+      std::unique_ptr<const base::Value> body,
+      int depth,
+      base::TimeTicks queued,
+      int attempts) = 0;
 
   // Gets all reports in the cache. The returned pointers are valid as long as
   // either no calls to |RemoveReports| have happened or the reports' |pending|
diff --git a/net/reporting/reporting_cache_impl.cc b/net/reporting/reporting_cache_impl.cc
index 4b0af50..ec112b88 100644
--- a/net/reporting/reporting_cache_impl.cc
+++ b/net/reporting/reporting_cache_impl.cc
@@ -27,6 +27,7 @@
 ReportingCacheImpl::~ReportingCacheImpl() = default;
 
 void ReportingCacheImpl::AddReport(
+    const absl::optional<base::UnguessableToken>& reporting_source,
     const NetworkIsolationKey& network_isolation_key,
     const GURL& url,
     const std::string& user_agent,
@@ -36,6 +37,8 @@
     int depth,
     base::TimeTicks queued,
     int attempts) {
+  // If |reporting_source| is present, it must not be empty.
+  DCHECK(!(reporting_source.has_value() && reporting_source->is_empty()));
   auto report = std::make_unique<ReportingReport>(
       absl::nullopt, network_isolation_key, url, user_agent, group_name, type,
       std::move(body), depth, queued, attempts);
diff --git a/net/reporting/reporting_cache_impl.h b/net/reporting/reporting_cache_impl.h
index 83283da..d2099ac 100644
--- a/net/reporting/reporting_cache_impl.h
+++ b/net/reporting/reporting_cache_impl.h
@@ -18,6 +18,7 @@
 #include "base/macros.h"
 #include "base/sequence_checker.h"
 #include "base/time/time.h"
+#include "base/unguessable_token.h"
 #include "base/values.h"
 #include "net/reporting/reporting_cache.h"
 #include "net/reporting/reporting_context.h"
@@ -37,7 +38,8 @@
   ~ReportingCacheImpl() override;
 
   // ReportingCache implementation
-  void AddReport(const NetworkIsolationKey& network_isolation_key,
+  void AddReport(const absl::optional<base::UnguessableToken>& reporting_source,
+                 const NetworkIsolationKey& network_isolation_key,
                  const GURL& url,
                  const std::string& user_agent,
                  const std::string& group_name,
diff --git a/net/reporting/reporting_cache_unittest.cc b/net/reporting/reporting_cache_unittest.cc
index 3f8515d14..e3fe083 100644
--- a/net/reporting/reporting_cache_unittest.cc
+++ b/net/reporting/reporting_cache_unittest.cc
@@ -125,8 +125,8 @@
     // in test cases, so I've optimized for readability over execution speed.
     std::vector<const ReportingReport*> before;
     cache()->GetReports(&before);
-    cache()->AddReport(network_isolation_key, url, user_agent, group, type,
-                       std::move(body), depth, queued, attempts);
+    cache()->AddReport(absl::nullopt, network_isolation_key, url, user_agent,
+                       group, type, std::move(body), depth, queued, attempts);
     std::vector<const ReportingReport*> after;
     cache()->GetReports(&after);
 
@@ -184,6 +184,8 @@
   const GURL kUrl2_ = GURL("https://origin2/path");
   const url::Origin kOrigin1_ = url::Origin::Create(GURL("https://origin1/"));
   const url::Origin kOrigin2_ = url::Origin::Create(GURL("https://origin2/"));
+  const absl::optional<base::UnguessableToken> kReportingSource_ =
+      absl::nullopt;
   const NetworkIsolationKey kNik_;
   const NetworkIsolationKey kOtherNik_ =
       NetworkIsolationKey(SchemefulSite(kOrigin1_), SchemefulSite(kOrigin2_));
@@ -234,9 +236,9 @@
   cache()->GetReports(&reports);
   EXPECT_TRUE(reports.empty());
 
-  cache()->AddReport(kNik_, kUrl1_, kUserAgent_, kGroup1_, kType_,
-                     std::make_unique<base::DictionaryValue>(), 0, kNowTicks_,
-                     0);
+  cache()->AddReport(kReportingSource_, kNik_, kUrl1_, kUserAgent_, kGroup1_,
+                     kType_, std::make_unique<base::DictionaryValue>(), 0,
+                     kNowTicks_, 0);
   EXPECT_EQ(1, observer()->cached_reports_update_count());
 
   cache()->GetReports(&reports);
@@ -273,12 +275,12 @@
 TEST_P(ReportingCacheTest, RemoveAllReports) {
   LoadReportingClients();
 
-  cache()->AddReport(kNik_, kUrl1_, kUserAgent_, kGroup1_, kType_,
-                     std::make_unique<base::DictionaryValue>(), 0, kNowTicks_,
-                     0);
-  cache()->AddReport(kNik_, kUrl1_, kUserAgent_, kGroup1_, kType_,
-                     std::make_unique<base::DictionaryValue>(), 0, kNowTicks_,
-                     0);
+  cache()->AddReport(kReportingSource_, kNik_, kUrl1_, kUserAgent_, kGroup1_,
+                     kType_, std::make_unique<base::DictionaryValue>(), 0,
+                     kNowTicks_, 0);
+  cache()->AddReport(kReportingSource_, kNik_, kUrl1_, kUserAgent_, kGroup1_,
+                     kType_, std::make_unique<base::DictionaryValue>(), 0,
+                     kNowTicks_, 0);
   EXPECT_EQ(2, observer()->cached_reports_update_count());
 
   std::vector<const ReportingReport*> reports;
@@ -295,9 +297,9 @@
 TEST_P(ReportingCacheTest, RemovePendingReports) {
   LoadReportingClients();
 
-  cache()->AddReport(kNik_, kUrl1_, kUserAgent_, kGroup1_, kType_,
-                     std::make_unique<base::DictionaryValue>(), 0, kNowTicks_,
-                     0);
+  cache()->AddReport(kReportingSource_, kNik_, kUrl1_, kUserAgent_, kGroup1_,
+                     kType_, std::make_unique<base::DictionaryValue>(), 0,
+                     kNowTicks_, 0);
   EXPECT_EQ(1, observer()->cached_reports_update_count());
 
   std::vector<const ReportingReport*> reports;
@@ -333,9 +335,9 @@
 TEST_P(ReportingCacheTest, RemoveAllPendingReports) {
   LoadReportingClients();
 
-  cache()->AddReport(kNik_, kUrl1_, kUserAgent_, kGroup1_, kType_,
-                     std::make_unique<base::DictionaryValue>(), 0, kNowTicks_,
-                     0);
+  cache()->AddReport(kReportingSource_, kNik_, kUrl1_, kUserAgent_, kGroup1_,
+                     kType_, std::make_unique<base::DictionaryValue>(), 0,
+                     kNowTicks_, 0);
   EXPECT_EQ(1, observer()->cached_reports_update_count());
 
   std::vector<const ReportingReport*> reports;
@@ -1178,16 +1180,16 @@
 
   // Enqueue the maximum number of reports, spaced apart in time.
   for (size_t i = 0; i < max_report_count; ++i) {
-    cache()->AddReport(kNik_, kUrl1_, kUserAgent_, kGroup1_, kType_,
-                       std::make_unique<base::DictionaryValue>(), 0,
+    cache()->AddReport(kReportingSource_, kNik_, kUrl1_, kUserAgent_, kGroup1_,
+                       kType_, std::make_unique<base::DictionaryValue>(), 0,
                        tick_clock()->NowTicks(), 0);
     tick_clock()->Advance(base::TimeDelta::FromMinutes(1));
   }
   EXPECT_EQ(max_report_count, report_count());
 
   // Add one more report to force the cache to evict one.
-  cache()->AddReport(kNik_, kUrl1_, kUserAgent_, kGroup1_, kType_,
-                     std::make_unique<base::DictionaryValue>(), 0,
+  cache()->AddReport(kReportingSource_, kNik_, kUrl1_, kUserAgent_, kGroup1_,
+                     kType_, std::make_unique<base::DictionaryValue>(), 0,
                      tick_clock()->NowTicks(), 0);
 
   // Make sure the cache evicted a report to make room for the new one, and make
@@ -1224,9 +1226,9 @@
 
   // Add one more report to force the cache to evict one. Since the cache has
   // only pending reports, it will be forced to evict the *new* report!
-  cache()->AddReport(kNik_, kUrl1_, kUserAgent_, kGroup1_, kType_,
-                     std::make_unique<base::DictionaryValue>(), 0, kNowTicks_,
-                     0);
+  cache()->AddReport(kReportingSource_, kNik_, kUrl1_, kUserAgent_, kGroup1_,
+                     kType_, std::make_unique<base::DictionaryValue>(), 0,
+                     kNowTicks_, 0);
 
   // Make sure the cache evicted a report, and make sure the report evicted was
   // the new, non-pending one.
diff --git a/net/reporting/reporting_delivery_agent_unittest.cc b/net/reporting/reporting_delivery_agent_unittest.cc
index dc63387..79f376d 100644
--- a/net/reporting/reporting_delivery_agent_unittest.cc
+++ b/net/reporting/reporting_delivery_agent_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/test/values_test_util.h"
 #include "base/time/time.h"
 #include "base/timer/mock_timer.h"
+#include "base/unguessable_token.h"
 #include "base/values.h"
 #include "net/base/backoff_entry.h"
 #include "net/base/features.h"
@@ -22,6 +23,7 @@
 #include "net/reporting/reporting_test_util.h"
 #include "net/reporting/reporting_uploader.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 #include "url/origin.h"
 
@@ -49,13 +51,14 @@
     report_body_.SetStringKey("key", "value");
   }
 
-  void AddReport(const NetworkIsolationKey& network_isolation_key,
+  void AddReport(const absl::optional<base::UnguessableToken>& reporting_source,
+                 const NetworkIsolationKey& network_isolation_key,
                  const GURL& url,
                  const std::string& group) {
-    cache()->AddReport(network_isolation_key, url, kUserAgent_, group, kType_,
-                       std::make_unique<base::Value>(report_body_.Clone()),
-                       0 /* depth */, tick_clock()->NowTicks() /* queued */,
-                       0 /* attempts */);
+    cache()->AddReport(
+        reporting_source, network_isolation_key, url, kUserAgent_, group,
+        kType_, std::make_unique<base::Value>(report_body_.Clone()),
+        0 /* depth */, tick_clock()->NowTicks() /* queued */, 0 /* attempts */);
   }
 
   // The first report added to the cache is uploaded immediately, and a timer is
@@ -68,8 +71,8 @@
         "dummy");
     ASSERT_TRUE(SetEndpointInCache(
         dummy_group, GURL("https://dummy.test/upload"), kExpires_));
-    AddReport(dummy_group.network_isolation_key, dummy_group.origin.GetURL(),
-              dummy_group.group_name);
+    AddReport(absl::nullopt, dummy_group.network_isolation_key,
+              dummy_group.origin.GetURL(), dummy_group.group_name);
 
     ASSERT_EQ(1u, pending_uploads().size());
     pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
@@ -86,6 +89,8 @@
   const url::Origin kOrigin_ = url::Origin::Create(GURL("https://origin/"));
   const url::Origin kOtherOrigin_ =
       url::Origin::Create(GURL("https://other-origin/"));
+  const absl::optional<base::UnguessableToken> kReportingSource_ =
+      absl::nullopt;
   const NetworkIsolationKey kNik_ =
       NetworkIsolationKey(SchemefulSite(kOrigin_), SchemefulSite(kOrigin_));
   const NetworkIsolationKey kOtherNik_ =
@@ -102,7 +107,7 @@
 
 TEST_F(ReportingDeliveryAgentTest, SuccessfulImmediateUpload) {
   ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
-  AddReport(kNik_, kUrl_, kGroup_);
+  AddReport(kReportingSource_, kNik_, kUrl_, kGroup_);
 
   // Upload is automatically started when cache is modified.
 
@@ -148,7 +153,7 @@
 TEST_F(ReportingDeliveryAgentTest, SuccessfulImmediateSubdomainUpload) {
   ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_,
                                  OriginSubdomains::INCLUDE));
-  AddReport(kNik_, kSubdomainUrl_, kGroup_);
+  AddReport(kReportingSource_, kNik_, kSubdomainUrl_, kGroup_);
 
   // Upload is automatically started when cache is modified.
 
@@ -195,7 +200,7 @@
        SuccessfulImmediateSubdomainUploadWithOverwrittenEndpoint) {
   ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_,
                                  OriginSubdomains::INCLUDE));
-  AddReport(kNik_, kSubdomainUrl_, kGroup_);
+  AddReport(kReportingSource_, kNik_, kSubdomainUrl_, kGroup_);
 
   // Upload is automatically started when cache is modified.
 
@@ -223,11 +228,11 @@
 TEST_F(ReportingDeliveryAgentTest, SuccessfulDelayedUpload) {
   // Trigger and complete an upload to start the delivery timer.
   ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
-  AddReport(kNik_, kUrl_, kGroup_);
+  AddReport(kReportingSource_, kNik_, kUrl_, kGroup_);
   pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
 
   // Add another report to upload after a delay.
-  AddReport(kNik_, kUrl_, kGroup_);
+  AddReport(kReportingSource_, kNik_, kUrl_, kGroup_);
 
   EXPECT_TRUE(delivery_timer()->IsRunning());
   delivery_timer()->Fire();
@@ -273,7 +278,7 @@
 
 TEST_F(ReportingDeliveryAgentTest, FailedUpload) {
   ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
-  AddReport(kNik_, kUrl_, kGroup_);
+  AddReport(kReportingSource_, kNik_, kUrl_, kGroup_);
 
   EXPECT_TRUE(delivery_timer()->IsRunning());
   delivery_timer()->Fire();
@@ -324,7 +329,7 @@
   body.SetString("key", "value");
 
   ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
-  AddReport(kNik_, kUrl_, kGroup_);
+  AddReport(kReportingSource_, kNik_, kUrl_, kGroup_);
 
   tick_clock()->Advance(base::TimeDelta::FromMilliseconds(kAgeMillis));
 
@@ -357,7 +362,7 @@
   ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
   ASSERT_TRUE(SetEndpointInCache(kOtherGroupKey, kEndpoint_, kExpires_));
 
-  AddReport(kNik_, kUrl_, kGroup_);
+  AddReport(kReportingSource_, kNik_, kUrl_, kGroup_);
 
   EXPECT_TRUE(delivery_timer()->IsRunning());
   delivery_timer()->Fire();
@@ -384,7 +389,7 @@
 
 TEST_F(ReportingDeliveryAgentTest, ConcurrentRemove) {
   ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
-  AddReport(kNik_, kUrl_, kGroup_);
+  AddReport(kReportingSource_, kNik_, kUrl_, kGroup_);
 
   EXPECT_TRUE(delivery_timer()->IsRunning());
   delivery_timer()->Fire();
@@ -418,7 +423,7 @@
   context()->test_delegate()->set_pause_permissions_check(true);
 
   ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
-  AddReport(kNik_, kUrl_, kGroup_);
+  AddReport(kReportingSource_, kNik_, kUrl_, kGroup_);
 
   ASSERT_TRUE(context()->test_delegate()->PermissionsCheckPaused());
 
@@ -464,16 +469,16 @@
 
   // Now that the delivery timer is running, these reports won't be immediately
   // uploaded.
-  AddReport(kNik_, kUrl_, kGroup_);
-  AddReport(kNik_, kOtherUrl_, kGroup_);
-  AddReport(kNik_, kOtherUrl_, kGroup_);
-  AddReport(kOtherNik_, kUrl_, kGroup_);
-  AddReport(kOtherNik_, kUrl_, kGroup_);
-  AddReport(kOtherNik_, kUrl_, kGroup_);
-  AddReport(kOtherNik_, kOtherUrl_, kGroup_);
-  AddReport(kOtherNik_, kOtherUrl_, kGroup_);
-  AddReport(kOtherNik_, kOtherUrl_, kGroup_);
-  AddReport(kOtherNik_, kOtherUrl_, kGroup_);
+  AddReport(kReportingSource_, kNik_, kUrl_, kGroup_);
+  AddReport(kReportingSource_, kNik_, kOtherUrl_, kGroup_);
+  AddReport(kReportingSource_, kNik_, kOtherUrl_, kGroup_);
+  AddReport(kReportingSource_, kOtherNik_, kUrl_, kGroup_);
+  AddReport(kReportingSource_, kOtherNik_, kUrl_, kGroup_);
+  AddReport(kReportingSource_, kOtherNik_, kUrl_, kGroup_);
+  AddReport(kReportingSource_, kOtherNik_, kOtherUrl_, kGroup_);
+  AddReport(kReportingSource_, kOtherNik_, kOtherUrl_, kGroup_);
+  AddReport(kReportingSource_, kOtherNik_, kOtherUrl_, kGroup_);
+  AddReport(kReportingSource_, kOtherNik_, kOtherUrl_, kGroup_);
   EXPECT_EQ(0u, pending_uploads().size());
 
   // There should be one upload per (NIK, origin).
@@ -511,14 +516,14 @@
   UploadFirstReportAndStartTimer();
 
   // First upload causes this group key to become pending.
-  AddReport(kNik_, kUrl_, kGroup_);
+  AddReport(kReportingSource_, kNik_, kUrl_, kGroup_);
   EXPECT_EQ(0u, pending_uploads().size());
   EXPECT_TRUE(delivery_timer()->IsRunning());
   delivery_timer()->Fire();
   EXPECT_EQ(1u, pending_uploads().size());
 
   // Second upload isn't started because the group is pending.
-  AddReport(kNik_, kUrl_, kGroup_);
+  AddReport(kReportingSource_, kNik_, kUrl_, kGroup_);
   EXPECT_TRUE(delivery_timer()->IsRunning());
   delivery_timer()->Fire();
   ASSERT_EQ(1u, pending_uploads().size());
@@ -562,8 +567,8 @@
   // Trigger and complete an upload to start the delivery timer.
   UploadFirstReportAndStartTimer();
 
-  AddReport(kNik_, kUrl_, kGroup_);
-  AddReport(kNik_, kUrl_, kDifferentGroup);
+  AddReport(kReportingSource_, kNik_, kUrl_, kGroup_);
+  AddReport(kReportingSource_, kNik_, kUrl_, kDifferentGroup);
 
   EXPECT_TRUE(delivery_timer()->IsRunning());
   delivery_timer()->Fire();
@@ -604,8 +609,8 @@
 
   UploadFirstReportAndStartTimer();
 
-  AddReport(kNik_, kUrl_, kGroup_);
-  AddReport(kNik_, kUrl_, kDifferentGroup);
+  AddReport(kReportingSource_, kNik_, kUrl_, kGroup_);
+  AddReport(kReportingSource_, kNik_, kUrl_, kDifferentGroup);
 
   EXPECT_TRUE(delivery_timer()->IsRunning());
   delivery_timer()->Fire();
diff --git a/net/reporting/reporting_endpoint_manager_unittest.cc b/net/reporting/reporting_endpoint_manager_unittest.cc
index b72935f5..0d96d1e 100644
--- a/net/reporting/reporting_endpoint_manager_unittest.cc
+++ b/net/reporting/reporting_endpoint_manager_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "base/time/time.h"
+#include "base/unguessable_token.h"
 #include "net/base/backoff_entry.h"
 #include "net/base/network_isolation_key.h"
 #include "net/base/schemeful_site.h"
@@ -17,6 +18,7 @@
 #include "net/reporting/reporting_policy.h"
 #include "net/reporting/reporting_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 #include "url/origin.h"
 
@@ -48,7 +50,8 @@
   }
 
   // Everything below is NOTREACHED.
-  void AddReport(const NetworkIsolationKey& network_isolation_key,
+  void AddReport(const absl::optional<base::UnguessableToken>& reporting_source,
+                 const NetworkIsolationKey& network_isolation_key,
                  const GURL& url,
                  const std::string& user_agent,
                  const std::string& group_name,
diff --git a/net/reporting/reporting_garbage_collector_unittest.cc b/net/reporting/reporting_garbage_collector_unittest.cc
index 71ea1cea..4f9f89d 100644
--- a/net/reporting/reporting_garbage_collector_unittest.cc
+++ b/net/reporting/reporting_garbage_collector_unittest.cc
@@ -14,6 +14,7 @@
 #include "net/reporting/reporting_report.h"
 #include "net/reporting/reporting_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace net {
 namespace {
@@ -26,6 +27,8 @@
     return reports.size();
   }
 
+  const absl::optional<base::UnguessableToken> kReportingSource_ =
+      absl::nullopt;
   const NetworkIsolationKey kNik_;
   const GURL kUrl_ = GURL("https://origin/path");
   const std::string kUserAgent_ = "Mozilla/1.0";
@@ -42,8 +45,8 @@
 TEST_F(ReportingGarbageCollectorTest, Timer) {
   EXPECT_FALSE(garbage_collection_timer()->IsRunning());
 
-  cache()->AddReport(kNik_, kUrl_, kUserAgent_, kGroup_, kType_,
-                     std::make_unique<base::DictionaryValue>(), 0,
+  cache()->AddReport(kReportingSource_, kNik_, kUrl_, kUserAgent_, kGroup_,
+                     kType_, std::make_unique<base::DictionaryValue>(), 0,
                      tick_clock()->NowTicks(), 0);
 
   EXPECT_TRUE(garbage_collection_timer()->IsRunning());
@@ -54,8 +57,8 @@
 }
 
 TEST_F(ReportingGarbageCollectorTest, Report) {
-  cache()->AddReport(kNik_, kUrl_, kUserAgent_, kGroup_, kType_,
-                     std::make_unique<base::DictionaryValue>(), 0,
+  cache()->AddReport(kReportingSource_, kNik_, kUrl_, kUserAgent_, kGroup_,
+                     kType_, std::make_unique<base::DictionaryValue>(), 0,
                      tick_clock()->NowTicks(), 0);
   garbage_collection_timer()->Fire();
 
@@ -63,8 +66,8 @@
 }
 
 TEST_F(ReportingGarbageCollectorTest, ExpiredReport) {
-  cache()->AddReport(kNik_, kUrl_, kUserAgent_, kGroup_, kType_,
-                     std::make_unique<base::DictionaryValue>(), 0,
+  cache()->AddReport(kReportingSource_, kNik_, kUrl_, kUserAgent_, kGroup_,
+                     kType_, std::make_unique<base::DictionaryValue>(), 0,
                      tick_clock()->NowTicks(), 0);
   tick_clock()->Advance(2 * policy().max_report_age);
   garbage_collection_timer()->Fire();
@@ -73,8 +76,8 @@
 }
 
 TEST_F(ReportingGarbageCollectorTest, FailedReport) {
-  cache()->AddReport(kNik_, kUrl_, kUserAgent_, kGroup_, kType_,
-                     std::make_unique<base::DictionaryValue>(), 0,
+  cache()->AddReport(kReportingSource_, kNik_, kUrl_, kUserAgent_, kGroup_,
+                     kType_, std::make_unique<base::DictionaryValue>(), 0,
                      tick_clock()->NowTicks(), 0);
 
   std::vector<const ReportingReport*> reports;
diff --git a/net/reporting/reporting_header_parser.cc b/net/reporting/reporting_header_parser.cc
index 93ac03b..82475719 100644
--- a/net/reporting/reporting_header_parser.cc
+++ b/net/reporting/reporting_header_parser.cc
@@ -330,11 +330,13 @@
 // static
 void ReportingHeaderParser::ProcessParsedReportingEndpointsHeader(
     ReportingContext* context,
+    const base::UnguessableToken& reporting_source,
     const NetworkIsolationKey& network_isolation_key,
     const url::Origin& origin,
     base::flat_map<std::string, std::string> header) {
   DCHECK(base::FeatureList::IsEnabled(net::features::kDocumentReporting));
   DCHECK(GURL::SchemeIsCryptographic(origin.scheme()));
+  DCHECK(!reporting_source.is_empty());
 
   ReportingDelegate* delegate = context->delegate();
   ReportingCache* cache = context->cache();
diff --git a/net/reporting/reporting_header_parser.h b/net/reporting/reporting_header_parser.h
index 6a1b955e..ea981b1ff 100644
--- a/net/reporting/reporting_header_parser.h
+++ b/net/reporting/reporting_header_parser.h
@@ -49,6 +49,7 @@
 
   static void ProcessParsedReportingEndpointsHeader(
       ReportingContext* context,
+      const base::UnguessableToken& reporting_source,
       const NetworkIsolationKey& network_isolation_key,
       const url::Origin& origin,
       base::flat_map<std::string, std::string> parsed_header);
diff --git a/net/reporting/reporting_header_parser_unittest.cc b/net/reporting/reporting_header_parser_unittest.cc
index af7eaf7..29735e3 100644
--- a/net/reporting/reporting_header_parser_unittest.cc
+++ b/net/reporting/reporting_header_parser_unittest.cc
@@ -1778,7 +1778,8 @@
 
     if (header_map) {
       ReportingHeaderParser::ProcessParsedReportingEndpointsHeader(
-          context(), network_isolation_key, origin, *header_map);
+          context(), base::UnguessableToken::Create(), network_isolation_key,
+          origin, *header_map);
     }
   }
 };
diff --git a/net/reporting/reporting_network_change_observer_unittest.cc b/net/reporting/reporting_network_change_observer_unittest.cc
index f5ae0ce..cb7edca 100644
--- a/net/reporting/reporting_network_change_observer_unittest.cc
+++ b/net/reporting/reporting_network_change_observer_unittest.cc
@@ -7,12 +7,14 @@
 #include "base/bind.h"
 #include "base/run_loop.h"
 #include "base/test/simple_test_tick_clock.h"
+#include "base/unguessable_token.h"
 #include "base/values.h"
 #include "net/base/network_change_notifier.h"
 #include "net/reporting/reporting_cache.h"
 #include "net/reporting/reporting_report.h"
 #include "net/reporting/reporting_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace net {
 namespace {
@@ -43,6 +45,8 @@
     return reports.size();
   }
 
+  const absl::optional<base::UnguessableToken> kReportingSource_ =
+      absl::nullopt;
   const NetworkIsolationKey kNik_;
   const GURL kUrl_ = GURL("https://origin/path");
   const url::Origin kOrigin_ = url::Origin::Create(kUrl_);
@@ -60,8 +64,8 @@
   new_policy.persist_clients_across_network_changes = true;
   UsePolicy(new_policy);
 
-  cache()->AddReport(kNik_, kUrl_, kUserAgent_, kGroup_, kType_,
-                     std::make_unique<base::DictionaryValue>(), 0,
+  cache()->AddReport(kReportingSource_, kNik_, kUrl_, kUserAgent_, kGroup_,
+                     kType_, std::make_unique<base::DictionaryValue>(), 0,
                      tick_clock()->NowTicks(), 0);
   SetEndpoint();
   ASSERT_EQ(1u, report_count());
@@ -79,8 +83,8 @@
   new_policy.persist_clients_across_network_changes = true;
   UsePolicy(new_policy);
 
-  cache()->AddReport(kNik_, kUrl_, kUserAgent_, kGroup_, kType_,
-                     std::make_unique<base::DictionaryValue>(), 0,
+  cache()->AddReport(kReportingSource_, kNik_, kUrl_, kUserAgent_, kGroup_,
+                     kType_, std::make_unique<base::DictionaryValue>(), 0,
                      tick_clock()->NowTicks(), 0);
   SetEndpoint();
   ASSERT_EQ(1u, report_count());
@@ -98,8 +102,8 @@
   new_policy.persist_clients_across_network_changes = false;
   UsePolicy(new_policy);
 
-  cache()->AddReport(kNik_, kUrl_, kUserAgent_, kGroup_, kType_,
-                     std::make_unique<base::DictionaryValue>(), 0,
+  cache()->AddReport(kReportingSource_, kNik_, kUrl_, kUserAgent_, kGroup_,
+                     kType_, std::make_unique<base::DictionaryValue>(), 0,
                      tick_clock()->NowTicks(), 0);
   SetEndpoint();
   ASSERT_EQ(1u, report_count());
@@ -117,8 +121,8 @@
   new_policy.persist_clients_across_network_changes = false;
   UsePolicy(new_policy);
 
-  cache()->AddReport(kNik_, kUrl_, kUserAgent_, kGroup_, kType_,
-                     std::make_unique<base::DictionaryValue>(), 0,
+  cache()->AddReport(kReportingSource_, kNik_, kUrl_, kUserAgent_, kGroup_,
+                     kType_, std::make_unique<base::DictionaryValue>(), 0,
                      tick_clock()->NowTicks(), 0);
   SetEndpoint();
   ASSERT_EQ(1u, report_count());
diff --git a/net/reporting/reporting_service.cc b/net/reporting/reporting_service.cc
index e32908f..477997ec 100644
--- a/net/reporting/reporting_service.cc
+++ b/net/reporting/reporting_service.cc
@@ -56,24 +56,31 @@
   }
 
   void SetDocumentReportingEndpoints(
+      const base::UnguessableToken& reporting_source,
       const url::Origin& origin,
       const net::NetworkIsolationKey& network_isolation_key,
       const base::flat_map<std::string, std::string>& endpoints) override {
-    DoOrBacklogTask(base::BindOnce(
-        &ReportingServiceImpl::DoSetDocumentReportingEndpoints,
-        base::Unretained(this), FixupNetworkIsolationKey(network_isolation_key),
-        origin, endpoints));
+    DCHECK(!reporting_source.is_empty());
+    DoOrBacklogTask(
+        base::BindOnce(&ReportingServiceImpl::DoSetDocumentReportingEndpoints,
+                       base::Unretained(this), reporting_source,
+                       FixupNetworkIsolationKey(network_isolation_key), origin,
+                       std::move(endpoints)));
   }
 
-  void QueueReport(const GURL& url,
-                   const NetworkIsolationKey& network_isolation_key,
-                   const std::string& user_agent,
-                   const std::string& group,
-                   const std::string& type,
-                   std::unique_ptr<const base::Value> body,
-                   int depth) override {
+  void QueueReport(
+      const GURL& url,
+      const absl::optional<base::UnguessableToken>& reporting_source,
+      const NetworkIsolationKey& network_isolation_key,
+      const std::string& user_agent,
+      const std::string& group,
+      const std::string& type,
+      std::unique_ptr<const base::Value> body,
+      int depth) override {
     DCHECK(context_);
     DCHECK(context_->delegate());
+    // If |reporting_source| is provided, it must not be empty.
+    DCHECK(!(reporting_source.has_value() && reporting_source->is_empty()));
 
     if (!context_->delegate()->CanQueueReport(url::Origin::Create(url)))
       return;
@@ -89,7 +96,7 @@
     // |task_backlog_| which will not outlive |this|.
     DoOrBacklogTask(base::BindOnce(
         &ReportingServiceImpl::DoQueueReport, base::Unretained(this),
-        FixupNetworkIsolationKey(network_isolation_key),
+        reporting_source, FixupNetworkIsolationKey(network_isolation_key),
         std::move(sanitized_url), user_agent, group, type, std::move(body),
         depth, queued_ticks));
   }
@@ -177,18 +184,20 @@
     std::move(task).Run();
   }
 
-  void DoQueueReport(const NetworkIsolationKey& network_isolation_key,
-                     GURL sanitized_url,
-                     const std::string& user_agent,
-                     const std::string& group,
-                     const std::string& type,
-                     std::unique_ptr<const base::Value> body,
-                     int depth,
-                     base::TimeTicks queued_ticks) {
+  void DoQueueReport(
+      const absl::optional<base::UnguessableToken>& reporting_source,
+      const NetworkIsolationKey& network_isolation_key,
+      GURL sanitized_url,
+      const std::string& user_agent,
+      const std::string& group,
+      const std::string& type,
+      std::unique_ptr<const base::Value> body,
+      int depth,
+      base::TimeTicks queued_ticks) {
     DCHECK(initialized_);
-    context_->cache()->AddReport(network_isolation_key, sanitized_url,
-                                 user_agent, group, type, std::move(body),
-                                 depth, queued_ticks, 0 /* attempts */);
+    context_->cache()->AddReport(
+        reporting_source, network_isolation_key, sanitized_url, user_agent,
+        group, type, std::move(body), depth, queued_ticks, 0 /* attempts */);
   }
 
   void DoProcessReportToHeader(const NetworkIsolationKey& network_isolation_key,
@@ -200,12 +209,14 @@
   }
 
   void DoSetDocumentReportingEndpoints(
+      const base::UnguessableToken& reporting_source,
       const NetworkIsolationKey& network_isolation_key,
       const url::Origin& origin,
       base::flat_map<std::string, std::string> header_value) {
     DCHECK(initialized_);
     ReportingHeaderParser::ProcessParsedReportingEndpointsHeader(
-        context_.get(), network_isolation_key, origin, std::move(header_value));
+        context_.get(), reporting_source, network_isolation_key, origin,
+        std::move(header_value));
   }
 
   void DoRemoveBrowsingData(
diff --git a/net/reporting/reporting_service.h b/net/reporting/reporting_service.h
index f0d52d7..d273bf5 100644
--- a/net/reporting/reporting_service.h
+++ b/net/reporting/reporting_service.h
@@ -11,9 +11,11 @@
 #include "base/callback.h"
 #include "base/containers/flat_map.h"
 #include "base/macros.h"
+#include "base/unguessable_token.h"
 #include "net/base/net_export.h"
 #include "net/reporting/reporting_cache.h"
 #include "net/reporting/reporting_cache_observer.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 class GURL;
 
@@ -50,21 +52,26 @@
       std::unique_ptr<ReportingContext> reporting_context);
 
   // Queues a report for delivery. |url| is the URL that originated the report.
-  // |network_isolation_key| is used to restrict what reports can be merged, and
-  // for sending the report.
+  // |reporting_source| is the reporting source token for the document or
+  // worker which triggered this report, if it can be associated with one, or
+  // nullopt otherwise. If present, it may not be empty.
+  // Along with |network_isolation_key|, it is used to restrict what reports
+  // can be merged, and for sending the report.
   // |user_agent| is the User-Agent header that was used for the request.
   // |group| is the endpoint group to which the report should be delivered.
   // |type| is the type of the report. |body| is the body of the report.
   //
   // The Reporting system will take ownership of |body|; all other parameters
   // will be copied.
-  virtual void QueueReport(const GURL& url,
-                           const NetworkIsolationKey& network_isolation_key,
-                           const std::string& user_agent,
-                           const std::string& group,
-                           const std::string& type,
-                           std::unique_ptr<const base::Value> body,
-                           int depth) = 0;
+  virtual void QueueReport(
+      const GURL& url,
+      const absl::optional<base::UnguessableToken>& reporting_source,
+      const NetworkIsolationKey& network_isolation_key,
+      const std::string& user_agent,
+      const std::string& group,
+      const std::string& type,
+      std::unique_ptr<const base::Value> body,
+      int depth) = 0;
 
   // Processes a Report-To header. |url| is the URL that originated the header;
   // |header_value| is the normalized value of the Report-To header.
@@ -74,9 +81,19 @@
       const std::string& header_value) = 0;
 
   // Configures reporting endpoints set by the Reporting-Endpoints header, once
-  // the associated document has been committed.
+  // the associated document or worker (represented by |reporting_source|) has
+  // been committed.
+  // |reporting_source| is the unique identifier for the resource with which
+  // this header was received, and must not be empty.
   // |endpoints| is a mapping of endpoint names to URLs.
+  // |origin| is the origin of the reporting source, and
+  // |network_isolation_key| is the appropriate NIK for that source.
+  // (The isolation provided by Reporting-Endpoints is stronger than that
+  // provided by Report-To, so the origin and NIK aren't strictly necessary,
+  // but are currently required here because of shared infrastructure between
+  // the two versions of the reporting API.)
   virtual void SetDocumentReportingEndpoints(
+      const base::UnguessableToken& reporting_source,
       const url::Origin& origin,
       const NetworkIsolationKey& network_isolation_key,
       const base::flat_map<std::string, std::string>& endpoints) = 0;
diff --git a/net/reporting/reporting_service_unittest.cc b/net/reporting/reporting_service_unittest.cc
index 3ce13d2d..ddb0a29b 100644
--- a/net/reporting/reporting_service_unittest.cc
+++ b/net/reporting/reporting_service_unittest.cc
@@ -27,6 +27,7 @@
 #include "net/test/test_with_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 #include "url/origin.h"
 
@@ -48,6 +49,8 @@
   const std::string kUserAgent_ = "Mozilla/1.0";
   const std::string kGroup_ = "group";
   const std::string kType_ = "type";
+  const absl::optional<base::UnguessableToken> kReportingSource_ =
+      base::UnguessableToken::Create();
   const NetworkIsolationKey kNik_ =
       NetworkIsolationKey(SchemefulSite(kOrigin_), SchemefulSite(kOrigin_));
   const NetworkIsolationKey kNik2_ =
@@ -100,8 +103,8 @@
 };
 
 TEST_P(ReportingServiceTest, QueueReport) {
-  service()->QueueReport(kUrl_, kNik_, kUserAgent_, kGroup_, kType_,
-                         std::make_unique<base::DictionaryValue>(), 0);
+  service()->QueueReport(kUrl_, kReportingSource_, kNik_, kUserAgent_, kGroup_,
+                         kType_, std::make_unique<base::DictionaryValue>(), 0);
   FinishLoading(true /* load_success */);
 
   std::vector<const ReportingReport*> reports;
@@ -117,8 +120,8 @@
 TEST_P(ReportingServiceTest, QueueReportSanitizeUrl) {
   // Same as kUrl_ but with username, password, and fragment.
   GURL url = GURL("https://username:password@origin/path#fragment");
-  service()->QueueReport(url, kNik_, kUserAgent_, kGroup_, kType_,
-                         std::make_unique<base::DictionaryValue>(), 0);
+  service()->QueueReport(url, kReportingSource_, kNik_, kUserAgent_, kGroup_,
+                         kType_, std::make_unique<base::DictionaryValue>(), 0);
   FinishLoading(true /* load_success */);
 
   std::vector<const ReportingReport*> reports;
@@ -135,8 +138,8 @@
   GURL url = GURL("https://");
   // This does not trigger an attempt to load from the store because the url
   // is immediately rejected as invalid.
-  service()->QueueReport(url, kNik_, kUserAgent_, kGroup_, kType_,
-                         std::make_unique<base::DictionaryValue>(), 0);
+  service()->QueueReport(url, kReportingSource_, kNik_, kUserAgent_, kGroup_,
+                         kType_, std::make_unique<base::DictionaryValue>(), 0);
 
   std::vector<const ReportingReport*> reports;
   context()->cache()->GetReports(&reports);
@@ -151,8 +154,8 @@
   // Re-create the store, so it reads the new feature value.
   Init();
 
-  service()->QueueReport(kUrl_, kNik_, kUserAgent_, kGroup_, kType_,
-                         std::make_unique<base::DictionaryValue>(), 0);
+  service()->QueueReport(kUrl_, kReportingSource_, kNik_, kUserAgent_, kGroup_,
+                         kType_, std::make_unique<base::DictionaryValue>(), 0);
   FinishLoading(true /* load_success */);
 
   std::vector<const ReportingReport*> reports;
@@ -191,7 +194,8 @@
   auto parsed_header =
       ParseReportingEndpoints(kGroup_ + "=\"" + kEndpoint_.spec() + "\"");
   ASSERT_TRUE(parsed_header.has_value());
-  service()->SetDocumentReportingEndpoints(kOrigin_, kNik_, *parsed_header);
+  service()->SetDocumentReportingEndpoints(*kReportingSource_, kOrigin_, kNik_,
+                                           *parsed_header);
   FinishLoading(true /* load_success */);
 
   EXPECT_EQ(1u, context()->cache()->GetEndpointCount());
@@ -204,7 +208,8 @@
   feature_list.InitAndEnableFeature(net::features::kDocumentReporting);
   auto parsed_header = ParseReportingEndpoints(kGroup_ + "=\"/path-absolute\"");
   ASSERT_TRUE(parsed_header.has_value());
-  service()->SetDocumentReportingEndpoints(kOrigin_, kNik_, *parsed_header);
+  service()->SetDocumentReportingEndpoints(*kReportingSource_, kOrigin_, kNik_,
+                                           *parsed_header);
   FinishLoading(true /* load_success */);
 
   EXPECT_EQ(1u, context()->cache()->GetEndpointCount());
@@ -326,8 +331,8 @@
   EXPECT_THAT(store()->GetAllCommands(),
               testing::UnorderedElementsAreArray(expected_commands));
 
-  service()->QueueReport(kUrl_, kNik_, kUserAgent_, kGroup_, kType_,
-                         std::make_unique<base::DictionaryValue>(), 0);
+  service()->QueueReport(kUrl_, kReportingSource_, kNik_, kUserAgent_, kGroup_,
+                         kType_, std::make_unique<base::DictionaryValue>(), 0);
   expected_commands.emplace_back(
       CommandType::UPDATE_REPORTING_ENDPOINT_GROUP_ACCESS_TIME, kGroupKey_);
   EXPECT_THAT(store()->GetAllCommands(),
@@ -387,8 +392,8 @@
   EXPECT_THAT(store()->GetAllCommands(),
               testing::UnorderedElementsAreArray(expected_commands));
 
-  service()->QueueReport(kUrl_, kNik_, kUserAgent_, kGroup_, kType_,
-                         std::make_unique<base::DictionaryValue>(), 0);
+  service()->QueueReport(kUrl_, kReportingSource_, kNik_, kUserAgent_, kGroup_,
+                         kType_, std::make_unique<base::DictionaryValue>(), 0);
   EXPECT_THAT(store()->GetAllCommands(),
               testing::UnorderedElementsAreArray(expected_commands));
 
diff --git a/net/reporting/reporting_test_util.cc b/net/reporting/reporting_test_util.cc
index 04b38610..887807e 100644
--- a/net/reporting/reporting_test_util.cc
+++ b/net/reporting/reporting_test_util.cc
@@ -317,6 +317,7 @@
 
 void TestReportingService::QueueReport(
     const GURL& url,
+    const absl::optional<base::UnguessableToken>& reporting_source,
     const NetworkIsolationKey& network_isolation_key,
     const std::string& user_agent,
     const std::string& group,
diff --git a/net/reporting/reporting_test_util.h b/net/reporting/reporting_test_util.h
index d4b0cae..700a5c3 100644
--- a/net/reporting/reporting_test_util.h
+++ b/net/reporting/reporting_test_util.h
@@ -13,6 +13,7 @@
 #include "base/macros.h"
 #include "base/test/simple_test_clock.h"
 #include "base/test/simple_test_tick_clock.h"
+#include "base/unguessable_token.h"
 #include "net/base/network_isolation_key.h"
 #include "net/base/rand_callback.h"
 #include "net/reporting/reporting_cache.h"
@@ -23,6 +24,7 @@
 #include "net/test/test_with_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 
 namespace base {
@@ -314,17 +316,20 @@
   ~TestReportingService() override;
 
   void SetDocumentReportingEndpoints(
+      const base::UnguessableToken& reporting_source,
       const url::Origin& origin,
       const net::NetworkIsolationKey& network_isolation_key,
       const base::flat_map<std::string, std::string>& endpoints) override {}
 
-  void QueueReport(const GURL& url,
-                   const NetworkIsolationKey& network_isolation_key,
-                   const std::string& user_agent,
-                   const std::string& group,
-                   const std::string& type,
-                   std::unique_ptr<const base::Value> body,
-                   int depth) override;
+  void QueueReport(
+      const GURL& url,
+      const absl::optional<base::UnguessableToken>& reporting_source,
+      const NetworkIsolationKey& network_isolation_key,
+      const std::string& user_agent,
+      const std::string& group,
+      const std::string& type,
+      std::unique_ptr<const base::Value> body,
+      int depth) override;
 
   void ProcessReportToHeader(const GURL& url,
                              const NetworkIsolationKey& network_isolation_key,
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
index 57b5f7a..68f7eaf 100644
--- a/services/network/network_context.cc
+++ b/services/network/network_context.cc
@@ -933,14 +933,16 @@
 }
 
 void NetworkContext::SetDocumentReportingEndpoints(
+    const base::UnguessableToken& reporting_source,
     const url::Origin& origin,
     const net::NetworkIsolationKey& network_isolation_key,
     const base::flat_map<std::string, std::string>& endpoints) {
+  DCHECK(!reporting_source.is_empty());
   net::ReportingService* reporting_service =
       url_request_context()->reporting_service();
   if (reporting_service) {
     reporting_service->SetDocumentReportingEndpoints(
-        origin, network_isolation_key, endpoints);
+        reporting_source, origin, network_isolation_key, endpoints);
   }
 }
 
@@ -948,9 +950,12 @@
     const std::string& type,
     const std::string& group,
     const GURL& url,
+    const absl::optional<base::UnguessableToken>& reporting_source,
     const net::NetworkIsolationKey& network_isolation_key,
     const absl::optional<std::string>& user_agent,
     base::Value body) {
+  // If |reporting_source| is provided, it must not be empty.
+  DCHECK(!(reporting_source.has_value() && reporting_source->is_empty()));
   if (require_network_isolation_key_)
     DCHECK(!network_isolation_key.IsEmpty());
 
@@ -975,8 +980,8 @@
   }
 
   reporting_service->QueueReport(
-      url, network_isolation_key, reported_user_agent, group, type,
-      base::Value::ToUniquePtrValue(std::move(body)), 0 /* depth */);
+      url, reporting_source, network_isolation_key, reported_user_agent, group,
+      type, base::Value::ToUniquePtrValue(std::move(body)), 0 /* depth */);
 }
 
 void NetworkContext::QueueSignedExchangeReport(
@@ -1105,6 +1110,7 @@
 }
 
 void NetworkContext::SetDocumentReportingEndpoints(
+    const base::UnguessableToken& reporting_source,
     const url::Origin& origin,
     const net::NetworkIsolationKey& network_isolation_key,
     const base::flat_map<std::string, std::string>& endpoints) {
@@ -1115,6 +1121,7 @@
     const std::string& type,
     const std::string& group,
     const GURL& url,
+    const absl::optional<base::UnguessableToken>& reporting_source,
     const net::NetworkIsolationKey& network_isolation_key,
     const absl::optional<std::string>& user_agent,
     base::Value body) {
diff --git a/services/network/network_context.h b/services/network/network_context.h
index 6912997..79fa191 100644
--- a/services/network/network_context.h
+++ b/services/network/network_context.h
@@ -21,6 +21,7 @@
 #include "base/containers/unique_ptr_adapters.h"
 #include "base/macros.h"
 #include "base/time/time.h"
+#include "base/unguessable_token.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
 #include "mojo/public/cpp/base/big_buffer.h"
@@ -407,15 +408,18 @@
   void CreateMdnsResponder(
       mojo::PendingReceiver<mojom::MdnsResponder> responder_receiver) override;
   void SetDocumentReportingEndpoints(
+      const base::UnguessableToken& reporting_source,
       const url::Origin& origin,
       const net::NetworkIsolationKey& network_isolation_key,
       const base::flat_map<std::string, std::string>& endpoints) override;
-  void QueueReport(const std::string& type,
-                   const std::string& group,
-                   const GURL& url,
-                   const net::NetworkIsolationKey& network_isolation_key,
-                   const absl::optional<std::string>& user_agent,
-                   base::Value body) override;
+  void QueueReport(
+      const std::string& type,
+      const std::string& group,
+      const GURL& url,
+      const absl::optional<base::UnguessableToken>& reporting_source,
+      const net::NetworkIsolationKey& network_isolation_key,
+      const absl::optional<std::string>& user_agent,
+      base::Value body) override;
   void QueueSignedExchangeReport(
       mojom::SignedExchangeReportPtr report,
       const net::NetworkIsolationKey& network_isolation_key) override;
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc
index b67657d..b61b27d 100644
--- a/services/network/network_context_unittest.cc
+++ b/services/network/network_context_unittest.cc
@@ -2139,8 +2139,9 @@
       reporting_service.get());
 
   GURL domain("http://google.com");
-  reporting_service->QueueReport(domain, net::NetworkIsolationKey(),
-                                 "Mozilla/1.0", "group", "type", nullptr, 0);
+  reporting_service->QueueReport(domain, absl::nullopt,
+                                 net::NetworkIsolationKey(), "Mozilla/1.0",
+                                 "group", "type", nullptr, 0);
 
   std::vector<const net::ReportingReport*> reports;
   reporting_cache->GetReports(&reports);
@@ -2169,11 +2170,13 @@
       reporting_service.get());
 
   GURL url1("http://google.com");
-  reporting_service->QueueReport(url1, net::NetworkIsolationKey(),
-                                 "Mozilla/1.0", "group", "type", nullptr, 0);
+  reporting_service->QueueReport(url1, absl::nullopt,
+                                 net::NetworkIsolationKey(), "Mozilla/1.0",
+                                 "group", "type", nullptr, 0);
   GURL url2("http://chromium.org");
-  reporting_service->QueueReport(url2, net::NetworkIsolationKey(),
-                                 "Mozilla/1.0", "group", "type", nullptr, 0);
+  reporting_service->QueueReport(url2, absl::nullopt,
+                                 net::NetworkIsolationKey(), "Mozilla/1.0",
+                                 "group", "type", nullptr, 0);
 
   std::vector<const net::ReportingReport*> reports;
   reporting_cache->GetReports(&reports);
@@ -2208,11 +2211,13 @@
       reporting_service.get());
 
   GURL url1("http://192.168.0.1");
-  reporting_service->QueueReport(url1, net::NetworkIsolationKey(),
-                                 "Mozilla/1.0", "group", "type", nullptr, 0);
+  reporting_service->QueueReport(url1, absl::nullopt,
+                                 net::NetworkIsolationKey(), "Mozilla/1.0",
+                                 "group", "type", nullptr, 0);
   GURL url2("http://192.168.0.2");
-  reporting_service->QueueReport(url2, net::NetworkIsolationKey(),
-                                 "Mozilla/1.0", "group", "type", nullptr, 0);
+  reporting_service->QueueReport(url2, absl::nullopt,
+                                 net::NetworkIsolationKey(), "Mozilla/1.0",
+                                 "group", "type", nullptr, 0);
 
   std::vector<const net::ReportingReport*> reports;
   reporting_cache->GetReports(&reports);
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom
index b51365f..ba3d678 100644
--- a/services/network/public/mojom/network_context.mojom
+++ b/services/network/public/mojom/network_context.mojom
@@ -919,35 +919,50 @@
 
   // Configures per-resource reporting endpoints set with the
   // Reporting-Endpoints header.
+  // |reporting_source| is a token which identifies the document or worker with
+  // which the header was received. The endpoints configured by this method are
+  // only used to deliver reports which are queued by that same source.
   // |network_isolation_key| is used when creating the endpoints in the
   // ReportingCache, and will need to match the key sent when reports are queued
-  // in order for these reporting endpoints to be considered for delivery.
+  // in order for these reporting endpoints to be considered for delivery,
+  // although this should always be the case when reports are queued by the
+  // same source which configured the endpoints.
   // |endpoints| is a mapping of endpoint name to URL (URLs here are represented
   // as strings, and will be rejected if they fail to parse or are not secure).
   //
   // Spec: https://w3c.github.io/reporting/#header
   SetDocumentReportingEndpoints(
+      mojo_base.mojom.UnguessableToken reporting_source,
       url.mojom.Origin origin, NetworkIsolationKey network_isolation_key,
       map<string,string> endpoints);
 
   // Queues a report via the Reporting API. |type| describes the type of report
   // (as well as what data will contained in |body|). |group| specifies the
   // endpoint group that the report will be delivered to. |url| indicates the
-  // URL of the resource that the report describes; |network_isolation_key|
-  // indicates the NetworkIsolationKey associated with the request, and is
-  // used for both looking up the appropriately scoped reporting information
-  // and for sending the report. |user_agent| may be provided, or will be
-  // automatically generated if omitted; |body| holds the contents of the
-  // report.
+  // URL of the resource that the report describes. |user_agent| may be
+  // provided, or will be automatically generated if omitted; |body| holds the
+  // contents of the report.
+  //
+  // |reporting_source| and |network_isolation_key| are used both for looking
+  // up the appropriately scoped reporting information and for sending the
+  // report. |network_isolation_key| indicates the NetworkIsolationKey
+  // associated with the request, while |reporting_source|, if not empty,
+  // identifies the specific document or worker instance causing the report to
+  // be queued. If |reporting_source| is not empty, then it will be used to
+  // look up reporting endpoints set with the SetDocumentReportingEndpoints
+  // method first, and if no matching endpoint is found, it will fall back to
+  // looking up a matching endpoint group configured for the origin and
+  // |network_isolation_key|.
   //
   // Note that this queued report will never be delivered if no reporting
-  // endpoint is registered for this |url| with the provided
-  // |network_isolation_key|.
+  // endpoint is registered for this |url| or |reporting_source| with the
+  // provided |network_isolation_key|.
   //
   // Spec: https://w3c.github.io/reporting/#concept-reports
   QueueReport(string type,
               string group,
               url.mojom.Url url,
+              mojo_base.mojom.UnguessableToken? reporting_source,
               NetworkIsolationKey network_isolation_key,
               string? user_agent,
               mojo_base.mojom.DictionaryValue body);
diff --git a/services/network/test/test_network_context.h b/services/network/test/test_network_context.h
index 09a53756..361add9 100644
--- a/services/network/test/test_network_context.h
+++ b/services/network/test/test_network_context.h
@@ -12,6 +12,7 @@
 
 #include "base/component_export.h"
 #include "base/time/time.h"
+#include "base/unguessable_token.h"
 #include "build/chromeos_buildflags.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
@@ -110,15 +111,18 @@
   void GetDomainReliabilityJSON(
       GetDomainReliabilityJSONCallback callback) override {}
   void SetDocumentReportingEndpoints(
+      const base::UnguessableToken& reporting_source,
       const url::Origin& origin,
       const net::NetworkIsolationKey& network_isolation_key,
       const base::flat_map<std::string, std::string>& endpoints) override {}
-  void QueueReport(const std::string& type,
-                   const std::string& group,
-                   const GURL& url,
-                   const net::NetworkIsolationKey& network_isolation_key,
-                   const absl::optional<std::string>& user_agent,
-                   base::Value body) override {}
+  void QueueReport(
+      const std::string& type,
+      const std::string& group,
+      const GURL& url,
+      const absl::optional<base::UnguessableToken>& reporting_source,
+      const net::NetworkIsolationKey& network_isolation_key,
+      const absl::optional<std::string>& user_agent,
+      base::Value body) override {}
   void QueueSignedExchangeReport(
       mojom::SignedExchangeReportPtr report,
       const net::NetworkIsolationKey& network_isolation_key) override {}