Index: Source/core/frame/EventHandlerRegistry.cpp |
diff --git a/Source/core/frame/EventHandlerRegistry.cpp b/Source/core/frame/EventHandlerRegistry.cpp |
index 0b57ec1f211f4d17e2b8ae8cc5258600eb7006ec..50da14fc8198f5c58e58b44eaed9d83d4f625028 100644 |
--- a/Source/core/frame/EventHandlerRegistry.cpp |
+++ b/Source/core/frame/EventHandlerRegistry.cpp |
@@ -6,12 +6,39 @@ |
#include "core/frame/EventHandlerRegistry.h" |
#include "core/events/ThreadLocalEventNames.h" |
+#include "core/frame/DOMWindow.h" |
+#include "core/frame/LocalFrame.h" |
#include "core/html/HTMLFrameOwnerElement.h" |
#include "core/page/Page.h" |
#include "core/page/scrolling/ScrollingCoordinator.h" |
namespace WebCore { |
+EventHandlerRegistry::WindowObserver::WindowObserver(EventHandlerRegistry& registry, DOMWindow& window) |
+ : DOMWindowLifecycleObserver(&window) |
+ , m_registry(registry) |
+{ |
+} |
+ |
+EventHandlerRegistry::WindowObserver::~WindowObserver() |
+{ |
+} |
+ |
+void EventHandlerRegistry::WindowObserver::didAddEventListener(DOMWindow* window, const AtomicString& eventType) |
+{ |
+ m_registry.didAddEventHandler(*window, eventType); |
+} |
+ |
+void EventHandlerRegistry::WindowObserver::didRemoveEventListener(DOMWindow* window, const AtomicString& eventType) |
+{ |
+ m_registry.didRemoveEventHandler(*window, eventType); |
+} |
+ |
+void EventHandlerRegistry::WindowObserver::didRemoveAllEventListeners(DOMWindow* window) |
+{ |
+ m_registry.didRemoveAllEventHandlers(*window); |
+} |
+ |
EventHandlerRegistry::EventHandlerRegistry(FrameHost& frameHost) |
: m_frameHost(frameHost) |
{ |
@@ -116,11 +143,19 @@ void EventHandlerRegistry::didRemoveEventHandler(EventTarget& target, EventHandl |
void EventHandlerRegistry::didMoveIntoFrameHost(EventTarget& target) |
{ |
updateAllEventHandlers(Add, target); |
+ if (DOMWindow* window = target.toDOMWindow()) { |
+ ASSERT(!m_windowObservers.contains(window)); |
+ m_windowObservers.set(window, adoptPtr(new WindowObserver(*this, *window))); |
+ } |
} |
void EventHandlerRegistry::didMoveOutOfFrameHost(EventTarget& target) |
{ |
updateAllEventHandlers(RemoveAll, target); |
+ if (DOMWindow* window = target.toDOMWindow()) { |
+ ASSERT(m_windowObservers.contains(window)); |
+ m_windowObservers.remove(window); |
+ } |
} |
void EventHandlerRegistry::didRemoveAllEventHandlers(EventTarget& target) |
@@ -176,18 +211,22 @@ void EventHandlerRegistry::trace(Visitor* visitor) |
void EventHandlerRegistry::clearWeakMembers(Visitor* visitor) |
{ |
- Vector<EventTarget*> deadNodeTargets; |
+ Vector<EventTarget*> deadTargets; |
for (size_t i = 0; i < EventHandlerClassCount; ++i) { |
EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i); |
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)) |
- deadNodeTargets.append(node); |
+ DOMWindow* window = it->key->toDOMWindow(); |
+ if (node && !visitor->isAlive(node)) { |
+ deadTargets.append(node); |
+ } else if (window && !visitor->isAlive(window)) { |
+ deadTargets.append(window); |
+ } |
} |
} |
- for (size_t i = 0; i < deadNodeTargets.size(); ++i) |
- didRemoveAllEventHandlers(*deadNodeTargets[i]); |
+ for (size_t i = 0; i < deadTargets.size(); ++i) |
+ didRemoveAllEventHandlers(*deadTargets[i]); |
} |
void EventHandlerRegistry::documentDetached(Document& document) |
@@ -205,6 +244,11 @@ void EventHandlerRegistry::documentDetached(Document& document) |
break; |
} |
} |
+ } else if (iter->key->toDOMWindow()) { |
+ // DOM windows may outlive their documents, so we should not |
+ // remove their handlers here. |
+ } else { |
+ ASSERT_NOT_REACHED(); |
} |
} |
for (size_t i = 0; i < targetsToRemove.size(); ++i) |
@@ -219,10 +263,14 @@ void EventHandlerRegistry::checkConsistency() const |
EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i); |
const EventTargetSet* targets = &m_targets[handlerClass]; |
for (EventTargetSet::const_iterator iter = targets->begin(); iter != targets->end(); ++iter) { |
+ // See the comment for |documentDetached| if any of these assertions fail. |
if (Node* node = iter->key->toNode()) { |
- // See the comment for |documentDetached| if either of these assertions fails. |
ASSERT(node->document().frameHost()); |
ASSERT(node->document().frameHost() == &m_frameHost); |
+ } else if (DOMWindow* window = iter->key->toDOMWindow()) { |
+ ASSERT(window->frame()); |
+ ASSERT(window->frame()->host()); |
+ ASSERT(window->frame()->host() == &m_frameHost); |
} |
} |
} |