diff --git a/src/inspector/v8-inspector-session-impl.cc b/src/inspector/v8-inspector-session-impl.cc index 105f957c9c..c4c4cc14a1 100644 --- a/src/inspector/v8-inspector-session-impl.cc +++ b/src/inspector/v8-inspector-session-impl.cc @@ -76,6 +76,8 @@ V8InspectorSessionImpl::V8InspectorSessionImpl(V8InspectorImpl* inspector, m_state = protocol::DictionaryValue::create(); } + m_state->getBoolean("use_binary_protocol", &use_binary_protocol_); + m_runtimeAgent.reset(new V8RuntimeAgentImpl( this, this, agentState(protocol::Runtime::Metainfo::domainName))); protocol::Runtime::Dispatcher::wire(&m_dispatcher, m_runtimeAgent.get()); @@ -330,7 +332,11 @@ void V8InspectorSessionImpl::dispatchProtocolMessage( const StringView& message) { bool binary_protocol = message.is8Bit() && message.length() && message.characters8()[0] == 0xD8; - if (binary_protocol) use_binary_protocol_ = true; + if (binary_protocol) { + use_binary_protocol_ = true; + m_state->setBoolean("use_binary_protocol", true); + } + int callId; std::unique_ptr parsed_message; if (binary_protocol) { diff --git a/third_party/inspector_protocol/README.v8 b/third_party/inspector_protocol/README.v8 index 2a4137245a..ca406fbc49 100644 --- a/third_party/inspector_protocol/README.v8 +++ b/third_party/inspector_protocol/README.v8 @@ -2,7 +2,7 @@ Name: inspector protocol Short Name: inspector_protocol URL: https://chromium.googlesource.com/deps/inspector_protocol/ Version: 0 -Revision: ec358ccfd63a2a657c147329c7793d217e278a58 +Revision: c40253f87c475880d1bdad4a90cf21c38dadf4ac License: BSD License File: LICENSE Security Critical: no diff --git a/third_party/inspector_protocol/lib/CBOR_cpp.template b/third_party/inspector_protocol/lib/CBOR_cpp.template index ad7b11676f..97ae156b22 100644 --- a/third_party/inspector_protocol/lib/CBOR_cpp.template +++ b/third_party/inspector_protocol/lib/CBOR_cpp.template @@ -15,34 +15,9 @@ namespace {{namespace}} { // ===== encoding/cbor.cc ===== +using namespace cbor; + namespace { -using cbor_internals::MajorType; - -// Indicates the number of bits the "initial byte" needs to be shifted to the -// right after applying |kMajorTypeMask| to produce the major type in the -// lowermost bits. -static constexpr uint8_t kMajorTypeBitShift = 5u; -// Mask selecting the low-order 5 bits of the "initial byte", which is where -// the additional information is encoded. -static constexpr uint8_t kAdditionalInformationMask = 0x1f; -// Mask selecting the high-order 3 bits of the "initial byte", which indicates -// the major type of the encoded value. -static constexpr uint8_t kMajorTypeMask = 0xe0; -// Indicates the integer is in the following byte. -static constexpr uint8_t kAdditionalInformation1Byte = 24u; -// Indicates the integer is in the next 2 bytes. -static constexpr uint8_t kAdditionalInformation2Bytes = 25u; -// Indicates the integer is in the next 4 bytes. -static constexpr uint8_t kAdditionalInformation4Bytes = 26u; -// Indicates the integer is in the next 8 bytes. -static constexpr uint8_t kAdditionalInformation8Bytes = 27u; - -// Encodes the initial byte, consisting of the |type| in the first 3 bits -// followed by 5 bits of |additional_info|. -constexpr uint8_t EncodeInitialByte(MajorType type, uint8_t additional_info) { - return (uint8_t(type) << kMajorTypeBitShift) | - (additional_info & kAdditionalInformationMask); -} // See RFC 7049 Section 2.3, Table 2. static constexpr uint8_t kEncodedTrue = @@ -53,38 +28,13 @@ static constexpr uint8_t kEncodedNull = EncodeInitialByte(MajorType::SIMPLE_VALUE, 22); static constexpr uint8_t kInitialByteForDouble = EncodeInitialByte(MajorType::SIMPLE_VALUE, 27); + } // namespace uint8_t EncodeTrue() { return kEncodedTrue; } uint8_t EncodeFalse() { return kEncodedFalse; } uint8_t EncodeNull() { return kEncodedNull; } -namespace { -// TAG 24 indicates that what follows is a byte string which is -// encoded in CBOR format. We use this as a wrapper for -// maps and arrays, allowing us to skip them, because the -// byte string carries its size (byte length). -// https://tools.ietf.org/html/rfc7049#section-2.4.4.1 -static constexpr uint8_t kInitialByteForEnvelope = - EncodeInitialByte(MajorType::TAG, 24); -// The initial byte for a byte string with at most 2^32 bytes -// of payload. This is used for envelope encoding, even if -// the byte string is shorter. -static constexpr uint8_t kInitialByteFor32BitLengthByteString = - EncodeInitialByte(MajorType::BYTE_STRING, 26); - -// See RFC 7049 Section 2.2.1, indefinite length arrays / maps have additional -// info = 31. -static constexpr uint8_t kInitialByteIndefiniteLengthArray = - EncodeInitialByte(MajorType::ARRAY, 31); -static constexpr uint8_t kInitialByteIndefiniteLengthMap = - EncodeInitialByte(MajorType::MAP, 31); -// See RFC 7049 Section 2.3, Table 1; this is used for finishing indefinite -// length maps / arrays. -static constexpr uint8_t kStopByte = - EncodeInitialByte(MajorType::SIMPLE_VALUE, 31); -} // namespace - uint8_t EncodeIndefiniteLengthArrayStart() { return kInitialByteIndefiniteLengthArray; } @@ -122,7 +72,7 @@ void WriteTokenStart(MajorType type, uint64_t value, if (value < 24) { // Values 0-23 are encoded directly into the additional info of the // initial byte. - encoded->push_back(EncodeInitialByte(type, /*additiona_info=*/value)); + encoded->push_back(EncodeInitialByte(type, /*additional_info=*/value)); return; } if (value <= std::numeric_limits::max()) { @@ -156,9 +106,9 @@ namespace { // See also: https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html template T ReadBytesMostSignificantByteFirst(span in) { - assert(size_t(in.size()) >= sizeof(T)); + assert(static_cast(in.size()) >= sizeof(T)); T result = 0; - for (size_t shift_bytes = 0; shift_bytes < sizeof(T); ++shift_bytes) + for (std::size_t shift_bytes = 0; shift_bytes < sizeof(T); ++shift_bytes) result |= T(in[sizeof(T) - 1 - shift_bytes]) << (shift_bytes * 8); return result; } @@ -185,19 +135,22 @@ int8_t ReadTokenStart(span bytes, MajorType* type, uint64_t* value) { } if (additional_information == kAdditionalInformation2Bytes) { // Values 256-65535: 1 initial byte + 2 bytes payload. - if (static_cast(bytes.size()) < 1 + sizeof(uint16_t)) return -1; + if (static_cast(bytes.size()) < 1 + sizeof(uint16_t)) + return -1; *value = ReadBytesMostSignificantByteFirst(bytes.subspan(1)); return 3; } if (additional_information == kAdditionalInformation4Bytes) { // 32 bit uint: 1 initial byte + 4 bytes payload. - if (static_cast(bytes.size()) < 1 + sizeof(uint32_t)) return -1; + if (static_cast(bytes.size()) < 1 + sizeof(uint32_t)) + return -1; *value = ReadBytesMostSignificantByteFirst(bytes.subspan(1)); return 5; } if (additional_information == kAdditionalInformation8Bytes) { // 64 bit uint: 1 initial byte + 8 bytes payload. - if (static_cast(bytes.size()) < 1 + sizeof(uint64_t)) return -1; + if (static_cast(bytes.size()) < 1 + sizeof(uint64_t)) + return -1; *value = ReadBytesMostSignificantByteFirst(bytes.subspan(1)); return 9; } @@ -205,7 +158,6 @@ int8_t ReadTokenStart(span bytes, MajorType* type, uint64_t* value) { } } // namespace cbor_internals -using cbor_internals::MajorType; using cbor_internals::WriteTokenStart; using cbor_internals::ReadTokenStart; @@ -669,7 +621,8 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) { SetError(Error::CBOR_INVALID_BINARY); return; } - SetToken(CBORTokenTag::BINARY, std::ptrdiff_t(token_byte_length)); + SetToken(CBORTokenTag::BINARY, + static_cast(token_byte_length)); return; } case kInitialByteForDouble: { // DOUBLE @@ -696,7 +649,7 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) { // Make sure the payload is contained within the message. if (token_start_internal_value_ + kEncodedEnvelopeHeaderSize + status_.pos > - size_t(bytes_.size())) { + static_cast(bytes_.size())) { SetError(Error::CBOR_INVALID_ENVELOPE); return; } @@ -731,8 +684,8 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) { SetToken(CBORTokenTag::INT32, token_start_length); return; case MajorType::STRING: { // STRING8. - if (!success || - remainder.size() < int64_t(token_start_internal_value_)) { + if (!success || remainder.size() < static_cast( + token_start_internal_value_)) { SetError(Error::CBOR_INVALID_STRING8); return; } @@ -742,7 +695,8 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) { } case MajorType::BYTE_STRING: { // STRING16. if (!success || - remainder.size() < int64_t(token_start_internal_value_) || + remainder.size() < + static_cast(token_start_internal_value_) || // Must be divisible by 2 since UTF16 is 2 bytes per character. token_start_internal_value_ & 1) { SetError(Error::CBOR_INVALID_STRING16); @@ -774,6 +728,75 @@ void CBORTokenizer::SetError(Error error) { status_.error = error; } +#if 0 +void DumpCBOR(span cbor) { + std::string indent; + CBORTokenizer tokenizer(cbor); + while (true) { + fprintf(stderr, "%s", indent.c_str()); + switch (tokenizer.TokenTag()) { + case CBORTokenTag::ERROR_VALUE: + fprintf(stderr, "ERROR {status.error=%d, status.pos=%ld}\n", + tokenizer.Status().error, tokenizer.Status().pos); + return; + case CBORTokenTag::DONE: + fprintf(stderr, "DONE\n"); + return; + case CBORTokenTag::TRUE_VALUE: + fprintf(stderr, "TRUE_VALUE\n"); + break; + case CBORTokenTag::FALSE_VALUE: + fprintf(stderr, "FALSE_VALUE\n"); + break; + case CBORTokenTag::NULL_VALUE: + fprintf(stderr, "NULL_VALUE\n"); + break; + case CBORTokenTag::INT32: + fprintf(stderr, "INT32 [%d]\n", tokenizer.GetInt32()); + break; + case CBORTokenTag::DOUBLE: + fprintf(stderr, "DOUBLE [%lf]\n", tokenizer.GetDouble()); + break; + case CBORTokenTag::STRING8: { + span v = tokenizer.GetString8(); + std::string t(v.begin(), v.end()); + fprintf(stderr, "STRING8 [%s]\n", t.c_str()); + break; + } + case CBORTokenTag::STRING16: { + span v = tokenizer.GetString16WireRep(); + std::string t(v.begin(), v.end()); + fprintf(stderr, "STRING16 [%s]\n", t.c_str()); + break; + } + case CBORTokenTag::BINARY: { + span v = tokenizer.GetBinary(); + std::string t(v.begin(), v.end()); + fprintf(stderr, "BINARY [%s]\n", t.c_str()); + break; + } + case CBORTokenTag::MAP_START: + fprintf(stderr, "MAP_START\n"); + indent += " "; + break; + case CBORTokenTag::ARRAY_START: + fprintf(stderr, "ARRAY_START\n"); + indent += " "; + break; + case CBORTokenTag::STOP: + fprintf(stderr, "STOP\n"); + indent.erase(0, 2); + break; + case CBORTokenTag::ENVELOPE: + fprintf(stderr, "ENVELOPE\n"); + tokenizer.EnterEnvelope(); + continue; + } + tokenizer.Next(); + } +} +#endif + {% for namespace in config.protocol.namespace %} } // namespace {{namespace}} diff --git a/third_party/inspector_protocol/lib/CBOR_h.template b/third_party/inspector_protocol/lib/CBOR_h.template index 551dfc1b20..dd637f19e7 100644 --- a/third_party/inspector_protocol/lib/CBOR_h.template +++ b/third_party/inspector_protocol/lib/CBOR_h.template @@ -135,7 +135,31 @@ class JSONParserHandler { // ===== encoding/cbor_internals.h ===== +namespace cbor { +enum class MajorType; +} + namespace cbor_internals { + +// Reads the start of a token with definitive size from |bytes|. +// |type| is the major type as specified in RFC 7049 Section 2.1. +// |value| is the payload (e.g. for MajorType::UNSIGNED) or is the size +// (e.g. for BYTE_STRING). +// If successful, returns the number of bytes read. Otherwise returns -1. +int8_t ReadTokenStart(span bytes, cbor::MajorType* type, + uint64_t* value); + +// Writes the start of a token with |type|. The |value| may indicate the size, +// or it may be the payload if the value is an unsigned integer. +void WriteTokenStart(cbor::MajorType type, uint64_t value, + std::vector* encoded); +} // namespace cbor_internals + +// ===== encoding/cbor.h ===== + + +namespace cbor { + // The major types from RFC 7049 Section 2.1. enum class MajorType { UNSIGNED = 0, @@ -148,20 +172,57 @@ enum class MajorType { SIMPLE_VALUE = 7 }; -// Reads the start of a token with definitive size from |bytes|. -// |type| is the major type as specified in RFC 7049 Section 2.1. -// |value| is the payload (e.g. for MajorType::UNSIGNED) or is the size -// (e.g. for BYTE_STRING). -// If successful, returns the number of bytes read. Otherwise returns -1. -int8_t ReadTokenStart(span bytes, MajorType* type, uint64_t* value); +// Indicates the number of bits the "initial byte" needs to be shifted to the +// right after applying |kMajorTypeMask| to produce the major type in the +// lowermost bits. +static constexpr uint8_t kMajorTypeBitShift = 5u; +// Mask selecting the low-order 5 bits of the "initial byte", which is where +// the additional information is encoded. +static constexpr uint8_t kAdditionalInformationMask = 0x1f; +// Mask selecting the high-order 3 bits of the "initial byte", which indicates +// the major type of the encoded value. +static constexpr uint8_t kMajorTypeMask = 0xe0; +// Indicates the integer is in the following byte. +static constexpr uint8_t kAdditionalInformation1Byte = 24u; +// Indicates the integer is in the next 2 bytes. +static constexpr uint8_t kAdditionalInformation2Bytes = 25u; +// Indicates the integer is in the next 4 bytes. +static constexpr uint8_t kAdditionalInformation4Bytes = 26u; +// Indicates the integer is in the next 8 bytes. +static constexpr uint8_t kAdditionalInformation8Bytes = 27u; -// Writes the start of a token with |type|. The |value| may indicate the size, -// or it may be the payload if the value is an unsigned integer. -void WriteTokenStart(MajorType type, uint64_t value, - std::vector* encoded); -} // namespace cbor_internals +// Encodes the initial byte, consisting of the |type| in the first 3 bits +// followed by 5 bits of |additional_info|. +constexpr uint8_t EncodeInitialByte(MajorType type, uint8_t additional_info) { + return (static_cast(type) << kMajorTypeBitShift) | + (additional_info & kAdditionalInformationMask); +} -// ===== encoding/cbor.h ===== +// TAG 24 indicates that what follows is a byte string which is +// encoded in CBOR format. We use this as a wrapper for +// maps and arrays, allowing us to skip them, because the +// byte string carries its size (byte length). +// https://tools.ietf.org/html/rfc7049#section-2.4.4.1 +static constexpr uint8_t kInitialByteForEnvelope = + EncodeInitialByte(MajorType::TAG, 24); +// The initial byte for a byte string with at most 2^32 bytes +// of payload. This is used for envelope encoding, even if +// the byte string is shorter. +static constexpr uint8_t kInitialByteFor32BitLengthByteString = + EncodeInitialByte(MajorType::BYTE_STRING, 26); + +// See RFC 7049 Section 2.2.1, indefinite length arrays / maps have additional +// info = 31. +static constexpr uint8_t kInitialByteIndefiniteLengthArray = + EncodeInitialByte(MajorType::ARRAY, 31); +static constexpr uint8_t kInitialByteIndefiniteLengthMap = + EncodeInitialByte(MajorType::MAP, 31); +// See RFC 7049 Section 2.3, Table 1; this is used for finishing indefinite +// length maps / arrays. +static constexpr uint8_t kStopByte = + EncodeInitialByte(MajorType::SIMPLE_VALUE, 31); + +} // namespace cbor // The binary encoding for the inspector protocol follows the CBOR specification // (RFC 7049). Additional constraints: @@ -231,7 +292,7 @@ class EnvelopeEncoder { bool EncodeStop(std::vector* out); private: - std::vector::size_type byte_size_pos_ = 0; + std::size_t byte_size_pos_ = 0; }; // This can be used to convert from JSON to CBOR, by passing the @@ -342,10 +403,13 @@ class CBORTokenizer { CBORTokenTag token_tag_; struct Status status_; std::ptrdiff_t token_byte_length_; - cbor_internals::MajorType token_start_type_; + cbor::MajorType token_start_type_; uint64_t token_start_internal_value_; }; +void DumpCBOR(span cbor); + + {% for namespace in config.protocol.namespace %} } // namespace {{namespace}} {% endfor %} diff --git a/third_party/inspector_protocol/lib/Values_cpp.template b/third_party/inspector_protocol/lib/Values_cpp.template index 6b4a785639..5e02612619 100644 --- a/third_party/inspector_protocol/lib/Values_cpp.template +++ b/third_party/inspector_protocol/lib/Values_cpp.template @@ -168,6 +168,7 @@ std::unique_ptr parseMap( String key; if (tokenizer->TokenTag() == CBORTokenTag::STRING8) { span key_span = tokenizer->GetString8(); + tokenizer->Next(); key = StringUtil::fromUTF8(key_span.data(), key_span.size()); } else if (tokenizer->TokenTag() == CBORTokenTag::STRING16) { return nullptr; // STRING16 not supported yet. @@ -178,6 +179,7 @@ std::unique_ptr parseMap( // Parse value. auto value = parseValue(stack_depth, tokenizer); if (!value) return nullptr; + dict->setValue(key, std::move(value)); } tokenizer->Next(); return dict; diff --git a/third_party/inspector_protocol/lib/Values_h.template b/third_party/inspector_protocol/lib/Values_h.template index 87ec0078dc..4a2e58f4cd 100644 --- a/third_party/inspector_protocol/lib/Values_h.template +++ b/third_party/inspector_protocol/lib/Values_h.template @@ -39,7 +39,8 @@ public: TypeBinary, TypeObject, TypeArray, - TypeSerialized + TypeSerialized, + TypeImported }; ValueType type() const { return m_type; } diff --git a/third_party/inspector_protocol/lib/base_string_adapter_cc.template b/third_party/inspector_protocol/lib/base_string_adapter_cc.template index 852822b62f..ed3316446f 100644 --- a/third_party/inspector_protocol/lib/base_string_adapter_cc.template +++ b/third_party/inspector_protocol/lib/base_string_adapter_cc.template @@ -12,6 +12,7 @@ #include "base/json/json_reader.h" #include "base/memory/ptr_util.h" #include "base/strings/string16.h" +#include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" @@ -229,6 +230,75 @@ Binary Binary::fromSpan(const uint8_t* data, size_t size) { new base::RefCountedBytes(data, size))); } +namespace { +int32_t ReadEnvelopeSize(const uint8_t* in) { + return (in[0] << 24) + (in[1] << 16) + (in[2] << 8) + in[3]; +} + +void WriteEnvelopeSize(uint32_t value, uint8_t* out) { + *(out++) = (value >> 24) & 0xFF; + *(out++) = (value >> 16) & 0xFF; + *(out++) = (value >> 8) & 0xFF; + *(out++) = (value) & 0xFF; +} + +} + +bool AppendStringValueToMapBinary(base::StringPiece in, + base::StringPiece key, base::StringPiece value, std::string* out) { + if (in.size() < 1 + 1 + 4 + 1 + 1) + return false; + const uint8_t* envelope = reinterpret_cast(in.data()); + if (cbor::kInitialByteForEnvelope != envelope[0]) + return false; + if (cbor::kInitialByteFor32BitLengthByteString != envelope[1]) + return false; + if (cbor::kInitialByteIndefiniteLengthMap != envelope[6]) + return false; + + uint32_t envelope_size = ReadEnvelopeSize(envelope + 2); + if (envelope_size + 2 + 4 != in.size()) + return false; + if (cbor::kStopByte != static_cast(*in.rbegin())) + return false; + + std::vector encoded_entry; + encoded_entry.reserve(1 + 4 + key.size() + 1 + 4 + value.size()); + span key_span( + reinterpret_cast(key.data()), key.size()); + EncodeString8(key_span, &encoded_entry); + span value_span( + reinterpret_cast(value.data()), value.size()); + EncodeString8(value_span, &encoded_entry); + + out->clear(); + out->reserve(in.size() + encoded_entry.size()); + out->append(in.begin(), in.end() - 1); + out->append(reinterpret_cast(encoded_entry.data()), + encoded_entry.size()); + out->append(1, static_cast(cbor::kStopByte)); + std::size_t new_size = envelope_size + out->size() - in.size(); + if (new_size > static_cast( + std::numeric_limits::max())) { + return false; + } + WriteEnvelopeSize(new_size, reinterpret_cast(&*out->begin() + 2)); + return true; +} + +bool AppendStringValueToMapJSON(base::StringPiece in, + base::StringPiece key, base::StringPiece value, std::string* out) { + if (!in.length() || *in.rbegin() != '}') + return false; + std::string suffix = + base::StringPrintf(", \"%s\": \"%s\"}", key.begin(), value.begin()); + out->clear(); + out->reserve(in.length() + suffix.length() - 1); + out->append(in.data(), in.length() - 1); + out->append(suffix); + return true; +} + {% for namespace in config.protocol.namespace %} } // namespace {{namespace}} {% endfor %} diff --git a/third_party/inspector_protocol/lib/base_string_adapter_h.template b/third_party/inspector_protocol/lib/base_string_adapter_h.template index 76c05f6524..2383777834 100644 --- a/third_party/inspector_protocol/lib/base_string_adapter_h.template +++ b/third_party/inspector_protocol/lib/base_string_adapter_h.template @@ -134,6 +134,11 @@ class {{config.lib.export_macro}} Binary { std::unique_ptr toProtocolValue(const base::Value* value, int depth); std::unique_ptr toBaseValue(Value* value, int depth); +bool AppendStringValueToMapBinary(base::StringPiece in, + base::StringPiece key, base::StringPiece value, std::string* out); +bool AppendStringValueToMapJSON(base::StringPiece in, + base::StringPiece key, base::StringPiece value, std::string* out); + {% for namespace in config.protocol.namespace %} } // namespace {{namespace}} {% endfor %} diff --git a/third_party/inspector_protocol/templates/Exported_h.template b/third_party/inspector_protocol/templates/Exported_h.template index 4ea9167345..765f6c2135 100644 --- a/third_party/inspector_protocol/templates/Exported_h.template +++ b/third_party/inspector_protocol/templates/Exported_h.template @@ -15,6 +15,17 @@ {% for namespace in config.protocol.namespace %} namespace {{namespace}} { {% endfor %} + +#ifndef {{"_".join(config.protocol.namespace)}}_exported_api_h +#define {{"_".join(config.protocol.namespace)}}_exported_api_h +class {{config.exported.export_macro}} Exported { +public: + virtual {{config.exported.string_out}} toJSONString() const = 0; + virtual void writeBinary(std::vector* out) const = 0; + virtual ~Exported() { } +}; +#endif // !defined({{"_".join(config.protocol.namespace)}}_exported_api_h) + namespace {{domain.domain}} { namespace API { @@ -48,11 +59,8 @@ namespace {{param.name | to_title_case}}Enum { {% for type in domain.types %} {% if not (type.type == "object") or not ("properties" in type) or not protocol.is_exported(domain.domain, type.id) %}{% continue %}{% endif %} -class {{config.exported.export_macro}} {{type.id}} { +class {{config.exported.export_macro}} {{type.id}} : public Exported { public: - virtual {{config.exported.string_out}} toJSONString() const = 0; - virtual std::vector toBinary() const = 0; - virtual ~{{type.id}}() { } static std::unique_ptr fromJSONString(const {{config.exported.string_in}}& json); static std::unique_ptr fromBinary(const uint8_t* data, size_t length); }; diff --git a/third_party/inspector_protocol/templates/Imported_h.template b/third_party/inspector_protocol/templates/Imported_h.template index 1102dea94f..f2e576a9c4 100644 --- a/third_party/inspector_protocol/templates/Imported_h.template +++ b/third_party/inspector_protocol/templates/Imported_h.template @@ -17,6 +17,37 @@ {% for namespace in config.protocol.namespace %} namespace {{namespace}} { {% endfor %} + +using Exported = {{"::".join(config.imported.namespace)}}::Exported; + +#ifndef {{"_".join(config.protocol.namespace)}}_imported_imported_h +#define {{"_".join(config.protocol.namespace)}}_imported_imported_h + +class {{config.lib.export_macro}} ImportedValue : public Value { +public: + static std::unique_ptr fromExported(const Exported* value) { + return std::unique_ptr(new ImportedValue(value)); + } + + void writeJSON(StringBuilder* output) const override { + auto json = m_exported->toJSONString(); + String local_json = ({{config.imported.from_imported_string % "std::move(json)"}}); + StringUtil::builderAppend(*output, local_json); + } + void writeBinary(std::vector* output) const override { + m_exported->writeBinary(output); + } + std::unique_ptr clone() const override { + return std::unique_ptr(new ImportedValue(m_exported)); + } + +private: + explicit ImportedValue(const Exported* exported) : Value(TypeImported), m_exported(exported) { } + const Exported* m_exported; +}; + +#endif // !defined({{"_".join(config.protocol.namespace)}}_imported_imported_h) + {% for type in domain.types %} {% if not (type.type == "object") or not ("properties" in type) or not protocol.is_imported(domain.domain, type.id) %}{% continue %}{% endif %} @@ -29,32 +60,17 @@ struct ValueConversions<{{"::".join(config.imported.namespace)}}::{{domain.domai return nullptr; } - // 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 binary = value->serializeToBinary(); - result = {{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}::fromBinary(binary.data(), binary.size()); - } else { - String json = value->serializeToJSON(); - result = {{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}::fromJSONString({{config.imported.to_imported_string % "json"}}); - } + std::vector binary; + value->writeBinary(&binary); + auto result = {{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}::fromBinary(binary.data(), binary.size()); if (!result) errors->addError("cannot parse"); return result; } - static std::unique_ptr toValue(const {{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}* value) + static std::unique_ptr toValue(const {{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}* exported) { - // TODO(pfeldman): toggle to true and delete the json branch when binary is ready. - 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); - } + return ImportedValue::fromExported(exported); } static std::unique_ptr toValue(const std::unique_ptr<{{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}>& value) @@ -62,6 +78,7 @@ struct ValueConversions<{{"::".join(config.imported.namespace)}}::{{domain.domai return toValue(value.get()); } }; + {% endfor %} {% for namespace in config.protocol.namespace %} diff --git a/third_party/inspector_protocol/templates/TypeBuilder_cpp.template b/third_party/inspector_protocol/templates/TypeBuilder_cpp.template index 07e45a32a8..4ef60a6ea2 100644 --- a/third_party/inspector_protocol/templates/TypeBuilder_cpp.template +++ b/third_party/inspector_protocol/templates/TypeBuilder_cpp.template @@ -105,9 +105,9 @@ std::unique_ptr<{{type.id}}> {{type.id}}::clone() const return {{config.exported.to_string_out % "json"}}; } -std::vector {{type.id}}::toBinary() const +void {{type.id}}::writeBinary(std::vector* out) const { - return toValue()->serializeToBinary(); + toValue()->writeBinary(out); } // static diff --git a/third_party/inspector_protocol/templates/TypeBuilder_h.template b/third_party/inspector_protocol/templates/TypeBuilder_h.template index c5e95d7777..c670d65c46 100644 --- a/third_party/inspector_protocol/templates/TypeBuilder_h.template +++ b/third_party/inspector_protocol/templates/TypeBuilder_h.template @@ -106,7 +106,7 @@ public: std::unique_ptr<{{type.id}}> clone() const; {% if protocol.is_exported(domain.domain, type.id) %} {{config.exported.string_out}} toJSONString() const override; - std::vector toBinary() const override; + void writeBinary(std::vector* out) const override; {% endif %} template