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