• 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_service.h"
6 
7 #include <optional>
8 #include <utility>
9 
10 #include "base/feature_list.h"
11 #include "base/functional/bind.h"
12 #include "base/json/json_reader.h"
13 #include "base/logging.h"
14 #include "base/memory/raw_ptr.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/time/tick_clock.h"
17 #include "base/time/time.h"
18 #include "base/values.h"
19 #include "net/base/features.h"
20 #include "net/base/isolation_info.h"
21 #include "net/http/structured_headers.h"
22 #include "net/reporting/reporting_browsing_data_remover.h"
23 #include "net/reporting/reporting_cache.h"
24 #include "net/reporting/reporting_context.h"
25 #include "net/reporting/reporting_delegate.h"
26 #include "net/reporting/reporting_delivery_agent.h"
27 #include "net/reporting/reporting_header_parser.h"
28 #include "net/reporting/reporting_uploader.h"
29 #include "url/gurl.h"
30 #include "url/origin.h"
31 
32 namespace net {
33 
34 namespace {
35 
36 constexpr int kMaxJsonSize = 16 * 1024;
37 constexpr int kMaxJsonDepth = 5;
38 
39 // If constructed with a PersistentReportingStore, the first call to any of
40 // QueueReport(), ProcessHeader(), RemoveBrowsingData(), or
41 // RemoveAllBrowsingData() on a valid input will trigger a load from the store.
42 // Tasks are queued pending completion of loading from the store.
43 class ReportingServiceImpl : public ReportingService {
44  public:
ReportingServiceImpl(std::unique_ptr<ReportingContext> context)45   explicit ReportingServiceImpl(std::unique_ptr<ReportingContext> context)
46       : context_(std::move(context)) {
47     if (!context_->IsClientDataPersisted())
48       initialized_ = true;
49   }
50 
51   ReportingServiceImpl(const ReportingServiceImpl&) = delete;
52   ReportingServiceImpl& operator=(const ReportingServiceImpl&) = delete;
53 
54   // ReportingService implementation:
55 
~ReportingServiceImpl()56   ~ReportingServiceImpl() override {
57     if (initialized_)
58       context_->cache()->Flush();
59   }
60 
SetDocumentReportingEndpoints(const base::UnguessableToken & reporting_source,const url::Origin & origin,const IsolationInfo & isolation_info,const base::flat_map<std::string,std::string> & endpoints)61   void SetDocumentReportingEndpoints(
62       const base::UnguessableToken& reporting_source,
63       const url::Origin& origin,
64       const IsolationInfo& isolation_info,
65       const base::flat_map<std::string, std::string>& endpoints) override {
66     DCHECK(!reporting_source.is_empty());
67     DoOrBacklogTask(
68         base::BindOnce(&ReportingServiceImpl::DoSetDocumentReportingEndpoints,
69                        base::Unretained(this), reporting_source, isolation_info,
70                        FixupNetworkAnonymizationKey(
71                            isolation_info.network_anonymization_key()),
72                        origin, std::move(endpoints)));
73   }
74 
SetEnterpriseReportingEndpoints(const base::flat_map<std::string,GURL> & endpoints)75   void SetEnterpriseReportingEndpoints(
76       const base::flat_map<std::string, GURL>& endpoints) override {
77     if (!base::FeatureList::IsEnabled(
78             net::features::kReportingApiEnableEnterpriseCookieIssues)) {
79       return;
80     }
81     context_->cache()->SetEnterpriseReportingEndpoints(endpoints);
82   }
83 
SendReportsAndRemoveSource(const base::UnguessableToken & reporting_source)84   void SendReportsAndRemoveSource(
85       const base::UnguessableToken& reporting_source) override {
86     DCHECK(!reporting_source.is_empty());
87     context_->delivery_agent()->SendReportsForSource(reporting_source);
88     context_->cache()->SetExpiredSource(reporting_source);
89   }
90 
QueueReport(const GURL & url,const std::optional<base::UnguessableToken> & reporting_source,const NetworkAnonymizationKey & network_anonymization_key,const std::string & user_agent,const std::string & group,const std::string & type,base::Value::Dict body,int depth,ReportingTargetType target_type)91   void QueueReport(
92       const GURL& url,
93       const std::optional<base::UnguessableToken>& reporting_source,
94       const NetworkAnonymizationKey& network_anonymization_key,
95       const std::string& user_agent,
96       const std::string& group,
97       const std::string& type,
98       base::Value::Dict body,
99       int depth,
100       ReportingTargetType target_type) override {
101     DCHECK(context_);
102     DCHECK(context_->delegate());
103     // If |reporting_source| is provided, it must not be empty.
104     DCHECK(!(reporting_source.has_value() && reporting_source->is_empty()));
105 
106     if (!context_->delegate()->CanQueueReport(url::Origin::Create(url)))
107       return;
108 
109     // Strip username, password, and ref fragment from the URL.
110     GURL sanitized_url = url.GetAsReferrer();
111     if (!sanitized_url.is_valid())
112       return;
113 
114     base::TimeTicks queued_ticks = context_->tick_clock().NowTicks();
115 
116     // base::Unretained is safe because the callback is stored in
117     // |task_backlog_| which will not outlive |this|.
118     DoOrBacklogTask(
119         base::BindOnce(&ReportingServiceImpl::DoQueueReport,
120                        base::Unretained(this), reporting_source,
121                        FixupNetworkAnonymizationKey(network_anonymization_key),
122                        std::move(sanitized_url), user_agent, group, type,
123                        std::move(body), depth, queued_ticks, target_type));
124   }
125 
ProcessReportToHeader(const url::Origin & origin,const NetworkAnonymizationKey & network_anonymization_key,const std::string & header_string)126   void ProcessReportToHeader(
127       const url::Origin& origin,
128       const NetworkAnonymizationKey& network_anonymization_key,
129       const std::string& header_string) override {
130     if (header_string.size() > kMaxJsonSize)
131       return;
132 
133     std::optional<base::Value> header_value = base::JSONReader::Read(
134         "[" + header_string + "]", base::JSON_PARSE_RFC, kMaxJsonDepth);
135     if (!header_value)
136       return;
137 
138     DVLOG(1) << "Received Reporting policy for " << origin;
139     DoOrBacklogTask(base::BindOnce(
140         &ReportingServiceImpl::DoProcessReportToHeader, base::Unretained(this),
141         FixupNetworkAnonymizationKey(network_anonymization_key), origin,
142         std::move(header_value).value()));
143   }
144 
RemoveBrowsingData(uint64_t data_type_mask,const base::RepeatingCallback<bool (const url::Origin &)> & origin_filter)145   void RemoveBrowsingData(
146       uint64_t data_type_mask,
147       const base::RepeatingCallback<bool(const url::Origin&)>& origin_filter)
148       override {
149     DoOrBacklogTask(base::BindOnce(&ReportingServiceImpl::DoRemoveBrowsingData,
150                                    base::Unretained(this), data_type_mask,
151                                    origin_filter));
152   }
153 
RemoveAllBrowsingData(uint64_t data_type_mask)154   void RemoveAllBrowsingData(uint64_t data_type_mask) override {
155     DoOrBacklogTask(
156         base::BindOnce(&ReportingServiceImpl::DoRemoveAllBrowsingData,
157                        base::Unretained(this), data_type_mask));
158   }
159 
OnShutdown()160   void OnShutdown() override {
161     shut_down_ = true;
162     context_->OnShutdown();
163   }
164 
GetPolicy() const165   const ReportingPolicy& GetPolicy() const override {
166     return context_->policy();
167   }
168 
StatusAsValue() const169   base::Value StatusAsValue() const override {
170     base::Value::Dict dict;
171     dict.Set("reportingEnabled", true);
172     dict.Set("clients", context_->cache()->GetClientsAsValue());
173     dict.Set("reports", context_->cache()->GetReportsAsValue());
174     return base::Value(std::move(dict));
175   }
176 
GetReports() const177   std::vector<raw_ptr<const ReportingReport, VectorExperimental>> GetReports()
178       const override {
179     std::vector<raw_ptr<const net::ReportingReport, VectorExperimental>>
180         reports;
181     context_->cache()->GetReports(&reports);
182     return reports;
183   }
184 
185   base::flat_map<url::Origin, std::vector<ReportingEndpoint>>
GetV1ReportingEndpointsByOrigin() const186   GetV1ReportingEndpointsByOrigin() const override {
187     return context_->cache()->GetV1ReportingEndpointsByOrigin();
188   }
189 
AddReportingCacheObserver(ReportingCacheObserver * observer)190   void AddReportingCacheObserver(ReportingCacheObserver* observer) override {
191     context_->AddCacheObserver(observer);
192   }
193 
RemoveReportingCacheObserver(ReportingCacheObserver * observer)194   void RemoveReportingCacheObserver(ReportingCacheObserver* observer) override {
195     context_->RemoveCacheObserver(observer);
196   }
197 
GetContextForTesting() const198   ReportingContext* GetContextForTesting() const override {
199     return context_.get();
200   }
201 
202  private:
DoOrBacklogTask(base::OnceClosure task)203   void DoOrBacklogTask(base::OnceClosure task) {
204     if (shut_down_)
205       return;
206 
207     FetchAllClientsFromStoreIfNecessary();
208 
209     if (!initialized_) {
210       task_backlog_.push_back(std::move(task));
211       return;
212     }
213 
214     std::move(task).Run();
215   }
216 
DoQueueReport(const std::optional<base::UnguessableToken> & reporting_source,const NetworkAnonymizationKey & network_anonymization_key,GURL sanitized_url,const std::string & user_agent,const std::string & group,const std::string & type,base::Value::Dict body,int depth,base::TimeTicks queued_ticks,ReportingTargetType target_type)217   void DoQueueReport(
218       const std::optional<base::UnguessableToken>& reporting_source,
219       const NetworkAnonymizationKey& network_anonymization_key,
220       GURL sanitized_url,
221       const std::string& user_agent,
222       const std::string& group,
223       const std::string& type,
224       base::Value::Dict body,
225       int depth,
226       base::TimeTicks queued_ticks,
227       ReportingTargetType target_type) {
228     DCHECK(initialized_);
229     context_->cache()->AddReport(reporting_source, network_anonymization_key,
230                                  sanitized_url, user_agent, group, type,
231                                  std::move(body), depth, queued_ticks,
232                                  0 /* attempts */, target_type);
233   }
234 
DoProcessReportToHeader(const NetworkAnonymizationKey & network_anonymization_key,const url::Origin & origin,const base::Value & header_value)235   void DoProcessReportToHeader(
236       const NetworkAnonymizationKey& network_anonymization_key,
237       const url::Origin& origin,
238       const base::Value& header_value) {
239     DCHECK(initialized_);
240     DCHECK(header_value.is_list());
241     ReportingHeaderParser::ParseReportToHeader(context_.get(),
242                                                network_anonymization_key,
243                                                origin, header_value.GetList());
244   }
245 
DoSetDocumentReportingEndpoints(const base::UnguessableToken & reporting_source,const IsolationInfo & isolation_info,const NetworkAnonymizationKey & network_anonymization_key,const url::Origin & origin,base::flat_map<std::string,std::string> header_value)246   void DoSetDocumentReportingEndpoints(
247       const base::UnguessableToken& reporting_source,
248       const IsolationInfo& isolation_info,
249       const NetworkAnonymizationKey& network_anonymization_key,
250       const url::Origin& origin,
251       base::flat_map<std::string, std::string> header_value) {
252     DCHECK(initialized_);
253     ReportingHeaderParser::ProcessParsedReportingEndpointsHeader(
254         context_.get(), reporting_source, isolation_info,
255         network_anonymization_key, origin, std::move(header_value));
256   }
257 
DoRemoveBrowsingData(uint64_t data_type_mask,const base::RepeatingCallback<bool (const url::Origin &)> & origin_filter)258   void DoRemoveBrowsingData(
259       uint64_t data_type_mask,
260       const base::RepeatingCallback<bool(const url::Origin&)>& origin_filter) {
261     DCHECK(initialized_);
262     ReportingBrowsingDataRemover::RemoveBrowsingData(
263         context_->cache(), data_type_mask, origin_filter);
264   }
265 
DoRemoveAllBrowsingData(uint64_t data_type_mask)266   void DoRemoveAllBrowsingData(uint64_t data_type_mask) {
267     DCHECK(initialized_);
268     ReportingBrowsingDataRemover::RemoveAllBrowsingData(context_->cache(),
269                                                         data_type_mask);
270   }
271 
ExecuteBacklog()272   void ExecuteBacklog() {
273     DCHECK(initialized_);
274     DCHECK(context_);
275 
276     if (shut_down_)
277       return;
278 
279     for (base::OnceClosure& task : task_backlog_) {
280       std::move(task).Run();
281     }
282     task_backlog_.clear();
283   }
284 
FetchAllClientsFromStoreIfNecessary()285   void FetchAllClientsFromStoreIfNecessary() {
286     if (!context_->IsClientDataPersisted() || started_loading_from_store_)
287       return;
288 
289     started_loading_from_store_ = true;
290     FetchAllClientsFromStore();
291   }
292 
FetchAllClientsFromStore()293   void FetchAllClientsFromStore() {
294     DCHECK(context_->IsClientDataPersisted());
295     DCHECK(!initialized_);
296 
297     context_->store()->LoadReportingClients(base::BindOnce(
298         &ReportingServiceImpl::OnClientsLoaded, weak_factory_.GetWeakPtr()));
299   }
300 
OnClientsLoaded(std::vector<ReportingEndpoint> loaded_endpoints,std::vector<CachedReportingEndpointGroup> loaded_endpoint_groups)301   void OnClientsLoaded(
302       std::vector<ReportingEndpoint> loaded_endpoints,
303       std::vector<CachedReportingEndpointGroup> loaded_endpoint_groups) {
304     initialized_ = true;
305     context_->cache()->AddClientsLoadedFromStore(
306         std::move(loaded_endpoints), std::move(loaded_endpoint_groups));
307     ExecuteBacklog();
308   }
309 
310   // Returns either |network_anonymization_key| or an empty
311   // NetworkAnonymizationKey, based on |respect_network_anonymization_key_|.
312   // Should be used on all NetworkAnonymizationKeys passed in through public API
313   // calls.
FixupNetworkAnonymizationKey(const NetworkAnonymizationKey & network_anonymization_key)314   const NetworkAnonymizationKey& FixupNetworkAnonymizationKey(
315       const NetworkAnonymizationKey& network_anonymization_key) {
316     if (respect_network_anonymization_key_)
317       return network_anonymization_key;
318     return empty_nak_;
319   }
320 
321   std::unique_ptr<ReportingContext> context_;
322   bool shut_down_ = false;
323   bool started_loading_from_store_ = false;
324   bool initialized_ = false;
325   std::vector<base::OnceClosure> task_backlog_;
326 
327   bool respect_network_anonymization_key_ =
328       NetworkAnonymizationKey::IsPartitioningEnabled();
329 
330   // Allows returning a NetworkAnonymizationKey by reference when
331   // |respect_network_anonymization_key_| is false.
332   NetworkAnonymizationKey empty_nak_;
333 
334   base::WeakPtrFactory<ReportingServiceImpl> weak_factory_{this};
335 };
336 
337 }  // namespace
338 
339 ReportingService::~ReportingService() = default;
340 
341 // static
Create(const ReportingPolicy & policy,URLRequestContext * request_context,ReportingCache::PersistentReportingStore * store,const base::flat_map<std::string,GURL> & enterprise_reporting_endpoints)342 std::unique_ptr<ReportingService> ReportingService::Create(
343     const ReportingPolicy& policy,
344     URLRequestContext* request_context,
345     ReportingCache::PersistentReportingStore* store,
346     const base::flat_map<std::string, GURL>& enterprise_reporting_endpoints) {
347   return std::make_unique<ReportingServiceImpl>(ReportingContext::Create(
348       policy, request_context, store, enterprise_reporting_endpoints));
349 }
350 
351 // static
CreateForTesting(std::unique_ptr<ReportingContext> reporting_context)352 std::unique_ptr<ReportingService> ReportingService::CreateForTesting(
353     std::unique_ptr<ReportingContext> reporting_context) {
354   return std::make_unique<ReportingServiceImpl>(std::move(reporting_context));
355 }
356 
StatusAsValue() const357 base::Value ReportingService::StatusAsValue() const {
358   NOTIMPLEMENTED();
359   return base::Value();
360 }
361 
362 }  // namespace net
363