blob: 80d342f0d27a06efeff5573267918e677e8affdb [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef EventHandlerRegistry_h
#define EventHandlerRegistry_h
#include "core/CoreExport.h"
#include "core/frame/FrameHost.h"
#include "wtf/HashCountedSet.h"
namespace blink {
class Document;
class EventListenerOptions;
class EventTarget;
typedef HashCountedSet<UntracedMember<EventTarget>> EventTargetSet;
// Registry for keeping track of event handlers. Note that only handlers on
// documents that can be rendered or can receive input (i.e., are attached to a
// FrameHost) are registered here.
class CORE_EXPORT EventHandlerRegistry final : public GarbageCollectedFinalized<EventHandlerRegistry> {
public:
explicit EventHandlerRegistry(FrameHost&);
virtual ~EventHandlerRegistry();
// Supported event handler classes. Note that each one may correspond to
// multiple event types.
enum EventHandlerClass {
ScrollEvent,
WheelEventBlocking,
WheelEventPassive,
TouchStartOrMoveEventBlocking,
TouchStartOrMoveEventPassive,
TouchEndOrCancelEventBlocking,
TouchEndOrCancelEventPassive,
#if ENABLE(ASSERT)
// Additional event categories for verifying handler tracking logic.
EventsForTesting,
#endif
EventHandlerClassCount, // Must be the last entry.
};
// Returns true if the FrameHost has event handlers of the specified class.
bool hasEventHandlers(EventHandlerClass) const;
// Returns a set of EventTargets which have registered handlers of the given class.
const EventTargetSet* eventHandlerTargets(EventHandlerClass) const;
// Registration and management of event handlers attached to EventTargets.
void didAddEventHandler(EventTarget&, const AtomicString& eventType, const EventListenerOptions&);
void didAddEventHandler(EventTarget&, EventHandlerClass);
void didRemoveEventHandler(EventTarget&, const AtomicString& eventType, const EventListenerOptions&);
void didRemoveEventHandler(EventTarget&, EventHandlerClass);
void didRemoveAllEventHandlers(EventTarget&);
void didMoveIntoFrameHost(EventTarget&);
void didMoveOutOfFrameHost(EventTarget&);
static void didMoveBetweenFrameHosts(EventTarget&, FrameHost* oldFrameHost, FrameHost* newFrameHost);
// Either |documentDetached| or |didMove{Into,OutOf,Between}FrameHosts| must
// be called whenever the FrameHost that is associated with a registered event
// target changes. This ensures the registry does not end up with stale
// references to handlers that are no longer related to it.
void documentDetached(Document&);
DECLARE_TRACE();
void clearWeakMembers(Visitor*);
private:
enum ChangeOperation {
Add, // Add a new event handler.
Remove, // Remove an existing event handler.
RemoveAll // Remove any and all existing event handlers for a given target.
};
// Returns true if |eventType| belongs to a class this registry tracks.
static bool eventTypeToClass(const AtomicString& eventType, const EventListenerOptions&, EventHandlerClass* result);
// Returns true if the operation actually added a new target or completely
// removed an existing one.
bool updateEventHandlerTargets(ChangeOperation, EventHandlerClass, EventTarget*);
// Called on the EventHandlerRegistry of the root Document to notify
// clients when we have added the first handler or removed the last one for
// a given event class. |hasActiveHandlers| can be used to distinguish
// between the two cases.
void notifyHasHandlersChanged(EventHandlerClass, bool hasActiveHandlers);
// Called to notify clients whenever a single event handler target is
// registered or unregistered. If several handlers are registered for the
// same target, only the first registration will trigger this notification.
void notifyDidAddOrRemoveEventHandlerTarget(EventHandlerClass);
// Record a change operation to a given event handler class and notify any
// parent registry and other clients accordingly.
void updateEventHandlerOfType(ChangeOperation, const AtomicString& eventType, const EventListenerOptions&, EventTarget*);
void updateEventHandlerInternal(ChangeOperation, EventHandlerClass, EventTarget*);
void updateAllEventHandlers(ChangeOperation, EventTarget&);
void checkConsistency() const;
Member<FrameHost> m_frameHost;
EventTargetSet m_targets[EventHandlerClassCount];
};
} // namespace blink
#endif // EventHandlerRegistry_h