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

Unified Diff: net/reporting/reporting_serializer.cc

Issue 2751883003: Reporting: Implement serializer. (Closed)
Patch Set: Move after Context CL Created 3 years, 9 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 side-by-side diff with in-line comments
Download patch
Index: net/reporting/reporting_serializer.cc
diff --git a/net/reporting/reporting_serializer.cc b/net/reporting/reporting_serializer.cc
new file mode 100644
index 0000000000000000000000000000000000000000..157cd97fc920a8c9edfc36b9e659be9cde8d222f
--- /dev/null
+++ b/net/reporting/reporting_serializer.cc
@@ -0,0 +1,298 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/reporting/reporting_serializer.h"
+
+#include <vector>
+
+#include "base/memory/ptr_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/time/clock.h"
+#include "base/time/tick_clock.h"
+#include "base/time/time.h"
+#include "base/values.h"
+#include "net/reporting/reporting_cache.h"
+#include "net/reporting/reporting_client.h"
+#include "net/reporting/reporting_context.h"
+#include "net/reporting/reporting_policy.h"
+#include "net/reporting/reporting_report.h"
+
+namespace net {
+
+namespace {
+
+std::string SerializeTicks(base::TimeTicks time_ticks,
+ ReportingContext* context) {
+ base::Time time =
+ time_ticks - context->tick_clock()->NowTicks() + context->clock()->Now();
+ return base::Int64ToString(time.ToInternalValue());
+}
+
+bool DeserializeTicks(const std::string& serialized,
+ base::TimeTicks* time_ticks_out,
+ ReportingContext* context) {
+ int64_t internal;
+ if (!base::StringToInt64(serialized, &internal))
+ return false;
+
+ base::Time time = base::Time::FromInternalValue(internal);
+ *time_ticks_out =
+ time - context->clock()->Now() + context->tick_clock()->NowTicks();
+ return true;
+}
+
+std::unique_ptr<base::Value> SerializeReport(const ReportingReport& report,
+ ReportingContext* context) {
+ auto serialized = base::MakeUnique<base::DictionaryValue>();
+
+ serialized->SetString("url", report.url.spec());
+ serialized->SetString("group", report.group);
+ serialized->SetString("type", report.type);
+ serialized->Set("body", report.body->CreateDeepCopy());
+ serialized->SetString("queued", SerializeTicks(report.queued, context));
+ serialized->SetInteger("attempts", report.attempts);
+
+ return std::move(serialized);
+}
+
+bool DeserializeReport(const base::DictionaryValue& report,
+ ReportingContext* context) {
+ std::string url_string;
+ if (!report.GetString("url", &url_string))
+ return false;
+ GURL url(url_string);
+ if (!url.is_valid())
+ return false;
+
+ std::string group;
+ if (!report.GetString("group", &group))
+ return false;
shivanisha 2017/04/05 18:47:31 dcheck group is not empty. Also type and body belo
Julia Tuttle 2017/04/06 20:20:55 There's nothing actually disallowing those members
+
+ std::string type;
+ if (!report.GetString("type", &type))
+ return false;
+
+ const base::Value* body;
+ if (!report.Get("body", &body))
+ return false;
+
+ std::string queued_string;
+ if (!report.GetString("queued", &queued_string))
+ return false;
+ base::TimeTicks queued;
+ if (!DeserializeTicks(queued_string, &queued, context))
+ return false;
+
+ int attempts;
+ if (!report.GetInteger("attempts", &attempts))
+ return false;
+ if (attempts < 0)
+ return false;
+
+ context->cache()->AddReport(url, group, type, body->CreateDeepCopy(), queued,
+ attempts);
shivanisha 2017/04/05 18:47:31 I believe the invocation of this call will only be
Julia Tuttle 2017/04/06 20:20:55 Yeah, I'll check in DeserializeFromValue that ther
+ return true;
+}
+
+std::unique_ptr<base::Value> SerializeReports(ReportingContext* context) {
+ std::vector<const ReportingReport*> reports;
+ context->cache()->GetReports(&reports);
+
+ auto serialized = base::MakeUnique<base::ListValue>();
+ for (const ReportingReport* report : reports)
+ serialized->Append(SerializeReport(*report, context));
+
+ return std::move(serialized);
+}
+
+bool DeserializeReports(const base::ListValue& reports,
+ ReportingContext* context) {
+ for (size_t i = 0; i < reports.GetSize(); ++i) {
+ const base::DictionaryValue* report;
+ if (!reports.GetDictionary(i, &report))
+ return false;
+ if (!DeserializeReport(*report, context))
+ return false;
+ }
+
+ return true;
+}
+
+std::unique_ptr<base::Value> SerializeOrigin(const url::Origin& origin) {
+ auto serialized = base::MakeUnique<base::DictionaryValue>();
+
+ serialized->SetString("scheme", origin.scheme());
+ serialized->SetString("host", origin.host());
+ serialized->SetInteger("port", origin.port());
+ serialized->SetString("suborigin", origin.suborigin());
+
+ return std::move(serialized);
+}
+
+bool DeserializeOrigin(const base::DictionaryValue& serialized,
+ url::Origin* origin_out) {
+ std::string scheme;
+ if (!serialized.GetString("scheme", &scheme))
+ return false;
+
+ std::string host;
+ if (!serialized.GetString("host", &host))
+ return false;
+
+ int port_int;
+ if (!serialized.GetInteger("port", &port_int))
+ return false;
+ uint16_t port = static_cast<uint16_t>(port_int);
+ if (port_int != port)
+ return false;
+
+ std::string suborigin;
+ if (!serialized.GetString("suborigin", &suborigin))
+ return false;
+
+ *origin_out = url::Origin::CreateFromNormalizedTupleWithSuborigin(
+ scheme, host, port, suborigin);
+ return true;
+}
+
+std::unique_ptr<base::Value> SerializeClient(const ReportingClient& client,
+ ReportingContext* context) {
+ auto serialized = base::MakeUnique<base::DictionaryValue>();
+
+ serialized->Set("origin", SerializeOrigin(client.origin));
+ serialized->SetString("endpoint", client.endpoint.spec());
+ serialized->SetBoolean(
+ "subdomains", client.subdomains == ReportingClient::Subdomains::INCLUDE);
+ serialized->SetString("group", client.group);
+ serialized->SetString("expires", SerializeTicks(client.expires, context));
+
+ return std::move(serialized);
+}
+
+bool DeserializeClient(const base::DictionaryValue& client,
+ ReportingContext* context) {
+ const base::DictionaryValue* origin_value;
+ if (!client.GetDictionary("origin", &origin_value))
+ return false;
+ url::Origin origin;
+ if (!DeserializeOrigin(*origin_value, &origin))
+ return false;
+
+ std::string endpoint_string;
+ if (!client.GetString("endpoint", &endpoint_string))
+ return false;
+ GURL endpoint(endpoint_string);
+ if (!endpoint.is_valid())
+ return false;
+
+ bool subdomains_bool;
+ if (!client.GetBoolean("subdomains", &subdomains_bool))
+ return false;
+ ReportingClient::Subdomains subdomains =
+ subdomains_bool ? ReportingClient::Subdomains::INCLUDE
+ : ReportingClient::Subdomains::EXCLUDE;
+
+ std::string group;
+ if (!client.GetString("group", &group))
+ return false;
+
+ std::string expires_string;
+ if (!client.GetString("expires", &expires_string))
+ return false;
+ base::TimeTicks expires;
+ if (!DeserializeTicks(expires_string, &expires, context))
+ return false;
+
+ context->cache()->SetClient(origin, endpoint, subdomains, group, expires);
+ return true;
+}
+
+std::unique_ptr<base::Value> SerializeClients(ReportingContext* context) {
+ std::vector<const ReportingClient*> clients;
+ context->cache()->GetClients(&clients);
+
+ auto serialized = base::MakeUnique<base::ListValue>();
+ for (const ReportingClient* client : clients)
+ serialized->Append(SerializeClient(*client, context));
+
+ return std::move(serialized);
+}
+
+bool DeserializeClients(const base::ListValue& clients,
+ ReportingContext* context) {
+ for (size_t i = 0; i < clients.GetSize(); ++i) {
+ const base::DictionaryValue* client;
+ if (!clients.GetDictionary(i, &client))
+ return false;
+ if (!DeserializeClient(*client, context))
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace
+
+// static
+std::unique_ptr<base::Value> ReportingSerializer::SerializeToValue(
+ ReportingContext* context) {
+ auto serialized = base::MakeUnique<base::DictionaryValue>();
+
+ serialized->SetInteger("reporting_serialized_cache_version", 1);
shivanisha 2017/04/05 18:47:31 May be have a static const as the version instead
Julia Tuttle 2017/04/06 20:20:55 Done.
+
+ bool persist_reports = context->policy().persist_reports_across_restarts;
+ serialized->SetBoolean("includes_reports", persist_reports);
+ if (persist_reports)
+ serialized->Set("reports", SerializeReports(context));
+
+ bool persist_clients = context->policy().persist_clients_across_restarts;
+ serialized->SetBoolean("includes_clients", persist_clients);
+ if (persist_clients)
+ serialized->Set("clients", SerializeClients(context));
+
+ return std::move(serialized);
+}
+
+// static
+bool ReportingSerializer::DeserializeFromValue(
+ const base::Value& serialized_value,
+ ReportingContext* context) {
+ int version;
+
+ const base::DictionaryValue* serialized;
+ if (!serialized_value.GetAsDictionary(&serialized))
+ return false;
+
+ if (!serialized->GetInteger("reporting_serialized_cache_version", &version))
+ return false;
+ if (version != 1)
+ return false;
+
+ bool includes_reports;
+ bool includes_clients;
+ if (!serialized->GetBoolean("includes_reports", &includes_reports) ||
+ !serialized->GetBoolean("includes_clients", &includes_clients)) {
+ return false;
+ }
+
shivanisha 2017/04/05 18:47:31 DCHECK that the cache does not contain any reports
Julia Tuttle 2017/04/06 20:20:55 Done.
+ if (includes_reports) {
+ const base::ListValue* reports;
+ if (!serialized->GetList("reports", &reports))
+ return false;
+ if (!DeserializeReports(*reports, context))
+ return false;
+ }
+
+ if (includes_clients) {
+ const base::ListValue* clients;
+ if (!serialized->GetList("clients", &clients))
+ return false;
+ if (!DeserializeClients(*clients, context))
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace net

Powered by Google App Engine
This is Rietveld 408576698