• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2013 Google Inc. All rights reserved.
2#
3# Redistribution and use in source and binary forms, with or without
4# modification, are permitted provided that the following conditions are
5# met:
6#
7#     * Redistributions of source code must retain the above copyright
8# notice, this list of conditions and the following disclaimer.
9#     * Redistributions in binary form must reproduce the above
10# copyright notice, this list of conditions and the following disclaimer
11# in the documentation and/or other materials provided with the
12# distribution.
13#     * Neither the name of Google Inc. nor the names of its
14# contributors may be used to endorse or promote products derived from
15# this software without specific prior written permission.
16#
17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29# THis file contains string resources for CodeGeneratorInspector.
30# Its syntax is a Python syntax subset, suitable for manual parsing.
31
32frontend_domain_class = (
33"""    class $domainClassName {
34    public:
35        $domainClassName(InspectorFrontendChannel* inspectorFrontendChannel) : m_inspectorFrontendChannel(inspectorFrontendChannel) { }
36${frontendDomainMethodDeclarations}        void setInspectorFrontendChannel(InspectorFrontendChannel* inspectorFrontendChannel) { m_inspectorFrontendChannel = inspectorFrontendChannel; }
37        InspectorFrontendChannel* getInspectorFrontendChannel() { return m_inspectorFrontendChannel; }
38    private:
39        InspectorFrontendChannel* m_inspectorFrontendChannel;
40    };
41
42    $domainClassName* $domainFieldName() { return &m_$domainFieldName; }
43
44""")
45
46backend_method = (
47"""void InspectorBackendDispatcherImpl::${domainName}_$methodName(long callId, JSONObject*$requestMessageObject)
48{
49    RefPtr<JSONArray> protocolErrors = JSONArray::create();
50
51    if (!$agentField)
52        protocolErrors->pushString("${domainName} handler is not available.");
53$methodOutCode
54$methodInCode
55    RefPtr<JSONObject> result = JSONObject::create();
56    RefPtr<JSONValue> resultErrorData;
57    ErrorString error;
58    if (!protocolErrors->length()) {
59        $agentField->$methodName(&error$agentCallParams);
60
61$errorCook${responseCook}
62    }
63    sendResponse(callId, result, commandName($commandNameIndex), protocolErrors, error, resultErrorData);
64}
65""")
66
67frontend_method = ("""void InspectorFrontend::$domainName::$eventName($parameters)
68{
69    RefPtr<JSONObject> jsonMessage = JSONObject::create();
70    jsonMessage->setString("method", "$domainName.$eventName");
71$code    if (m_inspectorFrontendChannel)
72        m_inspectorFrontendChannel->sendMessageToFrontend(jsonMessage->toJSONString());
73}
74""")
75
76callback_main_methods = (
77"""InspectorBackendDispatcher::$agentName::$callbackName::$callbackName(PassRefPtr<InspectorBackendDispatcherImpl> backendImpl, int id) : CallbackBase(backendImpl, id) {}
78
79void InspectorBackendDispatcher::$agentName::$callbackName::sendSuccess($parameters)
80{
81    RefPtr<JSONObject> jsonMessage = JSONObject::create();
82$code    sendIfActive(jsonMessage, ErrorString(), PassRefPtr<JSONValue>());
83}
84""")
85
86callback_failure_method = (
87"""void InspectorBackendDispatcher::$agentName::$callbackName::sendFailure(const ErrorString& error, $parameter)
88{
89    ASSERT(error.length());
90    RefPtr<JSONValue> errorDataValue;
91    if (error) {
92        errorDataValue = $argument;
93    }
94    sendIfActive(0, error, errorDataValue.release());
95}
96""")
97
98
99frontend_h = (
100"""#ifndef InspectorFrontend_h
101#define InspectorFrontend_h
102
103#include "InspectorTypeBuilder.h"
104#include "platform/JSONValues.h"
105#include "wtf/PassRefPtr.h"
106#include "wtf/text/WTFString.h"
107
108namespace WebCore {
109
110class InspectorFrontendChannel;
111
112typedef String ErrorString;
113
114class InspectorFrontend {
115public:
116    InspectorFrontend(InspectorFrontendChannel*);
117
118
119$domainClassList
120private:
121${fieldDeclarations}};
122
123} // namespace WebCore
124#endif // !defined(InspectorFrontend_h)
125""")
126
127backend_h = (
128"""#ifndef InspectorBackendDispatcher_h
129#define InspectorBackendDispatcher_h
130
131#include "InspectorTypeBuilder.h"
132
133#include "wtf/PassRefPtr.h"
134#include "wtf/RefCounted.h"
135#include "wtf/text/WTFString.h"
136
137namespace WebCore {
138
139class InspectorAgent;
140class JSONObject;
141class JSONArray;
142class InspectorFrontendChannel;
143
144typedef String ErrorString;
145
146class InspectorBackendDispatcherImpl;
147
148class InspectorBackendDispatcher: public RefCounted<InspectorBackendDispatcher> {
149public:
150    static PassRefPtr<InspectorBackendDispatcher> create(InspectorFrontendChannel* inspectorFrontendChannel);
151    virtual ~InspectorBackendDispatcher() { }
152
153    class CallbackBase: public RefCounted<CallbackBase> {
154    public:
155        CallbackBase(PassRefPtr<InspectorBackendDispatcherImpl> backendImpl, int id);
156        virtual ~CallbackBase();
157        void sendFailure(const ErrorString&);
158        bool isActive();
159
160    protected:
161        void sendIfActive(PassRefPtr<JSONObject> partialMessage, const ErrorString& invocationError, PassRefPtr<JSONValue> errorData);
162
163    private:
164        void disable() { m_alreadySent = true; }
165
166        RefPtr<InspectorBackendDispatcherImpl> m_backendImpl;
167        int m_id;
168        bool m_alreadySent;
169
170        friend class InspectorBackendDispatcherImpl;
171    };
172
173$agentInterfaces
174$virtualSetters
175
176    virtual void clearFrontend() = 0;
177
178    enum CommonErrorCode {
179        ParseError = 0,
180        InvalidRequest,
181        MethodNotFound,
182        InvalidParams,
183        InternalError,
184        ServerError,
185        LastEntry,
186    };
187
188    void reportProtocolError(const long* const callId, CommonErrorCode, const String& errorMessage) const;
189    virtual void reportProtocolError(const long* const callId, CommonErrorCode, const String& errorMessage, PassRefPtr<JSONValue> data) const = 0;
190    virtual void dispatch(const String& message) = 0;
191    static bool getCommandName(const String& message, String* result);
192
193    enum MethodNames {
194$methodNamesEnumContent
195
196        kMethodNamesEnumSize
197    };
198
199    static const char* commandName(MethodNames);
200
201private:
202    static const char commandNames[];
203    static const size_t commandNamesIndex[];
204};
205
206} // namespace WebCore
207#endif // !defined(InspectorBackendDispatcher_h)
208
209
210""")
211
212backend_cpp = (
213"""
214
215#include "config.h"
216#include "InspectorBackendDispatcher.h"
217
218#include "core/inspector/InspectorAgent.h"
219#include "core/inspector/InspectorFrontendChannel.h"
220#include "core/inspector/JSONParser.h"
221#include "platform/JSONValues.h"
222#include "wtf/text/CString.h"
223#include "wtf/text/WTFString.h"
224
225namespace WebCore {
226
227const char InspectorBackendDispatcher::commandNames[] = {
228$methodNameDeclarations
229};
230
231const size_t InspectorBackendDispatcher::commandNamesIndex[] = {
232$methodNameDeclarationsIndex
233};
234
235const char* InspectorBackendDispatcher::commandName(MethodNames index) {
236    COMPILE_ASSERT(static_cast<int>(kMethodNamesEnumSize) == WTF_ARRAY_LENGTH(commandNamesIndex), command_name_array_problem);
237    return commandNames + commandNamesIndex[index];
238}
239
240class InspectorBackendDispatcherImpl : public InspectorBackendDispatcher {
241public:
242    InspectorBackendDispatcherImpl(InspectorFrontendChannel* inspectorFrontendChannel)
243        : m_inspectorFrontendChannel(inspectorFrontendChannel)
244$constructorInit
245    { }
246
247    virtual void clearFrontend() { m_inspectorFrontendChannel = 0; }
248    virtual void dispatch(const String& message);
249    virtual void reportProtocolError(const long* const callId, CommonErrorCode, const String& errorMessage, PassRefPtr<JSONValue> data) const;
250    using InspectorBackendDispatcher::reportProtocolError;
251
252    void sendResponse(long callId, PassRefPtr<JSONObject> result, const ErrorString&invocationError, PassRefPtr<JSONValue> errorData);
253    bool isActive() { return m_inspectorFrontendChannel; }
254
255$setters
256private:
257$methodDeclarations
258
259    InspectorFrontendChannel* m_inspectorFrontendChannel;
260$fieldDeclarations
261
262    template<typename R, typename V, typename V0>
263    static R getPropertyValueImpl(JSONObject* object, const String& name, bool* valueFound, JSONArray* protocolErrors, V0 initial_value, bool (*as_method)(JSONValue*, V*), const char* type_name);
264
265    static int getInt(JSONObject* object, const String& name, bool* valueFound, JSONArray* protocolErrors);
266    static double getDouble(JSONObject* object, const String& name, bool* valueFound, JSONArray* protocolErrors);
267    static String getString(JSONObject* object, const String& name, bool* valueFound, JSONArray* protocolErrors);
268    static bool getBoolean(JSONObject* object, const String& name, bool* valueFound, JSONArray* protocolErrors);
269    static PassRefPtr<JSONObject> getObject(JSONObject* object, const String& name, bool* valueFound, JSONArray* protocolErrors);
270    static PassRefPtr<JSONArray> getArray(JSONObject* object, const String& name, bool* valueFound, JSONArray* protocolErrors);
271
272    void sendResponse(long callId, PassRefPtr<JSONObject> result, const char* commandName, PassRefPtr<JSONArray> protocolErrors, ErrorString invocationError, PassRefPtr<JSONValue> errorData);
273
274};
275
276$methods
277
278PassRefPtr<InspectorBackendDispatcher> InspectorBackendDispatcher::create(InspectorFrontendChannel* inspectorFrontendChannel)
279{
280    return adoptRef(new InspectorBackendDispatcherImpl(inspectorFrontendChannel));
281}
282
283
284void InspectorBackendDispatcherImpl::dispatch(const String& message)
285{
286    RefPtr<InspectorBackendDispatcher> protect = this;
287    typedef void (InspectorBackendDispatcherImpl::*CallHandler)(long callId, JSONObject* messageObject);
288    typedef HashMap<String, CallHandler> DispatchMap;
289    DEFINE_STATIC_LOCAL(DispatchMap, dispatchMap, );
290    long callId = 0;
291
292    if (dispatchMap.isEmpty()) {
293        static CallHandler handlers[] = {
294$messageHandlers
295        };
296        for (size_t i = 0; i < kMethodNamesEnumSize; ++i)
297            dispatchMap.add(commandName(static_cast<MethodNames>(i)), handlers[i]);
298    }
299
300    RefPtr<JSONValue> parsedMessage = parseJSON(message);
301    if (!parsedMessage) {
302        reportProtocolError(0, ParseError, "Message must be in JSON format");
303        return;
304    }
305
306    RefPtr<JSONObject> messageObject = parsedMessage->asObject();
307    if (!messageObject) {
308        reportProtocolError(0, InvalidRequest, "Message must be a JSONified object");
309        return;
310    }
311
312    RefPtr<JSONValue> callIdValue = messageObject->get("id");
313    if (!callIdValue) {
314        reportProtocolError(0, InvalidRequest, "'id' property was not found");
315        return;
316    }
317
318    if (!callIdValue->asNumber(&callId)) {
319        reportProtocolError(0, InvalidRequest, "The type of 'id' property must be number");
320        return;
321    }
322
323    RefPtr<JSONValue> methodValue = messageObject->get("method");
324    if (!methodValue) {
325        reportProtocolError(&callId, InvalidRequest, "'method' property wasn't found");
326        return;
327    }
328
329    String method;
330    if (!methodValue->asString(&method)) {
331        reportProtocolError(&callId, InvalidRequest, "The type of 'method' property must be string");
332        return;
333    }
334
335    HashMap<String, CallHandler>::iterator it = dispatchMap.find(method);
336    if (it == dispatchMap.end()) {
337        reportProtocolError(&callId, MethodNotFound, "'" + method + "' wasn't found");
338        return;
339    }
340
341    ((*this).*it->value)(callId, messageObject.get());
342}
343
344void InspectorBackendDispatcherImpl::sendResponse(long callId, PassRefPtr<JSONObject> result, const char* commandName, PassRefPtr<JSONArray> protocolErrors, ErrorString invocationError, PassRefPtr<JSONValue> errorData)
345{
346    if (protocolErrors->length()) {
347        String errorMessage = String::format("Some arguments of method '%s' can't be processed", commandName);
348        reportProtocolError(&callId, InvalidParams, errorMessage, protocolErrors);
349        return;
350    }
351    sendResponse(callId, result, invocationError, errorData);
352}
353
354void InspectorBackendDispatcherImpl::sendResponse(long callId, PassRefPtr<JSONObject> result, const ErrorString& invocationError, PassRefPtr<JSONValue> errorData)
355{
356    if (invocationError.length()) {
357        reportProtocolError(&callId, ServerError, invocationError, errorData);
358        return;
359    }
360
361    RefPtr<JSONObject> responseMessage = JSONObject::create();
362    responseMessage->setObject("result", result);
363    responseMessage->setNumber("id", callId);
364    if (m_inspectorFrontendChannel)
365        m_inspectorFrontendChannel->sendMessageToFrontend(responseMessage->toJSONString());
366}
367
368void InspectorBackendDispatcher::reportProtocolError(const long* const callId, CommonErrorCode code, const String& errorMessage) const
369{
370    reportProtocolError(callId, code, errorMessage, PassRefPtr<JSONValue>());
371}
372
373void InspectorBackendDispatcherImpl::reportProtocolError(const long* const callId, CommonErrorCode code, const String& errorMessage, PassRefPtr<JSONValue> data) const
374{
375    DEFINE_STATIC_LOCAL(Vector<int>,s_commonErrors,);
376    if (!s_commonErrors.size()) {
377        s_commonErrors.insert(ParseError, -32700);
378        s_commonErrors.insert(InvalidRequest, -32600);
379        s_commonErrors.insert(MethodNotFound, -32601);
380        s_commonErrors.insert(InvalidParams, -32602);
381        s_commonErrors.insert(InternalError, -32603);
382        s_commonErrors.insert(ServerError, -32000);
383    }
384    ASSERT(code >=0);
385    ASSERT((unsigned)code < s_commonErrors.size());
386    ASSERT(s_commonErrors[code]);
387    RefPtr<JSONObject> error = JSONObject::create();
388    error->setNumber("code", s_commonErrors[code]);
389    error->setString("message", errorMessage);
390    ASSERT(error);
391    if (data)
392        error->setValue("data", data);
393    RefPtr<JSONObject> message = JSONObject::create();
394    message->setObject("error", error);
395    if (callId)
396        message->setNumber("id", *callId);
397    else
398        message->setValue("id", JSONValue::null());
399    if (m_inspectorFrontendChannel)
400        m_inspectorFrontendChannel->sendMessageToFrontend(message->toJSONString());
401}
402
403template<typename R, typename V, typename V0>
404R InspectorBackendDispatcherImpl::getPropertyValueImpl(JSONObject* object, const String& name, bool* valueFound, JSONArray* protocolErrors, V0 initial_value, bool (*as_method)(JSONValue*, V*), const char* type_name)
405{
406    ASSERT(protocolErrors);
407
408    if (valueFound)
409        *valueFound = false;
410
411    V value = initial_value;
412
413    if (!object) {
414        if (!valueFound) {
415            // Required parameter in missing params container.
416            protocolErrors->pushString(String::format("'params' object must contain required parameter '%s' with type '%s'.", name.utf8().data(), type_name));
417        }
418        return value;
419    }
420
421    JSONObject::const_iterator end = object->end();
422    JSONObject::const_iterator valueIterator = object->find(name);
423
424    if (valueIterator == end) {
425        if (!valueFound)
426            protocolErrors->pushString(String::format("Parameter '%s' with type '%s' was not found.", name.utf8().data(), type_name));
427        return value;
428    }
429
430    if (!as_method(valueIterator->value.get(), &value))
431        protocolErrors->pushString(String::format("Parameter '%s' has wrong type. It must be '%s'.", name.utf8().data(), type_name));
432    else
433        if (valueFound)
434            *valueFound = true;
435    return value;
436}
437
438struct AsMethodBridges {
439    static bool asInt(JSONValue* value, int* output) { return value->asNumber(output); }
440    static bool asDouble(JSONValue* value, double* output) { return value->asNumber(output); }
441    static bool asString(JSONValue* value, String* output) { return value->asString(output); }
442    static bool asBoolean(JSONValue* value, bool* output) { return value->asBoolean(output); }
443    static bool asObject(JSONValue* value, RefPtr<JSONObject>* output) { return value->asObject(output); }
444    static bool asArray(JSONValue* value, RefPtr<JSONArray>* output) { return value->asArray(output); }
445};
446
447int InspectorBackendDispatcherImpl::getInt(JSONObject* object, const String& name, bool* valueFound, JSONArray* protocolErrors)
448{
449    return getPropertyValueImpl<int, int, int>(object, name, valueFound, protocolErrors, 0, AsMethodBridges::asInt, "Number");
450}
451
452double InspectorBackendDispatcherImpl::getDouble(JSONObject* object, const String& name, bool* valueFound, JSONArray* protocolErrors)
453{
454    return getPropertyValueImpl<double, double, double>(object, name, valueFound, protocolErrors, 0, AsMethodBridges::asDouble, "Number");
455}
456
457String InspectorBackendDispatcherImpl::getString(JSONObject* object, const String& name, bool* valueFound, JSONArray* protocolErrors)
458{
459    return getPropertyValueImpl<String, String, String>(object, name, valueFound, protocolErrors, "", AsMethodBridges::asString, "String");
460}
461
462bool InspectorBackendDispatcherImpl::getBoolean(JSONObject* object, const String& name, bool* valueFound, JSONArray* protocolErrors)
463{
464    return getPropertyValueImpl<bool, bool, bool>(object, name, valueFound, protocolErrors, false, AsMethodBridges::asBoolean, "Boolean");
465}
466
467PassRefPtr<JSONObject> InspectorBackendDispatcherImpl::getObject(JSONObject* object, const String& name, bool* valueFound, JSONArray* protocolErrors)
468{
469    return getPropertyValueImpl<PassRefPtr<JSONObject>, RefPtr<JSONObject>, JSONObject*>(object, name, valueFound, protocolErrors, 0, AsMethodBridges::asObject, "Object");
470}
471
472PassRefPtr<JSONArray> InspectorBackendDispatcherImpl::getArray(JSONObject* object, const String& name, bool* valueFound, JSONArray* protocolErrors)
473{
474    return getPropertyValueImpl<PassRefPtr<JSONArray>, RefPtr<JSONArray>, JSONArray*>(object, name, valueFound, protocolErrors, 0, AsMethodBridges::asArray, "Array");
475}
476
477bool InspectorBackendDispatcher::getCommandName(const String& message, String* result)
478{
479    RefPtr<JSONValue> value = parseJSON(message);
480    if (!value)
481        return false;
482
483    RefPtr<JSONObject> object = value->asObject();
484    if (!object)
485        return false;
486
487    if (!object->getString("method", result))
488        return false;
489
490    return true;
491}
492
493InspectorBackendDispatcher::CallbackBase::CallbackBase(PassRefPtr<InspectorBackendDispatcherImpl> backendImpl, int id)
494    : m_backendImpl(backendImpl), m_id(id), m_alreadySent(false) {}
495
496InspectorBackendDispatcher::CallbackBase::~CallbackBase() {}
497
498void InspectorBackendDispatcher::CallbackBase::sendFailure(const ErrorString& error)
499{
500    ASSERT(error.length());
501    sendIfActive(0, error, PassRefPtr<JSONValue>());
502}
503
504bool InspectorBackendDispatcher::CallbackBase::isActive()
505{
506    return !m_alreadySent && m_backendImpl->isActive();
507}
508
509void InspectorBackendDispatcher::CallbackBase::sendIfActive(PassRefPtr<JSONObject> partialMessage, const ErrorString& invocationError, PassRefPtr<JSONValue> errorData)
510{
511    if (m_alreadySent)
512        return;
513    m_backendImpl->sendResponse(m_id, partialMessage, invocationError, errorData);
514    m_alreadySent = true;
515}
516
517} // namespace WebCore
518
519""")
520
521frontend_cpp = (
522"""
523
524#include "config.h"
525#include "InspectorFrontend.h"
526
527#include "core/inspector/InspectorFrontendChannel.h"
528#include "platform/JSONValues.h"
529#include "wtf/text/CString.h"
530#include "wtf/text/WTFString.h"
531
532namespace WebCore {
533
534InspectorFrontend::InspectorFrontend(InspectorFrontendChannel* inspectorFrontendChannel)
535    : $constructorInit{
536}
537
538$methods
539
540} // namespace WebCore
541
542""")
543
544typebuilder_h = (
545"""
546#ifndef InspectorTypeBuilder_h
547#define InspectorTypeBuilder_h
548
549#include "platform/JSONValues.h"
550#include "wtf/Assertions.h"
551#include "wtf/PassRefPtr.h"
552
553namespace WebCore {
554
555namespace TypeBuilder {
556
557template<typename T>
558class OptOutput {
559public:
560    OptOutput() : m_assigned(false) { }
561
562    void operator=(T value)
563    {
564        m_value = value;
565        m_assigned = true;
566    }
567
568    bool isAssigned() { return m_assigned; }
569
570    T getValue()
571    {
572        ASSERT(isAssigned());
573        return m_value;
574    }
575
576private:
577    T m_value;
578    bool m_assigned;
579
580    WTF_MAKE_NONCOPYABLE(OptOutput);
581};
582
583
584// A small transient wrapper around int type, that can be used as a funciton parameter type
585// cleverly disallowing C++ implicit casts from float or double.
586class ExactlyInt {
587public:
588    template<typename T>
589    ExactlyInt(T t) : m_value(cast_to_int<T>(t)) {}
590
591    ExactlyInt() {}
592
593    operator int() { return m_value; }
594private:
595    int m_value;
596
597    template<typename T>
598    static int cast_to_int(T) { return T::default_case_cast_is_not_supported(); }
599};
600
601template<>
602inline int ExactlyInt::cast_to_int<int>(int i) { return i; }
603
604template<>
605inline int ExactlyInt::cast_to_int<unsigned int>(unsigned int i) { return i; }
606
607class RuntimeCastHelper {
608public:
609#if $validatorIfdefName
610    template<JSONValue::Type TYPE>
611    static void assertType(JSONValue* value)
612    {
613        ASSERT(value->type() == TYPE);
614    }
615    static void assertAny(JSONValue*);
616    static void assertInt(JSONValue* value);
617#endif
618};
619
620
621// This class provides "Traits" type for the input type T. It is programmed using C++ template specialization
622// technique. By default it simply takes "ItemTraits" type from T, but it doesn't work with the base types.
623template<typename T>
624struct ArrayItemHelper {
625    typedef typename T::ItemTraits Traits;
626};
627
628template<typename T>
629class Array : public JSONArrayBase {
630private:
631    Array() { }
632
633    JSONArray* openAccessors() {
634        COMPILE_ASSERT(sizeof(JSONArray) == sizeof(Array<T>), cannot_cast);
635        return static_cast<JSONArray*>(static_cast<JSONArrayBase*>(this));
636    }
637
638public:
639    void addItem(PassRefPtr<T> value)
640    {
641        ArrayItemHelper<T>::Traits::pushRefPtr(this->openAccessors(), value);
642    }
643
644    void addItem(T value)
645    {
646        ArrayItemHelper<T>::Traits::pushRaw(this->openAccessors(), value);
647    }
648
649    static PassRefPtr<Array<T> > create()
650    {
651        return adoptRef(new Array<T>());
652    }
653
654    static PassRefPtr<Array<T> > runtimeCast(PassRefPtr<JSONValue> value)
655    {
656        RefPtr<JSONArray> array;
657        bool castRes = value->asArray(&array);
658        ASSERT_UNUSED(castRes, castRes);
659#if $validatorIfdefName
660        assertCorrectValue(array.get());
661#endif  // $validatorIfdefName
662        COMPILE_ASSERT(sizeof(Array<T>) == sizeof(JSONArray), type_cast_problem);
663        return static_cast<Array<T>*>(static_cast<JSONArrayBase*>(array.get()));
664    }
665
666#if $validatorIfdefName
667    static void assertCorrectValue(JSONValue* value)
668    {
669        RefPtr<JSONArray> array;
670        bool castRes = value->asArray(&array);
671        ASSERT_UNUSED(castRes, castRes);
672        for (unsigned i = 0; i < array->length(); i++)
673            ArrayItemHelper<T>::Traits::template assertCorrectValue<T>(array->get(i).get());
674    }
675
676#endif // $validatorIfdefName
677};
678
679struct StructItemTraits {
680    static void pushRefPtr(JSONArray* array, PassRefPtr<JSONValue> value)
681    {
682        array->pushValue(value);
683    }
684
685#if $validatorIfdefName
686    template<typename T>
687    static void assertCorrectValue(JSONValue* value) {
688        T::assertCorrectValue(value);
689    }
690#endif  // $validatorIfdefName
691};
692
693template<>
694struct ArrayItemHelper<String> {
695    struct Traits {
696        static void pushRaw(JSONArray* array, const String& value)
697        {
698            array->pushString(value);
699        }
700
701#if $validatorIfdefName
702        template<typename T>
703        static void assertCorrectValue(JSONValue* value) {
704            RuntimeCastHelper::assertType<JSONValue::TypeString>(value);
705        }
706#endif  // $validatorIfdefName
707    };
708};
709
710template<>
711struct ArrayItemHelper<int> {
712    struct Traits {
713        static void pushRaw(JSONArray* array, int value)
714        {
715            array->pushInt(value);
716        }
717
718#if $validatorIfdefName
719        template<typename T>
720        static void assertCorrectValue(JSONValue* value) {
721            RuntimeCastHelper::assertInt(value);
722        }
723#endif  // $validatorIfdefName
724    };
725};
726
727template<>
728struct ArrayItemHelper<double> {
729    struct Traits {
730        static void pushRaw(JSONArray* array, double value)
731        {
732            array->pushNumber(value);
733        }
734
735#if $validatorIfdefName
736        template<typename T>
737        static void assertCorrectValue(JSONValue* value) {
738            RuntimeCastHelper::assertType<JSONValue::TypeNumber>(value);
739        }
740#endif  // $validatorIfdefName
741    };
742};
743
744template<>
745struct ArrayItemHelper<bool> {
746    struct Traits {
747        static void pushRaw(JSONArray* array, bool value)
748        {
749            array->pushBoolean(value);
750        }
751
752#if $validatorIfdefName
753        template<typename T>
754        static void assertCorrectValue(JSONValue* value) {
755            RuntimeCastHelper::assertType<JSONValue::TypeBoolean>(value);
756        }
757#endif  // $validatorIfdefName
758    };
759};
760
761template<>
762struct ArrayItemHelper<JSONValue> {
763    struct Traits {
764        static void pushRefPtr(JSONArray* array, PassRefPtr<JSONValue> value)
765        {
766            array->pushValue(value);
767        }
768
769#if $validatorIfdefName
770        template<typename T>
771        static void assertCorrectValue(JSONValue* value) {
772            RuntimeCastHelper::assertAny(value);
773        }
774#endif  // $validatorIfdefName
775    };
776};
777
778template<>
779struct ArrayItemHelper<JSONObject> {
780    struct Traits {
781        static void pushRefPtr(JSONArray* array, PassRefPtr<JSONValue> value)
782        {
783            array->pushValue(value);
784        }
785
786#if $validatorIfdefName
787        template<typename T>
788        static void assertCorrectValue(JSONValue* value) {
789            RuntimeCastHelper::assertType<JSONValue::TypeObject>(value);
790        }
791#endif  // $validatorIfdefName
792    };
793};
794
795template<>
796struct ArrayItemHelper<JSONArray> {
797    struct Traits {
798        static void pushRefPtr(JSONArray* array, PassRefPtr<JSONArray> value)
799        {
800            array->pushArray(value);
801        }
802
803#if $validatorIfdefName
804        template<typename T>
805        static void assertCorrectValue(JSONValue* value) {
806            RuntimeCastHelper::assertType<JSONValue::TypeArray>(value);
807        }
808#endif  // $validatorIfdefName
809    };
810};
811
812template<typename T>
813struct ArrayItemHelper<TypeBuilder::Array<T> > {
814    struct Traits {
815        static void pushRefPtr(JSONArray* array, PassRefPtr<TypeBuilder::Array<T> > value)
816        {
817            array->pushValue(value);
818        }
819
820#if $validatorIfdefName
821        template<typename S>
822        static void assertCorrectValue(JSONValue* value) {
823            S::assertCorrectValue(value);
824        }
825#endif  // $validatorIfdefName
826    };
827};
828
829${forwards}
830
831String getEnumConstantValue(int code);
832
833${typeBuilders}
834} // namespace TypeBuilder
835
836
837} // namespace WebCore
838
839#endif // !defined(InspectorTypeBuilder_h)
840
841""")
842
843typebuilder_cpp = (
844"""
845
846#include "config.h"
847
848#include "InspectorTypeBuilder.h"
849#include "wtf/text/CString.h"
850
851namespace WebCore {
852
853namespace TypeBuilder {
854
855const char* const enum_constant_values[] = {
856$enumConstantValues};
857
858String getEnumConstantValue(int code) {
859    return enum_constant_values[code];
860}
861
862} // namespace TypeBuilder
863
864$implCode
865
866#if $validatorIfdefName
867
868void TypeBuilder::RuntimeCastHelper::assertAny(JSONValue*)
869{
870    // No-op.
871}
872
873
874void TypeBuilder::RuntimeCastHelper::assertInt(JSONValue* value)
875{
876    double v;
877    bool castRes = value->asNumber(&v);
878    ASSERT_UNUSED(castRes, castRes);
879    ASSERT(static_cast<double>(static_cast<int>(v)) == v);
880}
881
882$validatorCode
883
884#endif // $validatorIfdefName
885
886} // namespace WebCore
887
888""")
889
890param_container_access_code = """
891    RefPtr<JSONObject> paramsContainer = requestMessageObject->getObject("params");
892    JSONObject* paramsContainerPtr = paramsContainer.get();
893    JSONArray* protocolErrorsPtr = protocolErrors.get();
894"""
895
896class_binding_builder_part_1 = (
897"""        AllFieldsSet = %s
898    };
899
900    template<int STATE>
901    class Builder {
902    private:
903        RefPtr<JSONObject> m_result;
904
905        template<int STEP> Builder<STATE | STEP>& castState()
906        {
907            return *reinterpret_cast<Builder<STATE | STEP>*>(this);
908        }
909
910        Builder(PassRefPtr</*%s*/JSONObject> ptr)
911        {
912            COMPILE_ASSERT(STATE == NoFieldsSet, builder_created_in_non_init_state);
913            m_result = ptr;
914        }
915        friend class %s;
916    public:
917""")
918
919class_binding_builder_part_2 = ("""
920        Builder<STATE | %s>& set%s(%s value)
921        {
922            COMPILE_ASSERT(!(STATE & %s), property_%s_already_set);
923            m_result->set%s("%s", %s);
924            return castState<%s>();
925        }
926""")
927
928class_binding_builder_part_3 = ("""
929        operator RefPtr<%s>& ()
930        {
931            COMPILE_ASSERT(STATE == AllFieldsSet, result_is_not_ready);
932            COMPILE_ASSERT(sizeof(%s) == sizeof(JSONObject), cannot_cast);
933            return *reinterpret_cast<RefPtr<%s>*>(&m_result);
934        }
935
936        PassRefPtr<%s> release()
937        {
938            return RefPtr<%s>(*this).release();
939        }
940    };
941
942""")
943
944class_binding_builder_part_4 = (
945"""    static Builder<NoFieldsSet> create()
946    {
947        return Builder<NoFieldsSet>(JSONObject::create());
948    }
949""")
950