| 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) {
|
|
|