18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
38f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian *  Copyright (C) 2003, 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#ifndef JSEventListener_h
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define JSEventListener_h
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "EventListener.h"
245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include "JSDOMWindow.h"
252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include <heap/Weak.h>
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    class JSDOMGlobalObject;
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    class JSEventListener : public EventListener {
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    public:
338a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        static PassRefPtr<JSEventListener> create(JSC::JSObject* listener, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld* isolatedWorld)
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        {
358a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block            return adoptRef(new JSEventListener(listener, wrapper, isAttribute, isolatedWorld));
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
37231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
38231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        static const JSEventListener* cast(const EventListener* listener)
39231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        {
40231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return listener->type() == JSEventListenerType
41231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                ? static_cast<const JSEventListener*>(listener)
42231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                : 0;
43231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
44231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        virtual ~JSEventListener();
46231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
47231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        virtual bool operator==(const EventListener& other);
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // Returns true if this event listener was created for an event handler attribute, like "onload" or "onclick".
505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        bool isAttribute() const { return m_isAttribute; }
518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
528a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        JSC::JSObject* jsFunction(ScriptExecutionContext*) const;
538a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        DOMWrapperWorld* isolatedWorld() const { return m_isolatedWorld.get(); }
548a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
558a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        JSC::JSObject* wrapper() const { return m_wrapper.get(); }
5681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        void setWrapper(JSC::JSGlobalData& globalData, JSC::JSObject* wrapper) const { m_wrapper.set(globalData, wrapper, 0); }
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    private:
598a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        virtual JSC::JSObject* initializeJSFunction(ScriptExecutionContext*) const;
600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        virtual void markJSFunction(JSC::MarkStack&);
615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        virtual bool virtualisAttribute() const;
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    protected:
648a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        JSEventListener(JSC::JSObject* function, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld* isolatedWorld);
65ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        virtual void handleEvent(ScriptExecutionContext*, Event*);
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
678a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    private:
682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        mutable JSC::WriteBarrier<JSC::JSObject> m_jsFunction;
692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        mutable JSC::Weak<JSC::JSObject> m_wrapper;
708a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        bool m_isAttribute;
72cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        RefPtr<DOMWrapperWorld> m_isolatedWorld;
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    };
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
758a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    inline JSC::JSObject* JSEventListener::jsFunction(ScriptExecutionContext* scriptExecutionContext) const
768a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    {
778a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        if (!m_jsFunction)
782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            m_jsFunction.set(*scriptExecutionContext->globalData(), m_wrapper.get(), initializeJSFunction(scriptExecutionContext));
798a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
808a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        // Verify that we have a valid wrapper protecting our function from
818a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        // garbage collection.
828a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        ASSERT(m_wrapper || !m_jsFunction);
838a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        if (!m_wrapper)
848a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block            return 0;
858a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
868a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        // Try to verify that m_jsFunction wasn't recycled. (Not exact, since an
878a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        // event listener can be almost anything, but this makes test-writing easier).
882fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        ASSERT(!m_jsFunction || static_cast<JSC::JSCell*>(m_jsFunction.get())->isObject());
898a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
902fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return m_jsFunction.get();
918a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    }
928a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
93d0825bca7fe65beaee391d30da42e937db621564Steve Block    // Creates a JS EventListener for an "onXXX" event attribute.
948a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    inline PassRefPtr<JSEventListener> createJSAttributeEventListener(JSC::ExecState* exec, JSC::JSValue listener, JSC::JSObject* wrapper)
95d0825bca7fe65beaee391d30da42e937db621564Steve Block    {
96d0825bca7fe65beaee391d30da42e937db621564Steve Block        if (!listener.isObject())
97d0825bca7fe65beaee391d30da42e937db621564Steve Block            return 0;
98d0825bca7fe65beaee391d30da42e937db621564Steve Block
998a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        return JSEventListener::create(asObject(listener), wrapper, true, currentWorld(exec));
100d0825bca7fe65beaee391d30da42e937db621564Steve Block    }
101d0825bca7fe65beaee391d30da42e937db621564Steve Block
102d0825bca7fe65beaee391d30da42e937db621564Steve Block
1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace WebCore
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif // JSEventListener_h
106