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. 4 5 #include "base/json/values_util.h" 6 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" 12 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. 16 17 namespace base { 18 19 namespace { 20 21 // Helper to serialize/deserialize an UnguessableToken. 22 // 23 // It assumes a little-endian CPU, which is arguably a bug. 24 union UnguessableTokenRepresentation { 25 struct Field { 26 uint64_t high; 27 uint64_t low; 28 } field; 29 30 uint8_t buffer[sizeof(Field)]; 31 }; 32 33 } // namespace 34 Int64ToValue(int64_t integer)35Value Int64ToValue(int64_t integer) { 36 return Value(NumberToString(integer)); 37 } 38 ValueToInt64(const Value * value)39absl::optional<int64_t> ValueToInt64(const Value* value) { 40 return value ? ValueToInt64(*value) : absl::nullopt; 41 } 42 ValueToInt64(const Value & value)43absl::optional<int64_t> ValueToInt64(const Value& value) { 44 if (!value.is_string()) 45 return absl::nullopt; 46 47 int64_t integer; 48 if (!StringToInt64(value.GetString(), &integer)) 49 return absl::nullopt; 50 51 return integer; 52 } 53 TimeDeltaToValue(TimeDelta time_delta)54Value TimeDeltaToValue(TimeDelta time_delta) { 55 return Int64ToValue(time_delta.InMicroseconds()); 56 } 57 ValueToTimeDelta(const Value * value)58absl::optional<TimeDelta> ValueToTimeDelta(const Value* value) { 59 return value ? ValueToTimeDelta(*value) : absl::nullopt; 60 } 61 ValueToTimeDelta(const Value & value)62absl::optional<TimeDelta> ValueToTimeDelta(const Value& value) { 63 absl::optional<int64_t> integer = ValueToInt64(value); 64 if (!integer) 65 return absl::nullopt; 66 return Microseconds(*integer); 67 } 68 TimeToValue(Time time)69Value TimeToValue(Time time) { 70 return TimeDeltaToValue(time.ToDeltaSinceWindowsEpoch()); 71 } 72 ValueToTime(const Value * value)73absl::optional<Time> ValueToTime(const Value* value) { 74 return value ? ValueToTime(*value) : absl::nullopt; 75 } 76 ValueToTime(const Value & value)77absl::optional<Time> ValueToTime(const Value& value) { 78 absl::optional<TimeDelta> time_delta = ValueToTimeDelta(value); 79 if (!time_delta) 80 return absl::nullopt; 81 return Time::FromDeltaSinceWindowsEpoch(*time_delta); 82 } 83 FilePathToValue(FilePath file_path)84Value FilePathToValue(FilePath file_path) { 85 return Value(file_path.AsUTF8Unsafe()); 86 } 87 ValueToFilePath(const Value * value)88absl::optional<FilePath> ValueToFilePath(const Value* value) { 89 return value ? ValueToFilePath(*value) : absl::nullopt; 90 } 91 ValueToFilePath(const Value & value)92absl::optional<FilePath> ValueToFilePath(const Value& value) { 93 if (!value.is_string()) 94 return absl::nullopt; 95 return FilePath::FromUTF8Unsafe(value.GetString()); 96 } 97 UnguessableTokenToValue(UnguessableToken token)98Value 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))); 103 } 104 ValueToUnguessableToken(const Value * value)105absl::optional<UnguessableToken> ValueToUnguessableToken(const Value* value) { 106 return value ? ValueToUnguessableToken(*value) : absl::nullopt; 107 } 108 ValueToUnguessableToken(const Value & value)109absl::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; 119 } 120 return token; 121 } 122 123 } // namespace base 124