Changeset 49050 in webkit


Ignore:
Timestamp:
Oct 2, 2009 3:40:59 PM (14 years ago)
Author:
eric@webkit.org
Message:

2009-10-02 Vitaly Repeshko <vitalyr@chromium.org>

Reviewed by Dimitri Glazkov.

[V8] Disconnect event listeners on navigation.
Fixes http://crbug.com/23597.
https://bugs.webkit.org/show_bug.cgi?id=30027

Added V8ListenerGuard that is shared by listeners and proxy. On
navigation proxy sets a flag in the guard turning off listeners.

  • bindings/v8/V8AbstractEventListener.cpp: (WebCore::V8AbstractEventListener::V8AbstractEventListener):
  • bindings/v8/V8AbstractEventListener.h: (WebCore::V8ListenerGuard::create): (WebCore::V8ListenerGuard::isDisconnected): (WebCore::V8ListenerGuard::disconnectListeners): (WebCore::V8ListenerGuard::V8ListenerGuard): (WebCore::V8AbstractEventListener::disconnected):
  • bindings/v8/V8DOMWrapper.cpp: (WebCore::V8DOMWrapper::getEventListener):
  • bindings/v8/V8EventListenerList.h: (WebCore::V8EventListenerList::findOrCreateWrapper):
  • bindings/v8/V8LazyEventListener.cpp: (WebCore::V8LazyEventListener::V8LazyEventListener):
  • bindings/v8/V8Proxy.cpp: (WebCore::V8Proxy::V8Proxy): (WebCore::V8Proxy::disconnectFrame): (WebCore::V8Proxy::disconnectEventListeners): (WebCore::V8Proxy::clearForNavigation):
  • bindings/v8/V8Proxy.h: (WebCore::V8Proxy::listenerGuard):
  • bindings/v8/V8WorkerContextEventListener.cpp: (WebCore::V8WorkerContextEventListener::V8WorkerContextEventListener):
  • bindings/v8/V8WorkerContextEventListener.h: (WebCore::V8WorkerContextEventListener::create):
  • bindings/v8/WorkerContextExecutionProxy.cpp: (WebCore::WorkerContextExecutionProxy::WorkerContextExecutionProxy): (WebCore::WorkerContextExecutionProxy::dispose): (WebCore::WorkerContextExecutionProxy::findOrCreateEventListener):
  • bindings/v8/WorkerContextExecutionProxy.h:
  • bindings/v8/custom/V8CustomEventListener.cpp: (WebCore::V8EventListener::V8EventListener):
  • bindings/v8/custom/V8CustomEventListener.h: (WebCore::V8EventListener::create):
Location:
trunk/WebCore
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r49049 r49050  
     12009-10-02  Vitaly Repeshko  <vitalyr@chromium.org>
     2
     3        Reviewed by Dimitri Glazkov.
     4
     5        [V8] Disconnect event listeners on navigation.
     6        Fixes http://crbug.com/23597.
     7        https://bugs.webkit.org/show_bug.cgi?id=30027
     8
     9        Added V8ListenerGuard that is shared by listeners and proxy. On
     10        navigation proxy sets a flag in the guard turning off listeners.
     11
     12        * bindings/v8/V8AbstractEventListener.cpp:
     13        (WebCore::V8AbstractEventListener::V8AbstractEventListener):
     14        * bindings/v8/V8AbstractEventListener.h:
     15        (WebCore::V8ListenerGuard::create):
     16        (WebCore::V8ListenerGuard::isDisconnected):
     17        (WebCore::V8ListenerGuard::disconnectListeners):
     18        (WebCore::V8ListenerGuard::V8ListenerGuard):
     19        (WebCore::V8AbstractEventListener::disconnected):
     20        * bindings/v8/V8DOMWrapper.cpp:
     21        (WebCore::V8DOMWrapper::getEventListener):
     22        * bindings/v8/V8EventListenerList.h:
     23        (WebCore::V8EventListenerList::findOrCreateWrapper):
     24        * bindings/v8/V8LazyEventListener.cpp:
     25        (WebCore::V8LazyEventListener::V8LazyEventListener):
     26        * bindings/v8/V8Proxy.cpp:
     27        (WebCore::V8Proxy::V8Proxy):
     28        (WebCore::V8Proxy::disconnectFrame):
     29        (WebCore::V8Proxy::disconnectEventListeners):
     30        (WebCore::V8Proxy::clearForNavigation):
     31        * bindings/v8/V8Proxy.h:
     32        (WebCore::V8Proxy::listenerGuard):
     33        * bindings/v8/V8WorkerContextEventListener.cpp:
     34        (WebCore::V8WorkerContextEventListener::V8WorkerContextEventListener):
     35        * bindings/v8/V8WorkerContextEventListener.h:
     36        (WebCore::V8WorkerContextEventListener::create):
     37        * bindings/v8/WorkerContextExecutionProxy.cpp:
     38        (WebCore::WorkerContextExecutionProxy::WorkerContextExecutionProxy):
     39        (WebCore::WorkerContextExecutionProxy::dispose):
     40        (WebCore::WorkerContextExecutionProxy::findOrCreateEventListener):
     41        * bindings/v8/WorkerContextExecutionProxy.h:
     42        * bindings/v8/custom/V8CustomEventListener.cpp:
     43        (WebCore::V8EventListener::V8EventListener):
     44        * bindings/v8/custom/V8CustomEventListener.h:
     45        (WebCore::V8EventListener::create):
     46
    1472009-10-02  Kenneth Russell  <kbr@google.com>
    248
  • trunk/WebCore/bindings/v8/V8AbstractEventListener.cpp

    r48978 r49050  
    3939#include "V8Binding.h"
    4040#include "V8EventListenerList.h"
     41#include "V8Proxy.h"
    4142#include "V8Utilities.h"
    4243
     
    4950}
    5051
    51 V8AbstractEventListener::V8AbstractEventListener(Frame* frame, bool isAttribute)
     52V8AbstractEventListener::V8AbstractEventListener(Frame* frame, PassRefPtr<V8ListenerGuard> guard, bool isAttribute)
    5253    : EventListener(JSEventListenerType)
    5354    , m_isWeak(true)
    5455    , m_isAttribute(isAttribute)
    5556    , m_frame(frame)
     57    , m_guard(guard)
    5658    , m_lineNumber(0)
    5759    , m_columnNumber(0)
  • trunk/WebCore/bindings/v8/V8AbstractEventListener.h

    r48978 r49050  
    3434#include "EventListener.h"
    3535#include "OwnHandle.h"
    36 #include "V8Proxy.h"
     36#include "SharedPersistent.h"
    3737#include <v8.h>
     38#include <wtf/PassRefPtr.h>
     39#include <wtf/RefCounted.h>
    3840
    3941namespace WebCore {
     
    4143    class Event;
    4244    class Frame;
     45    class V8Proxy;
     46
     47    // Shared by listener objects and V8Proxy so that V8Proxy can
     48    // silence listeners when needed.
     49    class V8ListenerGuard : public RefCounted<V8ListenerGuard> {
     50      public:
     51        static PassRefPtr<V8ListenerGuard> create()
     52        {
     53            return adoptRef(new V8ListenerGuard);
     54        }
     55
     56        bool isDisconnected() const { return m_disconnected; }
     57
     58        void disconnectListeners()
     59        {
     60            m_disconnected = true;
     61        }
     62
     63      private:
     64        V8ListenerGuard()
     65            : m_disconnected(false) { }
     66
     67        bool m_disconnected;
     68    };
    4369
    4470    // There are two kinds of event listeners: HTML or non-HMTL. onload,
     
    100126        void disconnectFrame() { m_frame = 0; }
    101127
    102         virtual bool disconnected() const { return !m_frame; }
     128        virtual bool disconnected() const { return m_guard && m_guard->isDisconnected(); }
    103129
    104130    protected:
    105         V8AbstractEventListener(Frame*, bool isAttribute);
     131        V8AbstractEventListener(Frame*, PassRefPtr<V8ListenerGuard>, bool isAttribute);
    106132
    107133        virtual void prepareListenerObject() { }
     
    135161        Frame* m_frame;
    136162        RefPtr<SharedPersistent<v8::Context> > m_context;
     163        RefPtr<V8ListenerGuard> m_guard;
    137164
    138165        // Position in the HTML source for HTML event listeners.
  • trunk/WebCore/bindings/v8/V8DOMWrapper.cpp

    r48978 r49050  
    13991399
    14001400    if (proxy)
    1401         return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(proxy->frame(), value, isAttribute);
     1401        return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(proxy->frame(), proxy->listenerGuard(), value, isAttribute);
    14021402
    14031403    return 0;
     
    14191419    V8Proxy* proxy = V8Proxy::retrieve(worker->scriptExecutionContext());
    14201420    if (proxy)
    1421         return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(proxy->frame(), value, isAttribute);
     1421        return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(proxy->frame(), proxy->listenerGuard(), value, isAttribute);
    14221422
    14231423    return 0;
     
    14351435    V8Proxy* proxy = V8Proxy::retrieve(notification->scriptExecutionContext());
    14361436    if (proxy)
    1437         return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(proxy->frame(), value, isAttribute);
     1437        return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(proxy->frame(), proxy->listenerGuard(), value, isAttribute);
    14381438
    14391439    return 0;
     
    14591459    V8Proxy* proxy = V8Proxy::retrieve(eventTarget->scriptExecutionContext());
    14601460    if (proxy)
    1461         return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(proxy->frame(), value, isAttribute);
     1461        return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(proxy->frame(), proxy->listenerGuard(), value, isAttribute);
    14621462
    14631463#if ENABLE(WORKERS)
     
    14731473{
    14741474    if (proxy)
    1475         return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(proxy->frame(), value, isAttribute);
     1475        return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(proxy->frame(), proxy->listenerGuard(), value, isAttribute);
    14761476
    14771477    return 0;
  • trunk/WebCore/bindings/v8/V8EventListenerList.h

    r48978 r49050  
    5656
    5757        template<typename WrapperType, typename ContextType>
    58         static PassRefPtr<V8EventListener> findOrCreateWrapper(ContextType*, v8::Local<v8::Value>, bool isAttribute);
     58        static PassRefPtr<V8EventListener> findOrCreateWrapper(ContextType*, PassRefPtr<V8ListenerGuard>, v8::Local<v8::Value>, bool isAttribute);
    5959
    6060        static void clearWrapper(v8::Handle<v8::Object> listenerObject, bool isAttribute)
     
    8282
    8383    template<typename WrapperType, typename ContextType>
    84     PassRefPtr<V8EventListener> V8EventListenerList::findOrCreateWrapper(ContextType* context, v8::Local<v8::Value> value, bool isAttribute)
     84    PassRefPtr<V8EventListener> V8EventListenerList::findOrCreateWrapper(ContextType* context, PassRefPtr<V8ListenerGuard> guard, v8::Local<v8::Value> value, bool isAttribute)
    8585    {
    8686        ASSERT(v8::Context::InContext());
     
    9595            return wrapper;
    9696
    97         PassRefPtr<V8EventListener> wrapperPtr = WrapperType::create(context, object, isAttribute);
     97        PassRefPtr<V8EventListener> wrapperPtr = WrapperType::create(context, guard, object, isAttribute);
    9898        if (wrapperPtr)
    9999            object->SetHiddenValue(wrapperProperty, v8::External::Wrap(wrapperPtr.get()));
  • trunk/WebCore/bindings/v8/V8LazyEventListener.cpp

    r48978 r49050  
    3939
    4040V8LazyEventListener::V8LazyEventListener(Frame* frame, const String& code, const String& functionName, bool isSVGEvent)
    41     : V8AbstractEventListener(frame, true)
     41    : V8AbstractEventListener(frame, 0, true)
    4242    , m_code(code)
    4343    , m_functionName(functionName)
  • trunk/WebCore/bindings/v8/V8Proxy.cpp

    r49047 r49050  
    212212}
    213213
     214V8Proxy::V8Proxy(Frame* frame)
     215    : m_frame(frame),
     216      m_context(SharedPersistent<v8::Context>::create()),
     217      m_listenerGuard(V8ListenerGuard::create()),
     218      m_inlineCode(false),
     219      m_timerCallback(false),
     220      m_recursion(0) { }
     221
    214222V8Proxy::~V8Proxy()
    215223{
     
    562570void V8Proxy::disconnectFrame()
    563571{
     572    disconnectEventListeners();
    564573}
    565574
     
    695704}
    696705
     706void V8Proxy::disconnectEventListeners()
     707{
     708    m_listenerGuard->disconnectListeners();
     709    m_listenerGuard = V8ListenerGuard::create();
     710}
     711
    697712void V8Proxy::clearForClose()
    698713{
     
    707722void V8Proxy::clearForNavigation()
    708723{
     724    disconnectEventListeners();
    709725    if (!context().IsEmpty()) {
    710726        v8::HandleScope handle;
  • trunk/WebCore/bindings/v8/V8Proxy.h

    r48978 r49050  
    3636#include "SecurityOrigin.h" // for WebCore::SecurityOrigin
    3737#include "SharedPersistent.h"
     38#include "V8AbstractEventListener.h"
    3839#include "V8DOMWrapper.h"
    3940#include "V8GCController.h"
     
    5859    class String;
    5960    class V8EventListener;
    60     class V8ObjectEventListener;
    6161
    6262    // FIXME: use standard logging facilities in WebCore.
     
    117117        };
    118118
    119         explicit V8Proxy(Frame* frame)
    120             : m_frame(frame),
    121               m_context(SharedPersistent<v8::Context>::create()),
    122               m_inlineCode(false),
    123               m_timerCallback(false),
    124               m_recursion(0) { }
     119        explicit V8Proxy(Frame*);
    125120
    126121        ~V8Proxy();
     
    303298        }
    304299
     300        PassRefPtr<V8ListenerGuard> listenerGuard()
     301        {
     302            return m_listenerGuard;
     303        }
     304
    305305        bool setContextDebugId(int id);
    306306        static int contextDebugId(v8::Handle<v8::Context>);
     
    348348        void releaseStorageMutex();
    349349
     350        void disconnectEventListeners();
     351
    350352        static bool canAccessPrivate(DOMWindow*);
    351353
     
    382384        RefPtr<SharedPersistent<v8::Context> > m_context;
    383385
     386        RefPtr<V8ListenerGuard> m_listenerGuard;
     387
    384388        // For each possible type of wrapper, we keep a boilerplate object.
    385389        // The boilerplate is used to create additional wrappers of the same
  • trunk/WebCore/bindings/v8/V8WorkerContextEventListener.cpp

    r48978 r49050  
    4141namespace WebCore {
    4242
    43 V8WorkerContextEventListener::V8WorkerContextEventListener(WorkerContextExecutionProxy* proxy, v8::Local<v8::Object> listener, bool isInline)
    44     : V8EventListener(0, listener, isInline)
     43V8WorkerContextEventListener::V8WorkerContextEventListener(WorkerContextExecutionProxy* proxy, PassRefPtr<V8ListenerGuard> guard, v8::Local<v8::Object> listener, bool isInline)
     44    : V8EventListener(0, guard, listener, isInline)
    4545    , m_proxy(proxy)
    4646{
  • trunk/WebCore/bindings/v8/V8WorkerContextEventListener.h

    r48978 r49050  
    4545    class V8WorkerContextEventListener : public V8EventListener {
    4646    public:
    47         static PassRefPtr<V8WorkerContextEventListener> create(WorkerContextExecutionProxy* proxy, v8::Local<v8::Object> listener, bool isInline)
     47        static PassRefPtr<V8WorkerContextEventListener> create(WorkerContextExecutionProxy* proxy, PassRefPtr<V8ListenerGuard> guard, v8::Local<v8::Object> listener, bool isInline)
    4848        {
    49             return adoptRef(new V8WorkerContextEventListener(proxy, listener, isInline));
     49            return adoptRef(new V8WorkerContextEventListener(proxy, guard, listener, isInline));
    5050        }
    51         V8WorkerContextEventListener(WorkerContextExecutionProxy*, v8::Local<v8::Object> listener, bool isInline);
    5251
    5352        virtual void handleEvent(ScriptExecutionContext*, Event*);
    5453        virtual bool reportError(const String& message, const String& url, int lineNumber);
    55         virtual bool disconnected() const { return !m_proxy; }
    5654
    5755        WorkerContextExecutionProxy* proxy() const { return m_proxy; }
    58         void disconnect() { m_proxy = 0; }
    5956
    6057    private:
     58        V8WorkerContextEventListener(WorkerContextExecutionProxy*, PassRefPtr<V8ListenerGuard>, v8::Local<v8::Object> listener, bool isInline);
     59
    6160        virtual v8::Local<v8::Value> callListenerFunction(v8::Handle<v8::Value> jsEvent, Event*);
    6261        v8::Local<v8::Object> getReceiverObject(Event*);
  • trunk/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp

    r48978 r49050  
    7171    : m_workerContext(workerContext)
    7272    , m_recursion(0)
     73    , m_listenerGuard(V8ListenerGuard::create())
    7374{
    7475    initV8IfNeeded();
     
    8283void WorkerContextExecutionProxy::dispose()
    8384{
     85    m_listenerGuard->disconnectListeners();
     86
    8487    // Detach all events from their JS wrappers.
    8588    for (size_t eventIndex = 0; eventIndex < m_events.size(); ++eventIndex) {
     
    397400PassRefPtr<V8EventListener> WorkerContextExecutionProxy::findOrCreateEventListener(v8::Local<v8::Value> object, bool isInline, bool findOnly)
    398401{
    399     return findOnly ? V8EventListenerList::findWrapper(object, isInline) : V8EventListenerList::findOrCreateWrapper<V8WorkerContextEventListener>(this, object, isInline);
     402    return findOnly ? V8EventListenerList::findWrapper(object, isInline) : V8EventListenerList::findOrCreateWrapper<V8WorkerContextEventListener>(this, m_listenerGuard, object, isInline);
    400403}
    401404
  • trunk/WebCore/bindings/v8/WorkerContextExecutionProxy.h

    r48978 r49050  
    111111        v8::Persistent<v8::Context> m_context;
    112112        int m_recursion;
     113        RefPtr<V8ListenerGuard> m_listenerGuard;
    113114
    114115        Vector<Event*> m_events;
  • trunk/WebCore/bindings/v8/custom/V8CustomEventListener.cpp

    r48978 r49050  
    3636namespace WebCore {
    3737
    38 V8EventListener::V8EventListener(Frame* frame, v8::Local<v8::Object> listener, bool isAttribute)
    39     : V8AbstractEventListener(frame, isAttribute)
     38V8EventListener::V8EventListener(Frame* frame, PassRefPtr<V8ListenerGuard> guard, v8::Local<v8::Object> listener, bool isAttribute)
     39    : V8AbstractEventListener(frame, guard, isAttribute)
    4040{
    4141    setListenerObject(listener);
  • trunk/WebCore/bindings/v8/custom/V8CustomEventListener.h

    r48978 r49050  
    4545    class V8EventListener : public V8AbstractEventListener {
    4646    public:
    47         static PassRefPtr<V8EventListener> create(Frame* frame, v8::Local<v8::Object> listener, bool isAttribute)
     47        static PassRefPtr<V8EventListener> create(Frame* frame, PassRefPtr<V8ListenerGuard> guard, v8::Local<v8::Object> listener, bool isAttribute)
    4848        {
    49             return adoptRef(new V8EventListener(frame, listener, isAttribute));
     49            return adoptRef(new V8EventListener(frame, guard, listener, isAttribute));
    5050        }
    5151
    5252    protected:
    53         V8EventListener(Frame*, v8::Local<v8::Object> listener, bool isAttribute);
     53        V8EventListener(Frame*, PassRefPtr<V8ListenerGuard>, v8::Local<v8::Object> listener, bool isAttribute);
    5454
    5555        v8::Local<v8::Function> getListenerFunction();
Note: See TracChangeset for help on using the changeset viewer.