0

Modernize base::Value usage in IPC message utils.

Prefer using value-based instead of unique_ptr-based APIs where it is
not too intrusive. Use the new representation to more efficiently
translate list and dictionary values (per the documented
recommendations). Replace CreateWithCopiedBuffer with construction from
a span.

base::PickleIterator was augmented with a span-of-bytes ReadData API, to
make this a little cleaner, since this is now preferred over a pair of a
const char* and length.

Bug: 646113
Change-Id: I6361bfffe65e2d84aa8d50390648bb7ac194f205
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2241936
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: Ken Rockot <rockot@google.com>
Commit-Queue: Jeremy Roman <jbroman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#777516}
This commit is contained in:
Jeremy Roman
2020-06-11 22:08:20 +00:00
committed by Commit Bot
parent d97168f56e
commit 2d8d780297
3 changed files with 38 additions and 23 deletions

@ -199,6 +199,17 @@ bool PickleIterator::ReadData(const char** data, int* length) {
return ReadBytes(data, *length); return ReadBytes(data, *length);
} }
bool PickleIterator::ReadData(base::span<const uint8_t>* data) {
const char* ptr;
int length;
if (!ReadData(&ptr, &length))
return false;
*data = base::as_bytes(base::make_span(ptr, length));
return true;
}
bool PickleIterator::ReadBytes(const char** data, int length) { bool PickleIterator::ReadBytes(const char** data, int length) {
const char* read_from = GetReadPointerAndAdvance(length); const char* read_from = GetReadPointerAndAdvance(length);
if (!read_from) if (!read_from)

@ -12,6 +12,7 @@
#include "base/base_export.h" #include "base/base_export.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/containers/span.h"
#include "base/gtest_prod_util.h" #include "base/gtest_prod_util.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
@ -56,6 +57,9 @@ class BASE_EXPORT PickleIterator {
// until the message data is mutated). Do not keep the pointer around! // until the message data is mutated). Do not keep the pointer around!
bool ReadData(const char** data, int* length) WARN_UNUSED_RESULT; bool ReadData(const char** data, int* length) WARN_UNUSED_RESULT;
// Similar, but using base::span for convenience.
bool ReadData(base::span<const uint8_t>* data) WARN_UNUSED_RESULT;
// A pointer to the data will be placed in |*data|. The caller specifies the // A pointer to the data will be placed in |*data|. The caller specifies the
// number of bytes to read, and ReadBytes will validate this length. The // number of bytes to read, and ReadBytes will validate this length. The
// pointer placed into |*data| points into the message's buffer so it will be // pointer placed into |*data| points into the message's buffer so it will be

@ -79,7 +79,7 @@ void LogBytes(const std::vector<CharType>& data, std::string* out) {
bool ReadValue(const base::Pickle* m, bool ReadValue(const base::Pickle* m,
base::PickleIterator* iter, base::PickleIterator* iter,
std::unique_ptr<base::Value>* value, base::Value* value,
int recursion); int recursion);
void WriteValue(base::Pickle* m, const base::Value* value, int recursion) { void WriteValue(base::Pickle* m, const base::Value* value, int recursion) {
@ -166,15 +166,16 @@ bool ReadDictionaryValue(const base::Pickle* m,
if (!ReadParam(m, iter, &size)) if (!ReadParam(m, iter, &size))
return false; return false;
for (int i = 0; i < size; ++i) { std::vector<std::pair<std::string, std::unique_ptr<base::Value>>> entries;
std::string key; entries.resize(size);
std::unique_ptr<base::Value> subval; for (auto& entry : entries) {
if (!ReadParam(m, iter, &key) || entry.second = std::make_unique<base::Value>();
!ReadValue(m, iter, &subval, recursion + 1)) if (!ReadParam(m, iter, &entry.first) ||
!ReadValue(m, iter, entry.second.get(), recursion + 1))
return false; return false;
value->SetWithoutPathExpansion(key, std::move(subval));
} }
*value = base::DictionaryValue(base::Value::DictStorage(std::move(entries)));
return true; return true;
} }
@ -188,19 +189,19 @@ bool ReadListValue(const base::Pickle* m,
if (!ReadParam(m, iter, &size)) if (!ReadParam(m, iter, &size))
return false; return false;
for (int i = 0; i < size; ++i) { base::Value::ListStorage list_storage;
std::unique_ptr<base::Value> subval; list_storage.resize(size);
for (base::Value& subval : list_storage) {
if (!ReadValue(m, iter, &subval, recursion + 1)) if (!ReadValue(m, iter, &subval, recursion + 1))
return false; return false;
value->Set(i, std::move(subval));
} }
*value = base::ListValue(std::move(list_storage));
return true; return true;
} }
bool ReadValue(const base::Pickle* m, bool ReadValue(const base::Pickle* m,
base::PickleIterator* iter, base::PickleIterator* iter,
std::unique_ptr<base::Value>* value, base::Value* value,
int recursion) { int recursion) {
if (recursion > kMaxRecursionDepth) { if (recursion > kMaxRecursionDepth) {
LOG(ERROR) << "Max recursion depth hit in ReadValue."; LOG(ERROR) << "Max recursion depth hit in ReadValue.";
@ -213,56 +214,55 @@ bool ReadValue(const base::Pickle* m,
switch (static_cast<base::Value::Type>(type)) { switch (static_cast<base::Value::Type>(type)) {
case base::Value::Type::NONE: case base::Value::Type::NONE:
*value = std::make_unique<base::Value>(); *value = base::Value();
break; break;
case base::Value::Type::BOOLEAN: { case base::Value::Type::BOOLEAN: {
bool val; bool val;
if (!ReadParam(m, iter, &val)) if (!ReadParam(m, iter, &val))
return false; return false;
*value = std::make_unique<base::Value>(val); *value = base::Value(val);
break; break;
} }
case base::Value::Type::INTEGER: { case base::Value::Type::INTEGER: {
int val; int val;
if (!ReadParam(m, iter, &val)) if (!ReadParam(m, iter, &val))
return false; return false;
*value = std::make_unique<base::Value>(val); *value = base::Value(val);
break; break;
} }
case base::Value::Type::DOUBLE: { case base::Value::Type::DOUBLE: {
double val; double val;
if (!ReadParam(m, iter, &val)) if (!ReadParam(m, iter, &val))
return false; return false;
*value = std::make_unique<base::Value>(val); *value = base::Value(val);
break; break;
} }
case base::Value::Type::STRING: { case base::Value::Type::STRING: {
std::string val; std::string val;
if (!ReadParam(m, iter, &val)) if (!ReadParam(m, iter, &val))
return false; return false;
*value = std::make_unique<base::Value>(std::move(val)); *value = base::Value(std::move(val));
break; break;
} }
case base::Value::Type::BINARY: { case base::Value::Type::BINARY: {
const char* data; base::span<const uint8_t> data;
int length; if (!iter->ReadData(&data))
if (!iter->ReadData(&data, &length))
return false; return false;
*value = base::Value::CreateWithCopiedBuffer(data, length); *value = base::Value(data);
break; break;
} }
case base::Value::Type::DICTIONARY: { case base::Value::Type::DICTIONARY: {
base::DictionaryValue val; base::DictionaryValue val;
if (!ReadDictionaryValue(m, iter, &val, recursion)) if (!ReadDictionaryValue(m, iter, &val, recursion))
return false; return false;
*value = std::make_unique<base::Value>(std::move(val)); *value = std::move(val);
break; break;
} }
case base::Value::Type::LIST: { case base::Value::Type::LIST: {
base::ListValue val; base::ListValue val;
if (!ReadListValue(m, iter, &val, recursion)) if (!ReadListValue(m, iter, &val, recursion))
return false; return false;
*value = std::make_unique<base::Value>(std::move(val)); *value = std::move(val);
break; break;
} }
default: default: