Chromium Code Reviews| Index: Source/core/dom/EventHandlerRegistry.cpp |
| diff --git a/Source/core/dom/EventHandlerRegistry.cpp b/Source/core/dom/EventHandlerRegistry.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..47b83aa7e887477e0f3a4655e9aee35e3f1a4564 |
| --- /dev/null |
| +++ b/Source/core/dom/EventHandlerRegistry.cpp |
| @@ -0,0 +1,202 @@ |
| +// 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. |
| + |
| +#include "config.h" |
| +#include "core/dom/EventHandlerRegistry.h" |
| + |
| +#include "core/dom/Document.h" |
| +#include "core/events/ThreadLocalEventNames.h" |
| +#include "core/events/WheelEvent.h" |
| +#include "core/frame/FrameHost.h" |
| +#include "core/frame/LocalFrame.h" |
| +#include "core/page/Chrome.h" |
| +#include "core/page/ChromeClient.h" |
| +#include "core/page/Page.h" |
| +#include "core/page/scrolling/ScrollingCoordinator.h" |
| + |
| +namespace WebCore { |
| + |
| +EventHandlerRegistry::HandlerState::HandlerState() |
| +{ |
| +} |
| + |
| +EventHandlerRegistry::HandlerState::~HandlerState() |
| +{ |
| +} |
| + |
| +EventHandlerRegistry::EventHandlerRegistry(Document& document) |
| + : m_document(document) |
| +{ |
| +} |
| + |
| +EventHandlerRegistry::~EventHandlerRegistry() |
| +{ |
| +} |
| + |
| +const char* EventHandlerRegistry::supplementName() |
| +{ |
| + return "EventHandlerRegistry"; |
| +} |
| + |
| +EventHandlerRegistry* EventHandlerRegistry::from(Document& document) |
| +{ |
| + EventHandlerRegistry* registry = static_cast<EventHandlerRegistry*>(DocumentSupplement::from(document, supplementName())); |
| + if (!registry) { |
| + registry = new EventHandlerRegistry(document); |
| + DocumentSupplement::provideTo(document, supplementName(), adoptPtr(registry)); |
| + } |
| + return registry; |
| +} |
| + |
| +bool EventHandlerRegistry::eventTypeToClass(const AtomicString& eventType, EventHandlerClass* result) |
| +{ |
| + if (eventType == EventTypeNames::scroll) { |
| + *result = ScrollEvent; |
| + } else { |
| + return false; |
| + } |
| + return true; |
| +} |
|
abarth-chromium
2014/04/17 18:05:12
I presume you've written this function this way be
Sami
2014/04/17 18:40:53
That's right. It looks a little awkward now but up
|
| + |
| +const EventTargetSet* EventHandlerRegistry::eventHandlerTargets(EventHandlerClass handlerClass) const |
| +{ |
| + return m_eventHandlers[handlerClass].targets.get(); |
| +} |
| + |
| +bool EventHandlerRegistry::hasEventHandlers(EventHandlerClass handlerClass) const |
| +{ |
| + EventTargetSet* targets = m_eventHandlers[handlerClass].targets.get(); |
| + return targets && targets->size(); |
| +} |
| + |
| +bool EventHandlerRegistry::updateEventHandlerTargets(ChangeOperation op, EventHandlerClass handlerClass, EventTarget* target) |
| +{ |
| + EventTargetSet* targets = m_eventHandlers[handlerClass].targets.get(); |
| + if (op == Add) { |
| +#ifndef NDEBUG |
|
abarth-chromium
2014/04/17 18:05:12
#if ASSERT_ENABLED
Sami
2014/04/17 18:40:53
Done.
|
| + if (Node* node = target->toNode()) |
| + ASSERT(&node->document() == &m_document); |
| +#endif // NDEBUG |
| + |
| + if (!targets) { |
| + m_eventHandlers[handlerClass].targets = adoptPtr(new EventTargetSet); |
| + targets = m_eventHandlers[handlerClass].targets.get(); |
| + } |
| + |
| + if (!targets->add(target).isNewEntry) { |
| + // Just incremented refcount, no real change. |
| + return false; |
| + } |
| + } else { |
| + // Note that we can't assert that |target| is in this document because |
| + // it might be in the process of moving out of it. |
| + ASSERT(op == Remove || op == RemoveAll); |
| + ASSERT(op == RemoveAll || targets->contains(target)); |
| + if (!targets) |
| + return false; |
| + |
| + if (op == RemoveAll) { |
| + if (!targets->contains(target)) |
| + return false; |
| + targets->removeAll(target); |
| + } else { |
| + if (!targets->remove(target)) { |
| + // Just decremented refcount, no real update. |
| + return false; |
| + } |
| + } |
| + } |
| + return true; |
| +} |
| + |
| +void EventHandlerRegistry::updateEventHandlerInternal(ChangeOperation op, EventHandlerClass handlerClass, EventTarget* target) |
| +{ |
| + // After the document has stopped, all updates become no-ops. |
| + if (!m_document.isActive()) { |
| + return; |
| + } |
| + |
| + bool hadHandlers = hasEventHandlers(handlerClass); |
| + updateEventHandlerTargets(op, handlerClass, target); |
| + bool hasHandlers = hasEventHandlers(handlerClass); |
| + |
| + // Notify the parent document's registry if we added the first or removed |
| + // the last handler. |
| + if (hadHandlers != hasHandlers && !m_document.parentDocument()) { |
| + // This is the root registry; notify clients accordingly. |
| + notifyHasHandlersChanged(handlerClass, hasHandlers); |
| + } |
| +} |
| + |
| +void EventHandlerRegistry::updateEventHandlerOfType(ChangeOperation op, const AtomicString& eventType, EventTarget* target) |
| +{ |
| + EventHandlerClass handlerClass; |
| + if (!eventTypeToClass(eventType, &handlerClass)) |
| + return; |
| + updateEventHandlerInternal(op, handlerClass, target); |
| +} |
| + |
| +void EventHandlerRegistry::didAddEventHandler(EventTarget& target, const AtomicString& eventType) |
| +{ |
| + updateEventHandlerOfType(Add, eventType, &target); |
| +} |
| + |
| +void EventHandlerRegistry::didRemoveEventHandler(EventTarget& target, const AtomicString& eventType) |
| +{ |
| + updateEventHandlerOfType(Remove, eventType, &target); |
| +} |
| + |
| +void EventHandlerRegistry::didAddEventHandler(EventTarget& target, EventHandlerClass handlerClass) |
| +{ |
| + updateEventHandlerInternal(Add, handlerClass, &target); |
| +} |
| + |
| +void EventHandlerRegistry::didRemoveEventHandler(EventTarget& target, EventHandlerClass handlerClass) |
| +{ |
| + updateEventHandlerInternal(Remove, handlerClass, &target); |
| +} |
| + |
| +void EventHandlerRegistry::didMoveFromOtherDocument(EventTarget& target, Document& oldDocument) |
| +{ |
| + EventHandlerRegistry* oldRegistry = EventHandlerRegistry::from(oldDocument); |
| + for (size_t i = 0; i < EventHandlerClassCount; ++i) { |
| + EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i); |
| + const EventTargetSet* targets = oldRegistry->eventHandlerTargets(handlerClass); |
| + if (!targets) |
| + continue; |
| + for (unsigned count = targets->count(&target); count > 0; --count) { |
| + oldRegistry->updateEventHandlerInternal(Remove, handlerClass, &target); |
| + updateEventHandlerInternal(Add, handlerClass, &target); |
| + } |
| + } |
| +} |
| + |
| +void EventHandlerRegistry::didRemoveAllEventHandlers(EventTarget& target) |
| +{ |
| + for (size_t i = 0; i < EventHandlerClassCount; ++i) { |
| + EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i); |
| + const EventTargetSet* targets = eventHandlerTargets(handlerClass); |
| + if (!targets) |
| + continue; |
| + updateEventHandlerInternal(RemoveAll, handlerClass, &target); |
| + } |
| +} |
| + |
| +void EventHandlerRegistry::notifyHasHandlersChanged(EventHandlerClass handlerClass, bool hasActiveHandlers) |
| +{ |
| + Page* page = m_document.page(); |
| + ScrollingCoordinator* scrollingCoordinator = page ? page->scrollingCoordinator() : 0; |
| + |
| + switch (handlerClass) { |
| + case ScrollEvent: |
| + if (scrollingCoordinator) |
| + scrollingCoordinator->updateHaveScrollEventHandlers(); |
| + break; |
| + default: |
| + ASSERT_NOT_REACHED(); |
| + break; |
| + } |
| +} |
| + |
| +} // namespace WebCore |