1#!/usr/bin/python 2# Copyright 2014 The Chromium Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6import sys 7import string 8import json 9 10package = sys.argv[1] 11output_cc_path = sys.argv[2] 12output_h_path = sys.argv[3] 13blink_protocol_path = sys.argv[4] 14browser_protocol_path = sys.argv[5] if len(sys.argv) > 5 else None 15 16template_h = string.Template("""\ 17// Copyright 2013 The Chromium Authors. All rights reserved. 18// Use of this source code is governed by a BSD-style license that can be 19// found in the LICENSE file. 20 21#ifndef ${PACKAGE}_BROWSER_DEVTOOLS_DEVTOOLS_PROTOCOL_CONSTANTS_H_ 22#define ${PACKAGE}_BROWSER_DEVTOOLS_DEVTOOLS_PROTOCOL_CONSTANTS_H_ 23 24// THIS FILE IS AUTOGENERATED. DO NOT EDIT. 25// Generated by 26// content/public/browser/devtools_protocol_constants_generator.py from 27// third_party/WebKit/Source/devtools/protocol.json and 28// content/browser/devtools/browser_protocol.json 29 30#include <string> 31 32namespace $package { 33namespace devtools { 34 35extern const char kProtocolVersion[]; 36 37bool IsSupportedProtocolVersion(const std::string& version); 38 39extern const char kResult[]; 40$contents 41 42} // devtools 43} // $package 44 45#endif // ${PACKAGE}_BROWSER_DEVTOOLS_DEVTOOLS_PROTOCOL_CONSTANTS_H_ 46""") 47 48template_cc = string.Template("""\ 49// Copyright 2013 The Chromium Authors. All rights reserved. 50// Use of this source code is governed by a BSD-style license that can be 51// found in the LICENSE file. 52 53// THIS FILE IS AUTOGENERATED. DO NOT EDIT. 54// Generated by 55// content/public/browser/devtools_protocol_constants_generator.py from 56// third_party/WebKit/Source/devtools/protocol.json and 57// content/browser/devtools/browser_protocol.json 58 59#include "base/strings/string_number_conversions.h" 60#include "base/strings/string_util.h" 61#include "$package/browser/devtools/devtools_protocol_constants.h" 62 63namespace $package { 64namespace devtools { 65 66const char kProtocolVersion[] = "$major.$minor"; 67 68bool IsSupportedProtocolVersion(const std::string& version) { 69 std::vector<std::string> tokens; 70 Tokenize(version, ".", &tokens); 71 int major, minor; 72 return tokens.size() == 2 && 73 base::StringToInt(tokens[0], &major) && major == $major && 74 base::StringToInt(tokens[1], &minor) && minor <= $minor; 75} 76 77const char kResult[] = "result"; 78$contents 79 80} // devtools 81} // $package 82""") 83 84def Capitalize(s): 85 return s[:1].capitalize() + s[1:] 86 87references = [] 88 89def CreateNamespace(domain_name, data, keys, prefixes, name = None): 90 result = {} 91 if name: 92 result["kName"] = name 93 for i, key in enumerate(keys): 94 if key in data: 95 for parameter in data[key]: 96 parameter_name = parameter["name"]; 97 result[prefixes[i] + Capitalize(parameter_name)] = parameter_name 98 if "enum" in parameter: 99 enum_name = Capitalize(parameter_name) 100 result[enum_name] = {} 101 for enum in parameter["enum"]: 102 result[enum_name]["kEnum" + Capitalize(enum)] = enum 103 reference = "" 104 if "$ref" in parameter: 105 reference = parameter["$ref"] 106 if "items" in parameter and "$ref" in parameter["items"]: 107 reference = parameter["items"]["$ref"] 108 if reference: 109 if not "." in reference: 110 reference = domain_name + "." + reference 111 references.append(reference) 112 return result 113 114def IsHandledInBrowser(item): 115 return "handlers" in item and "browser" in item["handlers"] 116 117def FormatContents(tree, indent, format_string): 118 outer = dict((key, value) for key, value in tree.iteritems() 119 if not isinstance(value, dict)) 120 inner = dict((key, value) for key, value in tree.iteritems() 121 if isinstance(value, dict)) 122 body = "" 123 body += "".join(indent + format_string.format(key, value) 124 for (key, value) in sorted(outer.items())) 125 body += "".join(FormatNamespace(key, value, indent, format_string) 126 for (key, value) in sorted(inner.items())) 127 return body 128 129def FormatNamespace(title, tree, indent, format_string): 130 if (not tree): 131 return "" 132 body = '\n' + indent + "namespace " + title + " {\n" 133 body += FormatContents(tree, indent + " ", format_string) 134 body += indent + "} // " + title + "\n" 135 return body 136 137def CreateHeader(tree, output_file): 138 contents = FormatContents(tree, "", "extern const char {0}[];\n") 139 output_file.write(template_h.substitute({ 140 "contents": contents, 141 "package": package, 142 "PACKAGE": package.upper() 143 })) 144 145def CreateBody(tree, version, output_file): 146 contents = FormatContents(tree, "", "const char {0}[] = \"{1}\";\n") 147 output_file.write(template_cc.substitute({ 148 "major": version["major"], 149 "minor": version["minor"], 150 "contents": contents, 151 "package": package 152 })) 153 154blink_protocol_data = open(blink_protocol_path).read() 155blink_protocol = json.loads(blink_protocol_data) 156blink_version = blink_protocol["version"] 157 158domains = blink_protocol["domains"] 159 160if browser_protocol_path: 161 browser_protocol_data = open(browser_protocol_path).read() 162 browser_protocol = json.loads(browser_protocol_data) 163 domains = domains + browser_protocol["domains"] 164 165namespace_tree = {} 166 167for domain in domains: 168 domain_value = {} 169 domain_namespace_name = Capitalize(domain["domain"]) 170 if "commands" in domain: 171 for command in domain["commands"]: 172 if (IsHandledInBrowser(command)): 173 domain_value[command["name"]] = CreateNamespace(domain["domain"], 174 command, ["parameters", "returns"], ["kParam", "kResponse"], 175 domain_namespace_name + "." + command["name"]) 176 177 if "events" in domain: 178 for event in domain["events"]: 179 if IsHandledInBrowser(event): 180 domain_value[event["name"]] = CreateNamespace(domain["domain"], 181 event, ["parameters"], ["kParam"], 182 domain_namespace_name + "." + event["name"]) 183 if domain_value: 184 namespace_tree[domain_namespace_name] = domain_value 185 186while (references): 187 reference = references.pop(); 188 path = reference.split("."); 189 parent_namespace = namespace_tree; 190 for path_segment in path[0:-1]: 191 if path_segment not in parent_namespace: 192 parent_namespace[path_segment] = {} 193 parent_namespace = parent_namespace[path_segment] 194 if (path[-1] not in parent_namespace): 195 try: 196 domain = [d for d in domains if d["domain"] == path[0]][0] 197 ref_type = [t for t in domain["types"] if t["id"] == path[1]][0] 198 parent_namespace[ref_type["id"]] = CreateNamespace(path[0], 199 ref_type, ["properties"], ["kParam"]) 200 except IndexError: 201 sys.stderr.write("Failed to resolve type [{0}].\n".format(reference)) 202 sys.exit(1) 203 204for (namespace_name, namespace) in namespace_tree.items(): 205 namespace["kName"] = namespace_name 206 207with open(output_cc_path, "w") as f: 208 CreateBody(namespace_tree, blink_version, f) 209 210with open(output_h_path, "w") as f: 211 CreateHeader(namespace_tree, f) 212