18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2001 Peter Kelly (pmk@post.com) 38f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All Rights Reserved. 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is free software; you can redistribute it and/or 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modify it under the terms of the GNU Lesser General Public 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * License as published by the Free Software Foundation; either 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * version 2 of the License, or (at your option) any later version. 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is distributed in the hope that it will be useful, 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Lesser General Public License for more details. 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * You should have received a copy of the GNU Lesser General Public 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * License along with this library; if not, write to the Free Software 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "JSEventListener.h" 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Event.h" 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Frame.h" 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "JSEvent.h" 268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "JSEventTarget.h" 27e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "JSMainThreadExecState.h" 282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "WorkerContext.h" 298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <runtime/JSLock.h> 308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/RefCountedLeakCounter.h> 318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace JSC; 338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore { 358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 368a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve BlockJSEventListener::JSEventListener(JSObject* function, JSObject* wrapper, bool isAttribute, DOMWrapperWorld* isolatedWorld) 37231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block : EventListener(JSEventListenerType) 3881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch , m_wrapper(*isolatedWorld->globalData(), wrapper) 395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian , m_isAttribute(isAttribute) 40cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block , m_isolatedWorld(isolatedWorld) 415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{ 422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (wrapper) 432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch m_jsFunction.set(*m_isolatedWorld->globalData(), wrapper, function); 442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch else 452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch ASSERT(!function); 462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian} 485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 495f1ab04193ad0130ca8204aadaceae083aca9881Feng QianJSEventListener::~JSEventListener() 505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{ 515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian} 525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 538a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve BlockJSObject* JSEventListener::initializeJSFunction(ScriptExecutionContext*) const 545f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{ 558a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block ASSERT_NOT_REACHED(); 568a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block return 0; 575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian} 585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid JSEventListener::markJSFunction(MarkStack& markStack) 605f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{ 610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (m_jsFunction) 622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block markStack.append(&m_jsFunction); 635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian} 645f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 65231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext, Event* event) 668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 67231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block ASSERT(scriptExecutionContext); 682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (!scriptExecutionContext || scriptExecutionContext->isJSExecutionForbidden()) 69231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return; 70231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch JSLock lock(SilenceAssertionsOnly); 728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 73231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block JSObject* jsFunction = this->jsFunction(scriptExecutionContext); 745f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (!jsFunction) 758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 77cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(scriptExecutionContext, m_isolatedWorld.get()); 788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!globalObject) 798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (scriptExecutionContext->isDocument()) { 828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project JSDOMWindow* window = static_cast<JSDOMWindow*>(globalObject); 83635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Frame* frame = window->impl()->frame(); 848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!frame) 858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // The window must still be active in its frame. See <https://bugs.webkit.org/show_bug.cgi?id=21921>. 878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: A better fix for this may be to change DOMWindow::frame() to not return a frame the detached window used to be in. 888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (frame->domWindow() != window->impl()) 898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: Is this check needed for other contexts? 918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ScriptController* script = frame->script(); 92dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!script->canExecuteScripts(AboutToExecuteScript) || script->isPaused()) 938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ExecState* exec = globalObject->globalExec(); 97643ca7872b450ea4efacab6188849e5aac2ba161Steve Block JSValue handleEventFunction = jsFunction->get(exec, Identifier(exec, "handleEvent")); 988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CallData callData; 100545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch CallType callType = getCallData(handleEventFunction, callData); 1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (callType == CallTypeNone) { 1025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian handleEventFunction = JSValue(); 1035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian callType = jsFunction->getCallData(callData); 1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (callType != CallTypeNone) { 1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ref(); 1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian MarkedArgumentBuffer args; 1100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch args.append(toJS(exec, globalObject, event)); 1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Event* savedEvent = globalObject->currentEvent(); 1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project globalObject->setCurrentEvent(event); 1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 115e14391e94c850b8bd03680c23b38978db68687a8John Reck JSGlobalData& globalData = globalObject->globalData(); 1162bde8e466a4451c7319e3a072d118917957d6554Steve Block DynamicGlobalObjectScope globalObjectScope(globalData, globalData.dynamicGlobalObject ? globalData.dynamicGlobalObject : globalObject); 117635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 118e14391e94c850b8bd03680c23b38978db68687a8John Reck globalData.timeoutChecker.start(); 119e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block JSValue retval; 120e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block if (handleEventFunction) { 121e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block retval = scriptExecutionContext->isDocument() 122e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block ? JSMainThreadExecState::call(exec, handleEventFunction, callType, callData, jsFunction, args) 123e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block : JSC::call(exec, handleEventFunction, callType, callData, jsFunction, args); 124e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block } else { 125e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block JSValue currentTarget = toJS(exec, globalObject, event->currentTarget()); 126e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block retval = scriptExecutionContext->isDocument() 127e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block ? JSMainThreadExecState::call(exec, jsFunction, callType, callData, currentTarget, args) 128e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block : JSC::call(exec, jsFunction, callType, callData, currentTarget, args); 129e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block } 130e14391e94c850b8bd03680c23b38978db68687a8John Reck globalData.timeoutChecker.stop(); 1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project globalObject->setCurrentEvent(savedEvent); 1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if ENABLE(WORKERS) 1352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (scriptExecutionContext->isWorkerContext()) { 1362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch bool terminatorCausedException = (exec->hadException() && exec->exception().isObject() && asObject(exec->exception())->exceptionType() == Terminated); 1372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (terminatorCausedException || globalData.terminator.shouldTerminate()) 1382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch static_cast<WorkerContext*>(scriptExecutionContext)->script()->forbidExecution(); 1392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch } 1402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#endif 1412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 14281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (exec->hadException()) { 14381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch event->target()->uncaughtExceptionInEventHandler(); 144635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project reportCurrentException(exec); 14581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch } else { 146635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!retval.isUndefinedOrNull() && event->storesResultAsString()) 147dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block event->storeResult(ustringToString(retval.toString(exec))); 1485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (m_isAttribute) { 1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool retvalbool; 150635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (retval.getBoolean(retvalbool) && !retvalbool) 1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project event->preventDefault(); 1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project deref(); 1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianbool JSEventListener::virtualisAttribute() const 1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return m_isAttribute; 1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 164231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockbool JSEventListener::operator==(const EventListener& listener) 165231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 166231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (const JSEventListener* jsEventListener = JSEventListener::cast(&listener)) 167231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return m_jsFunction == jsEventListener->m_jsFunction && m_isAttribute == jsEventListener->m_isAttribute; 168231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return false; 169231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} 170231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace WebCore 172