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