Index: Source/core/dom/EventHandlerRegistry.cpp |
diff --git a/Source/core/dom/EventHandlerRegistry.cpp b/Source/core/dom/EventHandlerRegistry.cpp |
index b72b465ffaadc0a31187c14559227570e38b81e7..fc2e138af1b23b525d30d21d6f46c631affb1835 100644 |
--- a/Source/core/dom/EventHandlerRegistry.cpp |
+++ b/Source/core/dom/EventHandlerRegistry.cpp |
@@ -25,8 +25,15 @@ EventHandlerRegistry::HandlerState::~HandlerState() |
{ |
} |
+EventHandlerRegistry* EventHandlerRegistry::create(Document& document) |
+{ |
+ EventHandlerRegistry* registry = new EventHandlerRegistry(document); |
+ registry->suspendIfNeeded(); |
+ return registry; |
+} |
+ |
EventHandlerRegistry::EventHandlerRegistry(Document& document) |
- : m_document(document) |
+ : ActiveDOMObject(&document) |
{ |
} |
@@ -39,11 +46,16 @@ const char* EventHandlerRegistry::supplementName() |
return "EventHandlerRegistry"; |
} |
+Document* EventHandlerRegistry::document() const |
+{ |
+ return static_cast<Document*>(executionContext()); |
+} |
+ |
EventHandlerRegistry* EventHandlerRegistry::from(Document& document) |
{ |
EventHandlerRegistry* registry = static_cast<EventHandlerRegistry*>(DocumentSupplement::from(document, supplementName())); |
if (!registry) { |
- registry = new EventHandlerRegistry(document); |
+ registry = create(document); |
DocumentSupplement::provideTo(document, supplementName(), adoptPtr(registry)); |
} |
return registry; |
@@ -75,8 +87,12 @@ bool EventHandlerRegistry::updateEventHandlerTargets(ChangeOperation op, EventHa |
EventTargetSet* targets = m_eventHandlers[handlerClass].targets.get(); |
if (op == Add) { |
#if ASSERT_ENABLED |
- if (Node* node = target->toNode()) |
- ASSERT(&node->document() == &m_document); |
+ if (Node* node = target->toNode()) { |
+ // The node should either be in the document, or be the Document node of a child |
+ // of the document. |
+ ASSERT(&node->document() == document() |
+ || (node->isDocumentNode() && toDocument(node)->parentDocument() == document())); |
+ } |
#endif // ASSERT_ENABLED |
if (!targets) { |
@@ -86,6 +102,11 @@ bool EventHandlerRegistry::updateEventHandlerTargets(ChangeOperation op, EventHa |
if (!targets->add(target).isNewEntry) { |
// Just incremented refcount, no real change. |
+#if ASSERT_ENABLED |
+ // If this is a child document node, then the count should never go above 1. |
+ if (Node* node = target->toNode()) |
+ ASSERT(!node->isDocumentNode() || &node->document() == document()); |
+#endif // ASSERT_ENABLED |
return false; |
} |
} else { |
@@ -113,19 +134,27 @@ 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()) { |
+ if (!document()->isActive()) |
return; |
- } |
- bool hadHandlers = hasEventHandlers(handlerClass); |
- updateEventHandlerTargets(op, handlerClass, target); |
- bool hasHandlers = hasEventHandlers(handlerClass); |
+ // Notify our parent registry if we added the first or removed the last handler. |
+ for (Document* document = this->document(); document; document = document->parentDocument()) { |
+ EventHandlerRegistry* registry = EventHandlerRegistry::from(*document); |
+ |
+ bool hadHandlers = registry->hasEventHandlers(handlerClass); |
+ registry->updateEventHandlerTargets(op, handlerClass, target); |
+ bool hasHandlers = registry->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); |
+ if (hadHandlers == hasHandlers) { |
+ break; |
+ } |
+ if (!document->parentDocument()) { |
+ // This is the root registry; notify clients accordingly. |
+ registry->notifyHasHandlersChanged(handlerClass, hasHandlers); |
+ } else { |
+ // Report change to parent with our Document as the target. |
+ target = document; |
abarth-chromium
2014/04/23 17:25:54
I see, I missed this line.
|
+ } |
} |
} |
@@ -185,7 +214,7 @@ void EventHandlerRegistry::didRemoveAllEventHandlers(EventTarget& target) |
void EventHandlerRegistry::notifyHasHandlersChanged(EventHandlerClass handlerClass, bool hasActiveHandlers) |
{ |
- Page* page = m_document.page(); |
+ Page* page = document()->page(); |
ScrollingCoordinator* scrollingCoordinator = page ? page->scrollingCoordinator() : 0; |
switch (handlerClass) { |
@@ -199,4 +228,13 @@ void EventHandlerRegistry::notifyHasHandlersChanged(EventHandlerClass handlerCla |
} |
} |
+void EventHandlerRegistry::stop() |
+{ |
+ Document* parentDocument = document()->parentDocument(); |
+ if (!parentDocument) |
+ return; |
+ EventHandlerRegistry* parentRegistry = EventHandlerRegistry::from(*parentDocument); |
+ parentRegistry->didRemoveAllEventHandlers(*document()); |
+} |
+ |
} // namespace WebCore |