| Index: Source/core/page/EventHandlerRegistry.cpp
|
| diff --git a/Source/core/dom/EventHandlerRegistry.cpp b/Source/core/page/EventHandlerRegistry.cpp
|
| similarity index 58%
|
| rename from Source/core/dom/EventHandlerRegistry.cpp
|
| rename to Source/core/page/EventHandlerRegistry.cpp
|
| index 232622c41e71dc96e88a6c8b878222467ad52a7f..8814c4fd18f57e96f4883f891c688957557c3ccb 100644
|
| --- a/Source/core/dom/EventHandlerRegistry.cpp
|
| +++ b/Source/core/page/EventHandlerRegistry.cpp
|
| @@ -3,35 +3,22 @@
|
| // found in the LICENSE file.
|
|
|
| #include "config.h"
|
| -#include "core/dom/EventHandlerRegistry.h"
|
| +#include "core/page/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/html/HTMLFrameOwnerElement.h"
|
| #include "core/page/scrolling/ScrollingCoordinator.h"
|
|
|
| namespace WebCore {
|
|
|
| -EventHandlerRegistry::HandlerState::HandlerState()
|
| -{
|
| -}
|
| -
|
| -EventHandlerRegistry::HandlerState::~HandlerState()
|
| -{
|
| -}
|
| -
|
| -EventHandlerRegistry::EventHandlerRegistry(Document& document)
|
| - : m_document(document)
|
| +EventHandlerRegistry::EventHandlerRegistry(Page& page)
|
| + : m_page(page)
|
| {
|
| }
|
|
|
| EventHandlerRegistry::~EventHandlerRegistry()
|
| {
|
| + checkConsistency();
|
| }
|
|
|
| const char* EventHandlerRegistry::supplementName()
|
| @@ -39,12 +26,12 @@ const char* EventHandlerRegistry::supplementName()
|
| return "EventHandlerRegistry";
|
| }
|
|
|
| -EventHandlerRegistry* EventHandlerRegistry::from(Document& document)
|
| +EventHandlerRegistry* EventHandlerRegistry::from(Page& page)
|
| {
|
| - EventHandlerRegistry* registry = static_cast<EventHandlerRegistry*>(DocumentSupplement::from(document, supplementName()));
|
| + EventHandlerRegistry* registry = static_cast<EventHandlerRegistry*>(WillBeHeapSupplement<Page>::from(page, supplementName()));
|
| if (!registry) {
|
| - registry = new EventHandlerRegistry(document);
|
| - DocumentSupplement::provideTo(document, supplementName(), adoptPtrWillBeNoop(registry));
|
| + registry = new EventHandlerRegistry(page);
|
| + Supplement<Page>::provideTo(page, supplementName(), adoptPtrWillBeNoop(registry));
|
| }
|
| return registry;
|
| }
|
| @@ -53,6 +40,10 @@ bool EventHandlerRegistry::eventTypeToClass(const AtomicString& eventType, Event
|
| {
|
| if (eventType == EventTypeNames::scroll) {
|
| *result = ScrollEvent;
|
| +#if ASSERT_ENABLED
|
| + } else if (eventType == EventTypeNames::load || eventType == EventTypeNames::mousemove || eventType == EventTypeNames::touchstart) {
|
| + *result = EventsForTesting;
|
| +#endif
|
| } else {
|
| return false;
|
| }
|
| @@ -61,40 +52,26 @@ bool EventHandlerRegistry::eventTypeToClass(const AtomicString& eventType, Event
|
|
|
| const EventTargetSet* EventHandlerRegistry::eventHandlerTargets(EventHandlerClass handlerClass) const
|
| {
|
| - return m_eventHandlers[handlerClass].targets.get();
|
| + checkConsistency();
|
| + return &m_targets[handlerClass];
|
| }
|
|
|
| bool EventHandlerRegistry::hasEventHandlers(EventHandlerClass handlerClass) const
|
| {
|
| - EventTargetSet* targets = m_eventHandlers[handlerClass].targets.get();
|
| - return targets && targets->size();
|
| + return m_targets[handlerClass].size();
|
| }
|
|
|
| bool EventHandlerRegistry::updateEventHandlerTargets(ChangeOperation op, EventHandlerClass handlerClass, EventTarget* target)
|
| {
|
| - EventTargetSet* targets = m_eventHandlers[handlerClass].targets.get();
|
| + EventTargetSet* targets = &m_targets[handlerClass];
|
| if (op == Add) {
|
| -#if ASSERT_ENABLED
|
| - if (Node* node = target->toNode())
|
| - ASSERT(&node->document() == &m_document);
|
| -#endif // ASSERT_ENABLED
|
| -
|
| - 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))
|
| @@ -112,21 +89,14 @@ bool EventHandlerRegistry::updateEventHandlerTargets(ChangeOperation op, EventHa
|
|
|
| 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.
|
| + if (hadHandlers != hasHandlers) {
|
| notifyHasHandlersChanged(handlerClass, hasHandlers);
|
| }
|
| + checkConsistency();
|
| }
|
|
|
| void EventHandlerRegistry::updateEventHandlerOfType(ChangeOperation op, const AtomicString& eventType, EventTarget* target)
|
| @@ -157,42 +127,56 @@ void EventHandlerRegistry::didRemoveEventHandler(EventTarget& target, EventHandl
|
| updateEventHandlerInternal(Remove, handlerClass, &target);
|
| }
|
|
|
| -void EventHandlerRegistry::didMoveFromOtherDocument(EventTarget& target, Document& oldDocument)
|
| +void EventHandlerRegistry::didMoveIntoPage(EventTarget& target)
|
| {
|
| - 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);
|
| - }
|
| - }
|
| + updateAllEventHandlers(Add, target);
|
| +}
|
| +
|
| +void EventHandlerRegistry::didMoveOutOfPage(EventTarget& target)
|
| +{
|
| + updateAllEventHandlers(RemoveAll, 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::updateAllEventHandlers(ChangeOperation op, EventTarget& target)
|
| +{
|
| + if (!target.hasEventListeners())
|
| + return;
|
| +
|
| + Vector<AtomicString> eventTypes = target.eventTypes();
|
| + for (size_t i = 0; i < eventTypes.size(); ++i) {
|
| + EventHandlerClass handlerClass;
|
| + if (!eventTypeToClass(eventTypes[i], &handlerClass))
|
| + continue;
|
| + if (op == RemoveAll) {
|
| + updateEventHandlerInternal(op, handlerClass, &target);
|
| + continue;
|
| + }
|
| + for (unsigned count = target.getEventListeners(eventTypes[i]).size(); count > 0; --count)
|
| + updateEventHandlerInternal(op, handlerClass, &target);
|
| + }
|
| +}
|
| +
|
| void EventHandlerRegistry::notifyHasHandlersChanged(EventHandlerClass handlerClass, bool hasActiveHandlers)
|
| {
|
| - Page* page = m_document.page();
|
| - ScrollingCoordinator* scrollingCoordinator = page ? page->scrollingCoordinator() : 0;
|
| + ScrollingCoordinator* scrollingCoordinator = m_page.scrollingCoordinator();
|
|
|
| switch (handlerClass) {
|
| case ScrollEvent:
|
| if (scrollingCoordinator)
|
| scrollingCoordinator->updateHaveScrollEventHandlers();
|
| break;
|
| +#if ASSERT_ENABLED
|
| + case EventsForTesting:
|
| + break;
|
| +#endif
|
| default:
|
| ASSERT_NOT_REACHED();
|
| break;
|
| @@ -206,17 +190,10 @@ void EventHandlerRegistry::trace(Visitor* visitor)
|
|
|
| void EventHandlerRegistry::clearWeakMembers(Visitor* visitor)
|
| {
|
| - // FIXME: Oilpan: This is pretty funky. The current code disables all modifications of the
|
| - // EventHandlerRegistry when the document becomes inactive. To keep that behavior we only
|
| - // perform weak processing of the registry when the document is active.
|
| - if (!m_document.isActive())
|
| - return;
|
| Vector<EventTarget*> deadNodeTargets;
|
| for (size_t i = 0; i < EventHandlerClassCount; ++i) {
|
| EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i);
|
| - const EventTargetSet* targets = eventHandlerTargets(handlerClass);
|
| - if (!targets)
|
| - continue;
|
| + const EventTargetSet* targets = &m_targets[handlerClass];
|
| for (EventTargetSet::const_iterator it = targets->begin(); it != targets->end(); ++it) {
|
| Node* node = it->key->toNode();
|
| if (node && !visitor->isAlive(node))
|
| @@ -227,4 +204,43 @@ void EventHandlerRegistry::clearWeakMembers(Visitor* visitor)
|
| didRemoveAllEventHandlers(*deadNodeTargets[i]);
|
| }
|
|
|
| +void EventHandlerRegistry::documentDetached(Document& document)
|
| +{
|
| + // Remove all event targets under the detached document.
|
| + for (size_t handlerClassIndex = 0; handlerClassIndex < EventHandlerClassCount; ++handlerClassIndex) {
|
| + EventHandlerClass handlerClass = static_cast<EventHandlerClass>(handlerClassIndex);
|
| + Vector<EventTarget*> targetsToRemove;
|
| + const EventTargetSet* targets = &m_targets[handlerClass];
|
| + for (EventTargetSet::const_iterator iter = targets->begin(); iter != targets->end(); ++iter) {
|
| + if (Node* node = iter->key->toNode()) {
|
| + for (Document* doc = &node->document(); doc; doc = doc->ownerElement() ? &doc->ownerElement()->document() : 0) {
|
| + if (doc == &document) {
|
| + targetsToRemove.append(iter->key);
|
| + break;
|
| + }
|
| + }
|
| + }
|
| + }
|
| + for (size_t i = 0; i < targetsToRemove.size(); ++i)
|
| + updateEventHandlerInternal(RemoveAll, handlerClass, targetsToRemove[i]);
|
| + }
|
| +}
|
| +
|
| +void EventHandlerRegistry::checkConsistency() const
|
| +{
|
| +#if ASSERT_ENABLED
|
| + for (size_t i = 0; i < EventHandlerClassCount; ++i) {
|
| + EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i);
|
| + const EventTargetSet* targets = &m_targets[handlerClass];
|
| + for (EventTargetSet::const_iterator iter = targets->begin(); iter != targets->end(); ++iter) {
|
| + if (Node* node = iter->key->toNode()) {
|
| + // See the comment for |documentDetached| if either of these assertions fails.
|
| + ASSERT(node->document().page());
|
| + ASSERT(node->document().page() == &m_page);
|
| + }
|
| + }
|
| + }
|
| +#endif // ASSERT_ENABLED
|
| +}
|
| +
|
| } // namespace WebCore
|
|
|