Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(980)

Unified Diff: Source/core/frame/LocalDOMWindow.cpp

Issue 1017043002: Remove all event listeners during window's frame destruction step. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Improve LocalDOMWindow::dispose() comment a bit Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/frame/LocalDOMWindow.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/frame/LocalDOMWindow.cpp
diff --git a/Source/core/frame/LocalDOMWindow.cpp b/Source/core/frame/LocalDOMWindow.cpp
index 7aeba5edc9a70729d129ee13b392159ae73d1fce..f66e3e594c9087a5429dda6f4e2b1853b77baf8d 100644
--- a/Source/core/frame/LocalDOMWindow.cpp
+++ b/Source/core/frame/LocalDOMWindow.cpp
@@ -203,14 +203,11 @@ private:
int m_asyncOperationId;
};
-static void disableSuddenTermination()
+static void updateSuddenTerminationStatus(LocalDOMWindow* domWindow, bool addedListener, FrameLoaderClient::SuddenTerminationDisablerType disablerType)
{
- blink::Platform::current()->suddenTerminationChanged(false);
-}
-
-static void enableSuddenTermination()
-{
- blink::Platform::current()->suddenTerminationChanged(true);
+ blink::Platform::current()->suddenTerminationChanged(!addedListener);
+ if (domWindow->frame() && domWindow->frame()->loader().client())
+ domWindow->frame()->loader().client()->suddenTerminationDisablerChanged(addedListener, disablerType);
}
typedef HashCountedSet<LocalDOMWindow*> DOMWindowSet;
@@ -230,13 +227,9 @@ static DOMWindowSet& windowsWithBeforeUnloadEventListeners()
static void addUnloadEventListener(LocalDOMWindow* domWindow)
{
DOMWindowSet& set = windowsWithUnloadEventListeners();
- if (set.isEmpty()) {
- disableSuddenTermination();
- if (domWindow->frame()) {
- domWindow->frame()->loader().client()->suddenTerminationDisablerChanged(
- true, FrameLoaderClient::UnloadHandler);
- }
- }
+ if (set.isEmpty())
+ updateSuddenTerminationStatus(domWindow, true, FrameLoaderClient::UnloadHandler);
+
set.add(domWindow);
}
@@ -247,13 +240,8 @@ static void removeUnloadEventListener(LocalDOMWindow* domWindow)
if (it == set.end())
return;
set.remove(it);
- if (set.isEmpty()) {
- enableSuddenTermination();
- if (domWindow->frame()) {
- domWindow->frame()->loader().client()->suddenTerminationDisablerChanged(
- false, FrameLoaderClient::UnloadHandler);
- }
- }
+ if (set.isEmpty())
+ updateSuddenTerminationStatus(domWindow, false, FrameLoaderClient::UnloadHandler);
}
static void removeAllUnloadEventListeners(LocalDOMWindow* domWindow)
@@ -263,25 +251,16 @@ static void removeAllUnloadEventListeners(LocalDOMWindow* domWindow)
if (it == set.end())
return;
set.removeAll(it);
- if (set.isEmpty()) {
- enableSuddenTermination();
- if (domWindow->frame()) {
- domWindow->frame()->loader().client()->suddenTerminationDisablerChanged(
- false, FrameLoaderClient::UnloadHandler);
- }
- }
+ if (set.isEmpty())
+ updateSuddenTerminationStatus(domWindow, false, FrameLoaderClient::UnloadHandler);
}
static void addBeforeUnloadEventListener(LocalDOMWindow* domWindow)
{
DOMWindowSet& set = windowsWithBeforeUnloadEventListeners();
- if (set.isEmpty()) {
- disableSuddenTermination();
- if (domWindow->frame()) {
- domWindow->frame()->loader().client()->suddenTerminationDisablerChanged(
- true, FrameLoaderClient::BeforeUnloadHandler);
- }
- }
+ if (set.isEmpty())
+ updateSuddenTerminationStatus(domWindow, true, FrameLoaderClient::BeforeUnloadHandler);
+
set.add(domWindow);
}
@@ -292,13 +271,8 @@ static void removeBeforeUnloadEventListener(LocalDOMWindow* domWindow)
if (it == set.end())
return;
set.remove(it);
- if (set.isEmpty()) {
- enableSuddenTermination();
- if (domWindow->frame()) {
- domWindow->frame()->loader().client()->suddenTerminationDisablerChanged(
- false, FrameLoaderClient::BeforeUnloadHandler);
- }
- }
+ if (set.isEmpty())
+ updateSuddenTerminationStatus(domWindow, false, FrameLoaderClient::BeforeUnloadHandler);
}
static void removeAllBeforeUnloadEventListeners(LocalDOMWindow* domWindow)
@@ -308,13 +282,8 @@ static void removeAllBeforeUnloadEventListeners(LocalDOMWindow* domWindow)
if (it == set.end())
return;
set.removeAll(it);
- if (set.isEmpty()) {
- enableSuddenTermination();
- if (domWindow->frame()) {
- domWindow->frame()->loader().client()->suddenTerminationDisablerChanged(
- false, FrameLoaderClient::BeforeUnloadHandler);
- }
- }
+ if (set.isEmpty())
+ updateSuddenTerminationStatus(domWindow, false, FrameLoaderClient::BeforeUnloadHandler);
}
static bool allowsBeforeUnloadListeners(LocalDOMWindow* window)
@@ -379,6 +348,9 @@ LocalDOMWindow::LocalDOMWindow(LocalFrame& frame)
, m_hasBeenReset(false)
#endif
{
+#if ENABLE(OILPAN)
+ ThreadState::current()->registerPreFinalizer(*this);
+#endif
}
void LocalDOMWindow::clearDocument()
@@ -532,24 +504,34 @@ void LocalDOMWindow::statePopped(PassRefPtr<SerializedScriptValue> stateObject)
LocalDOMWindow::~LocalDOMWindow()
{
#if ENABLE(OILPAN)
- // Oilpan: the frame host and document objects are
- // also garbage collected; cannot notify these
- // when removing event listeners.
- removeAllEventListenersInternal(DoNotBroadcastListenerRemoval);
-
// Cleared when detaching document.
ASSERT(!m_eventQueue);
#else
ASSERT(m_hasBeenReset);
- reset();
-
- removeAllEventListenersInternal(DoBroadcastListenerRemoval);
-
ASSERT(m_document->isStopped());
clearDocument();
#endif
}
+void LocalDOMWindow::dispose()
+{
+ // Oilpan: should the LocalDOMWindow be GCed along with its LocalFrame without the
+ // frame having first notified its observers of imminent destruction, the
+ // LocalDOMWindow will not have had an opportunity to remove event listeners.
+ // Do that here by way of a prefinalizing action.
+ //
+ // (Non-Oilpan, LocalDOMWindow::reset() will always be invoked, the last opportunity
+ // being via ~LocalFrame's setDOMWindow() call.)
+ if (!frame())
+ return;
+
+ // (Prefinalizing actions run to completion before the Oilpan GC start to lazily sweep,
+ // so keeping them short is worthwhile. Something that's worth keeping in mind when
+ // working out where to best place some actions that have to be performed very late
+ // on in LocalDOMWindow's lifetime.)
+ removeAllEventListeners();
+}
+
const AtomicString& LocalDOMWindow::interfaceName() const
{
return EventTargetNames::LocalDOMWindow;
@@ -587,6 +569,7 @@ void LocalDOMWindow::frameDestroyed()
willDestroyDocumentInFrame();
resetLocation();
m_properties.clear();
+ removeAllEventListeners();
}
void LocalDOMWindow::willDestroyDocumentInFrame()
@@ -1577,25 +1560,18 @@ bool LocalDOMWindow::dispatchEvent(PassRefPtrWillBeRawPtr<Event> prpEvent, PassR
return fireEventListeners(event.get());
}
-void LocalDOMWindow::removeAllEventListenersInternal(BroadcastListenerRemoval mode)
+void LocalDOMWindow::removeAllEventListeners()
{
EventTarget::removeAllEventListeners();
- if (mode == DoBroadcastListenerRemoval) {
- notifyRemoveAllEventListeners(this);
- if (frame() && frame()->host())
- frame()->host()->eventHandlerRegistry().didRemoveAllEventHandlers(*this);
- }
+ notifyRemoveAllEventListeners(this);
+ if (frame() && frame()->host())
+ frame()->host()->eventHandlerRegistry().didRemoveAllEventHandlers(*this);
removeAllUnloadEventListeners(this);
removeAllBeforeUnloadEventListeners(this);
}
-void LocalDOMWindow::removeAllEventListeners()
-{
- removeAllEventListenersInternal(DoBroadcastListenerRemoval);
-}
-
void LocalDOMWindow::finishedLoading()
{
if (m_shouldPrintWhenFinishedLoading) {
« no previous file with comments | « Source/core/frame/LocalDOMWindow.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698