2009-11-10 Vitaly Repeshko <vitalyr@chromium.org>
[WebKit-https.git] / WebCore / bindings / v8 / V8DOMWrapper.h
1 /*
2  * Copyright (C) 2009 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
31 #ifndef V8DOMWrapper_h
32 #define V8DOMWrapper_h
33
34 #include "Document.h"
35 #include "Event.h"
36 #include "Node.h"
37 #include "NodeFilter.h"
38 #include "PlatformString.h" // for WebCore::String
39 #include "V8CustomBinding.h"
40 #include "V8CustomXPathNSResolver.h"
41 #include "V8DOMMap.h"
42 #include "V8Index.h"
43 #include "V8Utilities.h"
44 #include "V8XPathNSResolver.h"
45 #include "XPathNSResolver.h"
46 #include <v8.h>
47
48 namespace WebCore {
49
50     // FIXME: This probably aren't all needed.
51     class CSSRule;
52     class CSSRuleList;
53     class CSSStyleDeclaration;
54     class CSSValue;
55     class CSSValueList;
56     class ClientRectList;
57     class DOMImplementation;
58     class DOMWindow;
59     class Document;
60     class Element;
61     class Event;
62     class EventListener;
63     class EventTarget;
64     class Frame;
65     class HTMLCollection;
66     class HTMLDocument;
67     class HTMLElement;
68     class HTMLOptionsCollection;
69     class MediaList;
70     class MimeType;
71     class MimeTypeArray;
72     class NamedNodeMap;
73     class Navigator;
74     class Node;
75     class NodeFilter;
76     class NodeList;
77     class Plugin;
78     class PluginArray;
79     class SVGElement;
80 #if ENABLE(SVG)
81     class SVGElementInstance;
82 #endif
83     class Screen;
84     class ScriptExecutionContext;
85 #if ENABLE(DOM_STORAGE)
86     class Storage;
87     class StorageEvent;
88 #endif
89     class String;
90     class StyleSheet;
91     class StyleSheetList;
92     class V8EventListener;
93     class V8ObjectEventListener;
94 #if ENABLE(WEB_SOCKETS)
95     class WebSocket;
96 #endif
97     class WorkerContext;
98
99     enum ListenerLookupType {
100         ListenerFindOnly,
101         ListenerFindOrCreate,
102     };
103
104     class V8DOMWrapper {
105     public:
106 #ifndef NDEBUG
107         // Checks if a v8 value can be a DOM wrapper
108         static bool maybeDOMWrapper(v8::Handle<v8::Value>);
109 #endif
110
111         // Sets contents of a DOM wrapper.
112         static void setDOMWrapper(v8::Handle<v8::Object>, int type, void* ptr);
113
114         static v8::Handle<v8::Object> lookupDOMWrapper(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Object> object)
115         {
116             return object.IsEmpty() ? object : object->FindInstanceInPrototypeChain(getTemplate(type));
117         }
118
119         // A helper function extract native object pointer from a DOM wrapper
120         // and cast to the specified type.
121         template <class C>
122         static C* convertDOMWrapperToNative(v8::Handle<v8::Object> object)
123         {
124             ASSERT(maybeDOMWrapper(object));
125             return reinterpret_cast<C*>(object->GetPointerFromInternalField(V8Custom::kDOMWrapperObjectIndex));
126         }
127
128         template <class C>
129         static C* convertDOMWrapperToNode(v8::Handle<v8::Object> object)
130         {
131             ASSERT(maybeDOMWrapper(object));
132             ASSERT(domWrapperType(object) == V8ClassIndex::NODE);
133             return convertDOMWrapperToNative<C>(object);
134         }
135
136         template<typename T>
137         static v8::Handle<v8::Value> convertToV8Object(V8ClassIndex::V8WrapperType type, PassRefPtr<T> imp)
138         {
139             return convertToV8Object(type, imp.get());
140         }
141
142         static v8::Handle<v8::Value> convertToV8Object(V8ClassIndex::V8WrapperType, void*);
143
144         // Fast-path for Node objects.
145         static v8::Handle<v8::Value> convertNodeToV8Object(PassRefPtr<Node> node)
146         {
147             return convertNodeToV8Object(node.get());
148         }
149
150         static v8::Handle<v8::Value> convertNodeToV8Object(Node* node)
151         {
152             if (!node)
153                 return v8::Null();
154
155             Document* document = node->document();
156             if (node == document)
157                 return convertDocumentToV8Object(document);
158
159             DOMWrapperMap<Node>& domNodeMap = getDOMNodeMap();
160             v8::Handle<v8::Object> wrapper = domNodeMap.get(node);
161             if (wrapper.IsEmpty())
162                 return convertNewNodeToV8Object(node, 0, domNodeMap);
163
164             return wrapper;
165         }
166
167         static v8::Handle<v8::Value> convertDocumentToV8Object(Document*);
168
169         static v8::Handle<v8::Value> convertNewNodeToV8Object(PassRefPtr<Node> node)
170         {
171             return convertNewNodeToV8Object(node.get());
172         }
173
174         static v8::Handle<v8::Value> convertNewNodeToV8Object(Node* node)
175         {
176             return convertNewNodeToV8Object(node, 0, getDOMNodeMap());
177         }
178
179         static v8::Handle<v8::Value> convertNewNodeToV8Object(Node*, V8Proxy*, DOMWrapperMap<Node>&);
180
181         template <class C>
182         static C* convertToNativeObject(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Object> object)
183         {
184             // Native event listener is per frame, it cannot be handled by this generic function.
185             ASSERT(type != V8ClassIndex::EVENTLISTENER);
186             ASSERT(type != V8ClassIndex::EVENTTARGET);
187
188             ASSERT(maybeDOMWrapper(object));
189
190 #ifndef NDEBUG
191             const bool typeIsValid =
192 #define MAKE_CASE(TYPE, NAME) (type != V8ClassIndex::TYPE) &&
193                 DOM_NODE_TYPES(MAKE_CASE)
194 #if ENABLE(SVG)
195                 SVG_NODE_TYPES(MAKE_CASE)
196 #endif
197 #undef MAKE_CASE
198                 true;
199             ASSERT(typeIsValid);
200 #endif
201
202             return convertDOMWrapperToNative<C>(object);
203         }
204
205         static V8ClassIndex::V8WrapperType domWrapperType(v8::Handle<v8::Object>);
206
207         static v8::Handle<v8::Value> convertEventToV8Object(PassRefPtr<Event> event)
208         {
209             return convertEventToV8Object(event.get());
210         }
211
212         static v8::Handle<v8::Value> convertEventToV8Object(Event*);
213
214         static Event* convertToNativeEvent(v8::Handle<v8::Value> jsEvent)
215         {
216             if (!isDOMEventWrapper(jsEvent))
217                 return 0;
218             return convertDOMWrapperToNative<Event>(v8::Handle<v8::Object>::Cast(jsEvent));
219         }
220
221         static v8::Handle<v8::Value> convertEventTargetToV8Object(PassRefPtr<EventTarget> eventTarget)
222         {
223             return convertEventTargetToV8Object(eventTarget.get());
224         }
225
226         static v8::Handle<v8::Value> convertEventTargetToV8Object(EventTarget*);
227
228         // Wrap and unwrap JS event listeners.
229         static v8::Handle<v8::Value> convertEventListenerToV8Object(ScriptExecutionContext* context, PassRefPtr<EventListener> eventListener)
230         {
231             return convertEventListenerToV8Object(context, eventListener.get());
232         }
233
234         static v8::Handle<v8::Value> convertEventListenerToV8Object(ScriptExecutionContext*, EventListener*);
235
236         static PassRefPtr<EventListener> getEventListener(Node* node, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup);
237
238         static PassRefPtr<EventListener> getEventListener(SVGElementInstance* element, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup);
239
240         static PassRefPtr<EventListener> getEventListener(AbstractWorker* worker, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup);
241
242 #if ENABLE(NOTIFICATIONS)
243         static PassRefPtr<EventListener> getEventListener(Notification* notification, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup);
244 #endif
245
246         static PassRefPtr<EventListener> getEventListener(WorkerContext* workerContext, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup);
247
248         static PassRefPtr<EventListener> getEventListener(XMLHttpRequestUpload* upload, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup);
249
250         static PassRefPtr<EventListener> getEventListener(EventTarget* eventTarget, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup);
251
252         static PassRefPtr<EventListener> getEventListener(V8Proxy* proxy, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup);
253
254
255         // XPath-related utilities
256         static RefPtr<XPathNSResolver> getXPathNSResolver(v8::Handle<v8::Value> value, V8Proxy* proxy = 0)
257         {
258             RefPtr<XPathNSResolver> resolver;
259             if (V8XPathNSResolver::HasInstance(value))
260                 resolver = convertToNativeObject<XPathNSResolver>(V8ClassIndex::XPATHNSRESOLVER, v8::Handle<v8::Object>::Cast(value));
261             else if (value->IsObject())
262                 resolver = V8CustomXPathNSResolver::create(proxy, value->ToObject());
263             return resolver;
264         }
265
266         // DOMImplementation is a singleton and it is handled in a special
267         // way. A wrapper is generated per document and stored in an
268         // internal field of the document.
269         static v8::Handle<v8::Value> convertDOMImplementationToV8Object(DOMImplementation*);
270
271         // Wrap JS node filter in C++.
272         static PassRefPtr<NodeFilter> wrapNativeNodeFilter(v8::Handle<v8::Value>);
273
274         static v8::Persistent<v8::FunctionTemplate> getTemplate(V8ClassIndex::V8WrapperType);
275         static v8::Local<v8::Function> getConstructorForContext(V8ClassIndex::V8WrapperType, v8::Handle<v8::Context>);
276         static v8::Local<v8::Function> getConstructor(V8ClassIndex::V8WrapperType, v8::Handle<v8::Value> objectPrototype);
277         static v8::Local<v8::Function> getConstructor(V8ClassIndex::V8WrapperType, DOMWindow*);
278         static v8::Local<v8::Function> getConstructor(V8ClassIndex::V8WrapperType, WorkerContext*);
279
280         // Checks whether a DOM object has a JS wrapper.
281         static bool domObjectHasJSWrapper(void*);
282         // Get JS wrapper of an existing DOM object, assuming that the wrapper
283         // exists.
284         static v8::Persistent<v8::Object> jsWrapperForDOMObject(void*);
285         static v8::Persistent<v8::Object> jsWrapperForActiveDOMObject(void*);
286         // Set JS wrapper of a DOM object, the caller in charge of increase ref.
287         static void setJSWrapperForDOMObject(void*, v8::Persistent<v8::Object>);
288         static void setJSWrapperForActiveDOMObject(void*, v8::Persistent<v8::Object>);
289         static void setJSWrapperForDOMNode(Node*, v8::Persistent<v8::Object>);
290
291         // Check whether a V8 value is a wrapper of type |classType|.
292         static bool isWrapperOfType(v8::Handle<v8::Value>, V8ClassIndex::V8WrapperType);
293
294         static void* convertToSVGPODTypeImpl(V8ClassIndex::V8WrapperType, v8::Handle<v8::Value>);
295
296         // Check whether a V8 value is a DOM Event wrapper.
297         static bool isDOMEventWrapper(v8::Handle<v8::Value>);
298
299         static v8::Handle<v8::Value> convertStyleSheetToV8Object(StyleSheet*);
300         static v8::Handle<v8::Value> convertCSSValueToV8Object(CSSValue*);
301         static v8::Handle<v8::Value> convertCSSRuleToV8Object(CSSRule*);
302         // Returns the JS wrapper of a window object, initializes the environment
303         // of the window frame if needed.
304         static v8::Handle<v8::Value> convertWindowToV8Object(DOMWindow*);
305
306 #if ENABLE(SVG)
307         static v8::Handle<v8::Value> convertSVGElementInstanceToV8Object(SVGElementInstance*);
308         static v8::Handle<v8::Value> convertSVGObjectWithContextToV8Object(V8ClassIndex::V8WrapperType, void*);
309 #endif
310
311 #if ENABLE(3D_CANVAS)
312         static void setIndexedPropertiesToExternalArray(v8::Handle<v8::Object>,
313                                                         int,
314                                                         void*,
315                                                         int);
316 #endif
317
318     private:
319         // Set hidden references in a DOMWindow object of a frame.
320         static void setHiddenWindowReference(Frame*, const int internalIndex, v8::Handle<v8::Object>);
321
322         static V8ClassIndex::V8WrapperType htmlElementType(HTMLElement*);
323 #if ENABLE(SVG)
324         static V8ClassIndex::V8WrapperType svgElementType(SVGElement*);
325 #endif
326
327         // The first V8WrapperType specifies the function descriptor
328         // used to create JS object. The second V8WrapperType specifies
329         // the actual type of the void* for type casting.
330         // For example, a HTML element has HTMLELEMENT for the first V8WrapperType, but always
331         // use NODE as the second V8WrapperType. JS wrapper stores the second
332         // V8WrapperType and the void* as internal fields.
333         static v8::Local<v8::Object> instantiateV8Object(V8ClassIndex::V8WrapperType descType, V8ClassIndex::V8WrapperType cptrType, void* impl)
334         {
335             return instantiateV8Object(NULL, descType, cptrType, impl);
336         }
337
338         static v8::Local<v8::Object> instantiateV8Object(V8Proxy*, V8ClassIndex::V8WrapperType, V8ClassIndex::V8WrapperType, void*);
339     };
340
341 }
342
343 #endif // V8DOMWrapper_h