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:
parent
37569a5a99
commit
bb18bc24b0
2
third_party/inspector_protocol/README.v8
vendored
2
third_party/inspector_protocol/README.v8
vendored
@ -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
|
||||
|
@ -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())
|
||||
|
93
third_party/inspector_protocol/code_generator.py
vendored
93
third_party/inspector_protocol/code_generator.py
vendored
@ -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))
|
||||
|
@ -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.
|
||||
|
@ -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:]))
|
||||
|
2
third_party/inspector_protocol/crdtp/cbor.cc
vendored
2
third_party/inspector_protocol/crdtp/cbor.cc
vendored
@ -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());
|
||||
|
31
third_party/inspector_protocol/crdtp/dispatch.cc
vendored
31
third_party/inspector_protocol/crdtp/dispatch.cc
vendored
@ -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() {
|
||||
|
14
third_party/inspector_protocol/crdtp/dispatch.h
vendored
14
third_party/inspector_protocol/crdtp/dispatch.h
vendored
@ -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_; }
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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";
|
||||
|
@ -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
|
||||
|
@ -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 += [
|
||||
|
@ -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;
|
||||
|
@ -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 %}
|
@ -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)
|
@ -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, ¶ms);
|
||||
if (MaybeReportInvalidParams(dispatchable, deserializer))
|
||||
if (!{{command.name}}Params::Deserialize(&deserializer, ¶ms)) {
|
||||
ReportInvalidParams(dispatchable, deserializer);
|
||||
return;
|
||||
{% endif %}
|
||||
}
|
||||
{% endif -%}
|
||||
|
||||
{% if "returns" in command and not protocol.is_async_command(domain.domain, command.name) %}
|
||||
// Declare output parameters.
|
||||
|
Loading…
Reference in New Issue
Block a user