#!/usr/bin/python # Copyright 2014 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. import sys import string import json package = sys.argv[1] output_cc_path = sys.argv[2] output_h_path = sys.argv[3] blink_protocol_path = sys.argv[4] browser_protocol_path = sys.argv[5] if len(sys.argv) > 5 else None template_h = string.Template("""\ // Copyright 2013 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 ${PACKAGE}_BROWSER_DEVTOOLS_DEVTOOLS_PROTOCOL_CONSTANTS_H_ #define ${PACKAGE}_BROWSER_DEVTOOLS_DEVTOOLS_PROTOCOL_CONSTANTS_H_ // THIS FILE IS AUTOGENERATED. DO NOT EDIT. // Generated by // content/public/browser/devtools_protocol_constants_generator.py from // third_party/WebKit/Source/devtools/protocol.json and // content/browser/devtools/browser_protocol.json #include namespace $package { namespace devtools { extern const char kProtocolVersion[]; bool IsSupportedProtocolVersion(const std::string& version); extern const char kResult[]; $contents } // devtools } // $package #endif // ${PACKAGE}_BROWSER_DEVTOOLS_DEVTOOLS_PROTOCOL_CONSTANTS_H_ """) template_cc = string.Template("""\ // Copyright 2013 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. // THIS FILE IS AUTOGENERATED. DO NOT EDIT. // Generated by // content/public/browser/devtools_protocol_constants_generator.py from // third_party/WebKit/Source/devtools/protocol.json and // content/browser/devtools/browser_protocol.json #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "$package/browser/devtools/devtools_protocol_constants.h" namespace $package { namespace devtools { const char kProtocolVersion[] = "$major.$minor"; bool IsSupportedProtocolVersion(const std::string& version) { std::vector tokens; Tokenize(version, ".", &tokens); int major, minor; return tokens.size() == 2 && base::StringToInt(tokens[0], &major) && major == $major && base::StringToInt(tokens[1], &minor) && minor <= $minor; } const char kResult[] = "result"; $contents } // devtools } // $package """) def Capitalize(s): return s[:1].capitalize() + s[1:] references = [] def CreateNamespace(domain_name, data, keys, prefixes, name = None): result = {} if name: result["kName"] = name for i, key in enumerate(keys): if key in data: for parameter in data[key]: parameter_name = parameter["name"]; result[prefixes[i] + Capitalize(parameter_name)] = parameter_name if "enum" in parameter: enum_name = Capitalize(parameter_name) result[enum_name] = {} for enum in parameter["enum"]: result[enum_name]["kEnum" + Capitalize(enum)] = enum reference = "" if "$ref" in parameter: reference = parameter["$ref"] if "items" in parameter and "$ref" in parameter["items"]: reference = parameter["items"]["$ref"] if reference: if not "." in reference: reference = domain_name + "." + reference references.append(reference) return result def IsHandledInBrowser(item): return "handlers" in item and "browser" in item["handlers"] def FormatContents(tree, indent, format_string): outer = dict((key, value) for key, value in tree.iteritems() if not isinstance(value, dict)) inner = dict((key, value) for key, value in tree.iteritems() if isinstance(value, dict)) body = "" body += "".join(indent + format_string.format(key, value) for (key, value) in sorted(outer.items())) body += "".join(FormatNamespace(key, value, indent, format_string) for (key, value) in sorted(inner.items())) return body def FormatNamespace(title, tree, indent, format_string): if (not tree): return "" body = '\n' + indent + "namespace " + title + " {\n" body += FormatContents(tree, indent + " ", format_string) body += indent + "} // " + title + "\n" return body def CreateHeader(tree, output_file): contents = FormatContents(tree, "", "extern const char {0}[];\n") output_file.write(template_h.substitute({ "contents": contents, "package": package, "PACKAGE": package.upper() })) def CreateBody(tree, version, output_file): contents = FormatContents(tree, "", "const char {0}[] = \"{1}\";\n") output_file.write(template_cc.substitute({ "major": version["major"], "minor": version["minor"], "contents": contents, "package": package })) blink_protocol_data = open(blink_protocol_path).read() blink_protocol = json.loads(blink_protocol_data) blink_version = blink_protocol["version"] domains = blink_protocol["domains"] if browser_protocol_path: browser_protocol_data = open(browser_protocol_path).read() browser_protocol = json.loads(browser_protocol_data) domains = domains + browser_protocol["domains"] namespace_tree = {} for domain in domains: domain_value = {} domain_namespace_name = Capitalize(domain["domain"]) if "commands" in domain: for command in domain["commands"]: if (IsHandledInBrowser(command)): domain_value[command["name"]] = CreateNamespace(domain["domain"], command, ["parameters", "returns"], ["kParam", "kResponse"], domain_namespace_name + "." + command["name"]) if "events" in domain: for event in domain["events"]: if IsHandledInBrowser(event): domain_value[event["name"]] = CreateNamespace(domain["domain"], event, ["parameters"], ["kParam"], domain_namespace_name + "." + event["name"]) if domain_value: namespace_tree[domain_namespace_name] = domain_value while (references): reference = references.pop(); path = reference.split("."); parent_namespace = namespace_tree; for path_segment in path[0:-1]: if path_segment not in parent_namespace: parent_namespace[path_segment] = {} parent_namespace = parent_namespace[path_segment] if (path[-1] not in parent_namespace): try: domain = [d for d in domains if d["domain"] == path[0]][0] ref_type = [t for t in domain["types"] if t["id"] == path[1]][0] parent_namespace[ref_type["id"]] = CreateNamespace(path[0], ref_type, ["properties"], ["kParam"]) except IndexError: sys.stderr.write("Failed to resolve type [{0}].\n".format(reference)) sys.exit(1) for (namespace_name, namespace) in namespace_tree.items(): namespace["kName"] = namespace_name with open(output_cc_path, "w") as f: CreateBody(namespace_tree, blink_version, f) with open(output_h_path, "w") as f: CreateHeader(namespace_tree, f)