| 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 // FIXME: Can |context| be 0 here? |
| 89 if (!context) | 89 if (!context) |
| 90 return v8::Local<v8::Value>(); | 90 return v8::Local<v8::Value>(); |
| 91 | 91 |
| 92 if (!context->isDocument()) | 92 if (!context->isDocument()) |
| 93 return v8::Local<v8::Value>(); | 93 return v8::Local<v8::Value>(); |
| 94 | 94 |
| 95 LocalFrame* frame = toDocument(context)->frame(); | 95 LocalFrame* frame = toDocument(context)->frame(); |
| 96 if (!frame) | 96 if (!frame) |
| 97 return v8::Local<v8::Value>(); | 97 return v8::Local<v8::Value>(); |
| 98 | 98 |
| 99 if (!frame->script().canExecuteScripts(AboutToExecuteScript)) | 99 if (!frame->script().canExecuteScripts(AboutToExecuteScript)) |
| 100 return v8::Local<v8::Value>(); | 100 return v8::Local<v8::Value>(); |
| 101 | 101 |
| 102 v8::Handle<v8::Value> parameters[1] = { jsEvent }; | 102 v8::Handle<v8::Value> parameters[1] = { jsEvent }; |
| 103 return frame->script().callFunction(handlerFunction, receiver, WTF_ARRAY_LEN
GTH(parameters), parameters); | 103 return frame->script().callFunction(handlerFunction, receiver, WTF_ARRAY_LEN
GTH(parameters), parameters); |
| 104 } | 104 } |
| 105 | 105 |
| 106 static void V8LazyEventListenerToString(const v8::FunctionCallbackInfo<v8::Value
>& info) | 106 static void V8LazyEventListenerToString(const v8::FunctionCallbackInfo<v8::Value
>& info) |
| 107 { | 107 { |
| 108 v8SetReturnValue(info, V8HiddenValue::getHiddenValue(info.GetIsolate(), info
.Holder(), V8HiddenValue::toStringString(info.GetIsolate()))); | 108 v8SetReturnValue(info, V8HiddenValue::getHiddenValue(info.GetIsolate(), info
.Holder(), V8HiddenValue::toStringString(info.GetIsolate()))); |
| 109 } | 109 } |
| 110 | 110 |
| 111 void V8LazyEventListener::handleEvent(ExecutionContext* context, Event* event) |
| 112 { |
| 113 v8::HandleScope handleScope(toIsolate(context)); |
| 114 // V8LazyEventListener doesn't know the associated context when created. |
| 115 // Thus we lazily get the associated context and set a ScriptState on V8Abst
ractEventListener. |
| 116 v8::Local<v8::Context> v8Context = toV8Context(context, world()); |
| 117 if (v8Context.IsEmpty()) |
| 118 return; |
| 119 setScriptState(ScriptState::from(v8Context)); |
| 120 |
| 121 V8AbstractEventListener::handleEvent(context, event); |
| 122 } |
| 123 |
| 111 void V8LazyEventListener::prepareListenerObject(ExecutionContext* context) | 124 void V8LazyEventListener::prepareListenerObject(ExecutionContext* context) |
| 112 { | 125 { |
| 113 if (context->isDocument() && !toDocument(context)->allowInlineEventHandlers(
m_node, this, m_sourceURL, m_position.m_line)) { | 126 if (context->isDocument() && !toDocument(context)->allowInlineEventHandlers(
m_node, this, m_sourceURL, m_position.m_line)) { |
| 114 clearListenerObject(); | 127 clearListenerObject(); |
| 115 return; | 128 return; |
| 116 } | 129 } |
| 117 | 130 |
| 118 if (hasExistingListenerObject()) | 131 if (hasExistingListenerObject()) |
| 119 return; | 132 return; |
| 120 | 133 |
| 121 ASSERT(context->isDocument()); | 134 ASSERT(context->isDocument()); |
| 122 | 135 |
| 123 v8::Isolate* isolate = toIsolate(context); | 136 v8::HandleScope handleScope(toIsolate(context)); |
| 124 v8::HandleScope handleScope(isolate); | 137 // V8LazyEventListener doesn't know the associated context when created. |
| 125 | 138 // Thus we lazily get the associated context and set a ScriptState on V8Abst
ractEventListener. |
| 126 // Use the outer scope to hold context. | |
| 127 v8::Local<v8::Context> v8Context = toV8Context(context, world()); | 139 v8::Local<v8::Context> v8Context = toV8Context(context, world()); |
| 128 // Bail out if we cannot get the context. | |
| 129 if (v8Context.IsEmpty()) | 140 if (v8Context.IsEmpty()) |
| 130 return; | 141 return; |
| 142 setScriptState(ScriptState::from(v8Context)); |
| 131 | 143 |
| 132 v8::Context::Scope scope(v8Context); | 144 ScriptState::Scope scope(scriptState()); |
| 133 | |
| 134 String listenerSource = InspectorInstrumentation::preprocessEventListener(t
oDocument(context)->frame(), m_code, m_sourceURL, m_functionName); | 145 String listenerSource = InspectorInstrumentation::preprocessEventListener(t
oDocument(context)->frame(), m_code, m_sourceURL, m_functionName); |
| 135 | 146 |
| 136 // FIXME: Remove the following 'with' hack. | 147 // FIXME: Remove the following 'with' hack. |
| 137 // | 148 // |
| 138 // Nodes other than the document object, when executing inline event | 149 // 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. | 150 // handlers push document, form owner, and the target node on the scope chai
n. |
| 140 // We do this by using 'with' statement. | 151 // We do this by using 'with' statement. |
| 141 // See chrome/fast/forms/form-action.html | 152 // See chrome/fast/forms/form-action.html |
| 142 // chrome/fast/forms/selected-index-value.html | 153 // chrome/fast/forms/selected-index-value.html |
| 143 // base/fast/overflow/onscroll-layer-self-destruct.html | 154 // base/fast/overflow/onscroll-layer-self-destruct.html |
| 144 // | 155 // |
| 145 // Don't use new lines so that lines in the modified handler | 156 // Don't use new lines so that lines in the modified handler |
| 146 // have the same numbers as in the original code. | 157 // have the same numbers as in the original code. |
| 147 // FIXME: V8 does not allow us to programmatically create object environment
s so | 158 // 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? | 159 // we have to do this hack! What if m_code escapes to run arbitrary s
cript? |
| 149 // | 160 // |
| 150 // Call with 4 arguments instead of 3, pass additional null as the last para
meter. | 161 // 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 | 162 // By calling the function with 4 arguments, we create a setter on arguments
object |
| 152 // which would shadow property "3" on the prototype. | 163 // which would shadow property "3" on the prototype. |
| 153 String code = "(function() {" | 164 String code = "(function() {" |
| 154 "with (this[2]) {" | 165 "with (this[2]) {" |
| 155 "with (this[1]) {" | 166 "with (this[1]) {" |
| 156 "with (this[0]) {" | 167 "with (this[0]) {" |
| 157 "return function(" + m_eventParameterName + ") {" + | 168 "return function(" + m_eventParameterName + ") {" + |
| 158 listenerSource + "\n" // Insert '\n' otherwise //-style comments
could break the handler. | 169 listenerSource + "\n" // Insert '\n' otherwise //-style comments
could break the handler. |
| 159 "};" | 170 "};" |
| 160 "}}}})"; | 171 "}}}})"; |
| 161 | 172 |
| 162 v8::Handle<v8::String> codeExternalString = v8String(isolate, code); | 173 v8::Handle<v8::String> codeExternalString = v8String(isolate(), code); |
| 163 | 174 |
| 164 v8::Local<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(co
deExternalString, isolate, m_sourceURL, m_position); | 175 v8::Local<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(co
deExternalString, isolate(), m_sourceURL, m_position); |
| 165 if (result.IsEmpty()) | 176 if (result.IsEmpty()) |
| 166 return; | 177 return; |
| 167 | 178 |
| 168 // Call the outer function to get the inner function. | 179 // Call the outer function to get the inner function. |
| 169 ASSERT(result->IsFunction()); | 180 ASSERT(result->IsFunction()); |
| 170 v8::Local<v8::Function> intermediateFunction = result.As<v8::Function>(); | 181 v8::Local<v8::Function> intermediateFunction = result.As<v8::Function>(); |
| 171 | 182 |
| 172 HTMLFormElement* formElement = 0; | 183 HTMLFormElement* formElement = 0; |
| 173 if (m_node && m_node->isHTMLElement()) | 184 if (m_node && m_node->isHTMLElement()) |
| 174 formElement = toHTMLElement(m_node)->formOwner(); | 185 formElement = toHTMLElement(m_node)->formOwner(); |
| 175 | 186 |
| 176 v8::Handle<v8::Object> nodeWrapper = toObjectWrapper<Node>(m_node, isolate); | 187 v8::Handle<v8::Object> nodeWrapper = toObjectWrapper<Node>(m_node, scriptSta
te()); |
| 177 v8::Handle<v8::Object> formWrapper = toObjectWrapper<HTMLFormElement>(formEl
ement, isolate); | 188 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); | 189 v8::Handle<v8::Object> documentWrapper = toObjectWrapper<Document>(m_node ?
m_node->ownerDocument() : 0, scriptState()); |
| 179 | 190 |
| 180 v8::Local<v8::Object> thisObject = v8::Object::New(isolate); | 191 v8::Local<v8::Object> thisObject = v8::Object::New(isolate()); |
| 181 if (thisObject.IsEmpty()) | 192 if (thisObject.IsEmpty()) |
| 182 return; | 193 return; |
| 183 if (!thisObject->ForceSet(v8::Integer::New(isolate, 0), nodeWrapper)) | 194 if (!thisObject->ForceSet(v8::Integer::New(isolate(), 0), nodeWrapper)) |
| 184 return; | 195 return; |
| 185 if (!thisObject->ForceSet(v8::Integer::New(isolate, 1), formWrapper)) | 196 if (!thisObject->ForceSet(v8::Integer::New(isolate(), 1), formWrapper)) |
| 186 return; | 197 return; |
| 187 if (!thisObject->ForceSet(v8::Integer::New(isolate, 2), documentWrapper)) | 198 if (!thisObject->ForceSet(v8::Integer::New(isolate(), 2), documentWrapper)) |
| 188 return; | 199 return; |
| 189 | 200 |
| 190 // FIXME: Remove this code when we stop doing the 'with' hack above. | 201 // 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); | 202 v8::Local<v8::Value> innerValue = V8ScriptRunner::callInternalFunction(inter
mediateFunction, thisObject, 0, 0, isolate()); |
| 192 if (innerValue.IsEmpty() || !innerValue->IsFunction()) | 203 if (innerValue.IsEmpty() || !innerValue->IsFunction()) |
| 193 return; | 204 return; |
| 194 | 205 |
| 195 v8::Local<v8::Function> wrappedFunction = innerValue.As<v8::Function>(); | 206 v8::Local<v8::Function> wrappedFunction = innerValue.As<v8::Function>(); |
| 196 | 207 |
| 197 // Change the toString function on the wrapper function to avoid it | 208 // Change the toString function on the wrapper function to avoid it |
| 198 // returning the source for the actual wrapper function. Instead it | 209 // returning the source for the actual wrapper function. Instead it |
| 199 // returns source for a clean wrapper function with the event | 210 // returns source for a clean wrapper function with the event |
| 200 // argument wrapping the event source code. The reason for this is | 211 // argument wrapping the event source code. The reason for this is |
| 201 // that some web sites use toString on event functions and eval the | 212 // that some web sites use toString on event functions and eval the |
| 202 // source returned (sometimes a RegExp is applied as well) for some | 213 // source returned (sometimes a RegExp is applied as well) for some |
| 203 // other use. That fails miserably if the actual wrapper source is | 214 // other use. That fails miserably if the actual wrapper source is |
| 204 // returned. | 215 // returned. |
| 205 v8::Local<v8::Function> toStringFunction = v8::Function::New(isolate, V8Lazy
EventListenerToString); | 216 v8::Local<v8::Function> toStringFunction = v8::Function::New(isolate(), V8La
zyEventListenerToString); |
| 206 ASSERT(!toStringFunction.IsEmpty()); | 217 ASSERT(!toStringFunction.IsEmpty()); |
| 207 String toStringString = "function " + m_functionName + "(" + m_eventParamete
rName + ") {\n " + m_code + "\n}"; | 218 String toStringString = "function " + m_functionName + "(" + m_eventParamete
rName + ") {\n " + m_code + "\n}"; |
| 208 V8HiddenValue::setHiddenValue(isolate, wrappedFunction, V8HiddenValue::toStr
ingString(isolate), v8String(isolate, toStringString)); | 219 V8HiddenValue::setHiddenValue(isolate(), wrappedFunction, V8HiddenValue::toS
tringString(isolate()), v8String(isolate(), toStringString)); |
| 209 wrappedFunction->Set(v8AtomicString(isolate, "toString"), toStringFunction); | 220 wrappedFunction->Set(v8AtomicString(isolate(), "toString"), toStringFunction
); |
| 210 wrappedFunction->SetName(v8String(isolate, m_functionName)); | 221 wrappedFunction->SetName(v8String(isolate(), m_functionName)); |
| 211 | 222 |
| 212 // FIXME: Remove the following comment-outs. | 223 // FIXME: Remove the following comment-outs. |
| 213 // See https://bugs.webkit.org/show_bug.cgi?id=85152 for more details. | 224 // See https://bugs.webkit.org/show_bug.cgi?id=85152 for more details. |
| 214 // | 225 // |
| 215 // For the time being, we comment out the following code since the | 226 // For the time being, we comment out the following code since the |
| 216 // second parsing can happen. | 227 // second parsing can happen. |
| 217 // // Since we only parse once, there's no need to keep data used for parsin
g around anymore. | 228 // // Since we only parse once, there's no need to keep data used for parsin
g around anymore. |
| 218 // m_functionName = String(); | 229 // m_functionName = String(); |
| 219 // m_code = String(); | 230 // m_code = String(); |
| 220 // m_eventParameterName = String(); | 231 // m_eventParameterName = String(); |
| 221 // m_sourceURL = String(); | 232 // m_sourceURL = String(); |
| 222 | 233 |
| 223 setListenerObject(wrappedFunction); | 234 setListenerObject(wrappedFunction); |
| 224 } | 235 } |
| 225 | 236 |
| 226 } // namespace WebCore | 237 } // namespace WebCore |
| OLD | NEW |