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 6 import sys 7 import string 8 import json 9 10 package = sys.argv[1] 11 output_cc_path = sys.argv[2] 12 output_h_path = sys.argv[3] 13 blink_protocol_path = sys.argv[4] 14 browser_protocol_path = sys.argv[5] if len(sys.argv) > 5 else None 15 16 template_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 32 namespace $package { 33 namespace devtools { 34 35 extern const char kProtocolVersion[]; 36 37 bool IsSupportedProtocolVersion(const std::string& version); 38 39 extern const char kResult[]; 40 $contents 41 42 } // devtools 43 } // $package 44 45 #endif // ${PACKAGE}_BROWSER_DEVTOOLS_DEVTOOLS_PROTOCOL_CONSTANTS_H_ 46 """) 47 48 template_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 63 namespace $package { 64 namespace devtools { 65 66 const char kProtocolVersion[] = "$major.$minor"; 67 68 bool 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 77 const char kResult[] = "result"; 78 $contents 79 80 } // devtools 81 } // $package 82 """) 83 84 def Capitalize(s): 85 return s[:1].capitalize() + s[1:] 86 87 references = [] 88 89 def 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 114 def IsHandledInBrowser(item): 115 return "handlers" in item and "browser" in item["handlers"] 116 117 def 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 129 def 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 137 def 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 145 def 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 154 blink_protocol_data = open(blink_protocol_path).read() 155 blink_protocol = json.loads(blink_protocol_data) 156 blink_version = blink_protocol["version"] 157 158 domains = blink_protocol["domains"] 159 160 if 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 165 namespace_tree = {} 166 167 for 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 186 while (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 204 for (namespace_name, namespace) in namespace_tree.items(): 205 namespace["kName"] = namespace_name 206 207 with open(output_cc_path, "w") as f: 208 CreateBody(namespace_tree, blink_version, f) 209 210 with open(output_h_path, "w") as f: 211 CreateHeader(namespace_tree, f) 212