Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1018)

Side by Side Diff: content/browser/devtools/devtools_protocol_handler_generator.py

Issue 508973003: DevTools: Protocol handler generator for content (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 #!/usr/bin/env 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 input_json_path = sys.argv[1]
11 output_h_path = sys.argv[2]
12 output_cc_path = sys.argv[3]
13
14 header = """\
15 // Copyright 2014 The Chromium Authors. All rights reserved.
16 // Use of this source code is governed by a BSD-style license that can be
17 // found in the LICENSE file.
18
19 // THIS FILE IS AUTOGENERATED. DO NOT EDIT.
20 // Generated by
21 // content/public/browser/devtools_protocol_handler_generator.py from
22 // third_party/WebKit/Source/devtools/protocol.json
23 """
24
25 template_h = string.Template(header + """\
26
27 #ifndef CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_PROTOCOL_HANDLER_H_
28 #define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_PROTOCOL_HANDLER_H_
29
30 #include "content/browser/devtools/devtools_protocol.h"
31 #include "content/browser/devtools/devtools_protocol_frontend.h"
32
33 namespace content {
34
35 class RenderViewHostImpl;
36 class DevToolsProtocolHandlerImpl;
37
38 namespace devtools {
39
40 ${types}\
41
42 ${handlers}\
43
44 ${frontends}\
45
46 }
47
48 class DevToolsProtocolHandlerImpl : public DevToolsProtocol::Handler {
49 public:
50 typedef DevToolsProtocolFrontend::Response Response;
51 typedef DevToolsProtocolFrontend::ResponseStatus ResponseStatus;
52
53 DevToolsProtocolHandlerImpl();
54 virtual ~DevToolsProtocolHandlerImpl();
55 void OnClientDetached();
56 void SetRenderViewHost(RenderViewHostImpl* host);
57
58 private:
59 ${friends}\
60
61 ${callbacks}\
62
63 ${to_value}\
64
65 ${fields}\
66 };
67
68 } // namespace content
69
70 #endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_PROTOCOL_HANDLER_H_
71 """)
72
73 tmpl_typedef = string.Template("""\
74 typedef ${param_type} ${declared_name};
75 """)
76
77 tmpl_struct = string.Template("""\
78 class ${declared_name} {
79 public:
80 ${declared_name}();
81
82 ${setters}\
83
84 private:
85 friend class ::content::DevToolsProtocolHandlerImpl;
86
87 ${fields}\
88 };
89 """)
90
91 tmpl_struct_setter = string.Template("""\
92 void set_${param}(${pass_type} ${param});
93 """)
94
95 tmpl_struct_field = string.Template("""\
96 ${param_type} ${param}_;
97 bool has_${param}_;
98 """)
99
100 tmpl_handler = string.Template("""\
101 class ${Domain}DomainHandler;
102 """)
103
104 tmpl_frontend = string.Template("""\
105 class ${Domain}DomainFrontend : public DevToolsProtocolFrontend {
106 public:
107 ${Domain}DomainFrontend(const EventCallback& event_callback);
108 virtual ~${Domain}DomainFrontend();
109
110 ${events}\
111 };
112 """)
113
114 tmpl_event = string.Template("""\
115 void ${Event}($params);
116 """)
117
118 tmpl_event_param = string.Template("${pass_type} ${param}")
119
120 tmpl_friend = string.Template("""\
121 friend class devtools::${Domain}DomainFrontend;
122 """)
123
124 tmpl_to_value = string.Template("""\
125 static base::Value* ToValue(${pass_type} src);
126 """)
127
128 tmpl_callback = string.Template("""\
129 scoped_refptr<DevToolsProtocol::Response> On${Domain}${Command}(
130 scoped_refptr<DevToolsProtocol::Command> command);
131 """)
132
133 tmpl_field = string.Template("""\
134 scoped_ptr<devtools::${Domain}DomainHandler> ${domain}_handler_;
135 """)
136
137 template_cc = string.Template(header + """\
138
139 #include "content/browser/devtools/devtools_protocol_handler.h"
140
141 #include "base/bind.h"
142 ${includes}\
143
144 namespace content {
145
146 DevToolsProtocolHandlerImpl::DevToolsProtocolHandlerImpl() {
147 ${initializations}\
148 }
149
150 DevToolsProtocolHandlerImpl::~DevToolsProtocolHandlerImpl() {
151 }
152
153 void DevToolsProtocolHandlerImpl::OnClientDetached() {
154 ${client_detached}\
155 }
156
157 void DevToolsProtocolHandlerImpl::SetRenderViewHost(RenderViewHostImpl* host) {
158 ${set_rvh}\
159 }
160
161 ${callbacks}\
162
163 ${to_value}\
164
165 namespace devtools {
166
167 ${types}\
168
169 ${frontends}\
170
171 } // namespace devtools
172
173 } // namespace content
174 """)
175
176 tmpl_include = string.Template("""\
177 #include "content/browser/devtools/${domain}_domain_handler.h"
178 """)
179
180 tmpl_struct_impl = string.Template("""\
181 ${declared_name}::${declared_name}()
182 : ${fields} {
183 }
184
185 ${setters}\
186 """)
187
188 tmpl_struct_field_init = string.Template("has_${param}_(false)")
189
190
191 tmpl_struct_setter_impl = string.Template("""\
192 void ${declared_name}::set_${param}(${pass_type} ${param}) {
193 ${param}_ = ${param};
194 has_${param}_ = true;
195 }
196 """)
197
198
199 tmpl_frontend_impl = string.Template("""\
200 ${Domain}DomainFrontend::${Domain}DomainFrontend(
201 const EventCallback& event_callback)
202 : DevToolsProtocolFrontend(event_callback) {
203 }
204
205 ${Domain}DomainFrontend::~${Domain}DomainFrontend() {
206 }
207
208 ${events}\
209 """)
210
211 tmpl_event_impl = string.Template("""\
212 void ${Domain}DomainFrontend::${Event}(${params}) {
213 base::DictionaryValue* dict = new base::DictionaryValue();
214 ${wrap}\
215 SendNotification("${Domain}.${event}", dict);
216 }
217 """)
218
219 tmpl_register = string.Template("""\
220 RegisterCommandHandler(
221 "${Domain}.${command}",
222 base::Bind(&DevToolsProtocolHandlerImpl::On${Domain}${Command},
223 base::Unretained(this)));
224 """)
225
226 tmpl_init_handler = string.Template("""\
227 ${domain}_handler_.reset(new devtools::${Domain}DomainHandler());
228 """)
229
230 tmpl_init_frontend = string.Template("""\
231 ${domain}_handler_->SetFrontend(make_scoped_ptr(
232 new devtools::${Domain}DomainFrontend(
233 base::Bind(&DevToolsProtocolHandlerImpl::SendNotification,
234 base::Unretained(this)))));
235 """)
236
237 tmpl_client_detached = string.Template("""\
238 ${domain}_handler_->OnClientDetached();
239 """)
240
241 tmpl_set_rvh = string.Template("""\
242 ${domain}_handler_->SetRenderViewHost(host);
243 """)
244
245 tmpl_to_value_impl = string.Template("""\
246 // static
247 base::Value* DevToolsProtocolHandlerImpl::ToValue(${pass_type} src) {
248 base::DictionaryValue* dict = new base::DictionaryValue();
249 ${dchecks}\
250 ${wrap}\
251 return dict;
252 }
253 """)
254
255 tmpl_dcheck = string.Template("""\
256 DCHECK(src.has_${param}_);
257 """)
258
259 tmpl_callback_impl = string.Template("""\
260 scoped_refptr<DevToolsProtocol::Response>
261 DevToolsProtocolHandlerImpl::On${Domain}${Command}(
262 scoped_refptr<DevToolsProtocol::Command> command) {
263 ${prep}\
264 Response response = ${domain}_handler_->${Command}(${args});
265 switch (response.status_) {
266 case ResponseStatus::RESPONSE_STATUS_FALLTHROUGH:
267 return NULL;
268 case ResponseStatus::RESPONSE_STATUS_OK:
269 break;
270 case ResponseStatus::RESPONSE_STATUS_INVALID_PARAMS:
271 return command->InvalidParamResponse(response.message_);
272 case ResponseStatus::RESPONSE_STATUS_SERVER_ERROR:
273 return command->ServerErrorResponse(response.message_);
274 }
275 base::DictionaryValue* dict = new base::DictionaryValue();
276 ${wrap}\
277 return command->SuccessResponse(dict);
278 }
279 """)
280
281 params_prep = """\
282 base::DictionaryValue* params = command->params();
283 if (!params)
284 return command->NoSuchMethodErrorResponse();
285 """
286
287 tmpl_prep_req = string.Template("""\
288 ${param_type} in_${param}${init};
289 if (!params->Get${Type}("${param}", &in_${param}))
290 return command->InvalidParamResponse("${param}");
291 """)
292
293 tmpl_prep_req_list = string.Template("""\
294 base::ListValue* list_${param} = NULL;
295 if (!params->GetList("${param}", &list_${param}))
296 return command->InvalidParamResponse("${param}");
297 ${param_type} in_${param};
298 for (base::ListValue::const_iterator it = list_${param}->begin();
299 it != list_${param}->end(); ++it) {
300 ${item_type} item${item_init};
301 if (!(*it)->GetAs${ItemType}(&item))
302 return command->InvalidParamResponse("${param}");
303 in_${param}.push_back(item);
304 }
305 """)
306
307 tmpl_prep_opt = string.Template("""\
308 ${param_type} in_${param}${init};
309 bool ${param}_found = params->Get${Type}("${param}", &in_${param});
310 """)
311
312 tmpl_prep_output = string.Template("""\
313 ${param_type} out_${param}${init};
314 """)
315
316 tmpl_arg_req = string.Template("in_${param}")
317
318 tmpl_arg_opt = string.Template("${param}_found ? &in_${param} : NULL")
319
320 tmpl_arg_output = string.Template("&out_${param}")
321
322 tmpl_wrap = string.Template("""\
323 dict->Set${Type}("${param}", ${var_name});
324 """)
325
326 tmpl_wrap_dict = string.Template("""\
327 dict->Set("${param}", DevToolsProtocolHandlerImpl::ToValue(${var_name}));
328 """)
329
330 tmpl_wrap_obj = string.Template("""\
331 dict->Set("${param}", ${var_name});
332 """)
333
334 tmpl_wrap_list = string.Template("""\
335 base::ListValue* list_${param} = new base::ListValue();
336 for (${param_type}::const_iterator it = ${var_name}.begin();
337 it != ${var_name}.end(); ++it) {
338 ${append}\
339 }
340 dict->Set("${param}", list_${param});
341 """)
342
343 tmpl_append = string.Template("""\
344 list_${param}->Append${Type}(*it);
345 """)
346
347 tmpl_append_dict = string.Template("""\
348 list_${param}->Append(DevToolsProtocolHandlerImpl::ToValue(*it));
349 """)
350
351 tmpl_append_obj = string.Template("""\
352 list_${param}->Append(*it);
353 """)
354
355 tmpl_wrap_opt = string.Template("""\
356 if (${cond_name})
357 dict->Set${Type}("${param}", ${var_name});
358 """)
359
360 def Capitalize(s):
361 return s[:1].upper() + s[1:]
362
363 def Decapitalize(s):
364 return s.lower()
365
366 types = {}
367 json_api = json.loads(open(input_json_path, "r").read())
368 type_decls = []
369 type_impls = []
370 to_value = []
371 to_value_impls = []
372
373 for json_domain in json_api["domains"]:
374 if "types" in json_domain:
375 for json_type in json_domain["types"]:
376 types["%s.%s" % (json_domain["domain"], json_type["id"])] = json_type
377
378 def DeclareStruct(json, mapping):
379 setters = []
380 fields = []
381 fields_init = []
382 setter_impls = []
383 dchecks = []
384 wrap = []
385 if "properties" in json:
386 for json_prop in json["properties"]:
387 prop_map = mapping.copy()
388 prop_map.pop("append", None)
389 prop_map.pop("wrap", None)
390 prop_map.pop("prep_req", None)
391 prop_map.pop("pass_type", None)
392 prop_map["param"] = json_prop["name"]
393 prop_map["var_name"] = "src.%s_" % json_prop["name"]
394 ResolveType(json_prop, prop_map)
395 prop_map["declared_name"] = mapping["declared_name"]
396 setters.append(tmpl_struct_setter.substitute(prop_map))
397 fields.append(tmpl_struct_field.substitute(prop_map))
398 fields_init.append(tmpl_struct_field_init.substitute(prop_map))
399 setter_impls.append(tmpl_struct_setter_impl.substitute(prop_map))
400 if json_prop.get("optional"):
401 wrap.append(tmpl_wrap_opt.substitute(prop_map,
402 cond_name = "src.has_%s_" % json_prop["name"]))
403 else:
404 dchecks.append(tmpl_dcheck.substitute(prop_map));
405 wrap.append(prop_map["wrap"])
406 type_decls.append(tmpl_struct.substitute(mapping,
407 setters = "".join(setters),
408 fields = "".join(fields)))
409 type_impls.append(tmpl_struct_impl.substitute(mapping,
410 fields = ",\n ".join(fields_init),
411 setters = "\n".join(setter_impls)))
412 to_value.append(tmpl_to_value.substitute(mapping))
413 to_value_impls.append(tmpl_to_value_impl.substitute(mapping,
414 dchecks = "".join(dchecks),
415 wrap = "".join(wrap)))
416
417 def ResolveType(json, mapping):
418 mapping["init"] = ""
419 if "$ref" in json:
420 dot_pos = json["$ref"].find(".")
421 if dot_pos == -1:
422 domain_name = mapping["Domain"]
423 type_name = json["$ref"]
424 else:
425 domain_name = json["$ref"][:dot_pos]
426 type_name = json["$ref"][dot_pos + 1:]
427 json_type = types["%s.%s" % (domain_name, type_name)]
428 mapping["declared_name"] = "%s%s" % (domain_name, Capitalize(type_name))
429 mapping["param_type"] = "devtools::%s" % mapping["declared_name"]
430 ResolveType(json_type, mapping)
431 if not "___mark" in json_type:
432 json_type["___mark"] = True;
433 if (json_type.get("type") == "object") and ("properties" in json_type):
434 DeclareStruct(json_type, mapping)
435 else:
436 type_decls.append(tmpl_typedef.substitute(mapping))
437 mapping["param_type"] = "devtools::%s" % mapping["declared_name"]
438 elif "type" in json:
439 json_type = json["type"]
440 if json_type == "array":
441 items_map = mapping.copy()
442 ResolveType(json["items"], items_map)
443 mapping["param_type"] = "std::vector<%s>" % items_map["param_type"]
444 mapping["Type"] = "List"
445 mapping["wrap"] = tmpl_wrap_list.substitute(mapping,
446 append = items_map["append"])
447 mapping["prep_req"] = tmpl_prep_req_list.substitute(mapping,
448 item_type = items_map["param_type"],
449 item_init = items_map["init"],
450 ItemType = items_map["Type"])
451 elif json_type == "boolean":
452 mapping["param_type"] = "bool"
453 mapping["Type"] = "Boolean"
454 mapping["init"] = " = false"
455 elif json_type == "integer":
456 mapping["param_type"] = "int"
457 mapping["Type"] = "Integer"
458 mapping["init"] = " = 0"
459 elif json_type == "number":
460 mapping["param_type"] = "double"
461 mapping["Type"] = "Double"
462 mapping["init"] = " = 0.0"
463 elif json_type == "object":
464 mapping["Type"] = "Dictionary"
465 if "properties" in json:
466 if not "declared_name" in mapping:
467 if "Command" in mapping:
468 subdomain = mapping["Command"]
469 elif "Event" in mapping:
470 subdomain = mapping["Event"]
471 else:
472 raise Exception("Unrecognized subdomain")
473 mapping["declared_name"] = ("%s%s%s" %
474 (mapping["Domain"], subdomain, Capitalize(mapping["param"])))
475 mapping["param_type"] = "devtools::%s" % mapping["declared_name"]
476 DeclareStruct(json_type, mapping)
477 mapping["append"] = tmpl_append_dict.substitute(mapping)
478 mapping["wrap"] = tmpl_wrap_dict.substitute(mapping)
479 mapping["pass_type"] = "const %s&" % mapping["param_type"]
480 else:
481 mapping["param_type"] = "base::DictionaryValue*"
482 mapping["append"] = tmpl_append_obj.substitute(mapping)
483 mapping["wrap"] = tmpl_wrap_obj.substitute(mapping)
484 elif json_type == "string":
485 mapping["param_type"] = "std::string"
486 mapping["pass_type"] = "const std::string&"
487 mapping["Type"] = "String"
488 else:
489 raise Exception("Unknown type: %s" % json_type)
490 else:
491 raise Exception("Unknown type at %s.%s %s" %
492 (mapping["Domain"], mapping["command"], mapping["param"]))
493 if not ("wrap" in mapping):
494 mapping["wrap"] = tmpl_wrap.substitute(mapping)
495 if not ("append" in mapping):
496 mapping["append"] = tmpl_append.substitute(mapping)
497 if not ("prep_req" in mapping):
498 mapping["prep_req"] = tmpl_prep_req.substitute(mapping)
499 if not ("pass_type" in mapping):
500 mapping["pass_type"] = mapping["param_type"]
501
502 handlers = []
503 frontends = []
504 friends = []
505 callbacks = []
506 fields = []
507
508 includes = []
509 initializations = []
510 client_detached = []
511 set_rvh = []
512 callback_impls = []
513 frontend_impls = []
514
515 for json_domain in json_api["domains"]:
516 domain_map = {}
517 domain_map["Domain"] = json_domain["domain"]
518 domain_map["domain"] = Decapitalize(json_domain["domain"])
519
520 events = []
521 event_impls = []
522 domain_has_commands = False
523 domain_has_events = False
524
525 if "commands" in json_domain:
526 for json_command in json_domain["commands"]:
527 if (not ("handlers" in json_command) or
528 not ("browser" in json_command["handlers"])):
529 continue
530 domain_has_commands = True
531
532 command_map = domain_map.copy()
533 command_map["command"] = json_command["name"]
534 command_map["Command"] = Capitalize(json_command["name"])
535
536 prep = []
537 args = []
538 wrap = []
539
540 if "parameters" in json_command:
541 for json_param in json_command["parameters"]:
542 param_map = command_map.copy()
543 param_map["param"] = json_param["name"]
544 param_map["var_name"] = "in_%s" % json_param["name"]
545
546 ResolveType(json_param, param_map)
547 if len(prep) == 0:
548 prep.append(params_prep)
549 if json_param.get("optional"):
550 if param_map["Type"] in ["List", "Dictionary"]:
551 raise Exception(
552 "Optional array and object parameters are not implemented")
553 prep.append(tmpl_prep_opt.substitute(param_map))
554 args.append(tmpl_arg_opt.substitute(param_map))
555 else:
556 prep.append(param_map["prep_req"])
557 args.append(tmpl_arg_req.substitute(param_map))
558
559 if "returns" in json_command:
560 for json_param in json_command["returns"]:
561 param_map = command_map.copy()
562 param_map["param"] = json_param["name"]
563 param_map["var_name"] = "out_%s" % json_param["name"]
564
565 if json_param.get("optional"):
566 raise Exception("Optional return values are not implemented")
567 ResolveType(json_param, param_map)
568 prep.append(tmpl_prep_output.substitute(param_map))
569 args.append(tmpl_arg_output.substitute(param_map))
570 wrap.append(param_map["wrap"])
571
572 initializations.append(tmpl_register.substitute(command_map))
573 callbacks.append(tmpl_callback.substitute(command_map))
574 callback_impls.append(tmpl_callback_impl.substitute(command_map,
575 prep = "".join(prep),
576 args = ", ".join(args),
577 wrap = "".join(wrap)))
578
579 if "events" in json_domain:
580 for json_event in json_domain["events"]:
581 if (not ("handlers" in json_event) or
582 not ("browser" in json_event["handlers"])):
583 continue
584 domain_has_events = True
585
586 event_map = domain_map.copy()
587 event_map["event"] = json_event["name"]
588 event_map["Event"] = Capitalize(json_event["name"])
589
590 params = []
591 wrap = []
592
593 if "parameters" in json_event:
594 for json_param in json_event["parameters"]:
595 param_map = event_map.copy()
596 param_map["var_name"] = param_map["param"] = json_param["name"]
597
598 if json_param.get("optional"):
599 raise Exception("Optional event params are not implemented")
600 ResolveType(json_param, param_map)
601 params.append(tmpl_event_param.substitute(param_map))
602 wrap.append(param_map["wrap"])
603
604 event_map["params"] = ", ".join(params)
605 events.append(tmpl_event.substitute(event_map))
606 event_impls.append(tmpl_event_impl.substitute(event_map,
607 wrap = "".join(wrap)))
608
609 if not (domain_has_commands or domain_has_events):
610 continue
611 handlers.append(tmpl_handler.substitute(domain_map))
612 fields.append(tmpl_field.substitute(domain_map))
613 includes.append(tmpl_include.substitute(domain_map))
614 initializations.append(tmpl_init_handler.substitute(domain_map))
615 client_detached.append(tmpl_client_detached.substitute(domain_map))
616 set_rvh.append(tmpl_set_rvh.substitute(domain_map))
617 if domain_has_events:
618 frontends.append(tmpl_frontend.substitute(domain_map,
619 events = "".join(events)))
620 friends.append(tmpl_friend.substitute(domain_map))
621 initializations.append(tmpl_init_frontend.substitute(domain_map))
622 frontend_impls.append(tmpl_frontend_impl.substitute(domain_map,
623 events = "\n".join(event_impls)))
624
625 output_h_file = open(output_h_path, "w")
626 output_cc_file = open(output_cc_path, "w")
627
628 output_h_file.write(template_h.substitute({},
629 types = "\n".join(type_decls),
630 handlers = "".join(handlers),
631 friends = "".join(friends),
632 callbacks = "".join(callbacks),
633 to_value = "".join(to_value),
634 fields = "".join(fields),
635 frontends = "\n".join(frontends)))
636
637 output_cc_file.write(template_cc.substitute({},
638 includes = "".join(includes),
639 initializations = "".join(initializations),
640 client_detached = "".join(client_detached),
641 set_rvh = "".join(set_rvh),
642 callbacks = "\n".join(callback_impls),
643 to_value = "\n".join(to_value_impls),
644 types = "\n".join(type_impls),
645 frontends = "\n".join(frontend_impls)))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698