Roll third_party/inspector_protocol to 817313aa48ebb9a53cba1bd88bbe6a1c5048060c

This includes conversion of python scripts to python3.

Change-Id: I5c05b3ab2aa00711a0dc26f1885a73f0ef4dbd85
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3530115
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Andrey Kosyakov <caseq@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80702}
This commit is contained in:
Andrey Kosyakov 2022-03-16 11:52:53 -07:00 committed by V8 LUCI CQ
parent 37569a5a99
commit bb18bc24b0
17 changed files with 650 additions and 669 deletions

View File

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

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# Copyright (c) 2011 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@ -54,435 +54,587 @@ import sys
import pdl
try:
import json
import json
except ImportError:
import simplejson as json
import simplejson as json
def list_to_map(items, key):
result = {}
for item in items:
if "experimental" not in item and "hidden" not in item:
result[item[key]] = item
return result
result = {}
for item in items:
if "experimental" not in item and "hidden" not in item:
result[item[key]] = item
return result
def named_list_to_map(container, name, key):
if name in container:
return list_to_map(container[name], key)
return {}
if name in container:
return list_to_map(container[name], key)
return {}
def removed(reverse):
if reverse:
return "added"
return "removed"
if reverse:
return "added"
return "removed"
def required(reverse):
if reverse:
return "optional"
return "required"
if reverse:
return "optional"
return "required"
def compare_schemas(d_1, d_2, reverse):
errors = []
domains_1 = copy.deepcopy(d_1)
domains_2 = copy.deepcopy(d_2)
types_1 = normalize_types_in_schema(domains_1)
types_2 = normalize_types_in_schema(domains_2)
errors = []
domains_1 = copy.deepcopy(d_1)
domains_2 = copy.deepcopy(d_2)
types_1 = normalize_types_in_schema(domains_1)
types_2 = normalize_types_in_schema(domains_2)
domains_by_name_1 = list_to_map(domains_1, "domain")
domains_by_name_2 = list_to_map(domains_2, "domain")
domains_by_name_1 = list_to_map(domains_1, "domain")
domains_by_name_2 = list_to_map(domains_2, "domain")
for name in domains_by_name_1:
domain_1 = domains_by_name_1[name]
if name not in domains_by_name_2:
errors.append("%s: domain has been %s" % (name, removed(reverse)))
continue
compare_domains(domain_1, domains_by_name_2[name], types_1, types_2, errors, reverse)
return errors
for name in domains_by_name_1:
domain_1 = domains_by_name_1[name]
if name not in domains_by_name_2:
errors.append("%s: domain has been %s" % (name, removed(reverse)))
continue
compare_domains(domain_1, domains_by_name_2[name], types_1, types_2, errors,
reverse)
return errors
def compare_domains(domain_1, domain_2, types_map_1, types_map_2, errors, reverse):
domain_name = domain_1["domain"]
commands_1 = named_list_to_map(domain_1, "commands", "name")
commands_2 = named_list_to_map(domain_2, "commands", "name")
for name in commands_1:
command_1 = commands_1[name]
if name not in commands_2:
errors.append("%s.%s: command has been %s" % (domain_1["domain"], name, removed(reverse)))
continue
compare_commands(domain_name, command_1, commands_2[name], types_map_1, types_map_2, errors, reverse)
domain_name = domain_1["domain"]
commands_1 = named_list_to_map(domain_1, "commands", "name")
commands_2 = named_list_to_map(domain_2, "commands", "name")
for name in commands_1:
command_1 = commands_1[name]
if name not in commands_2:
errors.append("%s.%s: command has been %s" %
(domain_1["domain"], name, removed(reverse)))
continue
compare_commands(domain_name, command_1, commands_2[name], types_map_1,
types_map_2, errors, reverse)
events_1 = named_list_to_map(domain_1, "events", "name")
events_2 = named_list_to_map(domain_2, "events", "name")
for name in events_1:
event_1 = events_1[name]
if name not in events_2:
errors.append("%s.%s: event has been %s" % (domain_1["domain"], name, removed(reverse)))
continue
compare_events(domain_name, event_1, events_2[name], types_map_1, types_map_2, errors, reverse)
events_1 = named_list_to_map(domain_1, "events", "name")
events_2 = named_list_to_map(domain_2, "events", "name")
for name in events_1:
event_1 = events_1[name]
if name not in events_2:
errors.append("%s.%s: event has been %s" %
(domain_1["domain"], name, removed(reverse)))
continue
compare_events(domain_name, event_1, events_2[name], types_map_1,
types_map_2, errors, reverse)
def compare_commands(domain_name, command_1, command_2, types_map_1, types_map_2, errors, reverse):
context = domain_name + "." + command_1["name"]
context = domain_name + "." + command_1["name"]
params_1 = named_list_to_map(command_1, "parameters", "name")
params_2 = named_list_to_map(command_2, "parameters", "name")
# Note the reversed order: we allow removing but forbid adding parameters.
compare_params_list(context, "parameter", params_2, params_1, types_map_2, types_map_1, 0, errors, not reverse)
params_1 = named_list_to_map(command_1, "parameters", "name")
params_2 = named_list_to_map(command_2, "parameters", "name")
# Note the reversed order: we allow removing but forbid adding parameters.
compare_params_list(context, "parameter", params_2, params_1, types_map_2,
types_map_1, 0, errors, not reverse)
returns_1 = named_list_to_map(command_1, "returns", "name")
returns_2 = named_list_to_map(command_2, "returns", "name")
compare_params_list(context, "response parameter", returns_1, returns_2, types_map_1, types_map_2, 0, errors, reverse)
returns_1 = named_list_to_map(command_1, "returns", "name")
returns_2 = named_list_to_map(command_2, "returns", "name")
compare_params_list(context, "response parameter", returns_1, returns_2,
types_map_1, types_map_2, 0, errors, reverse)
def compare_events(domain_name, event_1, event_2, types_map_1, types_map_2, errors, reverse):
context = domain_name + "." + event_1["name"]
params_1 = named_list_to_map(event_1, "parameters", "name")
params_2 = named_list_to_map(event_2, "parameters", "name")
compare_params_list(context, "parameter", params_1, params_2, types_map_1, types_map_2, 0, errors, reverse)
context = domain_name + "." + event_1["name"]
params_1 = named_list_to_map(event_1, "parameters", "name")
params_2 = named_list_to_map(event_2, "parameters", "name")
compare_params_list(context, "parameter", params_1, params_2, types_map_1,
types_map_2, 0, errors, reverse)
def compare_params_list(context, kind, params_1, params_2, types_map_1, types_map_2, depth, errors, reverse):
for name in params_1:
param_1 = params_1[name]
if name not in params_2:
if "optional" not in param_1:
errors.append("%s.%s: required %s has been %s" % (context, name, kind, removed(reverse)))
continue
for name in params_1:
param_1 = params_1[name]
if name not in params_2:
if "optional" not in param_1:
errors.append("%s.%s: required %s has been %s" %
(context, name, kind, removed(reverse)))
continue
param_2 = params_2[name]
if param_2 and "optional" in param_2 and "optional" not in param_1:
errors.append("%s.%s: %s %s is now %s" % (context, name, required(reverse), kind, required(not reverse)))
continue
type_1 = extract_type(param_1, types_map_1, errors)
type_2 = extract_type(param_2, types_map_2, errors)
compare_types(context + "." + name, kind, type_1, type_2, types_map_1, types_map_2, depth, errors, reverse)
param_2 = params_2[name]
if param_2 and "optional" in param_2 and "optional" not in param_1:
errors.append(
"%s.%s: %s %s is now %s" %
(context, name, required(reverse), kind, required(not reverse)))
continue
type_1 = extract_type(param_1, types_map_1, errors)
type_2 = extract_type(param_2, types_map_2, errors)
compare_types(context + "." + name, kind, type_1, type_2, types_map_1,
types_map_2, depth, errors, reverse)
def compare_types(context, kind, type_1, type_2, types_map_1, types_map_2, depth, errors, reverse):
if depth > 5:
return
if depth > 5:
return
base_type_1 = type_1["type"]
base_type_2 = type_2["type"]
base_type_1 = type_1["type"]
base_type_2 = type_2["type"]
# Binary and string have the same wire representation in JSON.
if ((base_type_1 == "string" and base_type_2 == "binary") or
(base_type_2 == "string" and base_type_1 == "binary")):
return
# Binary and string have the same wire representation in JSON.
if ((base_type_1 == "string" and base_type_2 == "binary") or
(base_type_2 == "string" and base_type_1 == "binary")):
return
if base_type_1 != base_type_2:
errors.append("%s: %s base type mismatch, '%s' vs '%s'" % (context, kind, base_type_1, base_type_2))
elif base_type_1 == "object":
params_1 = named_list_to_map(type_1, "properties", "name")
params_2 = named_list_to_map(type_2, "properties", "name")
# If both parameters have the same named type use it in the context.
if "id" in type_1 and "id" in type_2 and type_1["id"] == type_2["id"]:
type_name = type_1["id"]
else:
type_name = "<object>"
context += " %s->%s" % (kind, type_name)
compare_params_list(context, "property", params_1, params_2, types_map_1, types_map_2, depth + 1, errors, reverse)
elif base_type_1 == "array":
item_type_1 = extract_type(type_1["items"], types_map_1, errors)
item_type_2 = extract_type(type_2["items"], types_map_2, errors)
compare_types(context, kind, item_type_1, item_type_2, types_map_1, types_map_2, depth + 1, errors, reverse)
if base_type_1 != base_type_2:
errors.append("%s: %s base type mismatch, '%s' vs '%s'" %
(context, kind, base_type_1, base_type_2))
elif base_type_1 == "object":
params_1 = named_list_to_map(type_1, "properties", "name")
params_2 = named_list_to_map(type_2, "properties", "name")
# If both parameters have the same named type use it in the context.
if "id" in type_1 and "id" in type_2 and type_1["id"] == type_2["id"]:
type_name = type_1["id"]
else:
type_name = "<object>"
context += " %s->%s" % (kind, type_name)
compare_params_list(context, "property", params_1, params_2, types_map_1,
types_map_2, depth + 1, errors, reverse)
elif base_type_1 == "array":
item_type_1 = extract_type(type_1["items"], types_map_1, errors)
item_type_2 = extract_type(type_2["items"], types_map_2, errors)
compare_types(context, kind, item_type_1, item_type_2, types_map_1,
types_map_2, depth + 1, errors, reverse)
def extract_type(typed_object, types_map, errors):
if "type" in typed_object:
result = {"id": "<transient>", "type": typed_object["type"]}
if typed_object["type"] == "object":
result["properties"] = []
elif typed_object["type"] == "array":
result["items"] = typed_object["items"]
return result
elif "$ref" in typed_object:
ref = typed_object["$ref"]
if ref not in types_map:
errors.append("Can not resolve type: %s" % ref)
types_map[ref] = {"id": "<transient>", "type": "object"}
return types_map[ref]
if "type" in typed_object:
result = {"id": "<transient>", "type": typed_object["type"]}
if typed_object["type"] == "object":
result["properties"] = []
elif typed_object["type"] == "array":
result["items"] = typed_object["items"]
return result
elif "$ref" in typed_object:
ref = typed_object["$ref"]
if ref not in types_map:
errors.append("Can not resolve type: %s" % ref)
types_map[ref] = {"id": "<transient>", "type": "object"}
return types_map[ref]
def normalize_types_in_schema(domains):
types = {}
for domain in domains:
domain_name = domain["domain"]
normalize_types(domain, domain_name, types)
return types
types = {}
for domain in domains:
domain_name = domain["domain"]
normalize_types(domain, domain_name, types)
return types
def normalize_types(obj, domain_name, types):
if isinstance(obj, list):
for item in obj:
normalize_types(item, domain_name, types)
elif isinstance(obj, dict):
for key, value in obj.items():
if key == "$ref" and value.find(".") == -1:
obj[key] = "%s.%s" % (domain_name, value)
elif key == "id":
obj[key] = "%s.%s" % (domain_name, value)
types[obj[key]] = obj
else:
normalize_types(value, domain_name, types)
if isinstance(obj, list):
for item in obj:
normalize_types(item, domain_name, types)
elif isinstance(obj, dict):
for key, value in obj.items():
if key == "$ref" and value.find(".") == -1:
obj[key] = "%s.%s" % (domain_name, value)
elif key == "id":
obj[key] = "%s.%s" % (domain_name, value)
types[obj[key]] = obj
else:
normalize_types(value, domain_name, types)
def load_schema(file_name, domains):
# pylint: disable=W0613
if not os.path.isfile(file_name):
return
input_file = open(file_name, "r")
parsed_json = pdl.loads(input_file.read(), file_name)
input_file.close()
domains += parsed_json["domains"]
return parsed_json["version"]
# pylint: disable=W0613
if not os.path.isfile(file_name):
return
input_file = open(file_name, "r")
parsed_json = pdl.loads(input_file.read(), file_name)
input_file.close()
domains += parsed_json["domains"]
return parsed_json["version"]
def self_test():
def create_test_schema_1():
return [
{
"domain": "Network",
"types": [
{
"id": "LoaderId",
"type": "string"
},
{
"id": "Headers",
"type": "object"
},
{
"id": "Request",
"type": "object",
"properties": [
{"name": "url", "type": "string"},
{"name": "method", "type": "string"},
{"name": "headers", "$ref": "Headers"},
{"name": "becameOptionalField", "type": "string"},
{"name": "removedField", "type": "string"},
]
}
],
"commands": [
{
"name": "removedCommand",
},
{
"name": "setExtraHTTPHeaders",
"parameters": [
{"name": "headers", "$ref": "Headers"},
{"name": "mismatched", "type": "string"},
{"name": "becameOptional", "$ref": "Headers"},
{"name": "removedRequired", "$ref": "Headers"},
{"name": "becameRequired", "$ref": "Headers", "optional": True},
{"name": "removedOptional", "$ref": "Headers", "optional": True},
],
"returns": [
{"name": "mimeType", "type": "string"},
{"name": "becameOptional", "type": "string"},
{"name": "removedRequired", "type": "string"},
{"name": "becameRequired", "type": "string", "optional": True},
{"name": "removedOptional", "type": "string", "optional": True},
]
}
],
"events": [
{
"name": "requestWillBeSent",
"parameters": [
{"name": "frameId", "type": "string", "experimental": True},
{"name": "request", "$ref": "Request"},
{"name": "becameOptional", "type": "string"},
{"name": "removedRequired", "type": "string"},
{"name": "becameRequired", "type": "string", "optional": True},
{"name": "removedOptional", "type": "string", "optional": True},
]
},
{
"name": "removedEvent",
"parameters": [
{"name": "errorText", "type": "string"},
{"name": "canceled", "type": "boolean", "optional": True}
]
}
]
},
{
"domain": "removedDomain"
}
]
def create_test_schema_2():
return [
{
"domain": "Network",
"types": [
{
"id": "LoaderId",
"type": "string"
},
{
"id": "Request",
"type": "object",
"properties": [
{"name": "url", "type": "string"},
{"name": "method", "type": "string"},
{"name": "headers", "type": "object"},
{"name": "becameOptionalField", "type": "string", "optional": True},
]
}
],
"commands": [
{
"name": "addedCommand",
},
{
"name": "setExtraHTTPHeaders",
"parameters": [
{"name": "headers", "type": "object"},
{"name": "mismatched", "type": "object"},
{"name": "becameOptional", "type": "object", "optional": True},
{"name": "addedRequired", "type": "object"},
{"name": "becameRequired", "type": "object"},
{"name": "addedOptional", "type": "object", "optional": True},
],
"returns": [
{"name": "mimeType", "type": "string"},
{"name": "becameOptional", "type": "string", "optional": True},
{"name": "addedRequired", "type": "string"},
{"name": "becameRequired", "type": "string"},
{"name": "addedOptional", "type": "string", "optional": True},
]
}
],
"events": [
{
"name": "requestWillBeSent",
"parameters": [
{"name": "request", "$ref": "Request"},
{"name": "becameOptional", "type": "string", "optional": True},
{"name": "addedRequired", "type": "string"},
{"name": "becameRequired", "type": "string"},
{"name": "addedOptional", "type": "string", "optional": True},
]
},
{
"name": "addedEvent"
}
]
},
{
"domain": "addedDomain"
}
]
def create_test_schema_1():
return [{
"domain":
"Network",
"types": [{
"id": "LoaderId",
"type": "string"
}, {
"id": "Headers",
"type": "object"
}, {
"id":
"Request",
"type":
"object",
"properties": [
{
"name": "url",
"type": "string"
},
{
"name": "method",
"type": "string"
},
{
"name": "headers",
"$ref": "Headers"
},
{
"name": "becameOptionalField",
"type": "string"
},
{
"name": "removedField",
"type": "string"
},
]
}],
"commands": [{
"name": "removedCommand",
}, {
"name":
"setExtraHTTPHeaders",
"parameters": [
{
"name": "headers",
"$ref": "Headers"
},
{
"name": "mismatched",
"type": "string"
},
{
"name": "becameOptional",
"$ref": "Headers"
},
{
"name": "removedRequired",
"$ref": "Headers"
},
{
"name": "becameRequired",
"$ref": "Headers",
"optional": True
},
{
"name": "removedOptional",
"$ref": "Headers",
"optional": True
},
],
"returns": [
{
"name": "mimeType",
"type": "string"
},
{
"name": "becameOptional",
"type": "string"
},
{
"name": "removedRequired",
"type": "string"
},
{
"name": "becameRequired",
"type": "string",
"optional": True
},
{
"name": "removedOptional",
"type": "string",
"optional": True
},
]
}],
"events": [{
"name":
"requestWillBeSent",
"parameters": [
{
"name": "frameId",
"type": "string",
"experimental": True
},
{
"name": "request",
"$ref": "Request"
},
{
"name": "becameOptional",
"type": "string"
},
{
"name": "removedRequired",
"type": "string"
},
{
"name": "becameRequired",
"type": "string",
"optional": True
},
{
"name": "removedOptional",
"type": "string",
"optional": True
},
]
}, {
"name":
"removedEvent",
"parameters": [{
"name": "errorText",
"type": "string"
}, {
"name": "canceled",
"type": "boolean",
"optional": True
}]
}]
}, {
"domain": "removedDomain"
}]
expected_errors = [
"removedDomain: domain has been removed",
"Network.removedCommand: command has been removed",
"Network.removedEvent: event has been removed",
"Network.setExtraHTTPHeaders.mismatched: parameter base type mismatch, 'object' vs 'string'",
"Network.setExtraHTTPHeaders.addedRequired: required parameter has been added",
"Network.setExtraHTTPHeaders.becameRequired: optional parameter is now required",
"Network.setExtraHTTPHeaders.removedRequired: required response parameter has been removed",
"Network.setExtraHTTPHeaders.becameOptional: required response parameter is now optional",
"Network.requestWillBeSent.removedRequired: required parameter has been removed",
"Network.requestWillBeSent.becameOptional: required parameter is now optional",
"Network.requestWillBeSent.request parameter->Network.Request.removedField: required property has been removed",
"Network.requestWillBeSent.request parameter->Network.Request.becameOptionalField: required property is now optional",
]
def create_test_schema_2():
return [{
"domain":
"Network",
"types": [{
"id": "LoaderId",
"type": "string"
}, {
"id":
"Request",
"type":
"object",
"properties": [
{
"name": "url",
"type": "string"
},
{
"name": "method",
"type": "string"
},
{
"name": "headers",
"type": "object"
},
{
"name": "becameOptionalField",
"type": "string",
"optional": True
},
]
}],
"commands": [{
"name": "addedCommand",
}, {
"name":
"setExtraHTTPHeaders",
"parameters": [
{
"name": "headers",
"type": "object"
},
{
"name": "mismatched",
"type": "object"
},
{
"name": "becameOptional",
"type": "object",
"optional": True
},
{
"name": "addedRequired",
"type": "object"
},
{
"name": "becameRequired",
"type": "object"
},
{
"name": "addedOptional",
"type": "object",
"optional": True
},
],
"returns": [
{
"name": "mimeType",
"type": "string"
},
{
"name": "becameOptional",
"type": "string",
"optional": True
},
{
"name": "addedRequired",
"type": "string"
},
{
"name": "becameRequired",
"type": "string"
},
{
"name": "addedOptional",
"type": "string",
"optional": True
},
]
}],
"events": [{
"name":
"requestWillBeSent",
"parameters": [
{
"name": "request",
"$ref": "Request"
},
{
"name": "becameOptional",
"type": "string",
"optional": True
},
{
"name": "addedRequired",
"type": "string"
},
{
"name": "becameRequired",
"type": "string"
},
{
"name": "addedOptional",
"type": "string",
"optional": True
},
]
}, {
"name": "addedEvent"
}]
}, {
"domain": "addedDomain"
}]
expected_errors_reverse = [
"addedDomain: domain has been added",
"Network.addedEvent: event has been added",
"Network.addedCommand: command has been added",
"Network.setExtraHTTPHeaders.mismatched: parameter base type mismatch, 'string' vs 'object'",
"Network.setExtraHTTPHeaders.removedRequired: required parameter has been removed",
"Network.setExtraHTTPHeaders.becameOptional: required parameter is now optional",
"Network.setExtraHTTPHeaders.addedRequired: required response parameter has been added",
"Network.setExtraHTTPHeaders.becameRequired: optional response parameter is now required",
"Network.requestWillBeSent.becameRequired: optional parameter is now required",
"Network.requestWillBeSent.addedRequired: required parameter has been added",
]
expected_errors = [
"removedDomain: domain has been removed",
"Network.removedCommand: command has been removed",
"Network.removedEvent: event has been removed",
"Network.setExtraHTTPHeaders.mismatched: parameter base type mismatch, 'object' vs 'string'",
"Network.setExtraHTTPHeaders.addedRequired: required parameter has been added",
"Network.setExtraHTTPHeaders.becameRequired: optional parameter is now required",
"Network.setExtraHTTPHeaders.removedRequired: required response parameter has been removed",
"Network.setExtraHTTPHeaders.becameOptional: required response parameter is now optional",
"Network.requestWillBeSent.removedRequired: required parameter has been removed",
"Network.requestWillBeSent.becameOptional: required parameter is now optional",
"Network.requestWillBeSent.request parameter->Network.Request.removedField: required property has been removed",
"Network.requestWillBeSent.request parameter->Network.Request.becameOptionalField: required property is now optional",
]
def is_subset(subset, superset, message):
for i in range(len(subset)):
if subset[i] not in superset:
sys.stderr.write("%s error: %s\n" % (message, subset[i]))
return False
return True
expected_errors_reverse = [
"addedDomain: domain has been added",
"Network.addedEvent: event has been added",
"Network.addedCommand: command has been added",
"Network.setExtraHTTPHeaders.mismatched: parameter base type mismatch, 'string' vs 'object'",
"Network.setExtraHTTPHeaders.removedRequired: required parameter has been removed",
"Network.setExtraHTTPHeaders.becameOptional: required parameter is now optional",
"Network.setExtraHTTPHeaders.addedRequired: required response parameter has been added",
"Network.setExtraHTTPHeaders.becameRequired: optional response parameter is now required",
"Network.requestWillBeSent.becameRequired: optional parameter is now required",
"Network.requestWillBeSent.addedRequired: required parameter has been added",
]
def errors_match(expected, actual):
return (is_subset(actual, expected, "Unexpected") and
is_subset(expected, actual, "Missing"))
def is_subset(subset, superset, message):
for i in range(len(subset)):
if subset[i] not in superset:
sys.stderr.write("%s error: %s\n" % (message, subset[i]))
return False
return True
return (errors_match(expected_errors,
compare_schemas(create_test_schema_1(), create_test_schema_2(), False)) and
errors_match(expected_errors_reverse,
compare_schemas(create_test_schema_2(), create_test_schema_1(), True)))
def errors_match(expected, actual):
return (is_subset(actual, expected, "Unexpected") and
is_subset(expected, actual, "Missing"))
return (errors_match(
expected_errors,
compare_schemas(create_test_schema_1(), create_test_schema_2(),
False)) and errors_match(
expected_errors_reverse,
compare_schemas(create_test_schema_2(),
create_test_schema_1(), True)))
def load_domains_and_baselines(file_name, domains, baseline_domains):
version = load_schema(os.path.normpath(file_name), domains)
suffix = "-%s.%s.json" % (version["major"], version["minor"])
baseline_file = file_name.replace(".json", suffix)
baseline_file = file_name.replace(".pdl", suffix)
load_schema(os.path.normpath(baseline_file), baseline_domains)
return version
version = load_schema(os.path.normpath(file_name), domains)
suffix = "-%s.%s.json" % (version["major"], version["minor"])
baseline_file = file_name.replace(".json", suffix)
baseline_file = file_name.replace(".pdl", suffix)
load_schema(os.path.normpath(baseline_file), baseline_domains)
return version
def main():
if not self_test():
sys.stderr.write("Self-test failed")
return 1
if not self_test():
sys.stderr.write("Self-test failed")
return 1
cmdline_parser = optparse.OptionParser()
cmdline_parser.add_option("--show_changes")
cmdline_parser.add_option("--expected_errors")
cmdline_parser.add_option("--stamp")
arg_options, arg_values = cmdline_parser.parse_args()
cmdline_parser = optparse.OptionParser()
cmdline_parser.add_option("--show_changes")
cmdline_parser.add_option("--expected_errors")
cmdline_parser.add_option("--stamp")
arg_options, arg_values = cmdline_parser.parse_args()
if len(arg_values) < 1:
sys.stderr.write("Usage: %s [--show_changes] <protocol-1> [, <protocol-2>...]\n" % sys.argv[0])
return 1
if len(arg_values) < 1:
sys.stderr.write(
"Usage: %s [--show_changes] <protocol-1> [, <protocol-2>...]\n" %
sys.argv[0])
return 1
domains = []
baseline_domains = []
version = load_domains_and_baselines(arg_values[0], domains, baseline_domains)
for dependency in arg_values[1:]:
load_domains_and_baselines(dependency, domains, baseline_domains)
domains = []
baseline_domains = []
version = load_domains_and_baselines(arg_values[0], domains, baseline_domains)
for dependency in arg_values[1:]:
load_domains_and_baselines(dependency, domains, baseline_domains)
expected_errors = []
if arg_options.expected_errors:
expected_errors_file = open(arg_options.expected_errors, "r")
expected_errors = json.loads(expected_errors_file.read())["errors"]
expected_errors_file.close()
expected_errors = []
if arg_options.expected_errors:
expected_errors_file = open(arg_options.expected_errors, "r")
expected_errors = json.loads(expected_errors_file.read())["errors"]
expected_errors_file.close()
errors = compare_schemas(baseline_domains, domains, False)
unexpected_errors = []
for i in range(len(errors)):
if errors[i] not in expected_errors:
unexpected_errors.append(errors[i])
if len(unexpected_errors) > 0:
sys.stderr.write(" Compatibility checks FAILED\n")
for error in unexpected_errors:
sys.stderr.write(" %s\n" % error)
return 1
errors = compare_schemas(baseline_domains, domains, False)
unexpected_errors = []
for i in range(len(errors)):
if errors[i] not in expected_errors:
unexpected_errors.append(errors[i])
if len(unexpected_errors) > 0:
sys.stderr.write(" Compatibility checks FAILED\n")
for error in unexpected_errors:
sys.stderr.write(" %s\n" % error)
return 1
if arg_options.show_changes:
changes = compare_schemas(domains, baseline_domains, True)
if len(changes) > 0:
print(" Public changes since %s:" % version)
for change in changes:
print(" %s" % change)
if arg_options.show_changes:
changes = compare_schemas(domains, baseline_domains, True)
if len(changes) > 0:
print(" Public changes since %s:" % version)
for change in changes:
print(" %s" % change)
if arg_options.stamp:
with open(arg_options.stamp, 'a') as _:
pass
if arg_options.stamp:
with open(arg_options.stamp, 'a') as _:
pass
if __name__ == '__main__':
sys.exit(main())
sys.exit(main())

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
@ -95,27 +95,28 @@ def read_config():
config_base)
config_json_file.close()
defaults = {
".use_snake_file_names": False,
".use_title_case_methods": False,
".imported": False,
".imported.export_macro": "",
".imported.export_header": False,
".imported.header": False,
".imported.package": False,
".imported.options": False,
".protocol.export_macro": "",
".protocol.export_header": False,
".protocol.options": False,
".protocol.file_name_prefix": "",
".exported": False,
".exported.export_macro": "",
".exported.export_header": False,
".lib": False,
".lib.export_macro": "",
".lib.export_header": False,
".crdtp": False,
".crdtp.dir": os.path.join(inspector_protocol_dir, "crdtp"),
".crdtp.namespace": "crdtp",
".use_snake_file_names": False,
".use_title_case_methods": False,
".use_embedder_types": False,
".imported": False,
".imported.export_macro": "",
".imported.export_header": False,
".imported.header": False,
".imported.package": False,
".imported.options": False,
".protocol.export_macro": "",
".protocol.export_header": False,
".protocol.options": False,
".protocol.file_name_prefix": "",
".exported": False,
".exported.export_macro": "",
".exported.export_header": False,
".lib": False,
".lib.export_macro": "",
".lib.export_header": False,
".crdtp": False,
".crdtp.dir": os.path.join(inspector_protocol_dir, "crdtp"),
".crdtp.namespace": "crdtp",
}
for key_value in config_values:
parts = key_value.split("=")
@ -638,31 +639,32 @@ def main():
lib_templates_dir = os.path.join(module_path, "lib")
# Note these should be sorted in the right order.
# TODO(dgozman): sort them programmatically based on commented includes.
protocol_h_templates = [
"Values_h.template",
"Object_h.template",
"ValueConversions_h.template",
]
protocol_cpp_templates = [
"Protocol_cpp.template",
"Values_cpp.template",
"Object_cpp.template",
"ValueConversions_cpp.template",
]
# TODO(dgozman): sort them programmatically based on commented includes.
forward_h_templates = [
"Forward_h.template",
]
base_string_adapter_h_templates = [
"base_string_adapter_h.template",
]
protocol_h_templates = []
protocol_cpp_templates = []
base_string_adapter_cc_templates = [
"base_string_adapter_cc.template",
]
if not config.use_embedder_types:
protocol_h_templates += [
"Values_h.template",
"Object_h.template",
"ValueConversions_h.template",
]
protocol_cpp_templates += [
"Protocol_cpp.template",
"Values_cpp.template",
"Object_cpp.template",
"ValueConversions_cpp.template",
]
else:
protocol_h_templates += [
"Forward_h.template",
]
def generate_lib_file(file_name, template_files):
parts = []
@ -676,12 +678,11 @@ def main():
config, "Forward.h")), forward_h_templates)
generate_lib_file(os.path.join(config.lib.output, to_file_name(
config, "Protocol.h")), protocol_h_templates)
generate_lib_file(os.path.join(config.lib.output, to_file_name(
config, "Protocol.cpp")), protocol_cpp_templates)
generate_lib_file(os.path.join(config.lib.output, to_file_name(
config, "base_string_adapter.h")), base_string_adapter_h_templates)
generate_lib_file(os.path.join(config.lib.output, to_file_name(
config, "base_string_adapter.cc")), base_string_adapter_cc_templates)
if not config.use_embedder_types:
generate_lib_file(
os.path.join(config.lib.output, to_file_name(config, "Protocol.cpp")),
protocol_cpp_templates)
# Make gyp / make generatos happy, otherwise make rebuilds world.
inputs_ts = max(map(os.path.getmtime, inputs))

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# Copyright 2017 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
@ -11,31 +11,34 @@ import sys
import pdl
def open_to_write(path):
if sys.version_info >= (3,0):
return open(path, 'w', encoding='utf-8')
else:
return open(path, 'wb')
if sys.version_info >= (3, 0):
return open(path, 'w', encoding='utf-8')
else:
return open(path, 'wb')
def main(argv):
parser = argparse.ArgumentParser(description=(
"Converts from .pdl to .json by invoking the pdl Python module."))
parser.add_argument('--map_binary_to_string', type=bool,
help=('If set, binary in the .pdl is mapped to a '
'string in .json. Client code will have to '
'base64 decode the string to get the payload.'))
parser.add_argument("pdl_file", help="The .pdl input file to parse.")
parser.add_argument("json_file", help="The .json output file write.")
args = parser.parse_args(argv)
file_name = os.path.normpath(args.pdl_file)
input_file = open(file_name, "r")
pdl_string = input_file.read()
protocol = pdl.loads(pdl_string, file_name, args.map_binary_to_string)
input_file.close()
output_file = open_to_write(os.path.normpath(args.json_file))
json.dump(protocol, output_file, indent=4, separators=(',', ': '))
output_file.close()
parser = argparse.ArgumentParser(
description=(
"Converts from .pdl to .json by invoking the pdl Python module."))
parser.add_argument(
'--map_binary_to_string',
type=bool,
help=('If set, binary in the .pdl is mapped to a '
'string in .json. Client code will have to '
'base64 decode the string to get the payload.'))
parser.add_argument("pdl_file", help="The .pdl input file to parse.")
parser.add_argument("json_file", help="The .json output file write.")
args = parser.parse_args(argv)
file_name = os.path.normpath(args.pdl_file)
input_file = open(file_name, "r")
pdl_string = input_file.read()
protocol = pdl.loads(pdl_string, file_name, args.map_binary_to_string)
input_file.close()
output_file = open_to_write(os.path.normpath(args.json_file))
json.dump(protocol, output_file, indent=4, separators=(',', ': '))
output_file.close()
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))
sys.exit(main(sys.argv[1:]))

View File

@ -595,7 +595,7 @@ span<uint8_t> CBORTokenizer::GetEnvelopeContents() const {
// and then checking whether the sum went past it.
//
// See also
// https://chromium.googlesource.com/chromium/src/+/master/docs/security/integer-semantics.md
// https://chromium.googlesource.com/chromium/src/+/main/docs/security/integer-semantics.md
static const uint64_t kMaxValidLength =
std::min<uint64_t>(std::numeric_limits<uint64_t>::max() >> 2,
std::numeric_limits<size_t>::max());

View File

@ -310,15 +310,10 @@ class ProtocolError : public Serializable {
std::unique_ptr<Serializable> CreateErrorResponse(
int call_id,
DispatchResponse dispatch_response,
const ErrorSupport* errors) {
DispatchResponse dispatch_response) {
auto protocol_error =
std::make_unique<ProtocolError>(std::move(dispatch_response));
protocol_error->SetCallId(call_id);
if (errors && !errors->Errors().empty()) {
protocol_error->SetData(
std::string(errors->Errors().begin(), errors->Errors().end()));
}
return protocol_error;
}
@ -473,26 +468,9 @@ void DomainDispatcher::sendResponse(int call_id,
frontend_channel_->SendProtocolResponse(call_id, std::move(serializable));
}
bool DomainDispatcher::MaybeReportInvalidParams(
const Dispatchable& dispatchable,
const ErrorSupport& errors) {
if (errors.Errors().empty())
return false;
if (frontend_channel_) {
frontend_channel_->SendProtocolResponse(
dispatchable.CallId(),
CreateErrorResponse(
dispatchable.CallId(),
DispatchResponse::InvalidParams("Invalid parameters"), &errors));
}
return true;
}
bool DomainDispatcher::MaybeReportInvalidParams(
const Dispatchable& dispatchable,
const DeserializerState& state) {
if (state.status().ok())
return false;
void DomainDispatcher::ReportInvalidParams(const Dispatchable& dispatchable,
const DeserializerState& state) {
assert(!state.status().ok());
if (frontend_channel_) {
frontend_channel_->SendProtocolResponse(
dispatchable.CallId(),
@ -500,7 +478,6 @@ bool DomainDispatcher::MaybeReportInvalidParams(
dispatchable.CallId(),
DispatchResponse::InvalidParams("Invalid parameters"), state));
}
return true;
}
void DomainDispatcher::clearFrontend() {

View File

@ -31,7 +31,7 @@ enum class DispatchCode {
FALL_THROUGH = 2,
// For historical reasons, these error codes correspond to commonly used
// XMLRPC codes (e.g. see METHOD_NOT_FOUND in
// https://github.com/python/cpython/blob/master/Lib/xmlrpc/client.py).
// https://github.com/python/cpython/blob/main/Lib/xmlrpc/client.py).
PARSE_ERROR = -32700,
INVALID_REQUEST = -32600,
METHOD_NOT_FOUND = -32601,
@ -150,8 +150,7 @@ class Dispatchable {
std::unique_ptr<Serializable> CreateErrorResponse(
int callId,
DispatchResponse dispatch_response,
const ErrorSupport* errors = nullptr);
DispatchResponse dispatch_response);
std::unique_ptr<Serializable> CreateErrorNotification(
DispatchResponse dispatch_response);
@ -230,13 +229,8 @@ class DomainDispatcher {
const DispatchResponse&,
std::unique_ptr<Serializable> result = nullptr);
// Returns true if |errors| contains errors *and* reports these errors
// as a response on the frontend channel. Called from generated code,
// optimized for code size of the callee.
bool MaybeReportInvalidParams(const Dispatchable& dispatchable,
const ErrorSupport& errors);
bool MaybeReportInvalidParams(const Dispatchable& dispatchable,
const DeserializerState& state);
void ReportInvalidParams(const Dispatchable& dispatchable,
const DeserializerState& state);
FrontendChannel* channel() { return frontend_channel_; }

View File

@ -269,16 +269,8 @@ TEST(DispatchableTest, FaultyCBORTrailingJunk) {
// Helpers for creating protocol cresponses and notifications.
// =============================================================================
TEST(CreateErrorResponseTest, SmokeTest) {
ErrorSupport errors;
errors.Push();
errors.SetName("foo");
errors.Push();
errors.SetName("bar");
errors.AddError("expected a string");
errors.SetName("baz");
errors.AddError("expected a surprise");
auto serializable = CreateErrorResponse(
42, DispatchResponse::InvalidParams("invalid params message"), &errors);
42, DispatchResponse::InvalidParams("invalid params message"));
std::string json;
auto status =
json::ConvertCBORToJSON(SpanFrom(serializable->Serialize()), &json);
@ -286,9 +278,7 @@ TEST(CreateErrorResponseTest, SmokeTest) {
EXPECT_EQ(
"{\"id\":42,\"error\":"
"{\"code\":-32602,"
"\"message\":\"invalid params message\","
"\"data\":\"foo.bar: expected a string; "
"foo.baz: expected a surprise\"}}",
"\"message\":\"invalid params message\"}}",
json);
}

View File

@ -267,11 +267,11 @@ class DeserializableProtocolObject {
std::unique_ptr<T> value(new T());
auto deserializer = DeferredMessage::FromSpan(span<uint8_t>(bytes, size))
->MakeDeserializer();
Deserialize(&deserializer, value.get());
std::ignore = Deserialize(&deserializer, value.get());
return value;
}
static bool Deserialize(DeserializerState* state, T* value) {
[[nodiscard]] static bool Deserialize(DeserializerState* state, T* value) {
return T::deserializer_descriptor().Deserialize(state, value);
}
@ -348,6 +348,16 @@ struct ProtocolTypeTraits<
}
};
template <typename T, typename F>
bool ConvertProtocolValue(const F& from, T* to) {
std::vector<uint8_t> bytes;
ProtocolTypeTraits<F>::Serialize(from, &bytes);
auto deserializer =
DeferredMessage::FromSpan(span<uint8_t>(bytes.data(), bytes.size()))
->MakeDeserializer();
return ProtocolTypeTraits<T>::Deserialize(&deserializer, to);
}
#define DECLARE_DESERIALIZATION_SUPPORT() \
friend DeserializableBase<ProtocolType>; \
static const DeserializerDescriptorType& deserializer_descriptor()

View File

@ -115,6 +115,8 @@ std::string Status::Message() const {
return "BINDINGS: binary value expected";
case Error::BINDINGS_DICTIONARY_VALUE_EXPECTED:
return "BINDINGS: dictionary value expected";
case Error::BINDINGS_INVALID_BASE64_STRING:
return "BINDINGS: invalid base64 string";
}
// Some compilers can't figure out that we can't get here.
return "INVALID ERROR CODE";

View File

@ -78,6 +78,7 @@ enum class Error {
BINDINGS_STRING8_VALUE_EXPECTED = 0x35,
BINDINGS_BINARY_VALUE_EXPECTED = 0x36,
BINDINGS_DICTIONARY_VALUE_EXPECTED = 0x37,
BINDINGS_INVALID_BASE64_STRING = 0x38,
};
// A status value with position that can be copied. The default status

View File

@ -25,22 +25,14 @@ template("inspector_protocol_generate") {
assert(defined(invoker.outputs))
assert(defined(invoker.inspector_protocol_dir))
inspector_protocol_dir = invoker.inspector_protocol_dir
use_embedder_types =
defined(invoker.use_embedder_types) && invoker.use_embedder_types
action(target_name) {
script = "$inspector_protocol_dir/code_generator.py"
inputs = [
invoker.config_file,
"$inspector_protocol_dir/lib/base_string_adapter_cc.template",
"$inspector_protocol_dir/lib/base_string_adapter_h.template",
"$inspector_protocol_dir/lib/Forward_h.template",
"$inspector_protocol_dir/lib/Object_cpp.template",
"$inspector_protocol_dir/lib/Object_h.template",
"$inspector_protocol_dir/lib/Protocol_cpp.template",
"$inspector_protocol_dir/lib/ValueConversions_cpp.template",
"$inspector_protocol_dir/lib/ValueConversions_h.template",
"$inspector_protocol_dir/lib/Values_cpp.template",
"$inspector_protocol_dir/lib/Values_h.template",
"$inspector_protocol_dir/templates/Exported_h.template",
"$inspector_protocol_dir/templates/Imported_h.template",
"$inspector_protocol_dir/templates/TypeBuilder_cpp.template",
@ -49,12 +41,21 @@ template("inspector_protocol_generate") {
if (defined(invoker.inputs)) {
inputs += invoker.inputs
}
if (!use_embedder_types) {
inputs += [
"$inspector_protocol_dir/lib/ValueConversions_cpp.template",
"$inspector_protocol_dir/lib/ValueConversions_h.template",
"$inspector_protocol_dir/lib/Values_cpp.template",
"$inspector_protocol_dir/lib/Values_h.template",
"$inspector_protocol_dir/lib/Object_cpp.template",
"$inspector_protocol_dir/lib/Object_h.template",
]
}
args = [
"--jinja_dir",
rebase_path("//third_party/", root_build_dir), # jinja is in chromium's
# third_party
"--output_base",
rebase_path(invoker.out_dir, root_build_dir),
"--config",
@ -62,7 +63,12 @@ template("inspector_protocol_generate") {
"--inspector_protocol_dir",
"$inspector_protocol_dir",
]
if (use_embedder_types) {
args += [
"--config_value",
"use_embedder_types=true",
]
}
if (defined(invoker.config_values)) {
foreach(value, invoker.config_values) {
args += [

View File

@ -10,7 +10,6 @@
{% if config.lib.export_header %}
#include {{format_include(config.lib.export_header)}}
{% endif %}
#include {{format_include(config.lib.string_header)}}
#include <memory>
#include <vector>
@ -20,24 +19,40 @@
#include "{{config.crdtp.dir}}/frontend_channel.h"
#include "{{config.crdtp.dir}}/protocol_core.h"
{% if config.use_embedder_types %}
#include {{format_include(config.lib.protocol_traits)}}
{% else %}
#include {{format_include(config.lib.string_header)}}
{% endif %}
{% for namespace in config.protocol.namespace %}
namespace {{namespace}} {
{% endfor %}
class DictionaryValue;
using DispatchResponse = {{config.crdtp.namespace}}::DispatchResponse;
using ErrorSupport = {{config.crdtp.namespace}}::ErrorSupport;
using Serializable = {{config.crdtp.namespace}}::Serializable;
using FrontendChannel = {{config.crdtp.namespace}}::FrontendChannel;
using DomainDispatcher = {{config.crdtp.namespace}}::DomainDispatcher;
using UberDispatcher = {{config.crdtp.namespace}}::UberDispatcher;
using Response = DispatchResponse;
{% if config.use_embedder_types %}
using DictionaryValue = crdtp::traits::DictionaryValue;
using Object = crdtp::traits::DictionaryValue;
using ListValue = crdtp::traits::ListValue;
using Value = crdtp::traits::Value;
using String = crdtp::traits::String;
using Binary = crdtp::Binary;
{% else %}
class DictionaryValue;
class FundamentalValue;
class ListValue;
class Object;
using Response = DispatchResponse;
class SerializedValue;
class StringValue;
class Value;
{% endif %}
using {{config.crdtp.namespace}}::detail::PtrMaybe;
using {{config.crdtp.namespace}}::detail::ValueMaybe;

View File

@ -1,123 +0,0 @@
// This file is generated by base_string_adapter_cc.template.
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include {{format_include(config.protocol.package, "base_string_adapter")}}
#include {{format_include(config.protocol.package, "Protocol")}}
#include <utility>
#include "base/base64.h"
#include "base/json/json_reader.h"
#include "base/memory/ptr_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "{{config.crdtp.dir}}/cbor.h"
#include "{{config.crdtp.dir}}/protocol_core.h"
using namespace {{config.crdtp.namespace}};
using {{"::".join(config.protocol.namespace)}}::Binary;
using {{"::".join(config.protocol.namespace)}}::String;
using {{"::".join(config.protocol.namespace)}}::StringUtil;
{% for namespace in config.protocol.namespace %}
namespace {{namespace}} {
{% endfor %}
// In Chromium, we do not support big endian architectures, so no conversion is needed
// to interpret UTF16LE.
// static
String StringUtil::fromUTF16LE(const uint16_t* data, size_t length) {
std::string utf8;
base::UTF16ToUTF8(reinterpret_cast<const char16_t*>(data), length, &utf8);
return utf8;
}
std::unique_ptr<protocol::Value> toProtocolValue(
const base::Value& value, int depth) {
if (!depth)
return nullptr;
if (value.is_none())
return protocol::Value::null();
if (value.is_bool())
return protocol::FundamentalValue::create(value.GetBool());
if (value.is_int())
return protocol::FundamentalValue::create(value.GetInt());
if (value.is_double())
return protocol::FundamentalValue::create(value.GetDouble());
if (value.is_string())
return protocol::StringValue::create(value.GetString());
if (value.is_list()) {
auto result = protocol::ListValue::create();
for (const base::Value& item : value.GetList()) {
if (auto converted = toProtocolValue(item, depth - 1)) {
result->pushValue(std::move(converted));
}
}
return result;
}
if (value.is_dict()) {
auto result = protocol::DictionaryValue::create();
for (auto kv : value.DictItems()) {
if (auto converted = toProtocolValue(kv.second, depth - 1)) {
result->setValue(kv.first, std::move(converted));
}
}
return result;
}
return nullptr;
}
base::Value toBaseValue(Value* value, int depth) {
if (!value || !depth)
return base::Value();
if (value->type() == Value::TypeBoolean) {
bool inner;
value->asBoolean(&inner);
return base::Value(inner);
}
if (value->type() == Value::TypeInteger) {
int inner;
value->asInteger(&inner);
return base::Value(inner);
}
if (value->type() == Value::TypeDouble) {
double inner;
value->asDouble(&inner);
return base::Value(inner);
}
if (value->type() == Value::TypeString) {
std::string inner;
value->asString(&inner);
return base::Value(inner);
}
if (value->type() == Value::TypeArray) {
ListValue* list = ListValue::cast(value);
base::Value result(base::Value::Type::LIST);
for (size_t i = 0; i < list->size(); i++) {
base::Value converted = toBaseValue(list->at(i), depth - 1);
if (!converted.is_none())
result.Append(std::move(converted));
}
return result;
}
if (value->type() == Value::TypeObject) {
DictionaryValue* dict = DictionaryValue::cast(value);
base::Value result(base::Value::Type::DICTIONARY);
for (size_t i = 0; i < dict->size(); i++) {
DictionaryValue::Entry entry = dict->at(i);
base::Value converted = toBaseValue(entry.second, depth - 1);
if (!converted.is_none())
result.SetKey(entry.first, std::move(converted));
}
return result;
}
return base::Value();
}
{% for namespace in config.protocol.namespace %}
} // namespace {{namespace}} {
{% endfor %}

View File

@ -1,48 +0,0 @@
// This file is generated by base_string_adapter_h.template.
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef {{"_".join(config.protocol.namespace)}}_BASE_STRING_ADAPTER_H
#define {{"_".join(config.protocol.namespace)}}_BASE_STRING_ADAPTER_H
#include "{{config.crdtp.dir}}/chromium/protocol_traits.h"
{% if config.lib.export_header %}
#include "{{config.lib.export_header}}"
{% endif %}
{% for namespace in config.protocol.namespace %}
namespace {{namespace}} {
{% endfor %}
class Value;
using String = std::string;
using Binary = crdtp::Binary;
class {{config.lib.export_macro}} StringUtil {
public:
static String fromUTF8(const uint8_t* data, size_t length) {
return std::string(reinterpret_cast<const char*>(data), length);
}
static String fromUTF16LE(const uint16_t* data, size_t length);
static const uint8_t* CharactersLatin1(const String& s) { return nullptr; }
static const uint8_t* CharactersUTF8(const String& s) {
return reinterpret_cast<const uint8_t*>(s.data());
}
static const uint16_t* CharactersUTF16(const String& s) { return nullptr; }
static size_t CharacterCount(const String& s) { return s.size(); }
};
std::unique_ptr<Value> toProtocolValue(const base::Value& value, int depth);
base::Value toBaseValue(Value* value, int depth);
{% for namespace in config.protocol.namespace %}
} // namespace {{namespace}}
{% endfor %}
#endif // !defined({{"_".join(config.protocol.namespace)}}_BASE_STRING_ADAPTER_H)

View File

@ -276,10 +276,11 @@ void DomainDispatcherImpl::{{command.name}}(const {{config.crdtp.namespace}}::Di
{% if "parameters" in command %}
auto deserializer = {{config.crdtp.namespace}}::DeferredMessage::FromSpan(dispatchable.Params())->MakeDeserializer();
{{command.name}}Params params;
{{command.name}}Params::Deserialize(&deserializer, &params);
if (MaybeReportInvalidParams(dispatchable, deserializer))
if (!{{command.name}}Params::Deserialize(&deserializer, &params)) {
ReportInvalidParams(dispatchable, deserializer);
return;
{% endif %}
}
{% endif -%}
{% if "returns" in command and not protocol.is_async_command(domain.domain, command.name) %}
// Declare output parameters.