Web Inspector: clear fixme in generator script
[WebKit-https.git] / Source / WebCore / inspector / CodeGeneratorInspector.py
1 #!/usr/bin/env python
2 # Copyright (c) 2011 Google Inc. All rights reserved.
3 #
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are
6 # met:
7 #
8 #     * Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer.
10 #     * Redistributions in binary form must reproduce the above
11 # copyright notice, this list of conditions and the following disclaimer
12 # in the documentation and/or other materials provided with the
13 # distribution.
14 #     * Neither the name of Google Inc. nor the names of its
15 # contributors may be used to endorse or promote products derived from
16 # this software without specific prior written permission.
17 #
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 import os.path
31 import sys
32 import string
33 import optparse
34 from string import join
35 try:
36     import json
37 except ImportError:
38     import simplejson as json
39
40
41 DOMAIN_DEFINE_NAME_MAP = {
42     "Database": "ENABLE_SQL_DATABASE",
43     "Debugger": "ENABLE_JAVASCRIPT_DEBUGGER",
44     "DOMDebugger": "ENABLE_JAVASCRIPT_DEBUGGER",
45     "Profiler": "ENABLE_JAVASCRIPT_DEBUGGER",
46     "Worker": "ENABLE_WORKERS",
47 }
48
49
50 cmdline_parser = optparse.OptionParser()
51 cmdline_parser.add_option("--defines")
52 cmdline_parser.add_option("--output_h_dir")
53 cmdline_parser.add_option("--output_cpp_dir")
54
55 try:
56     arg_options, arg_values = cmdline_parser.parse_args()
57     if (len(arg_values) != 1):
58         raise Exception("Exactly one plain argument expected (found %s)" % len(arg_values))
59     input_json_filename = arg_values[0]
60     output_header_dirname = arg_options.output_h_dir
61     output_cpp_dirname = arg_options.output_cpp_dir
62     if not output_header_dirname:
63         raise Exception("Output .h directory must be specified")
64     if not output_cpp_dirname:
65         raise Exception("Output .cpp directory must be specified")
66 except Exception, e:
67     sys.stderr.write("Failed to parse command-line arguments: %s\n\n" % e)
68     sys.stderr.write("Usage: <script> Inspector.json --output_h_dir <output_header_dir> --output_cpp_dir <output_cpp_dir> [--defines <defines string>]\n")
69     exit(1)
70
71
72 def dash_to_camelcase(word):
73     return ''.join(x.capitalize() or '-' for x in word.split('-'))
74
75 def parse_defines(str):
76     if not str:
77         return {}
78
79     items = str.split()
80     result = {}
81     for item in items:
82         if item[0] == '"' and item[-1] == '"' and len(item) >= 2:
83             item = item[1:-1]
84         eq_pos = item.find("=")
85         if eq_pos == -1:
86             key = item
87             value = True
88         else:
89             key = item[:eq_pos]
90             value_str = item[eq_pos + 1:]
91             if value_str == "0":
92                 value = False
93             elif value_str == "1":
94                 value = True
95             else:
96                 # Should we support other values?
97                 raise Exception("Unrecognized define value: '%s' (key: '%s')" % (value_str, key))
98         result[key] = value
99     return result
100
101 defines_map = parse_defines(arg_options.defines)
102
103
104 class Capitalizer:
105     @staticmethod
106     def upper_camel_case_to_lower(str):
107         pos = 0
108         while pos < len(str) and str[pos].isupper():
109             pos += 1
110         if pos == 0:
111             return str
112         if pos == 1:
113             return str[0].lower() + str[1:]
114         if pos < len(str):
115             pos -= 1
116         possible_abbreviation = str[0:pos]
117         if possible_abbreviation not in Capitalizer.ABBREVIATION:
118             raise Exception("Unknown abbreviation %s" % possible_abbreviation)
119         str = possible_abbreviation.lower() + str[pos:]
120         return str
121
122     ABBREVIATION = frozenset(["XHR", "DOM", "CSS"])
123
124
125 class DomainNameFixes:
126     @classmethod
127     def get_fixed_data(cls, domain_name):
128         if domain_name in cls.agent_type_map:
129             agent_name_res = cls.agent_type_map[domain_name]
130         else:
131             agent_name_res = "Inspector%sAgent" % domain_name
132
133         field_name_res = Capitalizer.upper_camel_case_to_lower(domain_name) + "Agent"
134
135         class Res(object):
136             agent_type_name = agent_name_res
137             hidden = domain_name in cls.hidden_domains
138             skip_js_bind = domain_name in cls.skip_js_bind_domains
139             agent_field_name = field_name_res
140
141             @staticmethod
142             def is_disabled(defines):
143                 if not domain_name in DOMAIN_DEFINE_NAME_MAP:
144                     # Has not corresponding preprocessor symbol.
145                     return False
146
147                 define_name = DOMAIN_DEFINE_NAME_MAP[domain_name]
148
149                 if not define_name in defines:
150                     # Disabled when not mentioned
151                     return True
152
153                 define_value = defines[define_name]
154                 return not bool(define_value)
155
156         return Res
157
158     skip_js_bind_domains = set(["Runtime", "CSS", "DOMDebugger"])
159     hidden_domains = set(["Inspector"])
160     agent_type_map = {"Network": "InspectorResourceAgent"}
161
162
163 class CParamType(object):
164     def __init__(self, type, setter_format="%s"):
165         self.type = type
166         self.setter_format = setter_format
167
168     def get_text(self):
169         return self.type
170
171     def get_setter_format(self):
172         return self.setter_format
173
174
175 class RawTypes(object):
176     @staticmethod
177     def get(json_type):
178         if json_type == "boolean":
179             return RawTypes.Bool
180         elif json_type == "string":
181             return RawTypes.String
182         elif json_type == "array":
183             return RawTypes.Array
184         elif json_type == "object":
185             return RawTypes.Object
186         elif json_type == "integer":
187             return RawTypes.Int
188         elif json_type == "number":
189             return RawTypes.Number
190         else:
191             raise Exception("Unknown type: %s" % json_type)
192
193     class BaseType(object):
194         @classmethod
195         def get_c_param_type(cls, param_type, optional):
196             return cls.default_c_param_type
197
198         @staticmethod
199         def is_event_param_check_optional():
200             return False
201
202     class String(BaseType):
203         @classmethod
204         def get_c_param_type(cls, param_type, optional):
205             if param_type == ParamType.EVENT:
206                 return cls._ref_c_type
207             else:
208                 return cls._plain_c_type
209
210         @staticmethod
211         def get_getter_name():
212             return "String"
213
214         get_setter_name = get_getter_name
215
216         @staticmethod
217         def get_c_initializer():
218             return "\"\""
219
220         @staticmethod
221         def get_js_bind_type():
222             return "string"
223
224         _plain_c_type = CParamType("String")
225         _ref_c_type = CParamType("const String&")
226
227     class Int(BaseType):
228         @staticmethod
229         def get_getter_name():
230             return "Int"
231
232         @staticmethod
233         def get_setter_name():
234             return "Number"
235
236         @staticmethod
237         def get_c_initializer():
238             return "0"
239
240         @staticmethod
241         def get_js_bind_type():
242             return "number"
243
244         default_c_param_type = CParamType("int")
245
246     class Number(BaseType):
247         @staticmethod
248         def get_getter_name():
249             return "Object"
250
251         @staticmethod
252         def get_setter_name():
253             return "Number"
254
255         @staticmethod
256         def get_c_initializer():
257             raise Exception("Unsupported")
258
259         @staticmethod
260         def get_js_bind_type():
261             raise Exception("Unsupported")
262
263         default_c_param_type = CParamType("double")
264
265     class Bool(BaseType):
266         @classmethod
267         def get_c_param_type(cls, param_type, optional):
268             if (param_type == ParamType.EVENT):
269                 if optional:
270                     return cls._ref_c_type
271                 else:
272                     return cls._plain_c_type
273             else:
274                 return cls._plain_c_type
275
276         @staticmethod
277         def get_getter_name():
278             return "Boolean"
279
280         get_setter_name = get_getter_name
281
282         @staticmethod
283         def get_c_initializer():
284             return "false"
285
286         @staticmethod
287         def get_js_bind_type():
288             return "boolean"
289
290         @staticmethod
291         def is_event_param_check_optional():
292             return True
293
294         _plain_c_type = CParamType("bool")
295         _ref_c_type = CParamType("const bool* const", "*%s")
296
297     class Object(BaseType):
298         @classmethod
299         def get_c_param_type(cls, param_type, optional):
300             if param_type == ParamType.EVENT:
301                 return cls._ref_c_type
302             else:
303                 return cls._plain_c_type
304
305         @staticmethod
306         def get_getter_name():
307             return "Object"
308
309         get_setter_name = get_getter_name
310
311         @staticmethod
312         def get_c_initializer():
313             return "InspectorObject::create()"
314
315         @staticmethod
316         def get_js_bind_type():
317             return "object"
318
319         @staticmethod
320         def is_event_param_check_optional():
321             return True
322
323         _plain_c_type = CParamType("RefPtr<InspectorObject>")
324         _ref_c_type = CParamType("PassRefPtr<InspectorObject>")
325
326     class Array(BaseType):
327         @classmethod
328         def get_c_param_type(cls, param_type, optional):
329             if param_type == ParamType.OUTPUT:
330                 return cls._plain_c_type
331             elif param_type == ParamType.INPUT:
332                 return cls._plain_c_type
333             else:
334                 return cls._ref_c_type
335
336         @staticmethod
337         def get_getter_name():
338             return "Array"
339
340         get_setter_name = get_getter_name
341
342         @staticmethod
343         def get_c_initializer():
344             return "InspectorArray::create()"
345
346         @staticmethod
347         def get_js_bind_type():
348             return "object"
349
350         @staticmethod
351         def is_event_param_check_optional():
352             return True
353
354         _plain_c_type = CParamType("RefPtr<InspectorArray>")
355         _ref_c_type = CParamType("PassRefPtr<InspectorArray>")
356
357
358 class ParamType(object):
359     INPUT = "input"
360     OUTPUT = "output"
361     EVENT = "event"
362
363
364 class TypeData(object):
365     def __init__(self, json_type, json_domain):
366         self.json_type_ = json_type
367         self.json_domain_ = json_domain
368
369         if "type" in json_type:
370             json_type_name = json_type["type"]
371             raw_type = RawTypes.get(json_type_name)
372         else:
373             raise Exception("Unknown type")
374         self.raw_type_ = raw_type
375
376     def get_raw_type(self):
377         return self.raw_type_
378
379
380 class TypeMap:
381     def __init__(self, api):
382         self.map_ = {}
383         for json_domain in api["domains"]:
384             domain_name = json_domain["domain"]
385
386             domain_map = {}
387             self.map_[domain_name] = domain_map
388
389             if "types" in json_domain:
390                 for json_type in json_domain["types"]:
391                     type_name = json_type["id"]
392                     type_data = TypeData(json_type, json_domain)
393                     domain_map[type_name] = type_data
394
395     def get(self, domain_name, type_name):
396         return self.map_[domain_name][type_name]
397
398
399 def resolve_param_raw_type(json_parameter, scope_domain_name):
400     if "$ref" in json_parameter:
401         json_ref = json_parameter["$ref"]
402         type_data = get_ref_data(json_ref, scope_domain_name)
403         return type_data.get_raw_type()
404     elif "type" in json_parameter:
405         json_type = json_parameter["type"]
406         return RawTypes.get(json_type)
407     else:
408         raise Exception("Unknown type")
409
410
411 def get_ref_data(json_ref, scope_domain_name):
412     dot_pos = json_ref.find(".")
413     if dot_pos == -1:
414         domain_name = scope_domain_name
415         type_name = json_ref
416     else:
417         domain_name = json_ref[:dot_pos]
418         type_name = json_ref[dot_pos + 1:]
419
420     return type_map.get(domain_name, type_name)
421
422
423 input_file = open(input_json_filename, "r")
424 json_string = input_file.read()
425 json_api = json.loads(json_string)
426
427
428 class Templates:
429     frontend_domain_class = string.Template(
430 """    class $domainClassName {
431     public:$domainCapabilities
432         $domainClassName(InspectorFrontendChannel* inspectorFrontendChannel) : m_inspectorFrontendChannel(inspectorFrontendChannel) { }
433 ${frontendDomainMethodDeclarations}        void setInspectorFrontendChannel(InspectorFrontendChannel* inspectorFrontendChannel) { m_inspectorFrontendChannel = inspectorFrontendChannel; }
434         InspectorFrontendChannel* getInspectorFrontendChannel() { return m_inspectorFrontendChannel; }
435     private:
436         InspectorFrontendChannel* m_inspectorFrontendChannel;
437     };
438
439     $domainClassName* $domainFieldName() { return &m_$domainFieldName; }
440
441 """)
442
443     backend_method = string.Template(
444 """void InspectorBackendDispatcher::${domainName}_$methodName(long callId, InspectorObject*$requestMessageObject)
445 {
446     RefPtr<InspectorArray> protocolErrors = InspectorArray::create();
447
448     if (!$agentField)
449         protocolErrors->pushString("${domainName} handler is not available.");
450 $methodOutCode
451     ErrorString error;
452 $methodInCode
453     if (!protocolErrors->length())
454         $agentField->$methodName(&error$agentCallParams);
455
456     RefPtr<InspectorObject> result = InspectorObject::create();
457 ${responseCook}    sendResponse(callId, result, String::format("Some arguments of method '%s' can't be processed", "$domainName.$methodName"), protocolErrors, error);
458 }
459 """)
460
461     frontend_method = string.Template("""void InspectorFrontend::$domainName::$eventName($parameters)
462 {
463     RefPtr<InspectorObject> ${eventName}Message = InspectorObject::create();
464     ${eventName}Message->setString("method", "$domainName.$eventName");
465 $code    if (m_inspectorFrontendChannel)
466         m_inspectorFrontendChannel->sendMessageToFrontend(${eventName}Message->toJSONString());
467 }
468 """)
469
470     frontend_h = string.Template("""// Copyright (c) 2011 The Chromium Authors. All rights reserved.
471 // Use of this source code is governed by a BSD-style license that can be
472 // found in the LICENSE file.
473 #ifndef InspectorFrontend_h
474 #define InspectorFrontend_h
475
476 #include <PlatformString.h>
477 #include <wtf/PassRefPtr.h>
478
479 namespace WebCore {
480
481 class InspectorArray;
482 class InspectorFrontendChannel;
483 class InspectorObject;
484
485 typedef String ErrorString;
486
487 class InspectorFrontend {
488 public:
489     InspectorFrontend(InspectorFrontendChannel*);
490
491
492 $domainClassList
493 private:
494     InspectorFrontendChannel* m_inspectorFrontendChannel;
495 ${fieldDeclarations}};
496
497 } // namespace WebCore
498 #endif // !defined(InspectorFrontend_h)
499 """)
500
501     backend_h = string.Template("""// Copyright (c) 2011 The Chromium Authors. All rights reserved.
502 // Use of this source code is governed by a BSD-style license that can be
503 // found in the LICENSE file.
504 #ifndef InspectorBackendDispatcher_h
505 #define InspectorBackendDispatcher_h
506
507 #include <PlatformString.h>
508 #include <wtf/PassRefPtr.h>
509 #include <wtf/RefCounted.h>
510
511 namespace WebCore {
512
513 class InspectorAgent;
514 class InspectorObject;
515 class InspectorArray;
516 class InspectorFrontendChannel;
517
518 $forwardDeclarations
519
520 typedef String ErrorString;
521
522 class InspectorBackendDispatcher: public RefCounted<InspectorBackendDispatcher> {
523 public:
524     InspectorBackendDispatcher(InspectorFrontendChannel* inspectorFrontendChannel$constructorParams)
525         : m_inspectorFrontendChannel(inspectorFrontendChannel)
526 $constructorInit
527     { }
528
529     void clearFrontend() { m_inspectorFrontendChannel = 0; }
530
531     enum CommonErrorCode {
532         ParseError = 0,
533         InvalidRequest,
534         MethodNotFound,
535         InvalidParams,
536         InternalError,
537         ServerError,
538         LastEntry,
539     };
540
541     void reportProtocolError(const long* const callId, CommonErrorCode, const String& errorMessage) const;
542     void reportProtocolError(const long* const callId, CommonErrorCode, const String& errorMessage, PassRefPtr<InspectorArray> data) const;
543     void dispatch(const String& message);
544     static bool getCommandName(const String& message, String* result);
545
546     enum MethodNames {
547
548 $methodNamesEnumContent
549 };
550
551     static const char* commandNames[];
552
553 private:
554     static int getInt(InspectorObject* object, const String& name, bool* valueFound, InspectorArray* protocolErrors);
555     static String getString(InspectorObject* object, const String& name, bool* valueFound, InspectorArray* protocolErrors);
556     static bool getBoolean(InspectorObject* object, const String& name, bool* valueFound, InspectorArray* protocolErrors);
557     static PassRefPtr<InspectorObject> getObject(InspectorObject* object, const String& name, bool* valueFound, InspectorArray* protocolErrors);
558     static PassRefPtr<InspectorArray> getArray(InspectorObject* object, const String& name, bool* valueFound, InspectorArray* protocolErrors);
559     void sendResponse(long callId, PassRefPtr<InspectorObject> result, const String& errorMessage, PassRefPtr<InspectorArray> protocolErrors, ErrorString invocationError);
560
561 $methodDeclarations
562
563     InspectorFrontendChannel* m_inspectorFrontendChannel;
564 $fieldDeclarations
565 };
566
567 } // namespace WebCore
568 #endif // !defined(InspectorBackendDispatcher_h)
569
570
571 """)
572
573     backend_cpp = string.Template("""// Copyright (c) 2011 The Chromium Authors. All rights reserved.
574 // Use of this source code is governed by a BSD-style license that can be
575 // found in the LICENSE file.
576
577
578 #include "config.h"
579 #include "InspectorBackendDispatcher.h"
580 #include <wtf/text/WTFString.h>
581 #include <wtf/text/CString.h>
582
583 #if ENABLE(INSPECTOR)
584
585 #include "InspectorAgent.h"
586 #include "InspectorValues.h"
587 #include "PlatformString.h"
588 #include "InspectorFrontendChannel.h"
589 $includes
590
591 namespace WebCore {
592
593 const char* InspectorBackendDispatcher::commandNames[] = {
594 $methodNameDeclarations
595 };
596
597
598 $methods
599 void InspectorBackendDispatcher::dispatch(const String& message)
600 {
601     RefPtr<InspectorBackendDispatcher> protect = this;
602     typedef void (InspectorBackendDispatcher::*CallHandler)(long callId, InspectorObject* messageObject);
603     typedef HashMap<String, CallHandler> DispatchMap;
604     DEFINE_STATIC_LOCAL(DispatchMap, dispatchMap, );
605     long callId = 0;
606
607     if (dispatchMap.isEmpty()) {
608         static CallHandler handlers[] = {
609 $messageHandlers
610         };
611         size_t length = sizeof(commandNames) / sizeof(commandNames[0]);
612         for (size_t i = 0; i < length; ++i)
613             dispatchMap.add(commandNames[i], handlers[i]);
614     }
615
616     RefPtr<InspectorValue> parsedMessage = InspectorValue::parseJSON(message);
617     if (!parsedMessage) {
618         reportProtocolError(0, ParseError, "Message must be in JSON format");
619         return;
620     }
621
622     RefPtr<InspectorObject> messageObject = parsedMessage->asObject();
623     if (!messageObject) {
624         reportProtocolError(0, InvalidRequest, "Message must be a JSONified object");
625         return;
626     }
627
628     RefPtr<InspectorValue> callIdValue = messageObject->get("id");
629     if (!callIdValue) {
630         reportProtocolError(0, InvalidRequest, "'id' property was not found");
631         return;
632     }
633
634     if (!callIdValue->asNumber(&callId)) {
635         reportProtocolError(0, InvalidRequest, "The type of 'id' property must be number");
636         return;
637     }
638
639     RefPtr<InspectorValue> methodValue = messageObject->get("method");
640     if (!methodValue) {
641         reportProtocolError(&callId, InvalidRequest, "'method' property wasn't found");
642         return;
643     }
644
645     String method;
646     if (!methodValue->asString(&method)) {
647         reportProtocolError(&callId, InvalidRequest, "The type of 'method' property must be string");
648         return;
649     }
650
651     HashMap<String, CallHandler>::iterator it = dispatchMap.find(method);
652     if (it == dispatchMap.end()) {
653         reportProtocolError(&callId, MethodNotFound, "'" + method + "' wasn't found");
654         return;
655     }
656
657     ((*this).*it->second)(callId, messageObject.get());
658 }
659
660 void InspectorBackendDispatcher::sendResponse(long callId, PassRefPtr<InspectorObject> result, const String& errorMessage, PassRefPtr<InspectorArray> protocolErrors, ErrorString invocationError)
661 {
662     if (protocolErrors->length()) {
663         reportProtocolError(&callId, InvalidParams, errorMessage, protocolErrors);
664         return;
665     }
666     if (invocationError.length()) {
667         reportProtocolError(&callId, ServerError, invocationError);
668         return;
669     }
670
671     RefPtr<InspectorObject> responseMessage = InspectorObject::create();
672     responseMessage->setObject("result", result);
673     responseMessage->setNumber("id", callId);
674     if (m_inspectorFrontendChannel)
675         m_inspectorFrontendChannel->sendMessageToFrontend(responseMessage->toJSONString());
676 }
677
678 void InspectorBackendDispatcher::reportProtocolError(const long* const callId, CommonErrorCode code, const String& errorMessage) const
679 {
680     reportProtocolError(callId, code, errorMessage, 0);
681 }
682
683 void InspectorBackendDispatcher::reportProtocolError(const long* const callId, CommonErrorCode code, const String& errorMessage, PassRefPtr<InspectorArray> data) const
684 {
685     DEFINE_STATIC_LOCAL(Vector<int>,s_commonErrors,);
686     if (!s_commonErrors.size()) {
687         s_commonErrors.insert(ParseError, -32700);
688         s_commonErrors.insert(InvalidRequest, -32600);
689         s_commonErrors.insert(MethodNotFound, -32601);
690         s_commonErrors.insert(InvalidParams, -32602);
691         s_commonErrors.insert(InternalError, -32603);
692         s_commonErrors.insert(ServerError, -32000);
693     }
694     ASSERT(code >=0);
695     ASSERT((unsigned)code < s_commonErrors.size());
696     ASSERT(s_commonErrors[code]);
697     RefPtr<InspectorObject> error = InspectorObject::create();
698     error->setNumber("code", s_commonErrors[code]);
699     error->setString("message", errorMessage);
700     ASSERT(error);
701     if (data)
702         error->setArray("data", data);
703     RefPtr<InspectorObject> message = InspectorObject::create();
704     message->setObject("error", error);
705     if (callId)
706         message->setNumber("id", *callId);
707     else
708         message->setValue("id", InspectorValue::null());
709     if (m_inspectorFrontendChannel)
710         m_inspectorFrontendChannel->sendMessageToFrontend(message->toJSONString());
711 }
712
713 int InspectorBackendDispatcher::getInt(InspectorObject* object, const String& name, bool* valueFound, InspectorArray* protocolErrors)
714 {
715     ASSERT(protocolErrors);
716
717     if (valueFound)
718         *valueFound = false;
719
720     int value = 0;
721
722     if (!object) {
723         if (!valueFound) {
724             // Required parameter in missing params container.
725             protocolErrors->pushString(String::format("'params' object must contain required parameter '%s' with type 'Number'.", name.utf8().data()));
726         }
727         return value;
728     }
729
730     InspectorObject::const_iterator end = object->end();
731     InspectorObject::const_iterator valueIterator = object->find(name);
732
733     if (valueIterator == end) {
734         if (!valueFound)
735             protocolErrors->pushString(String::format("Parameter '%s' with type 'Number' was not found.", name.utf8().data()));
736         return value;
737     }
738
739     if (!valueIterator->second->asNumber(&value))
740         protocolErrors->pushString(String::format("Parameter '%s' has wrong type. It must be 'Number'.", name.utf8().data()));
741     else
742         if (valueFound)
743             *valueFound = true;
744     return value;
745 }
746
747 String InspectorBackendDispatcher::getString(InspectorObject* object, const String& name, bool* valueFound, InspectorArray* protocolErrors)
748 {
749     ASSERT(protocolErrors);
750
751     if (valueFound)
752         *valueFound = false;
753
754     String value = "";
755
756     if (!object) {
757         if (!valueFound) {
758             // Required parameter in missing params container.
759             protocolErrors->pushString(String::format("'params' object must contain required parameter '%s' with type 'String'.", name.utf8().data()));
760         }
761         return value;
762     }
763
764     InspectorObject::const_iterator end = object->end();
765     InspectorObject::const_iterator valueIterator = object->find(name);
766
767     if (valueIterator == end) {
768         if (!valueFound)
769             protocolErrors->pushString(String::format("Parameter '%s' with type 'String' was not found.", name.utf8().data()));
770         return value;
771     }
772
773     if (!valueIterator->second->asString(&value))
774         protocolErrors->pushString(String::format("Parameter '%s' has wrong type. It must be 'String'.", name.utf8().data()));
775     else
776         if (valueFound)
777             *valueFound = true;
778     return value;
779 }
780
781 bool InspectorBackendDispatcher::getBoolean(InspectorObject* object, const String& name, bool* valueFound, InspectorArray* protocolErrors)
782 {
783     ASSERT(protocolErrors);
784
785     if (valueFound)
786         *valueFound = false;
787
788     bool value = false;
789
790     if (!object) {
791         if (!valueFound) {
792             // Required parameter in missing params container.
793             protocolErrors->pushString(String::format("'params' object must contain required parameter '%s' with type 'Boolean'.", name.utf8().data()));
794         }
795         return value;
796     }
797
798     InspectorObject::const_iterator end = object->end();
799     InspectorObject::const_iterator valueIterator = object->find(name);
800
801     if (valueIterator == end) {
802         if (!valueFound)
803             protocolErrors->pushString(String::format("Parameter '%s' with type 'Boolean' was not found.", name.utf8().data()));
804         return value;
805     }
806
807     if (!valueIterator->second->asBoolean(&value))
808         protocolErrors->pushString(String::format("Parameter '%s' has wrong type. It must be 'Boolean'.", name.utf8().data()));
809     else
810         if (valueFound)
811             *valueFound = true;
812     return value;
813 }
814
815 PassRefPtr<InspectorObject> InspectorBackendDispatcher::getObject(InspectorObject* object, const String& name, bool* valueFound, InspectorArray* protocolErrors)
816 {
817     ASSERT(protocolErrors);
818
819     if (valueFound)
820         *valueFound = false;
821
822     RefPtr<InspectorObject> value = InspectorObject::create();
823
824     if (!object) {
825         if (!valueFound) {
826             // Required parameter in missing params container.
827             protocolErrors->pushString(String::format("'params' object must contain required parameter '%s' with type 'Object'.", name.utf8().data()));
828         }
829         return value;
830     }
831
832     InspectorObject::const_iterator end = object->end();
833     InspectorObject::const_iterator valueIterator = object->find(name);
834
835     if (valueIterator == end) {
836         if (!valueFound)
837             protocolErrors->pushString(String::format("Parameter '%s' with type 'Object' was not found.", name.utf8().data()));
838         return value;
839     }
840
841     if (!valueIterator->second->asObject(&value))
842         protocolErrors->pushString(String::format("Parameter '%s' has wrong type. It must be 'Object'.", name.utf8().data()));
843     else
844         if (valueFound)
845             *valueFound = true;
846     return value;
847 }
848
849 PassRefPtr<InspectorArray> InspectorBackendDispatcher::getArray(InspectorObject* object, const String& name, bool* valueFound, InspectorArray* protocolErrors)
850 {
851     ASSERT(protocolErrors);
852
853     if (valueFound)
854         *valueFound = false;
855
856     RefPtr<InspectorArray> value = InspectorArray::create();
857
858     if (!object) {
859         if (!valueFound) {
860             // Required parameter in missing params container.
861             protocolErrors->pushString(String::format("'params' object must contain required parameter '%s' with type 'Array'.", name.utf8().data()));
862         }
863         return value;
864     }
865
866     InspectorObject::const_iterator end = object->end();
867     InspectorObject::const_iterator valueIterator = object->find(name);
868
869     if (valueIterator == end) {
870         if (!valueFound)
871             protocolErrors->pushString(String::format("Parameter '%s' with type 'Array' was not found.", name.utf8().data()));
872         return value;
873     }
874
875     if (!valueIterator->second->asArray(&value))
876         protocolErrors->pushString(String::format("Parameter '%s' has wrong type. It must be 'Array'.", name.utf8().data()));
877     else
878         if (valueFound)
879             *valueFound = true;
880     return value;
881 }
882 bool InspectorBackendDispatcher::getCommandName(const String& message, String* result)
883 {
884     RefPtr<InspectorValue> value = InspectorValue::parseJSON(message);
885     if (!value)
886         return false;
887
888     RefPtr<InspectorObject> object = value->asObject();
889     if (!object)
890         return false;
891
892     if (!object->getString("method", result))
893         return false;
894
895     return true;
896 }
897
898
899 } // namespace WebCore
900
901 #endif // ENABLE(INSPECTOR)
902 """)
903
904     frontend_cpp = string.Template("""// Copyright (c) 2011 The Chromium Authors. All rights reserved.
905 // Use of this source code is governed by a BSD-style license that can be
906 // found in the LICENSE file.
907
908
909 #include "config.h"
910 #include "InspectorFrontend.h"
911 #include <wtf/text/WTFString.h>
912 #include <wtf/text/CString.h>
913
914 #if ENABLE(INSPECTOR)
915
916 #include "InspectorFrontendChannel.h"
917 #include "InspectorValues.h"
918 #include "PlatformString.h"
919
920 namespace WebCore {
921
922 $capabilities
923
924 InspectorFrontend::InspectorFrontend(InspectorFrontendChannel* inspectorFrontendChannel)
925     : m_inspectorFrontendChannel(inspectorFrontendChannel)
926 $constructorInit{
927 }
928
929 $methods
930
931 } // namespace WebCore
932
933 #endif // ENABLE(INSPECTOR)
934 """)
935
936     backend_js = string.Template("""// Copyright (c) 2011 The Chromium Authors. All rights reserved.
937 // Use of this source code is governed by a BSD-style license that can be
938 // found in the LICENSE file.
939
940
941 InspectorBackendStub = function()
942 {
943     this._lastCallbackId = 1;
944     this._pendingResponsesCount = 0;
945     this._callbacks = {};
946     this._domainDispatchers = {};
947     this._eventArgs = {};
948     this._replyArgs = {};
949 $delegates$eventArgs$replyArgs$domainDispatchers$capabilities}
950
951 InspectorBackendStub.prototype = {
952     dumpInspectorTimeStats: 0,
953     dumpInspectorProtocolMessages: 0,
954
955     _wrap: function(callback)
956     {
957         var callbackId = this._lastCallbackId++;
958         this._callbacks[callbackId] = callback || function() {};
959         return callbackId;
960     },
961
962     _registerDelegate: function(requestString)
963     {
964         var domainAndFunction = JSON.parse(requestString).method.split(".");
965         var agentName = domainAndFunction[0] + "Agent";
966         if (!window[agentName])
967             window[agentName] = {};
968         window[agentName][domainAndFunction[1]] = this._sendMessageToBackend.bind(this, requestString);
969         window[agentName][domainAndFunction[1]]["invoke"] = this._invoke.bind(this, requestString)
970     },
971
972     _invoke: function(requestString, args, callback)
973     {
974         var request = JSON.parse(requestString);
975         request.params = args;
976         this._wrapCallbackAndSendMessageObject(request, callback);
977     },
978
979     _sendMessageToBackend: function()
980     {
981         var args = Array.prototype.slice.call(arguments);
982         var request = JSON.parse(args.shift());
983         var callback = (args.length && typeof args[args.length - 1] === "function") ? args.pop() : 0;
984         var domainAndMethod = request.method.split(".");
985         var agentMethod = domainAndMethod[0] + "Agent." + domainAndMethod[1];
986
987         var hasParams = false;
988         if (request.params) {
989             for (var key in request.params) {
990                 var typeName = request.params[key].type;
991                 var optionalFlag = request.params[key].optional;
992
993                 if (args.length === 0 && !optionalFlag) {
994                     console.error("Protocol Error: Invalid number of arguments for method '" + agentMethod + "' call. It must have the next arguments '" + JSON.stringify(request.params) + "'.");
995                     return;
996                 }
997
998                 var value = args.shift();
999                 if (optionalFlag && typeof value === "undefined") {
1000                     delete request.params[key];
1001                     continue;
1002                 }
1003
1004                 if (typeof value !== typeName) {
1005                     console.error("Protocol Error: Invalid type of argument '" + key + "' for method '" + agentMethod + "' call. It must be '" + typeName + "' but it is '" + typeof value + "'.");
1006                     return;
1007                 }
1008
1009                 request.params[key] = value;
1010                 hasParams = true;
1011             }
1012             if (!hasParams)
1013                 delete request.params;
1014         }
1015
1016         if (args.length === 1 && !callback) {
1017             if (typeof args[0] !== "undefined") {
1018                 console.error("Protocol Error: Optional callback argument for method '" + agentMethod + "' call must be a function but its type is '" + typeof args[0] + "'.");
1019                 return;
1020             }
1021         }
1022
1023         this._wrapCallbackAndSendMessageObject(request, callback);
1024     },
1025
1026     _wrapCallbackAndSendMessageObject: function(messageObject, callback)
1027     {
1028         messageObject.id = this._wrap(callback);
1029
1030         var wrappedCallback = this._callbacks[messageObject.id];
1031         wrappedCallback.methodName = messageObject.method;
1032
1033         if (this.dumpInspectorTimeStats)
1034             wrappedCallback.sendRequestTime = Date.now();
1035
1036         if (this.dumpInspectorProtocolMessages)
1037             console.log("frontend: " + JSON.stringify(messageObject));
1038
1039         ++this._pendingResponsesCount;
1040         this.sendMessageObjectToBackend(messageObject);
1041     },
1042
1043     sendMessageObjectToBackend: function(messageObject)
1044     {
1045         console.timeStamp(messageObject.method);
1046         var message = JSON.stringify(messageObject);
1047         InspectorFrontendHost.sendMessageToBackend(message);
1048     },
1049
1050     _registerDomainDispatcher: function(domain, dispatcher)
1051     {
1052         this._domainDispatchers[domain] = dispatcher;
1053     },
1054
1055     dispatch: function(message)
1056     {
1057         if (this.dumpInspectorProtocolMessages)
1058             console.log("backend: " + ((typeof message === "string") ? message : JSON.stringify(message)));
1059
1060         var messageObject = (typeof message === "string") ? JSON.parse(message) : message;
1061
1062         if ("id" in messageObject) { // just a response for some request
1063             if (messageObject.error) {
1064                 messageObject.error.__proto__ = {
1065                     getDescription: function()
1066                     {
1067                         switch(this.code) {
1068                             case -32700: return "Parse error";
1069                             case -32600: return "Invalid Request";
1070                             case -32601: return "Method not found";
1071                             case -32602: return "Invalid params";
1072                             case -32603: return "Internal error";;
1073                             case -32000: return "Server error";
1074                         }
1075                     },
1076
1077                     toString: function()
1078                     {
1079                         var description ="Unknown error code";
1080                         return this.getDescription() + "(" + this.code + "): " + this.message + "." + (this.data ? " " + this.data.join(" ") : "");
1081                     },
1082
1083                     getMessage: function()
1084                     {
1085                         return this.message;
1086                     }
1087                 }
1088
1089                 if (messageObject.error.code !== -32000)
1090                     this.reportProtocolError(messageObject);
1091             }
1092
1093             var callback = this._callbacks[messageObject.id];
1094             if (callback) {
1095                 var argumentsArray = [];
1096                 if (messageObject.result) {
1097                     var paramNames = this._replyArgs[callback.methodName];
1098                     if (paramNames) {
1099                         for (var i = 0; i < paramNames.length; ++i)
1100                             argumentsArray.push(messageObject.result[paramNames[i]]);
1101                     }
1102                 }
1103
1104                 var processingStartTime;
1105                 if (this.dumpInspectorTimeStats && callback.methodName)
1106                     processingStartTime = Date.now();
1107
1108                 argumentsArray.unshift(messageObject.error);
1109                 callback.apply(null, argumentsArray);
1110                 --this._pendingResponsesCount;
1111                 delete this._callbacks[messageObject.id];
1112
1113                 if (this.dumpInspectorTimeStats && callback.methodName)
1114                     console.log("time-stats: " + callback.methodName + " = " + (processingStartTime - callback.sendRequestTime) + " + " + (Date.now() - processingStartTime));
1115             }
1116
1117             if (this._scripts && !this._pendingResponsesCount)
1118                 this.runAfterPendingDispatches();
1119
1120             return;
1121         } else {
1122             var method = messageObject.method.split(".");
1123             var domainName = method[0];
1124             var functionName = method[1];
1125             if (!(domainName in this._domainDispatchers)) {
1126                 console.error("Protocol Error: the message is for non-existing domain '" + domainName + "'");
1127                 return;
1128             }
1129             var dispatcher = this._domainDispatchers[domainName];
1130             if (!(functionName in dispatcher)) {
1131                 console.error("Protocol Error: Attempted to dispatch an unimplemented method '" + messageObject.method + "'");
1132                 return;
1133             }
1134
1135             if (!this._eventArgs[messageObject.method]) {
1136                 console.error("Protocol Error: Attempted to dispatch an unspecified method '" + messageObject.method + "'");
1137                 return;
1138             }
1139
1140             var params = [];
1141             if (messageObject.params) {
1142                 var paramNames = this._eventArgs[messageObject.method];
1143                 for (var i = 0; i < paramNames.length; ++i)
1144                     params.push(messageObject.params[paramNames[i]]);
1145             }
1146
1147             var processingStartTime;
1148             if (this.dumpInspectorTimeStats)
1149                 processingStartTime = Date.now();
1150
1151             dispatcher[functionName].apply(dispatcher, params);
1152
1153             if (this.dumpInspectorTimeStats)
1154                 console.log("time-stats: " + messageObject.method + " = " + (Date.now() - processingStartTime));
1155         }
1156     },
1157
1158     reportProtocolError: function(messageObject)
1159     {
1160         console.error("Request with id = " + messageObject.id + " failed. " + messageObject.error);
1161     },
1162
1163     runAfterPendingDispatches: function(script)
1164     {
1165         if (!this._scripts)
1166             this._scripts = [];
1167
1168         if (script)
1169             this._scripts.push(script);
1170
1171         if (!this._pendingResponsesCount) {
1172             var scripts = this._scripts;
1173             this._scripts = []
1174             for (var id = 0; id < scripts.length; ++id)
1175                  scripts[id].call(this);
1176         }
1177     }
1178 }
1179
1180 InspectorBackend = new InspectorBackendStub();""")
1181
1182     param_container_access_code = """
1183     RefPtr<InspectorObject> paramsContainer = requestMessageObject->getObject("params");
1184     InspectorObject* paramsContainerPtr = paramsContainer.get();
1185     InspectorArray* protocolErrorsPtr = protocolErrors.get();
1186 """
1187
1188
1189 type_map = TypeMap(json_api)
1190
1191 class Generator:
1192     frontend_class_field_lines = []
1193     frontend_domain_class_lines = []
1194
1195     method_name_enum_list = []
1196     backend_method_declaration_list = []
1197     backend_method_implementation_list = []
1198     backend_method_name_declaration_list = []
1199     method_handler_list = []
1200     frontend_method_list = []
1201     backend_js_initializer_list = []
1202     backend_js_event_list = []
1203     backend_js_reply_list = []
1204     backend_js_domain_dispatcher_list = []
1205     backend_js_capabilities_list = []
1206
1207     backend_constructor_param_list = []
1208     backend_constructor_init_list = []
1209     backend_field_list = []
1210     backend_forward_list = []
1211     backend_include_list = []
1212     frontend_constructor_init_list = []
1213     frontend_capabilities_constants_list = []
1214
1215     @staticmethod
1216     def go():
1217         for json_domain in json_api["domains"]:
1218             domain_name = json_domain["domain"]
1219             domain_name_lower = domain_name.lower()
1220
1221             domain_data = DomainNameFixes.get_fixed_data(domain_name)
1222
1223             if domain_data.is_disabled(defines_map):
1224                 continue
1225
1226             agent_field_name = domain_data.agent_field_name
1227
1228             frontend_method_declaration_lines = []
1229             domain_capabilities = []
1230             if "capabilities" in json_domain:
1231                 for json_capability in json_domain["capabilities"]:
1232                     name = json_capability["name"]
1233                     capability_variable_name = "capability%s" % dash_to_camelcase(name)
1234                     domain_capabilities.append("\n        static const char* %s;" % capability_variable_name)
1235                     Generator.frontend_capabilities_constants_list.append("const char* InspectorFrontend::%s::%s = \"%s\";" % (domain_name, capability_variable_name, name))
1236                     Generator.backend_js_capabilities_list.append("    %sAgent.%s = \"%s\";\n" % (domain_name, capability_variable_name, name))
1237
1238             if "events" in json_domain:
1239                 for json_event in json_domain["events"]:
1240                     Generator.process_event(json_event, domain_name, frontend_method_declaration_lines)
1241
1242             Generator.frontend_class_field_lines.append("    %s m_%s;\n" % (domain_name, domain_name_lower))
1243             Generator.frontend_constructor_init_list.append("    , m_%s(inspectorFrontendChannel)\n" % domain_name_lower)
1244             Generator.frontend_domain_class_lines.append(Templates.frontend_domain_class.substitute(None,
1245                 domainClassName=domain_name,
1246                 domainFieldName=domain_name_lower,
1247                 domainCapabilities=join(domain_capabilities, "\n"),
1248                 frontendDomainMethodDeclarations=join(frontend_method_declaration_lines, "")))
1249
1250             if "commands" in json_domain:
1251                 for json_command in json_domain["commands"]:
1252                     Generator.process_command(json_command, domain_name, agent_field_name)
1253
1254             if not domain_data.skip_js_bind:
1255                 Generator.backend_js_domain_dispatcher_list.append("    this.register%sDispatcher = this._registerDomainDispatcher.bind(this, \"%s\");\n" % (domain_name, domain_name))
1256
1257         sorted_json_domains = list(json_api["domains"])
1258         sorted_json_domains.sort(key=lambda o: o["domain"])
1259
1260         for json_domain in sorted_json_domains:
1261             domain_name = json_domain["domain"]
1262
1263             domain_data = DomainNameFixes.get_fixed_data(domain_name)
1264             if domain_data.is_disabled(defines_map):
1265                 continue
1266
1267             if domain_data.hidden:
1268                 continue
1269             agent_type_name = domain_data.agent_type_name
1270             agent_field_name = domain_data.agent_field_name
1271             Generator.backend_constructor_param_list.append(", %s* %s" % (agent_type_name, agent_field_name))
1272             Generator.backend_constructor_init_list.append("        , m_%s(%s)" % (agent_field_name, agent_field_name))
1273             Generator.backend_field_list.append("    %s* m_%s;" % (agent_type_name, agent_field_name))
1274             Generator.backend_forward_list.append("class %s;" % agent_type_name)
1275             Generator.backend_include_list.append("#include \"%s.h\"" % agent_type_name)
1276
1277     @staticmethod
1278     def process_event(json_event, domain_name, frontend_method_declaration_lines):
1279         event_name = json_event["name"]
1280         parameter_list = []
1281         method_line_list = []
1282         backend_js_event_param_list = []
1283         if "parameters" in json_event:
1284             method_line_list.append("    RefPtr<InspectorObject> paramsObject = InspectorObject::create();\n")
1285             for json_parameter in json_event["parameters"]:
1286                 parameter_name = json_parameter["name"]
1287
1288                 raw_type = resolve_param_raw_type(json_parameter, domain_name)
1289
1290                 json_optional = "optional" in json_parameter and json_parameter["optional"]
1291
1292                 optional_mask = raw_type.is_event_param_check_optional()
1293                 c_type = raw_type.get_c_param_type(ParamType.EVENT, json_optional)
1294
1295                 setter_type = raw_type.get_setter_name()
1296
1297                 optional = optional_mask and json_optional
1298
1299                 parameter_list.append("%s %s" % (c_type.get_text(), parameter_name))
1300
1301                 setter_argument = c_type.get_setter_format() % parameter_name
1302
1303                 setter_code = "    paramsObject->set%s(\"%s\", %s);\n" % (setter_type, parameter_name, setter_argument)
1304                 if optional:
1305                     setter_code = ("    if (%s)\n    " % parameter_name) + setter_code
1306                 method_line_list.append(setter_code)
1307
1308                 backend_js_event_param_list.append("\"%s\"" % parameter_name)
1309             method_line_list.append("    %sMessage->setObject(\"params\", paramsObject);\n" % event_name)
1310         frontend_method_declaration_lines.append(
1311             "        void %s(%s);\n" % (event_name, join(parameter_list, ", ")))
1312
1313         Generator.frontend_method_list.append(Templates.frontend_method.substitute(None,
1314             domainName=domain_name, eventName=event_name,
1315             parameters=join(parameter_list, ", "),
1316             code=join(method_line_list, "")))
1317
1318         Generator.backend_js_event_list.append("    this._eventArgs[\"%s.%s\"] = [%s];\n" % (
1319             domain_name, event_name, join(backend_js_event_param_list, ", ")))
1320
1321     @staticmethod
1322     def process_command(json_command, domain_name, agent_field_name):
1323         json_command_name = json_command["name"]
1324         Generator.method_name_enum_list.append("        k%s_%sCmd," % (domain_name, json_command["name"]))
1325         Generator.method_handler_list.append("            &InspectorBackendDispatcher::%s_%s," % (domain_name, json_command_name))
1326         Generator.backend_method_declaration_list.append("    void %s_%s(long callId, InspectorObject* requestMessageObject);" % (domain_name, json_command_name))
1327
1328         method_in_code = ""
1329         method_out_code = ""
1330         agent_call_param_list = []
1331         response_cook_list = []
1332         backend_js_reply_param_list = []
1333         request_message_param = ""
1334         js_parameters_text = ""
1335         if "parameters" in json_command:
1336             json_params = json_command["parameters"]
1337             method_in_code += Templates.param_container_access_code
1338             request_message_param = " requestMessageObject"
1339             js_param_list = []
1340
1341             for json_parameter in json_params:
1342                 json_param_name = json_parameter["name"]
1343                 param_raw_type = resolve_param_raw_type(json_parameter, domain_name)
1344
1345                 var_type = param_raw_type.get_c_param_type(ParamType.INPUT, None)
1346                 getter_name = param_raw_type.get_getter_name()
1347
1348                 if "optional" in json_parameter and json_parameter["optional"]:
1349                     code = ("    bool %s_valueFound = false;\n"
1350                             "    %s in_%s = get%s(paramsContainerPtr, \"%s\", &%s_valueFound, protocolErrorsPtr);\n" %
1351                            (json_param_name, var_type.get_text(), json_param_name, getter_name, json_param_name, json_param_name))
1352                     param = ", %s_valueFound ? &in_%s : 0" % (json_param_name, json_param_name)
1353                 else:
1354                     code = ("    %s in_%s = get%s(paramsContainerPtr, \"%s\", 0, protocolErrorsPtr);\n" %
1355                             (var_type.get_text(), json_param_name, getter_name, json_param_name))
1356                     param = ", in_%s" % json_param_name
1357
1358                 method_in_code += code
1359                 agent_call_param_list.append(param)
1360
1361                 js_bind_type = param_raw_type.get_js_bind_type()
1362                 js_param_text = "\"%s\": {\"optional\": %s, \"type\": \"%s\"}" % (
1363                     json_param_name,
1364                     ("true" if ("optional" in json_parameter and json_parameter["optional"]) else "false"),
1365                     js_bind_type)
1366
1367                 js_param_list.append(js_param_text)
1368
1369             js_parameters_text = ", \"params\": {" + join(js_param_list, ", ") + "}"
1370
1371         response_cook_text = ""
1372         if "returns" in json_command:
1373             method_out_code += "\n"
1374             for json_return in json_command["returns"]:
1375
1376                 json_return_name = json_return["name"]
1377                 raw_type = resolve_param_raw_type(json_return, domain_name)
1378                 setter_type = raw_type.get_setter_name()
1379                 initializer = raw_type.get_c_initializer()
1380                 var_type = raw_type.get_c_param_type(ParamType.OUTPUT, None)
1381
1382                 code = "    %s out_%s = %s;\n" % (var_type.get_text(), json_return_name, initializer)
1383                 param = ", &out_%s" % json_return_name
1384                 cook = "        result->set%s(\"%s\", out_%s);\n" % (setter_type, json_return_name, json_return_name)
1385                 if var_type.get_text() == "bool" and "optional" in json_return and json_return["optional"]:
1386                     cook = ("        if (out_%s)\n    " % json_return_name) + cook
1387
1388                 method_out_code += code
1389                 agent_call_param_list.append(param)
1390                 response_cook_list.append(cook)
1391
1392                 backend_js_reply_param_list.append("\"%s\"" % json_return_name)
1393
1394             Generator.backend_js_reply_list.append("    this._replyArgs[\"%s.%s\"] = [%s];\n" % (
1395                 domain_name, json_command_name, join(backend_js_reply_param_list, ", ")))
1396
1397             response_cook_text = "    if (!protocolErrors->length() && !error.length()) {\n%s    }\n" % join(response_cook_list, "")
1398
1399         Generator.backend_method_implementation_list.append(Templates.backend_method.substitute(None,
1400             domainName=domain_name, methodName=json_command_name,
1401             agentField="m_" + agent_field_name,
1402             methodInCode=method_in_code,
1403             methodOutCode=method_out_code,
1404             agentCallParams=join(agent_call_param_list, ""),
1405             requestMessageObject=request_message_param,
1406             responseCook=response_cook_text))
1407         Generator.backend_method_name_declaration_list.append("    \"%s.%s\"," % (domain_name, json_command_name))
1408
1409         Generator.backend_js_initializer_list.append("    this._registerDelegate('{\"method\": \"%s.%s\"%s, \"id\": 0}');\n" % (domain_name, json_command_name, js_parameters_text))
1410
1411 Generator.go()
1412
1413 backend_h_file = open(output_header_dirname + "/InspectorBackendDispatcher.h", "w")
1414 backend_cpp_file = open(output_cpp_dirname + "/InspectorBackendDispatcher.cpp", "w")
1415
1416 frontend_h_file = open(output_header_dirname + "/InspectorFrontend.h", "w")
1417 frontend_cpp_file = open(output_cpp_dirname + "/InspectorFrontend.cpp", "w")
1418
1419 backend_js_file = open(output_cpp_dirname + "/InspectorBackendStub.js", "w")
1420
1421
1422 frontend_h_file.write(Templates.frontend_h.substitute(None,
1423          fieldDeclarations=join(Generator.frontend_class_field_lines, ""),
1424          domainClassList=join(Generator.frontend_domain_class_lines, "")))
1425
1426 backend_h_file.write(Templates.backend_h.substitute(None,
1427     constructorInit=join(Generator.backend_constructor_init_list, "\n"),
1428     constructorParams=join(Generator.backend_constructor_param_list, ""),
1429     methodNamesEnumContent=join(Generator.method_name_enum_list, "\n"),
1430     methodDeclarations=join(Generator.backend_method_declaration_list, "\n"),
1431     fieldDeclarations=join(Generator.backend_field_list, "\n"),
1432     forwardDeclarations=join(Generator.backend_forward_list, "\n")))
1433
1434 frontend_cpp_file.write(Templates.frontend_cpp.substitute(None,
1435     constructorInit=join(Generator.frontend_constructor_init_list, ""),
1436     methods=join(Generator.frontend_method_list, "\n"),
1437     capabilities=join(Generator.frontend_capabilities_constants_list, "\n")))
1438
1439 backend_cpp_file.write(Templates.backend_cpp.substitute(None,
1440     methodNameDeclarations=join(Generator.backend_method_name_declaration_list, "\n"),
1441     includes=join(Generator.backend_include_list, "\n"),
1442     methods=join(Generator.backend_method_implementation_list, "\n"),
1443     messageHandlers=join(Generator.method_handler_list, "\n")))
1444
1445 backend_js_file.write(Templates.backend_js.substitute(None,
1446     delegates=join(Generator.backend_js_initializer_list, ""),
1447     replyArgs=join(Generator.backend_js_reply_list, ""),
1448     eventArgs=join(Generator.backend_js_event_list, ""),
1449     domainDispatchers=join(Generator.backend_js_domain_dispatcher_list, ""),
1450     capabilities=join(Generator.backend_js_capabilities_list, "")))
1451
1452 backend_h_file.close()
1453 backend_cpp_file.close()
1454
1455 frontend_h_file.close()
1456 frontend_cpp_file.close()
1457
1458 backend_js_file.close()