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 <optional> 8 9 #include "base/files/file_path.h" 10 #include "base/strings/string_number_conversions.h" 11 #include "base/time/time.h" 12 #include "base/unguessable_token.h" 13 14 // Warning: The Values involved could be stored on persistent storage like files 15 // on disks. Therefore, changes in implementation could lead to data corruption 16 // and must be done with caution. 17 18 namespace base { 19 20 namespace { 21 22 // Helper to serialize/deserialize an UnguessableToken. 23 // 24 // It assumes a little-endian CPU, which is arguably a bug. 25 union UnguessableTokenRepresentation { 26 struct Field { 27 uint64_t high; 28 uint64_t low; 29 } field; 30 31 uint8_t buffer[sizeof(Field)]; 32 }; 33 34 } // namespace 35 Int64ToValue(int64_t integer)36Value Int64ToValue(int64_t integer) { 37 return Value(NumberToString(integer)); 38 } 39 ValueToInt64(const Value * value)40std::optional<int64_t> ValueToInt64(const Value* value) { 41 return value ? ValueToInt64(*value) : std::nullopt; 42 } 43 ValueToInt64(const Value & value)44std::optional<int64_t> ValueToInt64(const Value& value) { 45 if (!value.is_string()) 46 return std::nullopt; 47 48 int64_t integer; 49 if (!StringToInt64(value.GetString(), &integer)) 50 return std::nullopt; 51 52 return integer; 53 } 54 TimeDeltaToValue(TimeDelta time_delta)55Value TimeDeltaToValue(TimeDelta time_delta) { 56 return Int64ToValue(time_delta.InMicroseconds()); 57 } 58 ValueToTimeDelta(const Value * value)59std::optional<TimeDelta> ValueToTimeDelta(const Value* value) { 60 return value ? ValueToTimeDelta(*value) : std::nullopt; 61 } 62 ValueToTimeDelta(const Value & value)63std::optional<TimeDelta> ValueToTimeDelta(const Value& value) { 64 std::optional<int64_t> integer = ValueToInt64(value); 65 if (!integer) 66 return std::nullopt; 67 return Microseconds(*integer); 68 } 69 TimeToValue(Time time)70Value TimeToValue(Time time) { 71 return TimeDeltaToValue(time.ToDeltaSinceWindowsEpoch()); 72 } 73 ValueToTime(const Value * value)74std::optional<Time> ValueToTime(const Value* value) { 75 return value ? ValueToTime(*value) : std::nullopt; 76 } 77 ValueToTime(const Value & value)78std::optional<Time> ValueToTime(const Value& value) { 79 std::optional<TimeDelta> time_delta = ValueToTimeDelta(value); 80 if (!time_delta) 81 return std::nullopt; 82 return Time::FromDeltaSinceWindowsEpoch(*time_delta); 83 } 84 FilePathToValue(FilePath file_path)85Value FilePathToValue(FilePath file_path) { 86 return Value(file_path.AsUTF8Unsafe()); 87 } 88 ValueToFilePath(const Value * value)89std::optional<FilePath> ValueToFilePath(const Value* value) { 90 return value ? ValueToFilePath(*value) : std::nullopt; 91 } 92 ValueToFilePath(const Value & value)93std::optional<FilePath> ValueToFilePath(const Value& value) { 94 if (!value.is_string()) 95 return std::nullopt; 96 return FilePath::FromUTF8Unsafe(value.GetString()); 97 } 98 UnguessableTokenToValue(UnguessableToken token)99Value UnguessableTokenToValue(UnguessableToken token) { 100 UnguessableTokenRepresentation repr; 101 repr.field.high = token.GetHighForSerialization(); 102 repr.field.low = token.GetLowForSerialization(); 103 return Value(HexEncode(repr.buffer, sizeof(repr.buffer))); 104 } 105 ValueToUnguessableToken(const Value * value)106std::optional<UnguessableToken> ValueToUnguessableToken(const Value* value) { 107 return value ? ValueToUnguessableToken(*value) : std::nullopt; 108 } 109 ValueToUnguessableToken(const Value & value)110std::optional<UnguessableToken> ValueToUnguessableToken(const Value& value) { 111 if (!value.is_string()) 112 return std::nullopt; 113 UnguessableTokenRepresentation repr; 114 if (!HexStringToSpan(value.GetString(), repr.buffer)) 115 return std::nullopt; 116 std::optional<base::UnguessableToken> token = 117 UnguessableToken::Deserialize(repr.field.high, repr.field.low); 118 if (!token.has_value()) { 119 return std::nullopt; 120 } 121 return token; 122 } 123 124 } // namespace base 125