| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006, 2007, 2008, 2009 Google Inc. All rights reserved. | 2 * Copyright (C) 2006, 2007, 2008, 2009 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 #include "core/html/HTMLFormElement.h" | 46 #include "core/html/HTMLFormElement.h" |
| 47 #include "core/inspector/InspectorInstrumentation.h" | 47 #include "core/inspector/InspectorInstrumentation.h" |
| 48 #include "core/frame/LocalFrame.h" | 48 #include "core/frame/LocalFrame.h" |
| 49 #include "core/frame/csp/ContentSecurityPolicy.h" | 49 #include "core/frame/csp/ContentSecurityPolicy.h" |
| 50 | 50 |
| 51 #include "wtf/StdLibExtras.h" | 51 #include "wtf/StdLibExtras.h" |
| 52 | 52 |
| 53 namespace WebCore { | 53 namespace WebCore { |
| 54 | 54 |
| 55 V8LazyEventListener::V8LazyEventListener(const AtomicString& functionName, const
AtomicString& eventParameterName, const String& code, const String sourceURL, c
onst TextPosition& position, Node* node, v8::Isolate* isolate) | 55 V8LazyEventListener::V8LazyEventListener(const AtomicString& functionName, const
AtomicString& eventParameterName, const String& code, const String sourceURL, c
onst TextPosition& position, Node* node, v8::Isolate* isolate) |
| 56 : V8AbstractEventListener(true, DOMWrapperWorld::mainWorld(), isolate) | 56 : V8AbstractEventListener(true, isolate) |
| 57 , m_functionName(functionName) | 57 , m_functionName(functionName) |
| 58 , m_eventParameterName(eventParameterName) | 58 , m_eventParameterName(eventParameterName) |
| 59 , m_code(code) | 59 , m_code(code) |
| 60 , m_sourceURL(sourceURL) | 60 , m_sourceURL(sourceURL) |
| 61 , m_node(node) | 61 , m_node(node) |
| 62 , m_position(position) | 62 , m_position(position) |
| 63 { | 63 { |
| 64 } | 64 } |
| 65 | 65 |
| 66 template<typename T> | 66 template<typename T> |
| 67 v8::Handle<v8::Object> toObjectWrapper(T* domObject, v8::Isolate* isolate) | 67 v8::Handle<v8::Object> toObjectWrapper(T* domObject, ScriptState* scriptState) |
| 68 { | 68 { |
| 69 if (!domObject) | 69 if (!domObject) |
| 70 return v8::Object::New(isolate); | 70 return v8::Object::New(scriptState->isolate()); |
| 71 v8::Handle<v8::Value> value = toV8(domObject, v8::Handle<v8::Object>(), isol
ate); | 71 v8::Handle<v8::Value> value = toV8(domObject, scriptState->context()->Global
(), scriptState->isolate()); |
| 72 if (value.IsEmpty()) | 72 if (value.IsEmpty()) |
| 73 return v8::Object::New(isolate); | 73 return v8::Object::New(scriptState->isolate()); |
| 74 return v8::Local<v8::Object>::New(isolate, value.As<v8::Object>()); | 74 return v8::Local<v8::Object>::New(scriptState->isolate(), value.As<v8::Objec
t>()); |
| 75 } | 75 } |
| 76 | 76 |
| 77 v8::Local<v8::Value> V8LazyEventListener::callListenerFunction(ExecutionContext*
context, v8::Handle<v8::Value> jsEvent, Event* event) | 77 v8::Local<v8::Value> V8LazyEventListener::callListenerFunction(ExecutionContext*
context, v8::Handle<v8::Value> jsEvent, Event* event) |
| 78 { | 78 { |
| 79 v8::Local<v8::Object> listenerObject = getListenerObject(context); | 79 v8::Local<v8::Object> listenerObject = getListenerObject(context); |
| 80 if (listenerObject.IsEmpty()) | 80 if (listenerObject.IsEmpty()) |
| 81 return v8::Local<v8::Value>(); | 81 return v8::Local<v8::Value>(); |
| 82 | 82 |
| 83 v8::Local<v8::Function> handlerFunction = listenerObject.As<v8::Function>(); | 83 v8::Local<v8::Function> handlerFunction = listenerObject.As<v8::Function>(); |
| 84 v8::Local<v8::Object> receiver = getReceiverObject(context, event); | 84 v8::Local<v8::Object> receiver = getReceiverObject(event); |
| 85 if (handlerFunction.IsEmpty() || receiver.IsEmpty()) | 85 if (handlerFunction.IsEmpty() || receiver.IsEmpty()) |
| 86 return v8::Local<v8::Value>(); | 86 return v8::Local<v8::Value>(); |
| 87 | 87 |
| 88 // FIXME: Can |context| be 0 here? | 88 if (!scriptState()->executionContext()->isDocument()) |
| 89 if (!context) | |
| 90 return v8::Local<v8::Value>(); | 89 return v8::Local<v8::Value>(); |
| 91 | 90 |
| 92 if (!context->isDocument()) | 91 LocalFrame* frame = toDocument(scriptState()->executionContext())->frame(); |
| 93 return v8::Local<v8::Value>(); | |
| 94 | |
| 95 LocalFrame* frame = toDocument(context)->frame(); | |
| 96 if (!frame) | 92 if (!frame) |
| 97 return v8::Local<v8::Value>(); | 93 return v8::Local<v8::Value>(); |
| 98 | 94 |
| 99 if (!frame->script().canExecuteScripts(AboutToExecuteScript)) | 95 if (!frame->script().canExecuteScripts(AboutToExecuteScript)) |
| 100 return v8::Local<v8::Value>(); | 96 return v8::Local<v8::Value>(); |
| 101 | 97 |
| 102 v8::Handle<v8::Value> parameters[1] = { jsEvent }; | 98 v8::Handle<v8::Value> parameters[1] = { jsEvent }; |
| 103 return frame->script().callFunction(handlerFunction, receiver, WTF_ARRAY_LEN
GTH(parameters), parameters); | 99 return frame->script().callFunction(handlerFunction, receiver, WTF_ARRAY_LEN
GTH(parameters), parameters); |
| 104 } | 100 } |
| 105 | 101 |
| 106 static void V8LazyEventListenerToString(const v8::FunctionCallbackInfo<v8::Value
>& info) | 102 static void V8LazyEventListenerToString(const v8::FunctionCallbackInfo<v8::Value
>& info) |
| 107 { | 103 { |
| 108 v8SetReturnValue(info, V8HiddenValue::getHiddenValue(info.GetIsolate(), info
.Holder(), V8HiddenValue::toStringString(info.GetIsolate()))); | 104 v8SetReturnValue(info, V8HiddenValue::getHiddenValue(info.GetIsolate(), info
.Holder(), V8HiddenValue::toStringString(info.GetIsolate()))); |
| 109 } | 105 } |
| 110 | 106 |
| 107 void V8LazyEventListener::handleEvent(ExecutionContext* context, Event* event) |
| 108 { |
| 109 v8::HandleScope handleScope(toIsolate(context)); |
| 110 // V8LazyEventListener doesn't know the associated context when created. |
| 111 // Thus we lazily get the associated context and set a ScriptState on V8Abst
ractEventListener. |
| 112 v8::Local<v8::Context> v8Context = toV8Context(context, world()); |
| 113 if (v8Context.IsEmpty()) |
| 114 return; |
| 115 setScriptState(ScriptState::from(v8Context)); |
| 116 |
| 117 V8AbstractEventListener::handleEvent(context, event); |
| 118 } |
| 119 |
| 111 void V8LazyEventListener::prepareListenerObject(ExecutionContext* context) | 120 void V8LazyEventListener::prepareListenerObject(ExecutionContext* context) |
| 112 { | 121 { |
| 122 v8::HandleScope handleScope(toIsolate(context)); |
| 123 // V8LazyEventListener doesn't know the associated context when created. |
| 124 // Thus we lazily get the associated context and set a ScriptState on V8Abst
ractEventListener. |
| 125 v8::Local<v8::Context> v8Context = toV8Context(context, world()); |
| 126 if (v8Context.IsEmpty()) |
| 127 return; |
| 128 setScriptState(ScriptState::from(v8Context)); |
| 129 |
| 113 if (context->isDocument() && !toDocument(context)->allowInlineEventHandlers(
m_node, this, m_sourceURL, m_position.m_line)) { | 130 if (context->isDocument() && !toDocument(context)->allowInlineEventHandlers(
m_node, this, m_sourceURL, m_position.m_line)) { |
| 114 clearListenerObject(); | 131 clearListenerObject(); |
| 115 return; | 132 return; |
| 116 } | 133 } |
| 117 | 134 |
| 118 if (hasExistingListenerObject()) | 135 if (hasExistingListenerObject()) |
| 119 return; | 136 return; |
| 120 | 137 |
| 121 ASSERT(context->isDocument()); | 138 ASSERT(context->isDocument()); |
| 122 | 139 |
| 123 v8::Isolate* isolate = toIsolate(context); | 140 ScriptState::Scope scope(scriptState()); |
| 124 v8::HandleScope handleScope(isolate); | |
| 125 | |
| 126 // Use the outer scope to hold context. | |
| 127 v8::Local<v8::Context> v8Context = toV8Context(context, world()); | |
| 128 // Bail out if we cannot get the context. | |
| 129 if (v8Context.IsEmpty()) | |
| 130 return; | |
| 131 | |
| 132 v8::Context::Scope scope(v8Context); | |
| 133 | |
| 134 String listenerSource = InspectorInstrumentation::preprocessEventListener(t
oDocument(context)->frame(), m_code, m_sourceURL, m_functionName); | 141 String listenerSource = InspectorInstrumentation::preprocessEventListener(t
oDocument(context)->frame(), m_code, m_sourceURL, m_functionName); |
| 135 | 142 |
| 136 // FIXME: Remove the following 'with' hack. | 143 // FIXME: Remove the following 'with' hack. |
| 137 // | 144 // |
| 138 // Nodes other than the document object, when executing inline event | 145 // Nodes other than the document object, when executing inline event |
| 139 // handlers push document, form owner, and the target node on the scope chai
n. | 146 // handlers push document, form owner, and the target node on the scope chai
n. |
| 140 // We do this by using 'with' statement. | 147 // We do this by using 'with' statement. |
| 141 // See chrome/fast/forms/form-action.html | 148 // See chrome/fast/forms/form-action.html |
| 142 // chrome/fast/forms/selected-index-value.html | 149 // chrome/fast/forms/selected-index-value.html |
| 143 // base/fast/overflow/onscroll-layer-self-destruct.html | 150 // base/fast/overflow/onscroll-layer-self-destruct.html |
| 144 // | 151 // |
| 145 // Don't use new lines so that lines in the modified handler | 152 // Don't use new lines so that lines in the modified handler |
| 146 // have the same numbers as in the original code. | 153 // have the same numbers as in the original code. |
| 147 // FIXME: V8 does not allow us to programmatically create object environment
s so | 154 // FIXME: V8 does not allow us to programmatically create object environment
s so |
| 148 // we have to do this hack! What if m_code escapes to run arbitrary s
cript? | 155 // we have to do this hack! What if m_code escapes to run arbitrary s
cript? |
| 149 // | 156 // |
| 150 // Call with 4 arguments instead of 3, pass additional null as the last para
meter. | 157 // Call with 4 arguments instead of 3, pass additional null as the last para
meter. |
| 151 // By calling the function with 4 arguments, we create a setter on arguments
object | 158 // By calling the function with 4 arguments, we create a setter on arguments
object |
| 152 // which would shadow property "3" on the prototype. | 159 // which would shadow property "3" on the prototype. |
| 153 String code = "(function() {" | 160 String code = "(function() {" |
| 154 "with (this[2]) {" | 161 "with (this[2]) {" |
| 155 "with (this[1]) {" | 162 "with (this[1]) {" |
| 156 "with (this[0]) {" | 163 "with (this[0]) {" |
| 157 "return function(" + m_eventParameterName + ") {" + | 164 "return function(" + m_eventParameterName + ") {" + |
| 158 listenerSource + "\n" // Insert '\n' otherwise //-style comments
could break the handler. | 165 listenerSource + "\n" // Insert '\n' otherwise //-style comments
could break the handler. |
| 159 "};" | 166 "};" |
| 160 "}}}})"; | 167 "}}}})"; |
| 161 | 168 |
| 162 v8::Handle<v8::String> codeExternalString = v8String(isolate, code); | 169 v8::Handle<v8::String> codeExternalString = v8String(isolate(), code); |
| 163 | 170 |
| 164 v8::Local<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(co
deExternalString, isolate, m_sourceURL, m_position); | 171 v8::Local<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(co
deExternalString, isolate(), m_sourceURL, m_position); |
| 165 if (result.IsEmpty()) | 172 if (result.IsEmpty()) |
| 166 return; | 173 return; |
| 167 | 174 |
| 168 // Call the outer function to get the inner function. | 175 // Call the outer function to get the inner function. |
| 169 ASSERT(result->IsFunction()); | 176 ASSERT(result->IsFunction()); |
| 170 v8::Local<v8::Function> intermediateFunction = result.As<v8::Function>(); | 177 v8::Local<v8::Function> intermediateFunction = result.As<v8::Function>(); |
| 171 | 178 |
| 172 HTMLFormElement* formElement = 0; | 179 HTMLFormElement* formElement = 0; |
| 173 if (m_node && m_node->isHTMLElement()) | 180 if (m_node && m_node->isHTMLElement()) |
| 174 formElement = toHTMLElement(m_node)->formOwner(); | 181 formElement = toHTMLElement(m_node)->formOwner(); |
| 175 | 182 |
| 176 v8::Handle<v8::Object> nodeWrapper = toObjectWrapper<Node>(m_node, isolate); | 183 v8::Handle<v8::Object> nodeWrapper = toObjectWrapper<Node>(m_node, scriptSta
te()); |
| 177 v8::Handle<v8::Object> formWrapper = toObjectWrapper<HTMLFormElement>(formEl
ement, isolate); | 184 v8::Handle<v8::Object> formWrapper = toObjectWrapper<HTMLFormElement>(formEl
ement, scriptState()); |
| 178 v8::Handle<v8::Object> documentWrapper = toObjectWrapper<Document>(m_node ?
m_node->ownerDocument() : 0, isolate); | 185 v8::Handle<v8::Object> documentWrapper = toObjectWrapper<Document>(m_node ?
m_node->ownerDocument() : 0, scriptState()); |
| 179 | 186 |
| 180 v8::Local<v8::Object> thisObject = v8::Object::New(isolate); | 187 v8::Local<v8::Object> thisObject = v8::Object::New(isolate()); |
| 181 if (thisObject.IsEmpty()) | 188 if (thisObject.IsEmpty()) |
| 182 return; | 189 return; |
| 183 if (!thisObject->ForceSet(v8::Integer::New(isolate, 0), nodeWrapper)) | 190 if (!thisObject->ForceSet(v8::Integer::New(isolate(), 0), nodeWrapper)) |
| 184 return; | 191 return; |
| 185 if (!thisObject->ForceSet(v8::Integer::New(isolate, 1), formWrapper)) | 192 if (!thisObject->ForceSet(v8::Integer::New(isolate(), 1), formWrapper)) |
| 186 return; | 193 return; |
| 187 if (!thisObject->ForceSet(v8::Integer::New(isolate, 2), documentWrapper)) | 194 if (!thisObject->ForceSet(v8::Integer::New(isolate(), 2), documentWrapper)) |
| 188 return; | 195 return; |
| 189 | 196 |
| 190 // FIXME: Remove this code when we stop doing the 'with' hack above. | 197 // FIXME: Remove this code when we stop doing the 'with' hack above. |
| 191 v8::Local<v8::Value> innerValue = V8ScriptRunner::callInternalFunction(inter
mediateFunction, thisObject, 0, 0, isolate); | 198 v8::Local<v8::Value> innerValue = V8ScriptRunner::callInternalFunction(inter
mediateFunction, thisObject, 0, 0, isolate()); |
| 192 if (innerValue.IsEmpty() || !innerValue->IsFunction()) | 199 if (innerValue.IsEmpty() || !innerValue->IsFunction()) |
| 193 return; | 200 return; |
| 194 | 201 |
| 195 v8::Local<v8::Function> wrappedFunction = innerValue.As<v8::Function>(); | 202 v8::Local<v8::Function> wrappedFunction = innerValue.As<v8::Function>(); |
| 196 | 203 |
| 197 // Change the toString function on the wrapper function to avoid it | 204 // Change the toString function on the wrapper function to avoid it |
| 198 // returning the source for the actual wrapper function. Instead it | 205 // returning the source for the actual wrapper function. Instead it |
| 199 // returns source for a clean wrapper function with the event | 206 // returns source for a clean wrapper function with the event |
| 200 // argument wrapping the event source code. The reason for this is | 207 // argument wrapping the event source code. The reason for this is |
| 201 // that some web sites use toString on event functions and eval the | 208 // that some web sites use toString on event functions and eval the |
| 202 // source returned (sometimes a RegExp is applied as well) for some | 209 // source returned (sometimes a RegExp is applied as well) for some |
| 203 // other use. That fails miserably if the actual wrapper source is | 210 // other use. That fails miserably if the actual wrapper source is |
| 204 // returned. | 211 // returned. |
| 205 v8::Local<v8::Function> toStringFunction = v8::Function::New(isolate, V8Lazy
EventListenerToString); | 212 v8::Local<v8::Function> toStringFunction = v8::Function::New(isolate(), V8La
zyEventListenerToString); |
| 206 ASSERT(!toStringFunction.IsEmpty()); | 213 ASSERT(!toStringFunction.IsEmpty()); |
| 207 String toStringString = "function " + m_functionName + "(" + m_eventParamete
rName + ") {\n " + m_code + "\n}"; | 214 String toStringString = "function " + m_functionName + "(" + m_eventParamete
rName + ") {\n " + m_code + "\n}"; |
| 208 V8HiddenValue::setHiddenValue(isolate, wrappedFunction, V8HiddenValue::toStr
ingString(isolate), v8String(isolate, toStringString)); | 215 V8HiddenValue::setHiddenValue(isolate(), wrappedFunction, V8HiddenValue::toS
tringString(isolate()), v8String(isolate(), toStringString)); |
| 209 wrappedFunction->Set(v8AtomicString(isolate, "toString"), toStringFunction); | 216 wrappedFunction->Set(v8AtomicString(isolate(), "toString"), toStringFunction
); |
| 210 wrappedFunction->SetName(v8String(isolate, m_functionName)); | 217 wrappedFunction->SetName(v8String(isolate(), m_functionName)); |
| 211 | 218 |
| 212 // FIXME: Remove the following comment-outs. | 219 // FIXME: Remove the following comment-outs. |
| 213 // See https://bugs.webkit.org/show_bug.cgi?id=85152 for more details. | 220 // See https://bugs.webkit.org/show_bug.cgi?id=85152 for more details. |
| 214 // | 221 // |
| 215 // For the time being, we comment out the following code since the | 222 // For the time being, we comment out the following code since the |
| 216 // second parsing can happen. | 223 // second parsing can happen. |
| 217 // // Since we only parse once, there's no need to keep data used for parsin
g around anymore. | 224 // // Since we only parse once, there's no need to keep data used for parsin
g around anymore. |
| 218 // m_functionName = String(); | 225 // m_functionName = String(); |
| 219 // m_code = String(); | 226 // m_code = String(); |
| 220 // m_eventParameterName = String(); | 227 // m_eventParameterName = String(); |
| 221 // m_sourceURL = String(); | 228 // m_sourceURL = String(); |
| 222 | 229 |
| 223 setListenerObject(wrappedFunction); | 230 setListenerObject(wrappedFunction); |
| 224 } | 231 } |
| 225 | 232 |
| 226 } // namespace WebCore | 233 } // namespace WebCore |
| OLD | NEW |