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 "bindings/v8/ScriptEventListener.h" 33 34 #include "bindings/v8/ScriptController.h" 35 #include "bindings/v8/ScriptScope.h" 36 #include "bindings/v8/V8AbstractEventListener.h" 37 #include "bindings/v8/V8Binding.h" 38 #include "bindings/v8/V8WindowShell.h" 39 #include "core/dom/Document.h" 40 #include "core/dom/DocumentParser.h" 41 #include "core/dom/EventListener.h" 42 #include "core/page/Frame.h" 43 44 namespace WebCore { 45 46 static const String& eventParameterName(bool isSVGEvent) 47 { 48 DEFINE_STATIC_LOCAL(const String, eventString, ("event")); 49 DEFINE_STATIC_LOCAL(const String, evtString, ("evt")); 50 return isSVGEvent ? evtString : eventString; 51 } 52 53 PassRefPtr<V8LazyEventListener> createAttributeEventListener(Node* node, const QualifiedName& name, const AtomicString& value) 54 { 55 ASSERT(node); 56 if (value.isNull()) 57 return 0; 58 59 // FIXME: Very strange: we initialize zero-based number with '1'. 60 TextPosition position(OrdinalNumber::fromZeroBasedInt(1), OrdinalNumber::first()); 61 String sourceURL; 62 63 if (Frame* frame = node->document()->frame()) { 64 ScriptController* scriptController = frame->script(); 65 if (!scriptController->canExecuteScripts(AboutToExecuteScript)) 66 return 0; 67 position = scriptController->eventHandlerPosition(); 68 sourceURL = node->document()->url().string(); 69 } 70 71 return V8LazyEventListener::create(name.localName().string(), eventParameterName(node->isSVGElement()), value, sourceURL, position, node); 72 } 73 74 PassRefPtr<V8LazyEventListener> createAttributeEventListener(Frame* frame, const QualifiedName& name, const AtomicString& value) 75 { 76 if (!frame) 77 return 0; 78 79 if (value.isNull()) 80 return 0; 81 82 ScriptController* scriptController = frame->script(); 83 if (!scriptController->canExecuteScripts(AboutToExecuteScript)) 84 return 0; 85 86 TextPosition position = scriptController->eventHandlerPosition(); 87 String sourceURL = frame->document()->url().string(); 88 89 return V8LazyEventListener::create(name.localName().string(), eventParameterName(frame->document()->isSVGDocument()), value, sourceURL, position, 0); 90 } 91 92 String eventListenerHandlerBody(Document* document, EventListener* listener) 93 { 94 if (listener->type() != EventListener::JSEventListenerType) 95 return ""; 96 97 v8::HandleScope scope; 98 V8AbstractEventListener* v8Listener = static_cast<V8AbstractEventListener*>(listener); 99 v8::Handle<v8::Context> context = toV8Context(document, v8Listener->world()); 100 v8::Context::Scope contextScope(context); 101 v8::Handle<v8::Object> function = v8Listener->getListenerObject(document); 102 if (function.IsEmpty()) 103 return ""; 104 105 return toWebCoreStringWithNullCheck(function); 106 } 107 108 ScriptValue eventListenerHandler(Document* document, EventListener* listener) 109 { 110 if (listener->type() != EventListener::JSEventListenerType) 111 return ScriptValue(); 112 113 v8::HandleScope scope; 114 V8AbstractEventListener* v8Listener = static_cast<V8AbstractEventListener*>(listener); 115 v8::Handle<v8::Context> context = toV8Context(document, v8Listener->world()); 116 v8::Context::Scope contextScope(context); 117 v8::Handle<v8::Object> function = v8Listener->getListenerObject(document); 118 if (function.IsEmpty()) 119 return ScriptValue(); 120 return ScriptValue(function); 121 } 122 123 ScriptState* eventListenerHandlerScriptState(Frame* frame, EventListener* listener) 124 { 125 if (listener->type() != EventListener::JSEventListenerType) 126 return 0; 127 V8AbstractEventListener* v8Listener = static_cast<V8AbstractEventListener*>(listener); 128 v8::HandleScope scope; 129 v8::Handle<v8::Context> v8Context = frame->script()->windowShell(v8Listener->world())->context(); 130 return ScriptState::forContext(v8Context); 131 } 132 133 bool eventListenerHandlerLocation(Document* document, EventListener* listener, String& sourceName, String& scriptId, int& lineNumber) 134 { 135 if (listener->type() != EventListener::JSEventListenerType) 136 return false; 137 138 v8::HandleScope scope; 139 V8AbstractEventListener* v8Listener = static_cast<V8AbstractEventListener*>(listener); 140 v8::Handle<v8::Context> context = toV8Context(document, v8Listener->world()); 141 v8::Context::Scope contextScope(context); 142 v8::Handle<v8::Object> object = v8Listener->getListenerObject(document); 143 if (object.IsEmpty() || !object->IsFunction()) 144 return false; 145 146 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(object); 147 v8::Handle<v8::Value> scriptIdValue = function->GetScriptId(); 148 scriptId = toWebCoreStringWithUndefinedOrNullCheck(scriptIdValue); 149 v8::ScriptOrigin origin = function->GetScriptOrigin(); 150 if (origin.ResourceName()->IsString() && !origin.ResourceName().IsEmpty()) 151 sourceName = toWebCoreString(origin.ResourceName()); 152 else 153 sourceName = ""; 154 lineNumber = function->GetScriptLineNumber(); 155 return true; 156 } 157 158 } // namespace WebCore 159