1 // Copyright 2019 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.
5 #include "base/json/values_util.h"
7 #include "base/files/file_path.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/time/time.h"
10 #include "base/unguessable_token.h"
11 #include "third_party/abseil-cpp/absl/types/optional.h"
13 // Warning: The Values involved could be stored on persistent storage like files
14 // on disks. Therefore, changes in implementation could lead to data corruption
15 // and must be done with caution.
21 // Helper to serialize/deserialize an UnguessableToken.
23 // It assumes a little-endian CPU, which is arguably a bug.
24 union UnguessableTokenRepresentation {
30 uint8_t buffer[sizeof(Field)];
35 Value Int64ToValue(int64_t integer) {
36 return Value(NumberToString(integer));
39 absl::optional<int64_t> ValueToInt64(const Value* value) {
40 return value ? ValueToInt64(*value) : absl::nullopt;
43 absl::optional<int64_t> ValueToInt64(const Value& value) {
44 if (!value.is_string())
48 if (!StringToInt64(value.GetString(), &integer))
54 Value TimeDeltaToValue(TimeDelta time_delta) {
55 return Int64ToValue(time_delta.InMicroseconds());
58 absl::optional<TimeDelta> ValueToTimeDelta(const Value* value) {
59 return value ? ValueToTimeDelta(*value) : absl::nullopt;
62 absl::optional<TimeDelta> ValueToTimeDelta(const Value& value) {
63 absl::optional<int64_t> integer = ValueToInt64(value);
66 return Microseconds(*integer);
69 Value TimeToValue(Time time) {
70 return TimeDeltaToValue(time.ToDeltaSinceWindowsEpoch());
73 absl::optional<Time> ValueToTime(const Value* value) {
74 return value ? ValueToTime(*value) : absl::nullopt;
77 absl::optional<Time> ValueToTime(const Value& value) {
78 absl::optional<TimeDelta> time_delta = ValueToTimeDelta(value);
81 return Time::FromDeltaSinceWindowsEpoch(*time_delta);
84 Value FilePathToValue(FilePath file_path) {
85 return Value(file_path.AsUTF8Unsafe());
88 absl::optional<FilePath> ValueToFilePath(const Value* value) {
89 return value ? ValueToFilePath(*value) : absl::nullopt;
92 absl::optional<FilePath> ValueToFilePath(const Value& value) {
93 if (!value.is_string())
95 return FilePath::FromUTF8Unsafe(value.GetString());
98 Value UnguessableTokenToValue(UnguessableToken token) {
99 UnguessableTokenRepresentation repr;
100 repr.field.high = token.GetHighForSerialization();
101 repr.field.low = token.GetLowForSerialization();
102 return Value(HexEncode(repr.buffer, sizeof(repr.buffer)));
105 absl::optional<UnguessableToken> ValueToUnguessableToken(const Value* value) {
106 return value ? ValueToUnguessableToken(*value) : absl::nullopt;
109 absl::optional<UnguessableToken> ValueToUnguessableToken(const Value& value) {
110 if (!value.is_string())
111 return absl::nullopt;
112 UnguessableTokenRepresentation repr;
113 if (!HexStringToSpan(value.GetString(), repr.buffer))
114 return absl::nullopt;
115 absl::optional<base::UnguessableToken> token =
116 UnguessableToken::Deserialize(repr.field.high, repr.field.low);
117 if (!token.has_value()) {
118 return absl::nullopt;