Home | History | Annotate | Download | only in v8
      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 #include "config.h"
     32 #include "V8DOMWrapper.h"
     33 
     34 #include "CSSMutableStyleDeclaration.h"
     35 #include "DOMDataStore.h"
     36 #include "DOMObjectsInclude.h"
     37 #include "DocumentLoader.h"
     38 #include "FrameLoaderClient.h"
     39 #include "Notification.h"
     40 #include "SVGElementInstance.h"
     41 #include "SVGPathSeg.h"
     42 #include "ScriptController.h"
     43 #include "V8AbstractEventListener.h"
     44 #include "V8Binding.h"
     45 #include "V8Collection.h"
     46 #include "V8CustomEventListener.h"
     47 #include "V8DOMApplicationCache.h"
     48 #include "V8DOMMap.h"
     49 #include "V8DOMWindow.h"
     50 #include "V8EventListenerList.h"
     51 #include "V8HTMLCollection.h"
     52 #include "V8HTMLDocument.h"
     53 #include "V8Index.h"
     54 #include "V8IsolatedContext.h"
     55 #include "V8Location.h"
     56 #include "V8MessageChannel.h"
     57 #include "V8NamedNodeMap.h"
     58 #include "V8Node.h"
     59 #include "V8NodeList.h"
     60 #include "V8Notification.h"
     61 #include "V8Proxy.h"
     62 #include "V8SVGElementInstance.h"
     63 #include "V8SharedWorker.h"
     64 #include "V8SharedWorkerContext.h"
     65 #include "V8StyleSheet.h"
     66 #include "V8WebSocket.h"
     67 #include "V8Worker.h"
     68 #include "V8WorkerContext.h"
     69 #include "V8XMLHttpRequest.h"
     70 #include "WebGLArray.h"
     71 #include "WebGLContextAttributes.h"
     72 #include "WebGLUniformLocation.h"
     73 #include "WorkerContextExecutionProxy.h"
     74 
     75 #include <algorithm>
     76 #include <utility>
     77 #include <v8.h>
     78 #include <v8-debug.h>
     79 #include <wtf/Assertions.h>
     80 #include <wtf/OwnArrayPtr.h>
     81 #include <wtf/StdLibExtras.h>
     82 #include <wtf/UnusedParam.h>
     83 
     84 namespace WebCore {
     85 
     86 typedef HashMap<Node*, v8::Object*> DOMNodeMap;
     87 typedef HashMap<void*, v8::Object*> DOMObjectMap;
     88 
     89 #if ENABLE(3D_CANVAS)
     90 void V8DOMWrapper::setIndexedPropertiesToExternalArray(v8::Handle<v8::Object> wrapper,
     91                                                        int index,
     92                                                        void* address,
     93                                                        int length)
     94 {
     95     v8::ExternalArrayType array_type = v8::kExternalByteArray;
     96     V8ClassIndex::V8WrapperType classIndex = V8ClassIndex::FromInt(index);
     97     switch (classIndex) {
     98     case V8ClassIndex::WEBGLBYTEARRAY:
     99         array_type = v8::kExternalByteArray;
    100         break;
    101     case V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY:
    102         array_type = v8::kExternalUnsignedByteArray;
    103         break;
    104     case V8ClassIndex::WEBGLSHORTARRAY:
    105         array_type = v8::kExternalShortArray;
    106         break;
    107     case V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY:
    108         array_type = v8::kExternalUnsignedShortArray;
    109         break;
    110     case V8ClassIndex::WEBGLINTARRAY:
    111         array_type = v8::kExternalIntArray;
    112         break;
    113     case V8ClassIndex::WEBGLUNSIGNEDINTARRAY:
    114         array_type = v8::kExternalUnsignedIntArray;
    115         break;
    116     case V8ClassIndex::WEBGLFLOATARRAY:
    117         array_type = v8::kExternalFloatArray;
    118         break;
    119     default:
    120         ASSERT_NOT_REACHED();
    121     }
    122     wrapper->SetIndexedPropertiesToExternalArrayData(address,
    123                                                      array_type,
    124                                                      length);
    125 }
    126 #endif
    127 
    128 // The caller must have increased obj's ref count.
    129 void V8DOMWrapper::setJSWrapperForDOMObject(void* object, v8::Persistent<v8::Object> wrapper)
    130 {
    131     ASSERT(V8DOMWrapper::maybeDOMWrapper(wrapper));
    132 #ifndef NDEBUG
    133     V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper);
    134     switch (type) {
    135 #define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE:
    136         ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE)
    137         ASSERT_NOT_REACHED();
    138 #undef MAKE_CASE
    139     default:
    140         break;
    141     }
    142 #endif
    143     getDOMObjectMap().set(object, wrapper);
    144 }
    145 
    146 // The caller must have increased obj's ref count.
    147 void V8DOMWrapper::setJSWrapperForActiveDOMObject(void* object, v8::Persistent<v8::Object> wrapper)
    148 {
    149     ASSERT(V8DOMWrapper::maybeDOMWrapper(wrapper));
    150 #ifndef NDEBUG
    151     V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper);
    152     switch (type) {
    153 #define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE: break;
    154         ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE)
    155     default:
    156         ASSERT_NOT_REACHED();
    157 #undef MAKE_CASE
    158     }
    159 #endif
    160     getActiveDOMObjectMap().set(object, wrapper);
    161 }
    162 
    163 // The caller must have increased node's ref count.
    164 void V8DOMWrapper::setJSWrapperForDOMNode(Node* node, v8::Persistent<v8::Object> wrapper)
    165 {
    166     ASSERT(V8DOMWrapper::maybeDOMWrapper(wrapper));
    167     getDOMNodeMap().set(node, wrapper);
    168 }
    169 
    170 v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> objectPrototype)
    171 {
    172     // A DOM constructor is a function instance created from a DOM constructor
    173     // template. There is one instance per context. A DOM constructor is
    174     // different from a normal function in two ways:
    175     //   1) it cannot be called as constructor (aka, used to create a DOM object)
    176     //   2) its __proto__ points to Object.prototype rather than
    177     //      Function.prototype.
    178     // The reason for 2) is that, in Safari, a DOM constructor is a normal JS
    179     // object, but not a function. Hotmail relies on the fact that, in Safari,
    180     // HTMLElement.__proto__ == Object.prototype.
    181     v8::Handle<v8::FunctionTemplate> functionTemplate = V8ClassIndex::getTemplate(type);
    182     // Getting the function might fail if we're running out of
    183     // stack or memory.
    184     v8::TryCatch tryCatch;
    185     v8::Local<v8::Function> value = functionTemplate->GetFunction();
    186     if (value.IsEmpty())
    187         return v8::Local<v8::Function>();
    188     // Hotmail fix, see comments above.
    189     if (!objectPrototype.IsEmpty())
    190         value->Set(v8::String::New("__proto__"), objectPrototype);
    191     return value;
    192 }
    193 
    194 v8::Local<v8::Function> V8DOMWrapper::getConstructorForContext(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Context> context)
    195 {
    196     // Enter the scope for this context to get the correct constructor.
    197     v8::Context::Scope scope(context);
    198 
    199     return getConstructor(type, V8DOMWindowShell::getHiddenObjectPrototype(context));
    200 }
    201 
    202 v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, DOMWindow* window)
    203 {
    204     Frame* frame = window->frame();
    205     if (!frame)
    206         return v8::Local<v8::Function>();
    207 
    208     v8::Handle<v8::Context> context = V8Proxy::context(frame);
    209     if (context.IsEmpty())
    210         return v8::Local<v8::Function>();
    211 
    212     return getConstructorForContext(type, context);
    213 }
    214 
    215 #if ENABLE(WORKERS)
    216 v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, WorkerContext*)
    217 {
    218     WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve();
    219     if (!proxy)
    220         return v8::Local<v8::Function>();
    221 
    222     v8::Handle<v8::Context> context = proxy->context();
    223     if (context.IsEmpty())
    224         return v8::Local<v8::Function>();
    225 
    226     return getConstructorForContext(type, context);
    227 }
    228 #endif
    229 
    230 void V8DOMWrapper::setHiddenWindowReference(Frame* frame, const int internalIndex, v8::Handle<v8::Object> jsObject)
    231 {
    232     // Get DOMWindow
    233     if (!frame)
    234         return; // Object might be detached from window
    235     v8::Handle<v8::Context> context = V8Proxy::context(frame);
    236     if (context.IsEmpty())
    237         return;
    238 
    239     ASSERT(internalIndex < V8DOMWindow::internalFieldCount);
    240 
    241     v8::Handle<v8::Object> global = context->Global();
    242     // Look for real DOM wrapper.
    243     global = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), global);
    244     ASSERT(!global.IsEmpty());
    245     ASSERT(global->GetInternalField(internalIndex)->IsUndefined());
    246     global->SetInternalField(internalIndex, jsObject);
    247 }
    248 
    249 V8ClassIndex::V8WrapperType V8DOMWrapper::domWrapperType(v8::Handle<v8::Object> object)
    250 {
    251     ASSERT(V8DOMWrapper::maybeDOMWrapper(object));
    252     v8::Handle<v8::Value> type = object->GetInternalField(v8DOMWrapperTypeIndex);
    253     return V8ClassIndex::FromInt(type->Int32Value());
    254 }
    255 
    256 PassRefPtr<NodeFilter> V8DOMWrapper::wrapNativeNodeFilter(v8::Handle<v8::Value> filter)
    257 {
    258     // A NodeFilter is used when walking through a DOM tree or iterating tree
    259     // nodes.
    260     // FIXME: we may want to cache NodeFilterCondition and NodeFilter
    261     // object, but it is minor.
    262     // NodeFilter is passed to NodeIterator that has a ref counted pointer
    263     // to NodeFilter. NodeFilter has a ref counted pointer to NodeFilterCondition.
    264     // In NodeFilterCondition, filter object is persisted in its constructor,
    265     // and disposed in its destructor.
    266     if (!filter->IsFunction())
    267         return 0;
    268 
    269     NodeFilterCondition* condition = new V8NodeFilterCondition(filter);
    270     return NodeFilter::create(condition);
    271 }
    272 
    273 static bool globalObjectPrototypeIsDOMWindow(v8::Handle<v8::Object> objectPrototype)
    274 {
    275 #if ENABLE(SHARED_WORKERS)
    276     // We can identify what type of context the global object is wrapping by looking at the
    277     // internal field count of its prototype. This assumes WorkerContexts and DOMWindows have different numbers
    278     // of internal fields, so a COMPILE_ASSERT is included to warn if this ever changes. DOMWindow has
    279     // traditionally had far more internal fields than any other class.
    280     COMPILE_ASSERT(V8DOMWindow::internalFieldCount != V8WorkerContext::internalFieldCount && V8DOMWindow::internalFieldCount != V8SharedWorkerContext::internalFieldCount,
    281         DOMWindowAndWorkerContextHaveUnequalFieldCounts);
    282 #endif
    283     return objectPrototype->InternalFieldCount() == V8DOMWindow::internalFieldCount;
    284 }
    285 
    286 v8::Local<v8::Object> V8DOMWrapper::instantiateV8Object(V8Proxy* proxy, V8ClassIndex::V8WrapperType type, void* impl)
    287 {
    288     WorkerContext* workerContext = 0;
    289     if (V8IsolatedContext::getEntered()) {
    290         // This effectively disables the wrapper cache for isolated worlds.
    291         proxy = 0;
    292         // FIXME: Do we need a wrapper cache for the isolated world?  We should
    293         //        see if the performance gains are worth while.
    294         // We'll get one once we give the isolated context a proper window shell.
    295     } else if (!proxy) {
    296         v8::Handle<v8::Context> context = v8::Context::GetCurrent();
    297         if (!context.IsEmpty()) {
    298             v8::Handle<v8::Object> globalPrototype = v8::Handle<v8::Object>::Cast(context->Global()->GetPrototype());
    299             if (globalObjectPrototypeIsDOMWindow(globalPrototype))
    300                 proxy = V8Proxy::retrieve(V8DOMWindow::toNative(globalPrototype)->frame());
    301 #if ENABLE(WORKERS)
    302             else
    303                 workerContext = V8WorkerContext::toNative(globalPrototype);
    304 #endif
    305         }
    306     }
    307 
    308     v8::Local<v8::Object> instance;
    309     if (proxy)
    310         // FIXME: Fix this to work properly with isolated worlds (see above).
    311         instance = proxy->windowShell()->createWrapperFromCache(type);
    312     else {
    313         v8::Local<v8::Function> function;
    314 #if ENABLE(WORKERS)
    315         if (workerContext)
    316             function = getConstructor(type, workerContext);
    317         else
    318 #endif
    319             function = V8ClassIndex::getTemplate(type)->GetFunction();
    320         instance = SafeAllocation::newInstance(function);
    321     }
    322     if (!instance.IsEmpty()) {
    323         // Avoid setting the DOM wrapper for failed allocations.
    324         setDOMWrapper(instance, V8ClassIndex::ToInt(type), impl);
    325     }
    326     return instance;
    327 }
    328 
    329 #ifndef NDEBUG
    330 bool V8DOMWrapper::maybeDOMWrapper(v8::Handle<v8::Value> value)
    331 {
    332     if (value.IsEmpty() || !value->IsObject())
    333         return false;
    334 
    335     v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value);
    336     if (!object->InternalFieldCount())
    337         return false;
    338 
    339     ASSERT(object->InternalFieldCount() >= v8DefaultWrapperInternalFieldCount);
    340 
    341     v8::Handle<v8::Value> type = object->GetInternalField(v8DOMWrapperTypeIndex);
    342     ASSERT(type->IsInt32());
    343     ASSERT(V8ClassIndex::INVALID_CLASS_INDEX < type->Int32Value() && type->Int32Value() < V8ClassIndex::CLASSINDEX_END);
    344 
    345     v8::Handle<v8::Value> wrapper = object->GetInternalField(v8DOMWrapperObjectIndex);
    346     ASSERT(wrapper->IsNumber() || wrapper->IsExternal());
    347 
    348     return true;
    349 }
    350 #endif
    351 
    352 bool V8DOMWrapper::isWrapperOfType(v8::Handle<v8::Value> value, V8ClassIndex::V8WrapperType classType)
    353 {
    354     if (value.IsEmpty() || !value->IsObject())
    355         return false;
    356 
    357     v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value);
    358     if (!object->InternalFieldCount())
    359         return false;
    360 
    361     ASSERT(object->InternalFieldCount() >= v8DefaultWrapperInternalFieldCount);
    362 
    363     v8::Handle<v8::Value> wrapper = object->GetInternalField(v8DOMWrapperObjectIndex);
    364     ASSERT(wrapper->IsNumber() || wrapper->IsExternal());
    365 
    366     v8::Handle<v8::Value> type = object->GetInternalField(v8DOMWrapperTypeIndex);
    367     ASSERT(type->IsInt32());
    368     ASSERT(V8ClassIndex::INVALID_CLASS_INDEX < type->Int32Value() && type->Int32Value() < V8ClassIndex::CLASSINDEX_END);
    369 
    370     return V8ClassIndex::FromInt(type->Int32Value()) == classType;
    371 }
    372 
    373 v8::Handle<v8::Object> V8DOMWrapper::getWrapper(Node* node)
    374 {
    375     ASSERT(WTF::isMainThread());
    376     V8IsolatedContext* context = V8IsolatedContext::getEntered();
    377     if (LIKELY(!context)) {
    378         v8::Persistent<v8::Object>* wrapper = node->wrapper();
    379         if (!wrapper)
    380             return v8::Handle<v8::Object>();
    381         return *wrapper;
    382     }
    383 
    384     DOMNodeMapping& domNodeMap = context->world()->domDataStore()->domNodeMap();
    385     return domNodeMap.get(node);
    386 }
    387 
    388 // A JS object of type EventTarget is limited to a small number of possible classes.
    389 // Check EventTarget.h for new type conversion methods
    390 v8::Handle<v8::Value> V8DOMWrapper::convertEventTargetToV8Object(EventTarget* target)
    391 {
    392     if (!target)
    393         return v8::Null();
    394 
    395 #if ENABLE(SVG)
    396     if (SVGElementInstance* instance = target->toSVGElementInstance())
    397         return toV8(instance);
    398 #endif
    399 
    400 #if ENABLE(WORKERS)
    401     if (Worker* worker = target->toWorker())
    402         return toV8(worker);
    403 
    404     if (DedicatedWorkerContext* workerContext = target->toDedicatedWorkerContext())
    405         return toV8(workerContext);
    406 #endif // WORKERS
    407 
    408 #if ENABLE(SHARED_WORKERS)
    409     if (SharedWorker* sharedWorker = target->toSharedWorker())
    410         return toV8(sharedWorker);
    411 
    412     if (SharedWorkerContext* sharedWorkerContext = target->toSharedWorkerContext())
    413         return toV8(sharedWorkerContext);
    414 #endif // SHARED_WORKERS
    415 
    416 #if ENABLE(NOTIFICATIONS)
    417     if (Notification* notification = target->toNotification())
    418         return toV8(notification);
    419 #endif
    420 
    421 #if ENABLE(WEB_SOCKETS)
    422     if (WebSocket* webSocket = target->toWebSocket())
    423         return toV8(webSocket);
    424 #endif
    425 
    426     if (Node* node = target->toNode())
    427         return toV8(node);
    428 
    429     if (DOMWindow* domWindow = target->toDOMWindow())
    430         return toV8(domWindow);
    431 
    432     // XMLHttpRequest is created within its JS counterpart.
    433     if (XMLHttpRequest* xmlHttpRequest = target->toXMLHttpRequest()) {
    434         v8::Handle<v8::Object> wrapper = getActiveDOMObjectMap().get(xmlHttpRequest);
    435         ASSERT(!wrapper.IsEmpty());
    436         return wrapper;
    437     }
    438 
    439     if (XMLHttpRequest* xhr = target->toXMLHttpRequest())
    440         return toV8(xhr);
    441 
    442     // MessagePort is created within its JS counterpart
    443     if (MessagePort* port = target->toMessagePort()) {
    444         v8::Handle<v8::Object> wrapper = getActiveDOMObjectMap().get(port);
    445         ASSERT(!wrapper.IsEmpty());
    446         return wrapper;
    447     }
    448 
    449     if (XMLHttpRequestUpload* upload = target->toXMLHttpRequestUpload()) {
    450         v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(upload);
    451         ASSERT(!wrapper.IsEmpty());
    452         return wrapper;
    453     }
    454 
    455 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
    456     if (DOMApplicationCache* domAppCache = target->toDOMApplicationCache())
    457         return toV8(domAppCache);
    458 #endif
    459 
    460 #if ENABLE(EVENTSOURCE)
    461     if (EventSource* eventSource = target->toEventSource())
    462         return toV8(eventSource);
    463 #endif
    464 
    465     ASSERT(0);
    466     return notHandledByInterceptor();
    467 }
    468 
    469 PassRefPtr<EventListener> V8DOMWrapper::getEventListener(Node* node, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup)
    470 {
    471     return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute);
    472 }
    473 
    474 #if ENABLE(SVG)
    475 PassRefPtr<EventListener> V8DOMWrapper::getEventListener(SVGElementInstance* element, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup)
    476 {
    477     return getEventListener(element->correspondingElement(), value, isAttribute, lookup);
    478 }
    479 #endif
    480 
    481 // ANDROID
    482 // Temporary fix until we merge http://trac.webkit.org/changeset/55096
    483 #if ENABLE(WORKERS)
    484 PassRefPtr<EventListener> V8DOMWrapper::getEventListener(AbstractWorker* worker, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup)
    485 {
    486     if (worker->scriptExecutionContext()->isWorkerContext()) {
    487         WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve();
    488         ASSERT(workerContextProxy);
    489         return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly);
    490     }
    491 
    492     return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute);
    493 }
    494 #endif
    495 
    496 #if ENABLE(NOTIFICATIONS)
    497 PassRefPtr<EventListener> V8DOMWrapper::getEventListener(Notification* notification, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup)
    498 {
    499     if (notification->scriptExecutionContext()->isWorkerContext()) {
    500         WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve();
    501         ASSERT(workerContextProxy);
    502         return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly);
    503     }
    504 
    505     return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute);
    506 }
    507 #endif
    508 
    509 // ANDROID
    510 // Temporary fix until we merge http://trac.webkit.org/changeset/55096
    511 #if ENABLE(WORKERS)
    512 PassRefPtr<EventListener> V8DOMWrapper::getEventListener(WorkerContext* workerContext, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup)
    513 {
    514     WorkerContextExecutionProxy* workerContextProxy = workerContext->script()->proxy();
    515     if (workerContextProxy)
    516         return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly);
    517 
    518     return 0;
    519 }
    520 #endif
    521 
    522 PassRefPtr<EventListener> V8DOMWrapper::getEventListener(XMLHttpRequestUpload* upload, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup)
    523 {
    524     return getEventListener(upload->associatedXMLHttpRequest(), value, isAttribute, lookup);
    525 }
    526 
    527 #if ENABLE(EVENTSOURCE)
    528 PassRefPtr<EventListener> V8DOMWrapper::getEventListener(EventSource* eventSource, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup)
    529 {
    530     if (V8Proxy::retrieve(eventSource->scriptExecutionContext()))
    531         return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute);
    532 
    533 #if ENABLE(WORKERS)
    534     WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve();
    535     if (workerContextProxy)
    536         return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly);
    537 #endif
    538 
    539     return 0;
    540 }
    541 #endif
    542 
    543 PassRefPtr<EventListener> V8DOMWrapper::getEventListener(EventTarget* eventTarget, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup)
    544 {
    545     if (V8Proxy::retrieve(eventTarget->scriptExecutionContext()))
    546         return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute);
    547 
    548 #if ENABLE(WORKERS)
    549     WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve();
    550     if (workerContextProxy)
    551         return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly);
    552 #endif
    553 
    554     return 0;
    555 }
    556 
    557 PassRefPtr<EventListener> V8DOMWrapper::getEventListener(V8Proxy* proxy, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup)
    558 {
    559     return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute);
    560 }
    561 
    562 }  // namespace WebCore
    563