Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / browser / devtools / protocol / devtools_protocol_handler_generator.py
blob6bce71e604749801f63191a919c7c24633d9630f
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.
6 import sys
7 import string
8 import json
10 blink_protocol_path = sys.argv[1]
11 browser_protocol_path = sys.argv[2]
12 output_cc_path = sys.argv[3]
13 output_h_path = sys.argv[4]
15 header = """\
16 // Copyright 2014 The Chromium Authors. All rights reserved.
17 // Use of this source code is governed by a BSD-style license that can be
18 // found in the LICENSE file.
20 // THIS FILE IS AUTOGENERATED. DO NOT EDIT.
21 // Generated by
22 // content/public/browser/devtools_protocol_handler_generator.py from
23 // third_party/WebKit/Source/devtools/protocol.json and
24 // content/browser/devtools/browser_protocol.json
25 """
27 template_h = string.Template(header + """\
29 #ifndef CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DEVTOOLS_PROTOCOL_DISPATCHER_H_
30 #define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DEVTOOLS_PROTOCOL_DISPATCHER_H_
32 #include "content/browser/devtools/protocol/devtools_protocol_client.h"
34 namespace content {
36 class DevToolsProtocolDispatcher;
38 namespace devtools {
40 extern const char kProtocolVersion[];
42 bool IsSupportedProtocolVersion(const std::string& version);
44 template<typename T>
45 base::Value* CreateValue(const T& param) {
46 return new base::FundamentalValue(param);
49 template<class T>
50 base::Value* CreateValue(scoped_ptr<T>& param) {
51 return param.release();
54 template<class T>
55 base::Value* CreateValue(scoped_refptr<T> param) {
56 return param->ToValue().release();
59 template<typename T>
60 base::Value* CreateValue(const std::vector<T> param) {
61 base::ListValue* result = new base::ListValue();
62 for (auto& item : param) {
63 result->Append(CreateValue(item));
65 return result;
68 template<>
69 base::Value* CreateValue(const std::string& param);
71 ${types}\
73 } // namespace devtools
75 class DevToolsProtocolDispatcher {
76 public:
77 using Notifier = DevToolsProtocolClient::RawMessageCallback;
78 using CommandHandler =
79 base::Callback<bool(int, scoped_ptr<base::DictionaryValue>)>;
81 explicit DevToolsProtocolDispatcher(const Notifier& notifier);
82 ~DevToolsProtocolDispatcher();
84 CommandHandler FindCommandHandler(const std::string& method);
86 ${setters}\
88 private:
89 using Response = DevToolsProtocolClient::Response;
90 using CommandHandlers = std::map<std::string, CommandHandler>;
92 ${methods}\
94 Notifier notifier_;
95 DevToolsProtocolClient client_;
96 CommandHandlers command_handlers_;
97 ${fields}\
100 } // namespace content
102 #endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DEVTOOLS_PROTOCOL_DISPATCHER_H_
103 """)
105 tmpl_typedef = string.Template("""\
106 namespace ${domain} {
107 typedef ${param_type} ${declared_name};
108 } // namespace ${domain}
109 """)
111 tmpl_struct = string.Template("""\
112 namespace ${domain} {
113 template<int MASK>
114 struct ${declared_name}Builder
115 : base::RefCounted<${declared_name}Builder<MASK>> {
116 public:
117 enum {
118 kAllSet = 0,
119 ${fields_enum}\
122 ${methods}\
124 static scoped_refptr<${declared_name}Builder<kNoneSet>> Create() {
125 return new ${declared_name}Builder<kNoneSet>();
128 scoped_ptr<base::DictionaryValue> ToValue() {
129 static_assert(MASK == kAllSet, "required properties missing");
130 return make_scoped_ptr(dict_->DeepCopy());
133 private:
134 friend struct ${declared_name}Builder<0>;
135 friend class base::RefCounted<${declared_name}Builder<MASK>>;
136 ~${declared_name}Builder() {}
138 ${declared_name}Builder() : dict_(new base::DictionaryValue()) {
141 template<class T> T* ThisAs() {
142 static_assert(sizeof(*this) == sizeof(T), "cannot cast");
143 return reinterpret_cast<T*>(this);
146 scoped_ptr<base::DictionaryValue> dict_;
149 typedef ${declared_name}Builder<0> ${declared_name};
151 } // namespace ${domain}
152 """)
154 tmpl_builder_setter_req = string.Template("""\
155 scoped_refptr<${declared_name}Builder<MASK & ~k${Param}>>
156 set_${param}(${pass_type} ${param}) {
157 static_assert(MASK & k${Param}, "already set");
158 dict_->Set("${proto_param}", CreateValue(${param}));
159 return ThisAs<${declared_name}Builder<MASK & ~k${Param}>>();
161 """)
163 tmpl_builder_setter_opt = string.Template("""\
164 scoped_refptr<${declared_name}Builder<MASK>>
165 set_${param}(${pass_type} ${param}) {
166 dict_->Set("${proto_param}", CreateValue(${param}));
167 return this;
169 """)
171 tmpl_builder_enum = string.Template("""\
172 k${Param} = 1 << ${ordinal},
173 """)
175 tmpl_builder_none_set = string.Template("""\
176 kNoneSet = ${all_fields}
177 """)
179 tmpl_named_enum = string.Template("""\
180 namespace ${domain} {
181 ${values}\
182 } // namespace ${domain}
183 """)
185 tmpl_inline_enum = string.Template("""\
186 namespace ${domain} {
187 namespace ${subdomain} {
188 ${values}\
189 } // namespace ${subdomain}
190 } // namespace ${domain}
191 """)
193 tmpl_enum_value = string.Template("""\
194 extern const char k${Enum}${Value}[];
195 """)
197 tmpl_enum_value_def = string.Template("""\
198 const char k${Enum}${Value}[] = "${value}";
199 """)
201 tmpl_handler = string.Template("""\
202 namespace ${domain} {
203 class ${Domain}Handler;
204 } // namespace domain
205 """)
207 tmpl_client = string.Template("""\
208 namespace ${domain} {
209 class Client : public DevToolsProtocolClient {
210 public:
211 explicit Client(const RawMessageCallback& raw_message_callback);
212 ~Client() override;
214 ${methods}\
216 } // namespace ${domain}
217 """)
219 tmpl_event = string.Template("""\
220 void ${Command}(
221 scoped_refptr<${Command}Params> params);
222 """)
224 tmpl_response = string.Template("""\
225 void Send${Command}Response(
226 DevToolsCommandId command_id,
227 scoped_refptr<${Command}Response> params);
228 """)
230 tmpl_setter = string.Template("""\
231 void Set${Domain}Handler(
232 devtools::${domain}::${Domain}Handler* ${domain}_handler);
233 """)
235 tmpl_callback = string.Template("""\
236 bool On${Domain}${Command}(
237 DevToolsCommandId command_id,
238 scoped_ptr<base::DictionaryValue> params);
239 """)
241 tmpl_field = string.Template("""\
242 devtools::${domain}::${Domain}Handler* ${domain}_handler_;
243 """)
245 template_cc = string.Template(header + """\
247 #include "base/bind.h"
248 #include "base/strings/string_number_conversions.h"
249 #include "base/strings/string_split.h"
250 ${includes}\
252 namespace content {
254 DevToolsProtocolDispatcher::DevToolsProtocolDispatcher(
255 const Notifier& notifier)
256 : notifier_(notifier),
257 client_(notifier),
258 ${fields_init} {
261 DevToolsProtocolDispatcher::~DevToolsProtocolDispatcher() {
264 DevToolsProtocolDispatcher::CommandHandler
265 DevToolsProtocolDispatcher::FindCommandHandler(const std::string& method) {
266 CommandHandlers::iterator it = command_handlers_.find(method);
267 return it == command_handlers_.end() ? CommandHandler() : it->second;
270 ${methods}\
272 namespace devtools {
274 const char kProtocolVersion[] = "${major}.${minor}";
276 bool IsSupportedProtocolVersion(const std::string& version) {
277 std::vector<base::StringPiece> tokens = base::SplitStringPiece(
278 version, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
279 int major, minor;
280 return tokens.size() == 2 &&
281 base::StringToInt(tokens[0], &major) && major == ${major} &&
282 base::StringToInt(tokens[1], &minor) && minor <= ${minor};
285 template<>
286 base::Value* CreateValue(const std::string& param) {
287 return new base::StringValue(param);
290 ${types}\
292 } // namespace devtools
294 } // namespace content
295 """)
297 tmpl_include = string.Template("""\
298 #include "content/browser/devtools/protocol/${domain}_handler.h"
299 """)
301 tmpl_field_init = string.Template("${domain}_handler_(nullptr)")
303 tmpl_setter_impl = string.Template("""\
304 void DevToolsProtocolDispatcher::Set${Domain}Handler(
305 devtools::${domain}::${Domain}Handler* ${domain}_handler) {
306 DCHECK(!${domain}_handler_);
307 ${domain}_handler_ = ${domain}_handler;
308 ${initializations}\
310 """)
312 tmpl_register = string.Template("""\
313 command_handlers_["${Domain}.${command}"] =
314 base::Bind(
315 &DevToolsProtocolDispatcher::On${TargetDomain}${Command},
316 base::Unretained(this));
317 """)
319 tmpl_init_client = string.Template("""\
320 ${domain}_handler_->SetClient(make_scoped_ptr(
321 new devtools::${domain}::Client(notifier_)));
322 """)
324 tmpl_callback_impl = string.Template("""\
325 bool DevToolsProtocolDispatcher::On${Domain}${Command}(
326 DevToolsCommandId command_id,
327 scoped_ptr<base::DictionaryValue> params) {
328 ${prep}\
329 Response response = ${domain}_handler_->${Command}(${args});
330 scoped_ptr<base::DictionaryValue> protocol_response;
331 if (client_.SendError(command_id, response))
332 return true;
333 if (response.IsFallThrough())
334 return false;
335 scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue());
336 ${wrap}\
337 client_.SendSuccess(command_id, result.Pass());
338 return true;
340 """)
342 tmpl_wrap = string.Template("""\
343 result->Set("${proto_param}", devtools::CreateValue(out_${param}));
344 """)
346 tmpl_callback_async_impl = string.Template("""\
347 bool DevToolsProtocolDispatcher::On${Domain}${Command}(
348 DevToolsCommandId command_id,
349 scoped_ptr<base::DictionaryValue> params) {
350 ${prep}\
351 Response response = ${domain}_handler_->${Command}(${args});
352 if (client_.SendError(command_id, response))
353 return true;
354 return !response.IsFallThrough();
356 """)
358 tmpl_prep_req = string.Template("""\
359 ${raw_type} in_${param}${init};
360 if (!params || !params->Get${Type}("${proto_param}", &in_${param})) {
361 client_.SendError(command_id, Response::InvalidParams("${proto_param}"));
362 return true;
364 """)
366 tmpl_prep_req_list = string.Template("""\
367 base::ListValue* list_${param} = nullptr;
368 if (!params || !params->GetList("${proto_param}", &list_${param})) {
369 client_.SendError(command_id, Response::InvalidParams("${proto_param}"));
370 return true;
372 std::vector<${item_type}> in_${param};
373 for (base::ListValue::const_iterator it =
374 list_${param}->begin(); it != list_${param}->end(); ++it) {
375 ${item_raw_type} item;
376 if (!(*it)->GetAs${ItemType}(&item)) {
377 client_.SendError(command_id, Response::InvalidParams("${proto_param}"));
378 return true;
380 in_${param}.push_back(${item_pass});
382 """)
384 tmpl_prep_opt = string.Template("""\
385 ${raw_type} in_${param}${init};
386 bool ${param}_found = params && params->Get${Type}(
387 "${proto_param}",
388 &in_${param});
389 """)
391 tmpl_prep_output = string.Template("""\
392 ${param_type} out_${param}${init};
393 """)
395 tmpl_arg_name = string.Template("in_${param}")
397 tmpl_arg_req = string.Template("${param_pass}")
399 tmpl_arg_opt = string.Template(
400 "${param}_found ? ${param_pass} : nullptr")
402 tmpl_object_pass = string.Template(
403 "make_scoped_ptr<base::DictionaryValue>(${name}->DeepCopy())")
405 tmpl_client_impl = string.Template("""\
406 namespace ${domain} {
408 Client::Client(const RawMessageCallback& raw_message_callback)
409 : DevToolsProtocolClient(raw_message_callback) {
412 Client::~Client() {
415 ${methods}\
417 } // namespace ${domain}
418 """)
420 tmpl_event_impl = string.Template("""\
421 void Client::${Command}(
422 scoped_refptr<${Command}Params> params) {
423 SendNotification("${Domain}.${command}",
424 params->ToValue().Pass());
426 """)
428 tmpl_response_impl = string.Template("""\
429 void Client::Send${Command}Response(
430 DevToolsCommandId command_id,
431 scoped_refptr<${Command}Response> params) {
432 SendSuccess(command_id, params->ToValue().Pass());
434 """)
436 tmpl_typename = string.Template("devtools::${domain}::${declared_name}")
438 def Capitalize(s):
439 return s[:1].upper() + s[1:]
441 def Uncamelcase(s):
442 result = ""
443 for i, c in enumerate(s):
444 if c.isupper():
445 if (i > 0) and ((i < len(s)-1) and s[i+1].islower() or s[i-1].islower()):
446 result += "_"
447 result += c.lower()
448 else:
449 result += c
450 return result
452 types = {}
453 blink_protocol = json.loads(open(blink_protocol_path, "r").read())
454 browser_protocol = json.loads(open(browser_protocol_path, "r").read())
455 type_decls = []
456 type_impls = []
457 handler_methods = []
458 handler_method_impls = []
459 domain_maps = []
460 redirects = {}
462 all_domains = blink_protocol["domains"] + browser_protocol["domains"]
464 for json_domain in all_domains:
465 if "types" in json_domain:
466 for json_type in json_domain["types"]:
467 types["%s.%s" % (json_domain["domain"], json_type["id"])] = json_type
469 def DeclareStruct(json_properties, mapping):
470 methods = []
471 fields_enum = []
472 enum_items = []
473 req_fields_num = 0
474 for json_prop in json_properties:
475 prop_map = mapping.copy()
476 prop_map["proto_param"] = json_prop["name"]
477 prop_map["param"] = Uncamelcase(json_prop["name"])
478 prop_map["Param"] = Capitalize(json_prop["name"])
479 prop_map["subdomain"] = Uncamelcase(prop_map["declared_name"])
480 del prop_map["declared_name"]
481 ResolveType(json_prop, prop_map)
482 prop_map["declared_name"] = mapping["declared_name"]
483 if json_prop.get("optional"):
484 methods.append(tmpl_builder_setter_opt.substitute(prop_map))
485 else:
486 methods.append(tmpl_builder_setter_req.substitute(prop_map))
487 enum_items.append("k%s" % prop_map["Param"]);
488 fields_enum.append(tmpl_builder_enum.substitute(prop_map,
489 ordinal = req_fields_num))
490 req_fields_num += 1
492 all_fields = "kAllSet"
493 if len(enum_items) > 0:
494 all_fields = " | ".join(enum_items)
495 fields_enum.append(tmpl_builder_none_set.substitute(mapping,
496 all_fields = all_fields))
497 type_decls.append(tmpl_struct.substitute(mapping,
498 methods = "\n".join(methods),
499 fields_enum = "".join(fields_enum)))
501 def DeclareEnum(json, mapping):
502 values = []
503 value_defs = []
504 tmpl_enum = tmpl_inline_enum
505 if "declared_name" in mapping:
506 mapping["Enum"] = mapping["declared_name"]
507 tmpl_enum = tmpl_named_enum
508 else:
509 mapping["Enum"] = Capitalize(mapping["proto_param"])
511 for enum_value in json["enum"]:
512 values.append(tmpl_enum_value.substitute(mapping,
513 Value = Capitalize(enum_value)))
514 value_defs.append(tmpl_enum_value_def.substitute(mapping,
515 value = enum_value,
516 Value = Capitalize(enum_value)))
517 type_decls.append(tmpl_enum.substitute(mapping,
518 values = "".join(values)))
519 type_impls.append(tmpl_enum.substitute(mapping,
520 values = "".join(value_defs)))
522 def ResolveRef(json, mapping):
523 dot_pos = json["$ref"].find(".")
524 if dot_pos == -1:
525 domain_name = mapping["Domain"]
526 type_name = json["$ref"]
527 else:
528 domain_name = json["$ref"][:dot_pos]
529 type_name = json["$ref"][dot_pos + 1:]
530 json_type = types["%s.%s" % (domain_name, type_name)]
531 mapping["declared_name"] = Capitalize(type_name)
532 mapping["Domain"] = domain_name
533 mapping["domain"] = Uncamelcase(domain_name)
534 mapping["param_type"] = tmpl_typename.substitute(mapping)
535 ResolveType(json_type, mapping)
536 if not "___type_declared" in json_type:
537 json_type["___type_declared"] = True;
538 if (json_type.get("type") == "object") and ("properties" in json_type):
539 DeclareStruct(json_type["properties"], mapping)
540 else:
541 if ("enum" in json_type):
542 DeclareEnum(json_type, mapping)
543 type_decls.append(tmpl_typedef.substitute(mapping))
545 def ResolveArray(json, mapping):
546 items_map = mapping.copy()
547 ResolveType(json["items"], items_map)
548 if items_map["Type"] == "List":
549 # TODO(dgozman) Implement this.
550 raise Exception("Nested arrays are not implemented")
551 mapping["param_type"] = "std::vector<%s>" % items_map["param_type"]
552 mapping["Type"] = "List"
553 mapping["pass_type"] = "const %s&" % mapping["param_type"]
554 mapping["storage_type"] = "std::vector<%s>" % items_map["storage_type"]
555 mapping["raw_type"] = mapping["storage_type"]
556 mapping["prep_req"] = tmpl_prep_req_list.substitute(mapping,
557 item_type = items_map["storage_type"],
558 item_init = items_map["init"],
559 item_raw_type = items_map["raw_type"],
560 item_pass = items_map["pass_template"].substitute(name="item", opt=""),
561 ItemType = items_map["Type"])
562 mapping["arg_out"] = "&out_%s" % mapping["param"]
564 def ResolveObject(json, mapping):
565 mapping["Type"] = "Dictionary"
566 mapping["storage_type"] = "scoped_ptr<base::DictionaryValue>"
567 mapping["raw_type"] = "base::DictionaryValue*"
568 mapping["pass_template"] = tmpl_object_pass
569 if "properties" in json:
570 if not "declared_name" in mapping:
571 mapping["declared_name"] = ("%s%s" %
572 (mapping["Command"], Capitalize(mapping["proto_param"])))
573 mapping["param_type"] = ("scoped_refptr<%s>" %
574 tmpl_typename.substitute(mapping))
575 DeclareStruct(json["properties"], mapping)
576 else:
577 mapping["param_type"] = ("scoped_refptr<%s>" %
578 tmpl_typename.substitute(mapping))
579 mapping["pass_type"] = mapping["param_type"]
580 mapping["arg_out"] = "&out_%s" % mapping["param"]
581 else:
582 mapping["param_type"] = "base::DictionaryValue"
583 mapping["pass_type"] = "scoped_ptr<base::DictionaryValue>"
584 mapping["arg_out"] = "out_%s.get()" % mapping["param"]
585 mapping["prep_req"] = tmpl_prep_req.substitute(mapping)
587 def ResolvePrimitive(json, mapping):
588 jsonrpc_type = json["type"]
589 if jsonrpc_type == "boolean":
590 mapping["param_type"] = "bool"
591 mapping["Type"] = "Boolean"
592 mapping["init"] = " = false"
593 elif jsonrpc_type == "integer":
594 mapping["param_type"] = "int"
595 mapping["Type"] = "Integer"
596 mapping["init"] = " = 0"
597 elif jsonrpc_type == "number":
598 mapping["param_type"] = "double"
599 mapping["Type"] = "Double"
600 mapping["init"] = " = 0.0"
601 elif jsonrpc_type == "string":
602 mapping["param_type"] = "std::string"
603 mapping["pass_type"] = "const std::string&"
604 mapping["Type"] = "String"
605 if "enum" in json and not "declared_name" in mapping:
606 if not "subdomain" in mapping:
607 mapping["subdomain"] = Uncamelcase(mapping["command"])
608 DeclareEnum(json, mapping)
609 else:
610 raise Exception("Unknown type: %s" % json_type)
611 mapping["storage_type"] = mapping["param_type"]
612 mapping["raw_type"] = mapping["param_type"]
613 mapping["prep_req"] = tmpl_prep_req.substitute(mapping)
614 if jsonrpc_type != "string":
615 mapping["pass_type"] = mapping["param_type"]
616 mapping["arg_out"] = "&out_%s" % mapping["param"]
618 def ResolveType(json, mapping):
619 mapping["init"] = ""
620 mapping["pass_template"] = string.Template("${opt}${name}")
621 if "$ref" in json:
622 ResolveRef(json, mapping)
623 elif "type" in json:
624 jsonrpc_type = json["type"]
625 if jsonrpc_type == "array":
626 ResolveArray(json, mapping)
627 elif jsonrpc_type == "object":
628 ResolveObject(json, mapping)
629 else:
630 ResolvePrimitive(json, mapping)
631 else:
632 raise Exception("Unknown type at %s.%s %s" %
633 (mapping["Domain"], mapping["command"], mapping["proto_param"]))
635 setters = []
636 fields = []
638 includes = []
639 fields_init = []
641 for json_domain in all_domains:
642 domain_map = {}
643 domain_map["Domain"] = json_domain["domain"]
644 domain_map["domain"] = Uncamelcase(json_domain["domain"])
646 initializations = []
647 client_methods = []
648 client_method_impls = []
649 domain_empty = True
650 domain_needs_client = False
652 if "commands" in json_domain:
653 for json_command in json_domain["commands"]:
654 if (not ("handlers" in json_command) or
655 not ("browser" in json_command["handlers"])):
656 continue
657 domain_empty = False
659 command_map = domain_map.copy()
660 command_map["command"] = json_command["name"]
661 command_map["Command"] = Capitalize(json_command["name"])
663 if "redirect" in json_command:
664 redirect_domain = json_command["redirect"]
665 if not (redirect_domain in redirects):
666 redirects[redirect_domain] = []
667 command_map["TargetDomain"] = redirect_domain
668 redirects[redirect_domain].append(tmpl_register.substitute(command_map))
669 continue
671 command_map["TargetDomain"] = command_map["Domain"]
672 prep = []
673 args = []
675 if "parameters" in json_command:
676 for json_param in json_command["parameters"]:
677 param_map = command_map.copy()
678 param_map["proto_param"] = json_param["name"]
679 param_map["param"] = Uncamelcase(json_param["name"])
680 ResolveType(json_param, param_map)
681 if json_param.get("optional"):
682 if param_map["Type"] in ["List"]:
683 # TODO(vkuzkokov) Implement transformation of base::ListValue
684 # to std::vector and base::DictonaryValue to struct.
685 raise Exception(
686 "Optional array parameters are not implemented")
687 prep.append(tmpl_prep_opt.substitute(param_map))
688 param_pass = param_map["pass_template"].substitute(
689 name=tmpl_arg_name.substitute(param_map),
690 opt="&")
691 args.append(
692 tmpl_arg_opt.substitute(param_map, param_pass=param_pass))
693 else:
694 prep.append(param_map["prep_req"])
695 param_pass = param_map["pass_template"].substitute(
696 name=tmpl_arg_name.substitute(param_map),
697 opt="")
698 args.append(
699 tmpl_arg_req.substitute(param_map, param_pass=param_pass))
701 if json_command.get("async"):
702 domain_needs_client = True
703 json_returns = []
704 if "returns" in json_command:
705 json_returns = json_command["returns"]
706 command_map["declared_name"] = "%sResponse" % command_map["Command"]
707 DeclareStruct(json_returns, command_map)
708 # TODO(vkuzkokov) Pass async callback instance similar to how
709 # InspectorBackendDispatcher does it. This, however, can work
710 # only if Blink and Chrome are in the same repo.
711 args.insert(0, "command_id")
712 handler_method_impls.append(
713 tmpl_callback_async_impl.substitute(command_map,
714 prep = "".join(prep),
715 args = "\n " + ",\n ".join(args)))
716 client_methods.append(tmpl_response.substitute(command_map))
717 client_method_impls.append(tmpl_response_impl.substitute(command_map))
718 else:
719 wrap = []
720 if "returns" in json_command:
721 for json_param in json_command["returns"]:
722 param_map = command_map.copy()
723 param_map["proto_param"] = json_param["name"]
724 param_map["param"] = Uncamelcase(json_param["name"])
725 if json_param.get("optional"):
726 # TODO(vkuzkokov) Implement Optional<T> for value types.
727 raise Exception("Optional return values are not implemented")
728 ResolveType(json_param, param_map)
729 prep.append(tmpl_prep_output.substitute(param_map))
730 args.append(param_map["arg_out"])
731 wrap.append(tmpl_wrap.substitute(param_map))
732 args_str = ""
733 if len(args) > 0:
734 args_str = "\n " + ",\n ".join(args)
735 handler_method_impls.append(tmpl_callback_impl.substitute(command_map,
736 prep = "".join(prep),
737 args = args_str,
738 wrap = "".join(wrap)))
740 initializations.append(tmpl_register.substitute(command_map))
741 handler_methods.append(tmpl_callback.substitute(command_map))
743 if "events" in json_domain:
744 for json_event in json_domain["events"]:
745 if (not ("handlers" in json_event) or
746 not ("browser" in json_event["handlers"])):
747 continue
748 domain_empty = False
749 domain_needs_client = True
751 event_map = domain_map.copy()
752 event_map["command"] = json_event["name"]
753 event_map["Command"] = Capitalize(json_event["name"])
755 json_parameters = []
756 if "parameters" in json_event:
757 json_parameters = json_event["parameters"]
758 event_map["declared_name"] = "%sParams" % event_map["Command"]
759 DeclareStruct(json_parameters, event_map);
761 client_methods.append(tmpl_event.substitute(event_map))
762 client_method_impls.append(tmpl_event_impl.substitute(event_map))
764 if domain_empty:
765 continue
766 type_decls.append(tmpl_handler.substitute(domain_map))
767 setters.append(tmpl_setter.substitute(domain_map))
768 fields.append(tmpl_field.substitute(domain_map))
769 includes.append(tmpl_include.substitute(domain_map))
770 fields_init.append(tmpl_field_init.substitute(domain_map))
771 if domain_needs_client:
772 type_decls.append(tmpl_client.substitute(domain_map,
773 methods = "".join(client_methods)))
774 initializations.append(tmpl_init_client.substitute(domain_map))
775 type_impls.append(tmpl_client_impl.substitute(domain_map,
776 methods = "\n".join(client_method_impls)))
777 domain_map["initializations"] = "".join(initializations)
778 domain_maps.append(domain_map)
780 for domain_map in domain_maps:
781 domain = domain_map["Domain"]
782 if domain in redirects:
783 domain_map["initializations"] += "".join(redirects[domain])
784 handler_method_impls.append(tmpl_setter_impl.substitute(domain_map))
786 output_h_file = open(output_h_path, "w")
787 output_cc_file = open(output_cc_path, "w")
789 output_h_file.write(template_h.substitute({},
790 types = "\n".join(type_decls),
791 setters = "".join(setters),
792 methods = "".join(handler_methods),
793 fields = "".join(fields)))
794 output_h_file.close()
796 output_cc_file.write(template_cc.substitute({},
797 major = blink_protocol["version"]["major"],
798 minor = blink_protocol["version"]["minor"],
799 includes = "".join(sorted(includes)),
800 fields_init = ",\n ".join(fields_init),
801 methods = "\n".join(handler_method_impls),
802 types = "\n".join(type_impls)))
803 output_cc_file.close()