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

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
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 context_->AddObserver(this);
70 }
71
72 // ReportingPersister implementation:
73
74 ~ReportingPersisterImpl() override { context_->RemoveObserver(this); }
75
76 void SetTimerForTesting(std::unique_ptr<base::Timer> timer) override {
77 DCHECK(!timer_->IsRunning());
78 timer_ = std::move(timer);
79 }
80
81 // ReportingObserver implementation:
82
83 void OnContextInitializing() override {
84 std::unique_ptr<const base::Value> persisted_data =
85 context_->delegate()->GetPersistedData();
86 if (persisted_data)
87 Deserialize(*persisted_data);
88 }
89
90 void OnCacheUpdated() override {
shivanisha 2017/04/10 18:29:29 dcheck that context is initialized. Also in Report
Julia Tuttle 2017/04/11 19:20:46 Done.
91 if (!timer_->IsRunning())
92 StartTimer();
93 }
94
95 private:
96 void StartTimer() {
97 timer_->Start(
98 FROM_HERE, context_->policy().persistence_interval,
99 base::Bind(&ReportingPersisterImpl::Persist, base::Unretained(this)));
100 }
101
102 void Persist() { delegate()->PersistData(Serialize()); }
103
104 std::string SerializeTicks(base::TimeTicks time_ticks) {
105 base::Time time = time_ticks - tick_clock()->NowTicks() + clock()->Now();
106 return base::Int64ToString(time.ToInternalValue());
107 }
108
109 bool DeserializeTicks(const std::string& serialized,
110 base::TimeTicks* time_ticks_out) {
111 int64_t internal;
112 if (!base::StringToInt64(serialized, &internal))
113 return false;
114
115 base::Time time = base::Time::FromInternalValue(internal);
116 *time_ticks_out = time - clock()->Now() + tick_clock()->NowTicks();
117 return true;
118 }
119
120 std::unique_ptr<base::Value> SerializeReport(const ReportingReport& report) {
121 auto serialized = base::MakeUnique<base::DictionaryValue>();
122
123 serialized->SetString("url", report.url.spec());
124 serialized->SetString("group", report.group);
125 serialized->SetString("type", report.type);
126 serialized->Set("body", report.body->CreateDeepCopy());
127 serialized->SetString("queued", SerializeTicks(report.queued));
128 serialized->SetInteger("attempts", report.attempts);
129
130 return std::move(serialized);
131 }
132
133 bool DeserializeReport(const base::DictionaryValue& report) {
134 std::string url_string;
135 if (!report.GetString("url", &url_string))
136 return false;
137 GURL url(url_string);
138 if (!url.is_valid())
139 return false;
140
141 std::string group;
142 if (!report.GetString("group", &group))
143 return false;
144
145 std::string type;
146 if (!report.GetString("type", &type))
147 return false;
148
149 const base::Value* body_original;
150 if (!report.Get("body", &body_original))
151 return false;
152 std::unique_ptr<base::Value> body = body_original->CreateDeepCopy();
153
154 std::string queued_string;
155 if (!report.GetString("queued", &queued_string))
156 return false;
157 base::TimeTicks queued;
158 if (!DeserializeTicks(queued_string, &queued))
159 return false;
160
161 int attempts;
162 if (!report.GetInteger("attempts", &attempts))
163 return false;
164 if (attempts < 0)
165 return false;
166
167 cache()->AddReport(url, group, type, std::move(body), queued, attempts);
168 return true;
169 }
170
171 std::unique_ptr<base::Value> SerializeReports() {
172 std::vector<const ReportingReport*> reports;
173 cache()->GetReports(&reports);
174
175 auto serialized = base::MakeUnique<base::ListValue>();
176 for (const ReportingReport* report : reports)
177 serialized->Append(SerializeReport(*report));
178
179 return std::move(serialized);
180 }
181
182 bool DeserializeReports(const base::ListValue& reports) {
183 for (size_t i = 0; i < reports.GetSize(); ++i) {
184 const base::DictionaryValue* report;
185 if (!reports.GetDictionary(i, &report))
186 return false;
187 if (!DeserializeReport(*report))
188 return false;
189 }
190
191 return true;
192 }
193
194 std::unique_ptr<base::Value> SerializeClient(const ReportingClient& client) {
195 auto serialized = base::MakeUnique<base::DictionaryValue>();
196
197 serialized->Set("origin", SerializeOrigin(client.origin));
198 serialized->SetString("endpoint", client.endpoint.spec());
199 serialized->SetBoolean(
200 "subdomains",
201 client.subdomains == ReportingClient::Subdomains::INCLUDE);
202 serialized->SetString("group", client.group);
203 serialized->SetString("expires", SerializeTicks(client.expires));
204
205 return std::move(serialized);
206 }
207
208 bool DeserializeClient(const base::DictionaryValue& client) {
209 const base::DictionaryValue* origin_value;
210 if (!client.GetDictionary("origin", &origin_value))
211 return false;
212 url::Origin origin;
213 if (!DeserializeOrigin(*origin_value, &origin))
214 return false;
215
216 std::string endpoint_string;
217 if (!client.GetString("endpoint", &endpoint_string))
218 return false;
219 GURL endpoint(endpoint_string);
220 if (!endpoint.is_valid())
221 return false;
222
223 bool subdomains_bool;
224 if (!client.GetBoolean("subdomains", &subdomains_bool))
225 return false;
226 ReportingClient::Subdomains subdomains =
227 subdomains_bool ? ReportingClient::Subdomains::INCLUDE
228 : ReportingClient::Subdomains::EXCLUDE;
229
230 std::string group;
231 if (!client.GetString("group", &group))
232 return false;
233
234 std::string expires_string;
235 if (!client.GetString("expires", &expires_string))
236 return false;
237 base::TimeTicks expires;
238 if (!DeserializeTicks(expires_string, &expires))
239 return false;
240
241 cache()->SetClient(origin, endpoint, subdomains, group, expires);
242 return true;
243 }
244
245 std::unique_ptr<base::Value> SerializeClients() {
246 std::vector<const ReportingClient*> clients;
247 cache()->GetClients(&clients);
248
249 auto serialized = base::MakeUnique<base::ListValue>();
250 for (const ReportingClient* client : clients)
251 serialized->Append(SerializeClient(*client));
252
253 return std::move(serialized);
254 }
255
256 bool DeserializeClients(const base::ListValue& clients) {
257 for (size_t i = 0; i < clients.GetSize(); ++i) {
258 const base::DictionaryValue* client;
259 if (!clients.GetDictionary(i, &client))
260 return false;
261 if (!DeserializeClient(*client))
262 return false;
263 }
264
265 return true;
266 }
267
268 static const int kSupportedVersion = 1;
269
270 std::unique_ptr<base::Value> Serialize() {
271 auto serialized = base::MakeUnique<base::DictionaryValue>();
272
273 serialized->SetInteger("reporting_serialized_cache_version",
274 kSupportedVersion);
275
276 bool persist_reports = policy().persist_reports_across_restarts;
277 serialized->SetBoolean("includes_reports", persist_reports);
278 if (persist_reports)
279 serialized->Set("reports", SerializeReports());
280
281 bool persist_clients = policy().persist_clients_across_restarts;
282 serialized->SetBoolean("includes_clients", persist_clients);
283 if (persist_clients)
284 serialized->Set("clients", SerializeClients());
285
286 return std::move(serialized);
287 }
288
289 bool Deserialize(const base::Value& serialized_value) {
290 std::vector<const ReportingReport*> reports;
291 cache()->GetReports(&reports);
292 DCHECK(reports.empty());
293
294 std::vector<const ReportingClient*> clients;
295 cache()->GetClients(&clients);
296 DCHECK(clients.empty());
297
298 int version;
299
300 const base::DictionaryValue* serialized;
301 if (!serialized_value.GetAsDictionary(&serialized))
302 return false;
303
304 if (!serialized->GetInteger("reporting_serialized_cache_version", &version))
305 return false;
306 if (version != kSupportedVersion)
307 return false;
308
309 bool includes_reports;
310 bool includes_clients;
311 if (!serialized->GetBoolean("includes_reports", &includes_reports) ||
312 !serialized->GetBoolean("includes_clients", &includes_clients)) {
313 return false;
314 }
315
316 if (includes_reports) {
317 const base::ListValue* reports;
318 if (!serialized->GetList("reports", &reports))
319 return false;
320 if (!DeserializeReports(*reports))
321 return false;
322 }
323
324 if (includes_clients) {
325 const base::ListValue* clients;
326 if (!serialized->GetList("clients", &clients))
327 return false;
328 if (!DeserializeClients(*clients))
329 return false;
330 }
331
332 return true;
333 }
334
335 const ReportingPolicy& policy() { return context_->policy(); }
336 ReportingDelegate* delegate() { return context_->delegate(); }
337 base::Clock* clock() { return context_->clock(); }
338 base::TickClock* tick_clock() { return context_->tick_clock(); }
339 ReportingCache* cache() { return context_->cache(); }
340
341 ReportingContext* context_;
342 std::unique_ptr<base::Timer> timer_;
343 };
344
345 } // namespace
346
347 // static
348 std::unique_ptr<ReportingPersister> ReportingPersister::Create(
349 ReportingContext* context) {
350 return base::MakeUnique<ReportingPersisterImpl>(context);
351 }
352
353 ReportingPersister::~ReportingPersister() {}
354
355 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698