Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(339)

Side by Side Diff: net/reporting/reporting_persister.cc

Issue 2751883003: Reporting: Implement serializer. (Closed)
Patch Set: rebase Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/reporting/reporting_persister.h ('k') | net/reporting/reporting_persister_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
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_persister.h"
6
7 #include <vector>
8
9 #include "base/memory/ptr_util.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/time/clock.h"
12 #include "base/time/tick_clock.h"
13 #include "base/time/time.h"
14 #include "base/timer/timer.h"
15 #include "base/values.h"
16 #include "net/reporting/reporting_cache.h"
17 #include "net/reporting/reporting_client.h"
18 #include "net/reporting/reporting_context.h"
19 #include "net/reporting/reporting_delegate.h"
20 #include "net/reporting/reporting_observer.h"
21 #include "net/reporting/reporting_policy.h"
22 #include "net/reporting/reporting_report.h"
23
24 namespace net {
25 namespace {
26
27 std::unique_ptr<base::Value> SerializeOrigin(const url::Origin& origin) {
28 auto serialized = base::MakeUnique<base::DictionaryValue>();
29
30 serialized->SetString("scheme", origin.scheme());
31 serialized->SetString("host", origin.host());
32 serialized->SetInteger("port", origin.port());
33 serialized->SetString("suborigin", origin.suborigin());
34
35 return std::move(serialized);
36 }
37
38 bool DeserializeOrigin(const base::DictionaryValue& serialized,
39 url::Origin* origin_out) {
40 std::string scheme;
41 if (!serialized.GetString("scheme", &scheme))
42 return false;
43
44 std::string host;
45 if (!serialized.GetString("host", &host))
46 return false;
47
48 int port_int;
49 if (!serialized.GetInteger("port", &port_int))
50 return false;
51 uint16_t port = static_cast<uint16_t>(port_int);
52 if (port_int != port)
53 return false;
54
55 std::string suborigin;
56 if (!serialized.GetString("suborigin", &suborigin))
57 return false;
58
59 *origin_out = url::Origin::CreateFromNormalizedTupleWithSuborigin(
60 scheme, host, port, suborigin);
61 return true;
62 }
63
64 class ReportingPersisterImpl : public ReportingPersister,
65 public ReportingObserver {
66 public:
67 ReportingPersisterImpl(ReportingContext* context)
68 : context_(context), timer_(base::MakeUnique<base::OneShotTimer>()) {}
69
70 // ReportingPersister implementation:
71
72 ~ReportingPersisterImpl() override {
73 DCHECK(context_->initialized());
74 context_->RemoveObserver(this);
75 }
76
77 void Initialize() override {
78 std::unique_ptr<const base::Value> persisted_data =
79 context_->delegate()->GetPersistedData();
80 if (persisted_data)
81 Deserialize(*persisted_data);
82 context_->AddObserver(this);
83 }
84
85 void SetTimerForTesting(std::unique_ptr<base::Timer> timer) override {
86 DCHECK(!context_->initialized());
87 timer_ = std::move(timer);
88 }
89
90 // ReportingObserver implementation:
91
92 void OnCacheUpdated() override {
93 DCHECK(context_->initialized());
94 if (!timer_->IsRunning())
95 StartTimer();
96 }
97
98 private:
99 void StartTimer() {
100 timer_->Start(
101 FROM_HERE, context_->policy().persistence_interval,
102 base::Bind(&ReportingPersisterImpl::Persist, base::Unretained(this)));
103 }
104
105 void Persist() { delegate()->PersistData(Serialize()); }
106
107 std::string SerializeTicks(base::TimeTicks time_ticks) {
108 base::Time time = time_ticks - tick_clock()->NowTicks() + clock()->Now();
109 return base::Int64ToString(time.ToInternalValue());
110 }
111
112 bool DeserializeTicks(const std::string& serialized,
113 base::TimeTicks* time_ticks_out) {
114 int64_t internal;
115 if (!base::StringToInt64(serialized, &internal))
116 return false;
117
118 base::Time time = base::Time::FromInternalValue(internal);
119 *time_ticks_out = time - clock()->Now() + tick_clock()->NowTicks();
120 return true;
121 }
122
123 std::unique_ptr<base::Value> SerializeReport(const ReportingReport& report) {
124 auto serialized = base::MakeUnique<base::DictionaryValue>();
125
126 serialized->SetString("url", report.url.spec());
127 serialized->SetString("group", report.group);
128 serialized->SetString("type", report.type);
129 serialized->Set("body", report.body->CreateDeepCopy());
130 serialized->SetString("queued", SerializeTicks(report.queued));
131 serialized->SetInteger("attempts", report.attempts);
132
133 return std::move(serialized);
134 }
135
136 bool DeserializeReport(const base::DictionaryValue& report) {
137 std::string url_string;
138 if (!report.GetString("url", &url_string))
139 return false;
140 GURL url(url_string);
141 if (!url.is_valid())
142 return false;
143
144 std::string group;
145 if (!report.GetString("group", &group))
146 return false;
147
148 std::string type;
149 if (!report.GetString("type", &type))
150 return false;
151
152 const base::Value* body_original;
153 if (!report.Get("body", &body_original))
154 return false;
155 std::unique_ptr<base::Value> body = body_original->CreateDeepCopy();
156
157 std::string queued_string;
158 if (!report.GetString("queued", &queued_string))
159 return false;
160 base::TimeTicks queued;
161 if (!DeserializeTicks(queued_string, &queued))
162 return false;
163
164 int attempts;
165 if (!report.GetInteger("attempts", &attempts))
166 return false;
167 if (attempts < 0)
168 return false;
169
170 cache()->AddReport(url, group, type, std::move(body), queued, attempts);
171 return true;
172 }
173
174 std::unique_ptr<base::Value> SerializeReports() {
175 std::vector<const ReportingReport*> reports;
176 cache()->GetReports(&reports);
177
178 auto serialized = base::MakeUnique<base::ListValue>();
179 for (const ReportingReport* report : reports)
180 serialized->Append(SerializeReport(*report));
181
182 return std::move(serialized);
183 }
184
185 bool DeserializeReports(const base::ListValue& reports) {
186 for (size_t i = 0; i < reports.GetSize(); ++i) {
187 const base::DictionaryValue* report;
188 if (!reports.GetDictionary(i, &report))
189 return false;
190 if (!DeserializeReport(*report))
191 return false;
192 }
193
194 return true;
195 }
196
197 std::unique_ptr<base::Value> SerializeClient(const ReportingClient& client) {
198 auto serialized = base::MakeUnique<base::DictionaryValue>();
199
200 serialized->Set("origin", SerializeOrigin(client.origin));
201 serialized->SetString("endpoint", client.endpoint.spec());
202 serialized->SetBoolean(
203 "subdomains",
204 client.subdomains == ReportingClient::Subdomains::INCLUDE);
205 serialized->SetString("group", client.group);
206 serialized->SetString("expires", SerializeTicks(client.expires));
207
208 return std::move(serialized);
209 }
210
211 bool DeserializeClient(const base::DictionaryValue& client) {
212 const base::DictionaryValue* origin_value;
213 if (!client.GetDictionary("origin", &origin_value))
214 return false;
215 url::Origin origin;
216 if (!DeserializeOrigin(*origin_value, &origin))
217 return false;
218
219 std::string endpoint_string;
220 if (!client.GetString("endpoint", &endpoint_string))
221 return false;
222 GURL endpoint(endpoint_string);
223 if (!endpoint.is_valid())
224 return false;
225
226 bool subdomains_bool;
227 if (!client.GetBoolean("subdomains", &subdomains_bool))
228 return false;
229 ReportingClient::Subdomains subdomains =
230 subdomains_bool ? ReportingClient::Subdomains::INCLUDE
231 : ReportingClient::Subdomains::EXCLUDE;
232
233 std::string group;
234 if (!client.GetString("group", &group))
235 return false;
236
237 std::string expires_string;
238 if (!client.GetString("expires", &expires_string))
239 return false;
240 base::TimeTicks expires;
241 if (!DeserializeTicks(expires_string, &expires))
242 return false;
243
244 cache()->SetClient(origin, endpoint, subdomains, group, expires);
245 return true;
246 }
247
248 std::unique_ptr<base::Value> SerializeClients() {
249 std::vector<const ReportingClient*> clients;
250 cache()->GetClients(&clients);
251
252 auto serialized = base::MakeUnique<base::ListValue>();
253 for (const ReportingClient* client : clients)
254 serialized->Append(SerializeClient(*client));
255
256 return std::move(serialized);
257 }
258
259 bool DeserializeClients(const base::ListValue& clients) {
260 for (size_t i = 0; i < clients.GetSize(); ++i) {
261 const base::DictionaryValue* client;
262 if (!clients.GetDictionary(i, &client))
263 return false;
264 if (!DeserializeClient(*client))
265 return false;
266 }
267
268 return true;
269 }
270
271 static const int kSupportedVersion = 1;
272
273 std::unique_ptr<base::Value> Serialize() {
274 auto serialized = base::MakeUnique<base::DictionaryValue>();
275
276 serialized->SetInteger("reporting_serialized_cache_version",
277 kSupportedVersion);
278
279 bool persist_reports = policy().persist_reports_across_restarts;
280 serialized->SetBoolean("includes_reports", persist_reports);
281 if (persist_reports)
282 serialized->Set("reports", SerializeReports());
283
284 bool persist_clients = policy().persist_clients_across_restarts;
285 serialized->SetBoolean("includes_clients", persist_clients);
286 if (persist_clients)
287 serialized->Set("clients", SerializeClients());
288
289 return std::move(serialized);
290 }
291
292 bool Deserialize(const base::Value& serialized_value) {
293 std::vector<const ReportingReport*> reports;
294 cache()->GetReports(&reports);
295 DCHECK(reports.empty());
296
297 std::vector<const ReportingClient*> clients;
298 cache()->GetClients(&clients);
299 DCHECK(clients.empty());
300
301 int version;
302
303 const base::DictionaryValue* serialized;
304 if (!serialized_value.GetAsDictionary(&serialized))
305 return false;
306
307 if (!serialized->GetInteger("reporting_serialized_cache_version", &version))
308 return false;
309 if (version != kSupportedVersion)
310 return false;
311
312 bool includes_reports;
313 bool includes_clients;
314 if (!serialized->GetBoolean("includes_reports", &includes_reports) ||
315 !serialized->GetBoolean("includes_clients", &includes_clients)) {
316 return false;
317 }
318
319 if (includes_reports) {
320 const base::ListValue* reports;
321 if (!serialized->GetList("reports", &reports))
322 return false;
323 if (!DeserializeReports(*reports))
324 return false;
325 }
326
327 if (includes_clients) {
328 const base::ListValue* clients;
329 if (!serialized->GetList("clients", &clients))
330 return false;
331 if (!DeserializeClients(*clients))
332 return false;
333 }
334
335 return true;
336 }
337
338 const ReportingPolicy& policy() { return context_->policy(); }
339 ReportingDelegate* delegate() { return context_->delegate(); }
340 base::Clock* clock() { return context_->clock(); }
341 base::TickClock* tick_clock() { return context_->tick_clock(); }
342 ReportingCache* cache() { return context_->cache(); }
343
344 ReportingContext* context_;
345 std::unique_ptr<base::Timer> timer_;
346 };
347
348 } // namespace
349
350 // static
351 std::unique_ptr<ReportingPersister> ReportingPersister::Create(
352 ReportingContext* context) {
353 return base::MakeUnique<ReportingPersisterImpl>(context);
354 }
355
356 ReportingPersister::~ReportingPersister() {}
357
358 } // namespace net
OLDNEW
« no previous file with comments | « net/reporting/reporting_persister.h ('k') | net/reporting/reporting_persister_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698