summaryrefslogtreecommitdiff
path: root/Tools/DumpRenderTree/chromium/TestRunner/CppBoundClass.h
blob: 4fb5361e1bc83da0c635d47a13f3a4a43f6b945b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
/*
 * Copyright (C) 2010 Google Inc. All rights reserved.
 * Copyright (C) 2009 Pawel Hajdan (phajdan.jr@chromium.org)
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
  CppBoundClass class:
  This base class serves as a parent for C++ classes designed to be bound to
  JavaScript objects.

  Subclasses should define the constructor to build the property and method
  lists needed to bind this class to a JS object.  They should also declare
  and define member variables and methods to be exposed to JS through
  that object.
*/

#ifndef CppBoundClass_h
#define CppBoundClass_h

#include "CppVariant.h"
#include <wtf/HashMap.h>
#include <wtf/Noncopyable.h>
#include <wtf/OwnPtr.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/Vector.h>

namespace WebKit {
class WebFrame;
class WebString;
}

typedef Vector<CppVariant> CppArgumentList;

// CppBoundClass lets you map Javascript method calls and property accesses
// directly to C++ method calls and CppVariant* variable access.
class CppBoundClass {
    WTF_MAKE_NONCOPYABLE(CppBoundClass);
public:
    class PropertyCallback {
    public:
        virtual ~PropertyCallback() { }

        // Sets |value| to the value of the property. Returns false in case of
        // failure. |value| is always non-0.
        virtual bool getValue(CppVariant* result) = 0;

        // sets the property value to |value|. Returns false in case of failure.
        virtual bool setValue(const CppVariant&) = 0;
    };

    // Callback class for "void function(CppVariant*)"
    class GetterCallback {
    public:
        virtual ~GetterCallback() { }
        virtual void run(CppVariant*) = 0;
    };

    // The constructor should call BindMethod, BindProperty, and
    // SetFallbackMethod as needed to set up the methods, properties, and
    // fallback method.
    CppBoundClass() : m_boundToFrame(false) { }
    virtual ~CppBoundClass();

    // Return a CppVariant representing this class, for use with BindProperty().
    // The variant type is guaranteed to be NPVariantType_Object.
    CppVariant* getAsCppVariant();

    // Given a WebFrame, BindToJavascript builds the NPObject that will represent
    // the class and binds it to the frame's window under the given name. This
    // should generally be called from the WebView delegate's
    // WindowObjectCleared(). A class so bound will be accessible to JavaScript
    // as window.<classname>. The owner of the CppBoundObject is responsible for
    // keeping the object around while the frame is alive, and for destroying it
    // afterwards.
    void bindToJavascript(WebKit::WebFrame*, const WebKit::WebString& classname);

    // Used by a test. Returns true if a method with the specified name exists,
    // regardless of whether a fallback is registered.
    bool isMethodRegistered(const std::string&) const;

protected:
    // Callback for "void function(const CppArguemntList&, CppVariant*)"
    class Callback {
    public:
        virtual ~Callback() { }
        virtual void run(const CppArgumentList&, CppVariant*) = 0;
    };

    // Callback for "void T::method(const CppArguemntList&, CppVariant*)"
    template <class T> class MemberCallback : public Callback {
    public:
        typedef void (T::*MethodType)(const CppArgumentList&, CppVariant*);
        MemberCallback(T* object, MethodType method)
            : m_object(object)
            , m_method(method) { }
        virtual ~MemberCallback() { }

        virtual void run(const CppArgumentList& arguments, CppVariant* result)
        {
            (m_object->*m_method)(arguments, result);
        }

    private:
        T* m_object;
        MethodType m_method;
    };

    // Callback class for "void T::method(CppVariant*)"
    template <class T> class MemberGetterCallback : public GetterCallback {
    public:
        typedef void (T::*MethodType)(CppVariant*);
        MemberGetterCallback(T* object, MethodType method)
            : m_object(object)
            , m_method(method) { }
        virtual ~MemberGetterCallback() { }

        virtual void run(CppVariant* result) { (m_object->*m_method)(result); }

    private:
        T* m_object;
        MethodType m_method;
    };

    // Bind the Javascript method called the string parameter to the C++ method.
    void bindCallback(const std::string&, Callback*);

    // A wrapper for bindCallback, to simplify the common case of binding a
    // method on the current object. Though not verified here, the method parameter
    // must be a method of this CppBoundClass subclass.
    template<class T>
    void bindMethod(const std::string& name, void (T::*method)(const CppArgumentList&, CppVariant*))
    {
        Callback* callback = new MemberCallback<T>(static_cast<T*>(this), method);
        bindCallback(name, callback);
    }

    // Bind Javascript property |name| to the C++ getter callback |callback|.
    // This can be used to create read-only properties.
    void bindGetterCallback(const std::string&, PassOwnPtr<GetterCallback>);

    // A wrapper for BindGetterCallback, to simplify the common case of binding a
    // property on the current object. Though not verified here, the method parameter
    // must be a method of this CppBoundClass subclass.
    template<class T>
    void bindProperty(const std::string& name, void (T::*method)(CppVariant*))
    {
        OwnPtr<GetterCallback> callback = adoptPtr(new MemberGetterCallback<T>(static_cast<T*>(this), method));
        bindGetterCallback(name, callback.release());
    }

    // Bind the Javascript property called |name| to a CppVariant.
    void bindProperty(const std::string&, CppVariant*);

    // Bind Javascript property called |name| to a PropertyCallback.
    // CppBoundClass assumes control over the life time of the callback.
    void bindProperty(const std::string&, PropertyCallback*);

    // Set the fallback callback, which is called when when a callback is
    // invoked that isn't bound.
    // If it is 0 (its default value), a JavaScript exception is thrown in
    // that case (as normally expected). If non 0, the fallback method is
    // invoked and the script continues its execution.
    // Passing 0 clears out any existing binding.
    // It is used for tests and should probably only be used in such cases
    // as it may cause unexpected behaviors (a JavaScript object with a
    // fallback always returns true when checked for a method's
    // existence).
    void bindFallbackCallback(PassOwnPtr<Callback> fallbackCallback)
    {
        m_fallbackCallback = fallbackCallback;
    }

    // A wrapper for BindFallbackCallback, to simplify the common case of
    // binding a method on the current object. Though not verified here,
    // |method| must be a method of this CppBoundClass subclass.
    // Passing 0 for |method| clears out any existing binding.
    template<class T>
    void bindFallbackMethod(void (T::*method)(const CppArgumentList&, CppVariant*))
    {
        if (method) {
            OwnPtr<Callback> callback = adoptPtr(new MemberCallback<T>(static_cast<T*>(this), method));
            bindFallbackCallback(callback.release());
        } else
            bindFallbackCallback(nullptr);
    }

    // Some fields are protected because some tests depend on accessing them,
    // but otherwise they should be considered private.

    typedef HashMap<NPIdentifier, PropertyCallback*> PropertyList;
    typedef HashMap<NPIdentifier, Callback*> MethodList;
    // These maps associate names with property and method pointers to be
    // exposed to JavaScript.
    PropertyList m_properties;
    MethodList m_methods;

    // The callback gets invoked when a call is made to an nonexistent method.
    OwnPtr<Callback> m_fallbackCallback;

private:
    // NPObject callbacks.
    friend struct CppNPObject;
    bool hasMethod(NPIdentifier) const;
    bool invoke(NPIdentifier, const NPVariant* args, size_t argCount,
                NPVariant* result);
    bool hasProperty(NPIdentifier) const;
    bool getProperty(NPIdentifier, NPVariant* result) const;
    bool setProperty(NPIdentifier, const NPVariant*);

    // A lazily-initialized CppVariant representing this class. We retain 1
    // reference to this object, and it is released on deletion.
    CppVariant m_selfVariant;

    // True if our np_object has been bound to a WebFrame, in which case it must
    // be unregistered with V8 when we delete it.
    bool m_boundToFrame;
};

#endif // CppBoundClass_h