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