Roll third_party/inspector_protocol to 8cb7a4f50ff7d5b1b7f2e5df0542dc577c88bdc3

This roll includes:
- [inspector_protocol] fixed compatibility with latest jinja 2.9.6
- [inspector_protocol] removed unused variable
- Follow up on alph's review comments.
- Provide default escape implementation for latin and wide strings.
- Allow escaping utf8 strings in embedders that operate std::string.
- Upload inspector_protocol changes to Gerrit by default
- [inspector_protocol] Fix building with non-ASCII paths
- [inspector_protocol] added StringUtil::toDouble method as requirement
- Add const char* overloads to ErrorSupport

BUG=chromium:743313
R=dgozman@chromium.org

Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel
Change-Id: Ic81a62c638bf592ae65c84055d53d926e50715ac
Reviewed-on: https://chromium-review.googlesource.com/713538
Reviewed-by: Dmitry Gozman <dgozman@chromium.org>
Commit-Queue: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48477}
This commit is contained in:
Alexey Kozyatinskiy 2017-10-11 14:57:46 -07:00 committed by Commit Bot
parent a445b97cfd
commit 744b49ef0d
12 changed files with 102 additions and 34 deletions

View File

@ -121,6 +121,18 @@ std::unique_ptr<protocol::Value> StringUtil::parseJSON(const String16& string) {
static_cast<int>(string.length()));
}
// static
void StringUtil::builderAppendQuotedString(StringBuilder& builder,
const String& str) {
builder.append('"');
if (!str.isEmpty()) {
escapeWideStringForJSON(
reinterpret_cast<const uint16_t*>(str.characters16()),
static_cast<int>(str.length()), &builder);
}
builder.append('"');
}
} // namespace protocol
// static

View File

@ -49,6 +49,7 @@ class StringUtil {
static void builderAppend(StringBuilder& builder, const char* s, size_t len) {
builder.append(s, len);
}
static void builderAppendQuotedString(StringBuilder&, const String&);
static void builderReserve(StringBuilder& builder, size_t capacity) {
builder.reserveCapacity(capacity);
}

View File

@ -59,12 +59,15 @@ def read_config():
jinja_dir = arg_options.jinja_dir
if not jinja_dir:
raise Exception("jinja directory must be specified")
jinja_dir = jinja_dir.decode('utf8')
output_base = arg_options.output_base
if not output_base:
raise Exception("Base output directory must be specified")
output_base = output_base.decode('utf8')
config_file = arg_options.config
if not config_file:
raise Exception("Config file name must be specified")
config_file = config_file.decode('utf8')
config_base = os.path.dirname(config_file)
config_values = arg_options.config_value
if not config_values:
@ -440,6 +443,12 @@ class Protocol(object):
return self.check_options(self.config.protocol.options, domain, event, "include_events", "exclude_events", True)
def generate_type(self, domain, typename):
if not self.config.protocol.options:
return domain in self.generate_domains
return self.check_options(self.config.protocol.options, domain, typename, "include_types", "exclude_types", True)
def is_async_command(self, domain, command):
if not self.config.protocol.options:
return False
@ -473,6 +482,10 @@ class Protocol(object):
return True
def is_imported_dependency(self, domain):
return domain in self.generate_domains or domain in self.imported_domains
def main():
jinja_dir, config_file, config = read_config()

View File

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

View File

@ -248,7 +248,13 @@ void UberDispatcher::registerBackend(const String& name, std::unique_ptr<protoco
m_dispatchers[name] = std::move(dispatcher);
}
DispatchResponse::Status UberDispatcher::dispatch(std::unique_ptr<Value> parsedMessage)
void UberDispatcher::setupRedirects(const HashMap<String, String>& redirects)
{
for (const auto& pair : redirects)
m_redirects[pair.first] = pair.second;
}
DispatchResponse::Status UberDispatcher::dispatch(std::unique_ptr<Value> parsedMessage, int* outCallId, String* outMethod)
{
if (!parsedMessage) {
reportProtocolErrorTo(m_frontendChannel, DispatchResponse::kParseError, "Message must be a valid JSON");
@ -263,6 +269,8 @@ DispatchResponse::Status UberDispatcher::dispatch(std::unique_ptr<Value> parsedM
int callId = 0;
protocol::Value* callIdValue = messageObject->get("id");
bool success = callIdValue && callIdValue->asInteger(&callId);
if (outCallId)
*outCallId = callId;
if (!success) {
reportProtocolErrorTo(m_frontendChannel, DispatchResponse::kInvalidRequest, "Message must have integer 'id' porperty");
return DispatchResponse::kError;
@ -271,11 +279,17 @@ DispatchResponse::Status UberDispatcher::dispatch(std::unique_ptr<Value> parsedM
protocol::Value* methodValue = messageObject->get("method");
String method;
success = methodValue && methodValue->asString(&method);
if (outMethod)
*outMethod = method;
if (!success) {
reportProtocolErrorTo(m_frontendChannel, callId, DispatchResponse::kInvalidRequest, "Message must have string 'method' porperty", nullptr);
return DispatchResponse::kError;
}
HashMap<String, String>::iterator redirectIt = m_redirects.find(method);
if (redirectIt != m_redirects.end())
method = redirectIt->second;
size_t dotIndex = StringUtil::find(method, ".");
if (dotIndex == StringUtil::kNotFound) {
if (m_fallThroughForNotFound)

View File

@ -113,7 +113,8 @@ class {{config.lib.export_macro}} UberDispatcher {
public:
explicit UberDispatcher(FrontendChannel*);
void registerBackend(const String& name, std::unique_ptr<protocol::DispatcherBase>);
DispatchResponse::Status dispatch(std::unique_ptr<Value> message);
void setupRedirects(const HashMap<String, String>&);
DispatchResponse::Status dispatch(std::unique_ptr<Value> message, int* callId = nullptr, String* method = nullptr);
FrontendChannel* channel() { return m_frontendChannel; }
bool fallThroughForNotFound() { return m_fallThroughForNotFound; }
void setFallThroughForNotFound(bool);
@ -122,6 +123,7 @@ public:
private:
FrontendChannel* m_frontendChannel;
bool m_fallThroughForNotFound;
HashMap<String, String> m_redirects;
protocol::HashMap<String, std::unique_ptr<protocol::DispatcherBase>> m_dispatchers;
};

View File

@ -11,6 +11,11 @@ namespace {{namespace}} {
ErrorSupport::ErrorSupport() { }
ErrorSupport::~ErrorSupport() { }
void ErrorSupport::setName(const char* name)
{
setName(String(name));
}
void ErrorSupport::setName(const String& name)
{
DCHECK(m_path.size());
@ -27,6 +32,11 @@ void ErrorSupport::pop()
m_path.pop_back();
}
void ErrorSupport::addError(const char* error)
{
addError(String(error));
}
void ErrorSupport::addError(const String& error)
{
StringBuilder builder;

View File

@ -17,8 +17,10 @@ public:
~ErrorSupport();
void push();
void setName(const char*);
void setName(const String&);
void pop();
void addError(const char*);
void addError(const String&);
bool hasErrors();
String errors();

View File

@ -42,30 +42,22 @@ void appendUnsignedAsHex(uint16_t number, StringBuilder* dst)
}
}
void escapeStringForJSON(const String& str, StringBuilder* dst)
template <typename Char>
void escapeStringForJSONInternal(const Char* str, unsigned len,
StringBuilder* dst)
{
for (unsigned i = 0; i < str.length(); ++i) {
uint16_t c = str[i];
if (!escapeChar(c, dst)) {
if (c < 32 || c > 126 || c == '<' || c == '>') {
// 1. Escaping <, > to prevent script execution.
// 2. Technically, we could also pass through c > 126 as UTF8, but this
// is also optional. It would also be a pain to implement here.
appendUnsignedAsHex(c, dst);
} else {
StringUtil::builderAppend(*dst, c);
}
for (unsigned i = 0; i < len; ++i) {
Char c = str[i];
if (escapeChar(c, dst))
continue;
if (c < 32 || c > 126) {
appendUnsignedAsHex(c, dst);
} else {
StringUtil::builderAppend(*dst, c);
}
}
}
void doubleQuoteStringForJSON(const String& str, StringBuilder* dst)
{
StringUtil::builderAppend(*dst, '"');
escapeStringForJSON(str, dst);
StringUtil::builderAppend(*dst, '"');
}
} // anonymous namespace
bool Value::asBoolean(bool*) const
@ -181,7 +173,7 @@ bool StringValue::asString(String* output) const
void StringValue::writeJSON(StringBuilder* output) const
{
DCHECK(type() == TypeString);
doubleQuoteStringForJSON(m_stringValue, output);
StringUtil::builderAppendQuotedString(*output, m_stringValue);
}
std::unique_ptr<Value> StringValue::clone() const
@ -336,7 +328,7 @@ void DictionaryValue::writeJSON(StringBuilder* output) const
CHECK(it != m_data.end());
if (i)
StringUtil::builderAppend(*output, ',');
doubleQuoteStringForJSON(it->first, output);
StringUtil::builderAppendQuotedString(*output, it->first);
StringUtil::builderAppend(*output, ':');
it->second->writeJSON(output);
}
@ -402,6 +394,16 @@ protocol::Value* ListValue::at(size_t index)
return m_data[index].get();
}
void escapeLatinStringForJSON(const uint8_t* str, unsigned len, StringBuilder* dst)
{
escapeStringForJSONInternal<uint8_t>(str, len, dst);
}
void escapeWideStringForJSON(const uint16_t* str, unsigned len, StringBuilder* dst)
{
escapeStringForJSONInternal<uint16_t>(str, len, dst);
}
{% for namespace in config.protocol.namespace %}
} // namespace {{namespace}}
{% endfor %}

View File

@ -239,6 +239,9 @@ private:
std::vector<std::unique_ptr<Value>> m_data;
};
void escapeLatinStringForJSON(const uint8_t* str, unsigned len, StringBuilder* dst);
void escapeWideStringForJSON(const uint16_t* str, unsigned len, StringBuilder* dst);
{% for namespace in config.protocol.namespace %}
} // namespace {{namespace}}
{% endfor %}

View File

@ -19,6 +19,7 @@ const char Metainfo::domainName[] = "{{domain.domain}}";
const char Metainfo::commandPrefix[] = "{{domain.domain}}.";
const char Metainfo::version[] = "{{domain.version}}";
{% for type in domain.types %}
{% if not protocol.generate_type(domain.domain, type.id) %}{% continue %} {% endif %}
{% if "enum" in type %}
namespace {{type.id}}Enum {
@ -200,18 +201,23 @@ public:
, m_backend(backend)
, m_fallThroughForNotFound(fallThroughForNotFound) {
{% for command in domain.commands %}
{% if "redirect" in command %}{% continue %}{% endif %}
{% if "redirect" in command %}
m_redirects["{{domain.domain}}.{{command.name}}"] = "{{command.redirect}}.{{command.name}}";
{% continue %}
{% endif %}
{% if not protocol.generate_command(domain.domain, command.name) %}{% continue %}{% endif %}
m_dispatchMap["{{domain.domain}}.{{command.name}}"] = &DispatcherImpl::{{command.name}};
{% endfor %}
}
~DispatcherImpl() override { }
DispatchResponse::Status dispatch(int callId, const String& method, std::unique_ptr<protocol::DictionaryValue> messageObject) override;
HashMap<String, String>& redirects() { return m_redirects; }
protected:
using CallHandler = DispatchResponse::Status (DispatcherImpl::*)(int callId, std::unique_ptr<DictionaryValue> messageObject, ErrorSupport* errors);
using DispatchMap = protocol::HashMap<String, CallHandler>;
DispatchMap m_dispatchMap;
HashMap<String, String> m_redirects;
{% for command in domain.commands %}
{% if "redirect" in command %}{% continue %}{% endif %}
@ -337,9 +343,9 @@ DispatchResponse::Status DispatcherImpl::{{command.name}}(int callId, std::uniqu
&out_{{parameter.name}}
{%- endfor %}
{% endif %});
{% if "returns" in command %}
if (response.status() == DispatchResponse::kFallThrough)
return response.status();
{% if "returns" in command %}
std::unique_ptr<protocol::DictionaryValue> result = DictionaryValue::create();
if (response.status() == DispatchResponse::kSuccess) {
{% for parameter in command.returns %}
@ -378,9 +384,11 @@ DispatchResponse::Status DispatcherImpl::{{command.name}}(int callId, std::uniqu
{% endfor %}
// static
void Dispatcher::wire(UberDispatcher* dispatcher, Backend* backend)
void Dispatcher::wire(UberDispatcher* uber, Backend* backend)
{
dispatcher->registerBackend("{{domain.domain}}", std::unique_ptr<protocol::DispatcherBase>(new DispatcherImpl(dispatcher->channel(), backend, dispatcher->fallThroughForNotFound())));
std::unique_ptr<DispatcherImpl> dispatcher(new DispatcherImpl(uber->channel(), backend, uber->fallThroughForNotFound()));
uber->setupRedirects(dispatcher->redirects());
uber->registerBackend("{{domain.domain}}", std::move(dispatcher));
}
} // {{domain.domain}}

View File

@ -14,7 +14,9 @@
// For each imported domain we generate a ValueConversions struct instead of a full domain definition
// and include Domain::API version from there.
{% for name in domain.dependencies %}
{% if protocol.is_imported_dependency(name) %}
#include {{format_include(config.protocol.package, name)}}
{% endif %}
{% endfor %}
{% if protocol.is_exported_domain(domain.domain) %}
#include {{format_include(config.exported.package, domain.domain)}}
@ -27,6 +29,7 @@ namespace {{domain.domain}} {
// ------------- Forward and enum declarations.
{% for type in domain.types %}
{% if not protocol.generate_type(domain.domain, type.id) %}{% continue %}{% endif %}
{% if type.type == "object" %}
{% if "properties" in type %}
// {{type.description}}
@ -41,6 +44,7 @@ using {{type.id}} = {{protocol.resolve_type(type).type}};
{% endif %}
{% endfor %}
{% for type in domain.types %}
{% if not protocol.generate_type(domain.domain, type.id) %}{% continue %}{% endif %}
{% if "enum" in type %}
namespace {{type.id}}Enum {
@ -67,6 +71,7 @@ namespace {{param.name | to_title_case}}Enum {
// ------------- Type and builder declarations.
{% for type in domain.types %}
{% if not protocol.generate_type(domain.domain, type.id) %}{% continue %}{% endif %}
{% if not (type.type == "object") or not ("properties" in type) %}{% continue %}{% endif %}
// {{type.description}}
@ -110,12 +115,8 @@ public:
public:
enum {
NoFieldsSet = 0,
{% set count = 0 %}
{% for property in type.properties %}
{% if not(property.optional) %}
{% set count = count + 1 %}
{{property.name | to_title_case}}Set = 1 << {{count}},
{% endif %}
{% for property in type.properties|rejectattr("optional") %}
{{property.name | to_title_case}}Set = 1 << {{loop.index}},
{% endfor %}
AllFieldsSet = (
{%- for property in type.properties %}