DevTools: roll third_party/inspector_protocol, wire binary operation.

Bug: chromium:929862
Change-Id: I8c23be1d22f70d1143d570050514c36ecfb30fc7
Reviewed-on: https://chromium-review.googlesource.com/c/1466003
Reviewed-by: Alexei Filippov <alph@chromium.org>
Commit-Queue: Pavel Feldman <pfeldman@chromium.org>
Commit-Queue: Alexei Filippov <alph@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59541}
This commit is contained in:
Pavel Feldman 2019-02-12 11:00:13 -08:00 committed by Commit Bot
parent ba78fef1f2
commit 5dffb59630
18 changed files with 262 additions and 91 deletions

View File

@ -120,7 +120,7 @@ bool substituteObjectTags(int sessionId, const String16& groupName,
return false; return false;
} }
v8::Local<v8::Value> jsonWrapper; v8::Local<v8::Value> jsonWrapper;
String16 serialized = wrapper->serialize(); String16 serialized = wrapper->toJSON();
if (!v8::JSON::Parse(context, toV8String(isolate, serialized)) if (!v8::JSON::Parse(context, toV8String(isolate, serialized))
.ToLocal(&jsonWrapper)) { .ToLocal(&jsonWrapper)) {
reportError(context, tryCatch, "cannot wrap value"); reportError(context, tryCatch, "cannot wrap value");

View File

@ -585,7 +585,7 @@ Response InjectedScript::resolveCallArgument(
if (callArgument->hasValue() || callArgument->hasUnserializableValue()) { if (callArgument->hasValue() || callArgument->hasUnserializableValue()) {
String16 value; String16 value;
if (callArgument->hasValue()) { if (callArgument->hasValue()) {
value = "(" + callArgument->getValue(nullptr)->serialize() + ")"; value = "(" + callArgument->getValue(nullptr)->toJSONString() + ")";
} else { } else {
String16 unserializableValue = callArgument->getUnserializableValue(""); String16 unserializableValue = callArgument->getUnserializableValue("");
// Protect against potential identifier resolution for NaN and Infinity. // Protect against potential identifier resolution for NaN and Infinity.

View File

@ -122,6 +122,26 @@ std::unique_ptr<protocol::Value> StringUtil::parseJSON(const String16& string) {
static_cast<int>(string.length())); static_cast<int>(string.length()));
} }
// static
std::unique_ptr<protocol::Value> StringUtil::parseProtocolMessage(
const ProtocolMessage& message) {
return parseJSON(message.json);
}
// static
ProtocolMessage StringUtil::jsonToMessage(String message) {
ProtocolMessage result;
result.json = std::move(message);
return result;
}
// static
ProtocolMessage StringUtil::binaryToMessage(std::vector<uint8_t> message) {
ProtocolMessage result;
result.binary = std::move(message);
return result;
}
// static // static
void StringUtil::builderAppendQuotedString(StringBuilder& builder, void StringUtil::builderAppendQuotedString(StringBuilder& builder,
const String& str) { const String& str) {

View File

@ -22,6 +22,10 @@ class Value;
using String = v8_inspector::String16; using String = v8_inspector::String16;
using StringBuilder = v8_inspector::String16Builder; using StringBuilder = v8_inspector::String16Builder;
struct ProtocolMessage {
String json;
std::vector<uint8_t> binary;
};
class StringUtil { class StringUtil {
public: public:
@ -59,6 +63,10 @@ class StringUtil {
} }
static std::unique_ptr<protocol::Value> parseJSON(const String16& json); static std::unique_ptr<protocol::Value> parseJSON(const String16& json);
static std::unique_ptr<protocol::Value> parseJSON(const StringView& json); static std::unique_ptr<protocol::Value> parseJSON(const StringView& json);
static std::unique_ptr<protocol::Value> parseProtocolMessage(
const ProtocolMessage&);
static ProtocolMessage jsonToMessage(String message);
static ProtocolMessage binaryToMessage(std::vector<uint8_t> message);
}; };
// A read-only sequence of uninterpreted bytes with reference-counted storage. // A read-only sequence of uninterpreted bytes with reference-counted storage.
@ -101,6 +109,19 @@ class StringBufferImpl : public StringBuffer {
DISALLOW_COPY_AND_ASSIGN(StringBufferImpl); DISALLOW_COPY_AND_ASSIGN(StringBufferImpl);
}; };
class BinaryStringBuffer : public StringBuffer {
public:
explicit BinaryStringBuffer(std::vector<uint8_t> data)
: m_data(std::move(data)), m_string(m_data.data(), m_data.size()) {}
const StringView& string() override { return m_string; }
private:
std::vector<uint8_t> m_data;
StringView m_string;
DISALLOW_COPY_AND_ASSIGN(BinaryStringBuffer);
};
String16 debuggerIdToString(const std::pair<int64_t, int64_t>& debuggerId); String16 debuggerIdToString(const std::pair<int64_t, int64_t>& debuggerId);
String16 stackTraceIdToString(uintptr_t id); String16 stackTraceIdToString(uintptr_t id);

View File

@ -137,41 +137,53 @@ namespace {
class MessageBuffer : public StringBuffer { class MessageBuffer : public StringBuffer {
public: public:
static std::unique_ptr<MessageBuffer> create( static std::unique_ptr<MessageBuffer> create(
std::unique_ptr<protocol::Serializable> message) { std::unique_ptr<protocol::Serializable> message, bool binary) {
return std::unique_ptr<MessageBuffer>( return std::unique_ptr<MessageBuffer>(
new MessageBuffer(std::move(message))); new MessageBuffer(std::move(message), binary));
} }
const StringView& string() override { const StringView& string() override {
if (!m_serialized) { if (!m_serialized) {
m_serialized = StringBuffer::create(toStringView(m_message->serialize())); if (m_binary) {
// Encode binary response as an 8bit string buffer.
m_serialized.reset(
new BinaryStringBuffer(m_message->serializeToBinary()));
} else {
m_serialized =
StringBuffer::create(toStringView(m_message->serializeToJSON()));
}
m_message.reset(nullptr); m_message.reset(nullptr);
} }
return m_serialized->string(); return m_serialized->string();
} }
private: private:
explicit MessageBuffer(std::unique_ptr<protocol::Serializable> message) explicit MessageBuffer(std::unique_ptr<protocol::Serializable> message,
: m_message(std::move(message)) {} bool binary)
: m_message(std::move(message)), m_binary(binary) {}
std::unique_ptr<protocol::Serializable> m_message; std::unique_ptr<protocol::Serializable> m_message;
std::unique_ptr<StringBuffer> m_serialized; std::unique_ptr<StringBuffer> m_serialized;
bool m_binary;
}; };
} // namespace } // namespace
void V8InspectorSessionImpl::sendProtocolResponse( void V8InspectorSessionImpl::sendProtocolResponse(
int callId, std::unique_ptr<protocol::Serializable> message) { int callId, std::unique_ptr<protocol::Serializable> message) {
m_channel->sendResponse(callId, MessageBuffer::create(std::move(message))); m_channel->sendResponse(
callId, MessageBuffer::create(std::move(message), use_binary_protocol_));
} }
void V8InspectorSessionImpl::sendProtocolNotification( void V8InspectorSessionImpl::sendProtocolNotification(
std::unique_ptr<protocol::Serializable> message) { std::unique_ptr<protocol::Serializable> message) {
m_channel->sendNotification(MessageBuffer::create(std::move(message))); m_channel->sendNotification(
MessageBuffer::create(std::move(message), use_binary_protocol_));
} }
void V8InspectorSessionImpl::fallThrough(int callId, const String16& method, void V8InspectorSessionImpl::fallThrough(
const String16& message) { int callId, const String16& method,
const protocol::ProtocolMessage& message) {
// There's no other layer to handle the command. // There's no other layer to handle the command.
UNREACHABLE(); UNREACHABLE();
} }
@ -316,19 +328,28 @@ void V8InspectorSessionImpl::reportAllContexts(V8RuntimeAgentImpl* agent) {
void V8InspectorSessionImpl::dispatchProtocolMessage( void V8InspectorSessionImpl::dispatchProtocolMessage(
const StringView& message) { const StringView& message) {
bool binary_protocol =
message.is8Bit() && message.length() && message.characters8()[0] == 0xDA;
if (binary_protocol) use_binary_protocol_ = true;
int callId; int callId;
std::unique_ptr<protocol::Value> parsed_message;
if (binary_protocol) {
parsed_message = protocol::Value::parseBinary(
message.characters8(), static_cast<unsigned>(message.length()));
} else {
parsed_message = protocol::StringUtil::parseJSON(message);
}
String16 method; String16 method;
std::unique_ptr<protocol::Value> parsedMessage = if (m_dispatcher.parseCommand(parsed_message.get(), &callId, &method)) {
protocol::StringUtil::parseJSON(message);
if (m_dispatcher.parseCommand(parsedMessage.get(), &callId, &method)) {
// Pass empty string instead of the actual message to save on a conversion. // Pass empty string instead of the actual message to save on a conversion.
// We're allowed to do so because fall-through is not implemented. // We're allowed to do so because fall-through is not implemented.
m_dispatcher.dispatch(callId, method, std::move(parsedMessage), ""); m_dispatcher.dispatch(callId, method, std::move(parsed_message),
protocol::ProtocolMessage());
} }
} }
std::unique_ptr<StringBuffer> V8InspectorSessionImpl::stateJSON() { std::unique_ptr<StringBuffer> V8InspectorSessionImpl::stateJSON() {
String16 json = m_state->serialize(); String16 json = m_state->toJSONString();
return StringBufferImpl::adopt(json); return StringBufferImpl::adopt(json);
} }

View File

@ -102,7 +102,7 @@ class V8InspectorSessionImpl : public V8InspectorSession,
void sendProtocolNotification( void sendProtocolNotification(
std::unique_ptr<protocol::Serializable> message) override; std::unique_ptr<protocol::Serializable> message) override;
void fallThrough(int callId, const String16& method, void fallThrough(int callId, const String16& method,
const String16& message) override; const protocol::ProtocolMessage& message) override;
void flushProtocolNotifications() override; void flushProtocolNotifications() override;
int m_contextGroupId; int m_contextGroupId;
@ -122,6 +122,7 @@ class V8InspectorSessionImpl : public V8InspectorSession,
std::unique_ptr<V8SchemaAgentImpl> m_schemaAgent; std::unique_ptr<V8SchemaAgentImpl> m_schemaAgent;
std::vector<std::unique_ptr<V8InspectorSession::Inspectable>> std::vector<std::unique_ptr<V8InspectorSession::Inspectable>>
m_inspectedObjects; m_inspectedObjects;
bool use_binary_protocol_ = false;
DISALLOW_COPY_AND_ASSIGN(V8InspectorSessionImpl); DISALLOW_COPY_AND_ASSIGN(V8InspectorSessionImpl);
}; };

View File

@ -2,7 +2,7 @@ Name: inspector protocol
Short Name: inspector_protocol Short Name: inspector_protocol
URL: https://chromium.googlesource.com/deps/inspector_protocol/ URL: https://chromium.googlesource.com/deps/inspector_protocol/
Version: 0 Version: 0
Revision: 8515c2a1c5c016646b61221586cd4e5839f425ee Revision: e8a0de7351b5d72aadde777e2ad9b412d1431ffa
License: BSD License: BSD
License File: LICENSE License File: LICENSE
Security Critical: no Security Critical: no

View File

@ -70,7 +70,7 @@ DispatcherBase::WeakPtr::~WeakPtr()
m_dispatcher->m_weakPtrs.erase(this); m_dispatcher->m_weakPtrs.erase(this);
} }
DispatcherBase::Callback::Callback(std::unique_ptr<DispatcherBase::WeakPtr> backendImpl, int callId, const String& method, const String& message) DispatcherBase::Callback::Callback(std::unique_ptr<DispatcherBase::WeakPtr> backendImpl, int callId, const String& method, const ProtocolMessage& message)
: m_backendImpl(std::move(backendImpl)) : m_backendImpl(std::move(backendImpl))
, m_callId(callId) , m_callId(callId)
, m_method(method) , m_method(method)
@ -142,18 +142,14 @@ public:
return std::unique_ptr<ProtocolError>(new ProtocolError(code, errorMessage)); return std::unique_ptr<ProtocolError>(new ProtocolError(code, errorMessage));
} }
String serialize() override String serializeToJSON() override
{ {
std::unique_ptr<protocol::DictionaryValue> error = DictionaryValue::create(); return serialize()->serializeToJSON();
error->setInteger("code", m_code); }
error->setString("message", m_errorMessage);
if (m_data.length()) std::vector<uint8_t> serializeToBinary() override
error->setString("data", m_data); {
std::unique_ptr<protocol::DictionaryValue> message = DictionaryValue::create(); return serialize()->serializeToBinary();
message->setObject("error", std::move(error));
if (m_hasCallId)
message->setInteger("id", m_callId);
return message->serialize();
} }
~ProtocolError() override {} ~ProtocolError() override {}
@ -165,6 +161,19 @@ private:
{ {
} }
std::unique_ptr<DictionaryValue> serialize() {
std::unique_ptr<protocol::DictionaryValue> error = DictionaryValue::create();
error->setInteger("code", m_code);
error->setString("message", m_errorMessage);
if (m_data.length())
error->setString("data", m_data);
std::unique_ptr<protocol::DictionaryValue> message = DictionaryValue::create();
message->setObject("error", std::move(error));
if (m_hasCallId)
message->setInteger("id", m_callId);
return message;
}
DispatchResponse::ErrorCode m_code; DispatchResponse::ErrorCode m_code;
String m_errorMessage; String m_errorMessage;
String m_data; String m_data;
@ -275,7 +284,7 @@ bool UberDispatcher::canDispatch(const String& in_method)
return !!findDispatcher(method); return !!findDispatcher(method);
} }
void UberDispatcher::dispatch(int callId, const String& in_method, std::unique_ptr<Value> parsedMessage, const String& rawMessage) void UberDispatcher::dispatch(int callId, const String& in_method, std::unique_ptr<Value> parsedMessage, const ProtocolMessage& rawMessage)
{ {
String method = in_method; String method = in_method;
auto redirectIt = m_redirects.find(method); auto redirectIt = m_redirects.find(method);
@ -304,18 +313,32 @@ std::unique_ptr<InternalResponse> InternalResponse::createNotification(const Str
return std::unique_ptr<InternalResponse>(new InternalResponse(0, notification, std::move(params))); return std::unique_ptr<InternalResponse>(new InternalResponse(0, notification, std::move(params)));
} }
String InternalResponse::serialize() String InternalResponse::serializeToJSON()
{ {
std::unique_ptr<DictionaryValue> result = DictionaryValue::create(); std::unique_ptr<DictionaryValue> result = DictionaryValue::create();
std::unique_ptr<Serializable> params(m_params ? std::move(m_params) : DictionaryValue::create()); std::unique_ptr<Serializable> params(m_params ? std::move(m_params) : DictionaryValue::create());
if (m_notification.length()) { if (m_notification.length()) {
result->setString("method", m_notification); result->setString("method", m_notification);
result->setValue("params", SerializedValue::create(params->serialize())); result->setValue("params", SerializedValue::fromJSON(params->serializeToJSON()));
} else { } else {
result->setInteger("id", m_callId); result->setInteger("id", m_callId);
result->setValue("result", SerializedValue::create(params->serialize())); result->setValue("result", SerializedValue::fromJSON(params->serializeToJSON()));
} }
return result->serialize(); return result->serializeToJSON();
}
std::vector<uint8_t> InternalResponse::serializeToBinary()
{
std::unique_ptr<DictionaryValue> result = DictionaryValue::create();
std::unique_ptr<Serializable> params(m_params ? std::move(m_params) : DictionaryValue::create());
if (m_notification.length()) {
result->setString("method", m_notification);
result->setValue("params", SerializedValue::fromBinary(params->serializeToBinary()));
} else {
result->setInteger("id", m_callId);
result->setValue("result", SerializedValue::fromBinary(params->serializeToBinary()));
}
return result->serializeToBinary();
} }
InternalResponse::InternalResponse(int callId, const String& notification, std::unique_ptr<Serializable> params) InternalResponse::InternalResponse(int callId, const String& notification, std::unique_ptr<Serializable> params)

View File

@ -68,7 +68,7 @@ public:
class {{config.lib.export_macro}} Callback { class {{config.lib.export_macro}} Callback {
public: public:
Callback(std::unique_ptr<WeakPtr> backendImpl, int callId, const String& method, const String& message); Callback(std::unique_ptr<WeakPtr> backendImpl, int callId, const String& method, const ProtocolMessage& message);
virtual ~Callback(); virtual ~Callback();
void dispose(); void dispose();
@ -80,14 +80,14 @@ public:
std::unique_ptr<WeakPtr> m_backendImpl; std::unique_ptr<WeakPtr> m_backendImpl;
int m_callId; int m_callId;
String m_method; String m_method;
String m_message; ProtocolMessage m_message;
}; };
explicit DispatcherBase(FrontendChannel*); explicit DispatcherBase(FrontendChannel*);
virtual ~DispatcherBase(); virtual ~DispatcherBase();
virtual bool canDispatch(const String& method) = 0; virtual bool canDispatch(const String& method) = 0;
virtual void dispatch(int callId, const String& method, const String& rawMessage, std::unique_ptr<protocol::DictionaryValue> messageObject) = 0; virtual void dispatch(int callId, const String& method, const ProtocolMessage& rawMessage, std::unique_ptr<protocol::DictionaryValue> messageObject) = 0;
FrontendChannel* channel() { return m_frontendChannel; } FrontendChannel* channel() { return m_frontendChannel; }
void sendResponse(int callId, const DispatchResponse&, std::unique_ptr<protocol::DictionaryValue> result); void sendResponse(int callId, const DispatchResponse&, std::unique_ptr<protocol::DictionaryValue> result);
@ -111,7 +111,7 @@ public:
void setupRedirects(const std::unordered_map<String, String>&); void setupRedirects(const std::unordered_map<String, String>&);
bool parseCommand(Value* message, int* callId, String* method); bool parseCommand(Value* message, int* callId, String* method);
bool canDispatch(const String& method); bool canDispatch(const String& method);
void dispatch(int callId, const String& method, std::unique_ptr<Value> message, const String& rawMessage); void dispatch(int callId, const String& method, std::unique_ptr<Value> message, const ProtocolMessage& rawMessage);
FrontendChannel* channel() { return m_frontendChannel; } FrontendChannel* channel() { return m_frontendChannel; }
virtual ~UberDispatcher(); virtual ~UberDispatcher();
@ -128,7 +128,8 @@ public:
static std::unique_ptr<InternalResponse> createResponse(int callId, std::unique_ptr<Serializable> params); static std::unique_ptr<InternalResponse> createResponse(int callId, std::unique_ptr<Serializable> params);
static std::unique_ptr<InternalResponse> createNotification(const String& notification, std::unique_ptr<Serializable> params = nullptr); static std::unique_ptr<InternalResponse> createNotification(const String& notification, std::unique_ptr<Serializable> params = nullptr);
String serialize() override; String serializeToJSON() override;
std::vector<uint8_t> serializeToBinary() override;
~InternalResponse() override {} ~InternalResponse() override {}
@ -142,24 +143,36 @@ private:
class InternalRawNotification : public Serializable { class InternalRawNotification : public Serializable {
public: public:
static std::unique_ptr<InternalRawNotification> create(const String& notification) static std::unique_ptr<InternalRawNotification> fromJSON(String notification)
{ {
return std::unique_ptr<InternalRawNotification>(new InternalRawNotification(notification)); return std::unique_ptr<InternalRawNotification>(new InternalRawNotification(std::move(notification)));
} }
static std::unique_ptr<InternalRawNotification> fromBinary(std::vector<uint8_t> notification)
{
return std::unique_ptr<InternalRawNotification>(new InternalRawNotification(std::move(notification)));
}
~InternalRawNotification() override {} ~InternalRawNotification() override {}
String serialize() override String serializeToJSON() override
{ {
return m_notification; return std::move(m_jsonNotification);
}
std::vector<uint8_t> serializeToBinary() override
{
return std::move(m_binaryNotification);
} }
private: private:
explicit InternalRawNotification(const String& notification) explicit InternalRawNotification(String notification)
: m_notification(notification) : m_jsonNotification(std::move(notification)) { }
{ explicit InternalRawNotification(std::vector<uint8_t> notification)
} : m_binaryNotification(std::move(notification)) { }
String m_notification; String m_jsonNotification;
std::vector<uint8_t> m_binaryNotification;
}; };
{% for namespace in config.protocol.namespace %} {% for namespace in config.protocol.namespace %}

View File

@ -13,7 +13,14 @@ namespace {{namespace}} {
class {{config.lib.export_macro}} Serializable { class {{config.lib.export_macro}} Serializable {
public: public:
virtual String serialize() = 0; ProtocolMessage serialize(bool binary) {
if (binary)
return StringUtil::binaryToMessage(serializeToBinary());
else
return StringUtil::jsonToMessage(serializeToJSON());
}
virtual String serializeToJSON() = 0;
virtual std::vector<uint8_t> serializeToBinary() = 0;
virtual ~Serializable() = default; virtual ~Serializable() = default;
}; };
@ -22,7 +29,7 @@ public:
virtual ~FrontendChannel() { } virtual ~FrontendChannel() { }
virtual void sendProtocolResponse(int callId, std::unique_ptr<Serializable> message) = 0; virtual void sendProtocolResponse(int callId, std::unique_ptr<Serializable> message) = 0;
virtual void sendProtocolNotification(std::unique_ptr<Serializable> message) = 0; virtual void sendProtocolNotification(std::unique_ptr<Serializable> message) = 0;
virtual void fallThrough(int callId, const String& method, const String& message) = 0; virtual void fallThrough(int callId, const String& method, const ProtocolMessage& message) = 0;
virtual void flushProtocolNotifications() = 0; virtual void flushProtocolNotifications() = 0;
}; };

View File

@ -62,6 +62,11 @@ void escapeStringForJSONInternal(const Char* str, unsigned len,
} // anonymous namespace } // anonymous namespace
// static
std::unique_ptr<Value> Value::parseBinary(const uint8_t* data, unsigned size) {
return nullptr;
}
bool Value::asBoolean(bool*) const bool Value::asBoolean(bool*) const
{ {
return false; return false;
@ -82,11 +87,6 @@ bool Value::asString(String*) const
return false; return false;
} }
bool Value::asSerialized(String*) const
{
return false;
}
void Value::writeJSON(StringBuilder* output) const void Value::writeJSON(StringBuilder* output) const
{ {
DCHECK(m_type == TypeNull); DCHECK(m_type == TypeNull);
@ -98,7 +98,7 @@ std::unique_ptr<Value> Value::clone() const
return Value::null(); return Value::null();
} }
String Value::serialize() String Value::toJSONString() const
{ {
StringBuilder result; StringBuilder result;
StringUtil::builderReserve(result, 512); StringUtil::builderReserve(result, 512);
@ -106,6 +106,14 @@ String Value::serialize()
return StringUtil::builderToString(result); return StringUtil::builderToString(result);
} }
String Value::serializeToJSON() {
return toJSONString();
}
std::vector<uint8_t> Value::serializeToBinary() {
return std::vector<uint8_t>();
}
bool FundamentalValue::asBoolean(bool* output) const bool FundamentalValue::asBoolean(bool* output) const
{ {
if (type() != TypeBoolean) if (type() != TypeBoolean)
@ -183,21 +191,15 @@ std::unique_ptr<Value> StringValue::clone() const
return StringValue::create(m_stringValue); return StringValue::create(m_stringValue);
} }
bool SerializedValue::asSerialized(String* output) const
{
*output = m_serializedValue;
return true;
}
void SerializedValue::writeJSON(StringBuilder* output) const void SerializedValue::writeJSON(StringBuilder* output) const
{ {
DCHECK(type() == TypeSerialized); DCHECK(type() == TypeSerialized);
StringUtil::builderAppend(*output, m_serializedValue); StringUtil::builderAppend(*output, m_serializedJSON);
} }
std::unique_ptr<Value> SerializedValue::clone() const std::unique_ptr<Value> SerializedValue::clone() const
{ {
return SerializedValue::create(m_serializedValue); return std::unique_ptr<SerializedValue>(new SerializedValue(m_serializedJSON, m_serializedBinary));
} }
DictionaryValue::~DictionaryValue() DictionaryValue::~DictionaryValue()

View File

@ -28,6 +28,8 @@ public:
return std::unique_ptr<Value>(new Value()); return std::unique_ptr<Value>(new Value());
} }
static std::unique_ptr<Value> parseBinary(const uint8_t*data, unsigned size);
enum ValueType { enum ValueType {
TypeNull = 0, TypeNull = 0,
TypeBoolean, TypeBoolean,
@ -47,11 +49,13 @@ public:
virtual bool asDouble(double* output) const; virtual bool asDouble(double* output) const;
virtual bool asInteger(int* output) const; virtual bool asInteger(int* output) const;
virtual bool asString(String* output) const; virtual bool asString(String* output) const;
virtual bool asSerialized(String* output) const;
virtual void writeJSON(StringBuilder* output) const; virtual void writeJSON(StringBuilder* output) const;
virtual std::unique_ptr<Value> clone() const; virtual std::unique_ptr<Value> clone() const;
String serialize() override; String toJSONString() const;
String serializeToJSON() override;
std::vector<uint8_t> serializeToBinary() override;
protected: protected:
Value() : m_type(TypeNull) { } Value() : m_type(TypeNull) { }
@ -124,19 +128,26 @@ private:
class {{config.lib.export_macro}} SerializedValue : public Value { class {{config.lib.export_macro}} SerializedValue : public Value {
public: public:
static std::unique_ptr<SerializedValue> create(const String& value) static std::unique_ptr<SerializedValue> fromJSON(const String& value)
{ {
return std::unique_ptr<SerializedValue>(new SerializedValue(value)); return std::unique_ptr<SerializedValue>(new SerializedValue(value));
} }
bool asSerialized(String* output) const override; static std::unique_ptr<SerializedValue> fromBinary(std::vector<uint8_t> value)
{
return std::unique_ptr<SerializedValue>(new SerializedValue(std::move(value)));
}
void writeJSON(StringBuilder* output) const override; void writeJSON(StringBuilder* output) const override;
std::unique_ptr<Value> clone() const override; std::unique_ptr<Value> clone() const override;
private: private:
explicit SerializedValue(const String& value) : Value(TypeSerialized), m_serializedValue(value) { } explicit SerializedValue(const String& json) : Value(TypeSerialized), m_serializedJSON(json) { }
explicit SerializedValue(std::vector<uint8_t> binary) : Value(TypeSerialized), m_serializedBinary(std::move(binary)) { }
String m_serializedValue; SerializedValue(const String& json, const std::vector<uint8_t>& binary)
: Value(TypeSerialized), m_serializedJSON(json), m_serializedBinary(binary) { }
String m_serializedJSON;
std::vector<uint8_t> m_serializedBinary;
}; };
class {{config.lib.export_macro}} DictionaryValue : public Value { class {{config.lib.export_macro}} DictionaryValue : public Value {

View File

@ -128,12 +128,28 @@ std::unique_ptr<base::Value> toBaseValue(Value* value, int depth) {
} }
// static // static
std::unique_ptr<Value> StringUtil::parseJSON( std::unique_ptr<Value> StringUtil::parseMessage(
const std::string& json) { const std::string& message, bool binary) {
std::unique_ptr<base::Value> value = base::JSONReader::Read(json); if (binary) {
return Value::parseBinary(
reinterpret_cast<const uint8_t*>(message.data()),
message.length());
}
std::unique_ptr<base::Value> value = base::JSONReader::Read(message);
return toProtocolValue(value.get(), 1000); return toProtocolValue(value.get(), 1000);
} }
// static
ProtocolMessage StringUtil::jsonToMessage(String message) {
return message;
}
// static
ProtocolMessage StringUtil::binaryToMessage(std::vector<uint8_t> message) {
// TODO(pfeldman): figure out what to do with this copy.
return std::string(reinterpret_cast<const char*>(message.data()), message.size());
}
StringBuilder::StringBuilder() {} StringBuilder::StringBuilder() {}
StringBuilder::~StringBuilder() {} StringBuilder::~StringBuilder() {}

View File

@ -30,6 +30,7 @@ namespace {{namespace}} {
class Value; class Value;
using String = std::string; using String = std::string;
using ProtocolMessage = std::string;
class {{config.lib.export_macro}} StringBuilder { class {{config.lib.export_macro}} StringBuilder {
public: public:
@ -90,7 +91,9 @@ class {{config.lib.export_macro}} StringUtil {
return std::vector<uint8_t>(str.begin(), str.end()); return std::vector<uint8_t>(str.begin(), str.end());
} }
static std::unique_ptr<Value> parseJSON(const String&); static std::unique_ptr<Value> parseMessage(const std::string& message, bool binary);
static ProtocolMessage jsonToMessage(String message);
static ProtocolMessage binaryToMessage(std::vector<uint8_t> message);
}; };
// A read-only sequence of uninterpreted bytes with reference-counted storage. // A read-only sequence of uninterpreted bytes with reference-counted storage.

View File

@ -51,8 +51,10 @@ namespace {{param.name | to_title_case}}Enum {
class {{config.exported.export_macro}} {{type.id}} { class {{config.exported.export_macro}} {{type.id}} {
public: public:
virtual {{config.exported.string_out}} toJSONString() const = 0; virtual {{config.exported.string_out}} toJSONString() const = 0;
virtual std::vector<uint8_t> toBinary() const = 0;
virtual ~{{type.id}}() { } virtual ~{{type.id}}() { }
static std::unique_ptr<protocol::{{domain.domain}}::API::{{type.id}}> fromJSONString(const {{config.exported.string_in}}& json); static std::unique_ptr<protocol::{{domain.domain}}::API::{{type.id}}> fromJSONString(const {{config.exported.string_in}}& json);
static std::unique_ptr<protocol::{{domain.domain}}::API::{{type.id}}> fromBinary(std::vector<uint8_t> binary);
}; };
{% endfor %} {% endfor %}

View File

@ -28,8 +28,17 @@ struct ValueConversions<{{"::".join(config.imported.namespace)}}::{{domain.domai
errors->addError("value expected"); errors->addError("value expected");
return nullptr; return nullptr;
} }
String json = value->serialize();
auto result = {{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}::fromJSONString({{config.imported.to_imported_string % "json"}}); // TODO(pfeldman): toggle to true and delete the json branch when binary is ready.
bool binary_protocol = false;
std::unique_ptr<{{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}> result;
if (binary_protocol) {
std::vector<uint8_t> binary = value->serializeToBinary();
result = {{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}::fromBinary(std::move(binary));
} else {
String json = value->serializeToJSON();
result = {{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}::fromJSONString({{config.imported.to_imported_string % "json"}});
}
if (!result) if (!result)
errors->addError("cannot parse"); errors->addError("cannot parse");
return result; return result;
@ -37,8 +46,15 @@ struct ValueConversions<{{"::".join(config.imported.namespace)}}::{{domain.domai
static std::unique_ptr<protocol::Value> toValue(const {{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}* value) static std::unique_ptr<protocol::Value> toValue(const {{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}* value)
{ {
auto json = value->toJSONString(); // TODO(pfeldman): toggle to true and delete the json branch when binary is ready.
return SerializedValue::create({{config.imported.from_imported_string % "std::move(json)"}}); bool binary_protocol = false;
if (binary_protocol) {
return SerializedValue::fromBinary(value->toBinary());
} else {
auto json = value->toJSONString();
String local_json = ({{config.imported.from_imported_string % "std::move(json)"}});
return SerializedValue::fromJSON(local_json);
}
} }
static std::unique_ptr<protocol::Value> toValue(const std::unique_ptr<{{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}>& value) static std::unique_ptr<protocol::Value> toValue(const std::unique_ptr<{{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}>& value)

View File

@ -101,10 +101,15 @@ std::unique_ptr<{{type.id}}> {{type.id}}::clone() const
{{config.exported.string_out}} {{type.id}}::toJSONString() const {{config.exported.string_out}} {{type.id}}::toJSONString() const
{ {
String json = toValue()->serialize(); String json = toValue()->serializeToJSON();
return {{config.exported.to_string_out % "json"}}; return {{config.exported.to_string_out % "json"}};
} }
std::vector<uint8_t> {{type.id}}::toBinary() const
{
return toValue()->serializeToBinary();
}
// static // static
std::unique_ptr<API::{{type.id}}> API::{{type.id}}::fromJSONString(const {{config.exported.string_in}}& json) std::unique_ptr<API::{{type.id}}> API::{{type.id}}::fromJSONString(const {{config.exported.string_in}}& json)
{ {
@ -114,6 +119,7 @@ std::unique_ptr<API::{{type.id}}> API::{{type.id}}::fromJSONString(const {{confi
return nullptr; return nullptr;
return protocol::{{domain.domain}}::{{type.id}}::fromValue(value.get(), &errors); return protocol::{{domain.domain}}::{{type.id}}::fromValue(value.get(), &errors);
} }
{% endif %} {% endif %}
{% endfor %} {% endfor %}
@ -187,9 +193,14 @@ void Frontend::flush()
m_frontendChannel->flushProtocolNotifications(); m_frontendChannel->flushProtocolNotifications();
} }
void Frontend::sendRawNotification(const String& notification) void Frontend::sendRawNotification(String notification)
{ {
m_frontendChannel->sendProtocolNotification(InternalRawNotification::create(notification)); m_frontendChannel->sendProtocolNotification(InternalRawNotification::fromJSON(std::move(notification)));
}
void Frontend::sendRawNotification(std::vector<uint8_t> notification)
{
m_frontendChannel->sendProtocolNotification(InternalRawNotification::fromBinary(std::move(notification)));
} }
// --------------------- Dispatcher. // --------------------- Dispatcher.
@ -210,11 +221,11 @@ public:
} }
~DispatcherImpl() override { } ~DispatcherImpl() override { }
bool canDispatch(const String& method) override; bool canDispatch(const String& method) override;
void dispatch(int callId, const String& method, const String& message, std::unique_ptr<protocol::DictionaryValue> messageObject) override; void dispatch(int callId, const String& method, const ProtocolMessage& message, std::unique_ptr<protocol::DictionaryValue> messageObject) override;
std::unordered_map<String, String>& redirects() { return m_redirects; } std::unordered_map<String, String>& redirects() { return m_redirects; }
protected: protected:
using CallHandler = void (DispatcherImpl::*)(int callId, const String& method, const String& message, std::unique_ptr<DictionaryValue> messageObject, ErrorSupport* errors); using CallHandler = void (DispatcherImpl::*)(int callId, const String& method, const ProtocolMessage& message, std::unique_ptr<DictionaryValue> messageObject, ErrorSupport* errors);
using DispatchMap = std::unordered_map<String, CallHandler>; using DispatchMap = std::unordered_map<String, CallHandler>;
DispatchMap m_dispatchMap; DispatchMap m_dispatchMap;
std::unordered_map<String, String> m_redirects; std::unordered_map<String, String> m_redirects;
@ -222,7 +233,7 @@ protected:
{% for command in domain.commands %} {% for command in domain.commands %}
{% if "redirect" in command %}{% continue %}{% endif %} {% if "redirect" in command %}{% continue %}{% endif %}
{% if not protocol.generate_command(domain.domain, command.name) %}{% continue %}{% endif %} {% if not protocol.generate_command(domain.domain, command.name) %}{% continue %}{% endif %}
void {{command.name}}(int callId, const String& method, const String& message, std::unique_ptr<DictionaryValue> requestMessageObject, ErrorSupport*); void {{command.name}}(int callId, const String& method, const ProtocolMessage& message, std::unique_ptr<DictionaryValue> requestMessageObject, ErrorSupport*);
{% endfor %} {% endfor %}
Backend* m_backend; Backend* m_backend;
@ -232,7 +243,7 @@ bool DispatcherImpl::canDispatch(const String& method) {
return m_dispatchMap.find(method) != m_dispatchMap.end(); return m_dispatchMap.find(method) != m_dispatchMap.end();
} }
void DispatcherImpl::dispatch(int callId, const String& method, const String& message, std::unique_ptr<protocol::DictionaryValue> messageObject) void DispatcherImpl::dispatch(int callId, const String& method, const ProtocolMessage& message, std::unique_ptr<protocol::DictionaryValue> messageObject)
{ {
std::unordered_map<String, CallHandler>::iterator it = m_dispatchMap.find(method); std::unordered_map<String, CallHandler>::iterator it = m_dispatchMap.find(method);
DCHECK(it != m_dispatchMap.end()); DCHECK(it != m_dispatchMap.end());
@ -248,7 +259,7 @@ void DispatcherImpl::dispatch(int callId, const String& method, const String& me
class {{command_name_title}}CallbackImpl : public Backend::{{command_name_title}}Callback, public DispatcherBase::Callback { class {{command_name_title}}CallbackImpl : public Backend::{{command_name_title}}Callback, public DispatcherBase::Callback {
public: public:
{{command_name_title}}CallbackImpl(std::unique_ptr<DispatcherBase::WeakPtr> backendImpl, int callId, const String& method, const String& message) {{command_name_title}}CallbackImpl(std::unique_ptr<DispatcherBase::WeakPtr> backendImpl, int callId, const String& method, const ProtocolMessage& message)
: DispatcherBase::Callback(std::move(backendImpl), callId, method, message) { } : DispatcherBase::Callback(std::move(backendImpl), callId, method, message) { }
void sendSuccess( void sendSuccess(
@ -286,7 +297,7 @@ public:
}; };
{% endif %} {% endif %}
void DispatcherImpl::{{command.name}}(int callId, const String& method, const String& message, std::unique_ptr<DictionaryValue> requestMessageObject, ErrorSupport* errors) void DispatcherImpl::{{command.name}}(int callId, const String& method, const ProtocolMessage& message, std::unique_ptr<DictionaryValue> requestMessageObject, ErrorSupport* errors)
{ {
{% if "parameters" in command %} {% if "parameters" in command %}
// Prepare input parameters. // Prepare input parameters.

View File

@ -100,10 +100,13 @@ public:
{% endfor %} {% endfor %}
std::unique_ptr<protocol::DictionaryValue> toValue() const; std::unique_ptr<protocol::DictionaryValue> toValue() const;
String serialize() override { return toValue()->serialize(); } String serializeToJSON() override { return toValue()->serializeToJSON(); }
std::vector<uint8_t> serializeToBinary() override { return toValue()->serializeToBinary(); }
String toJSON() const { return toValue()->toJSONString(); }
std::unique_ptr<{{type.id}}> clone() const; std::unique_ptr<{{type.id}}> clone() const;
{% if protocol.is_exported(domain.domain, type.id) %} {% if protocol.is_exported(domain.domain, type.id) %}
{{config.exported.string_out}} toJSONString() const override; {{config.exported.string_out}} toJSONString() const override;
std::vector<uint8_t> toBinary() const override;
{% endif %} {% endif %}
template<int STATE> template<int STATE>
@ -266,7 +269,8 @@ public:
{% endfor %} {% endfor %}
void flush(); void flush();
void sendRawNotification(const String&); void sendRawNotification(String);
void sendRawNotification(std::vector<uint8_t>);
private: private:
FrontendChannel* m_frontendChannel; FrontendChannel* m_frontendChannel;
}; };