diff options
| author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2016-07-26 13:43:04 +0200 |
|---|---|---|
| committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2016-08-10 12:23:11 +0000 |
| commit | 08417fb9a57b2894f619225b13c7c5c2d0ac41ab (patch) | |
| tree | 8424447188dd779228ede4b76dd01c4a1abba8cd | |
| parent | f6e6743a20dd7e53b8f51787f661ae8a319b4b18 (diff) | |
| download | qtwebengine-chromium-08417fb9a57b2894f619225b13c7c5c2d0ac41ab.tar.gz | |
[Backport] Protect the provisional loader from detaching during prepareForCommit
This patch fixes a crash caused by a frame losing both its DocumentLoaders.
When the main document loader is detached, various subresources can hook
into 'abort' and try to stop the provisional load that is about to commit.
This causes both document loaders to be detached, and the frame to be in a
non-detached limbo state.
BUG=394055
Review URL: https://codereview.chromium.org/1714063002
Change-Id: Ia7c4e9ef42ee9675c939a4c5057f0def1e694214
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
| -rw-r--r-- | chromium/third_party/WebKit/Source/core/loader/FrameLoader.cpp | 24 | ||||
| -rw-r--r-- | chromium/third_party/WebKit/Source/core/loader/FrameLoader.h | 1 |
2 files changed, 18 insertions, 7 deletions
diff --git a/chromium/third_party/WebKit/Source/core/loader/FrameLoader.cpp b/chromium/third_party/WebKit/Source/core/loader/FrameLoader.cpp index 060f6e0371e..8e79a0f09ff 100644 --- a/chromium/third_party/WebKit/Source/core/loader/FrameLoader.cpp +++ b/chromium/third_party/WebKit/Source/core/loader/FrameLoader.cpp @@ -166,6 +166,7 @@ FrameLoader::FrameLoader(LocalFrame* frame) , m_didAccessInitialDocumentTimer(this, &FrameLoader::didAccessInitialDocumentTimerFired) , m_forcedSandboxFlags(SandboxNone) , m_dispatchingDidClearWindowObjectInMainWorld(false) + , m_protectProvisionalLoader(false) { } @@ -252,6 +253,9 @@ void FrameLoader::saveScrollState() void FrameLoader::dispatchUnloadEvent() { + // If the frame is unloading, the provisional loader should no longer be + // protected. It will be detached soon. + m_protectProvisionalLoader = false; saveScrollState(); if (m_frame->document() && !SVGImage::isInSVGImage(m_frame->document())) @@ -989,12 +993,15 @@ void FrameLoader::stopAllLoaders() m_frame->document()->setParsingState(Document::FinishedParsing); } m_frame->document()->setReadyState(Document::Complete); - if (m_provisionalDocumentLoader) + // Don't stop loading the provisional loader if it is being protected (i.e. + // it is about to be committed) See prepareForCommit() for more details. + if (m_provisionalDocumentLoader && !m_protectProvisionalLoader) m_provisionalDocumentLoader->stopLoading(); if (m_documentLoader) m_documentLoader->stopLoading(); - detachDocumentLoader(m_provisionalDocumentLoader); + if (!m_protectProvisionalLoader) + detachDocumentLoader(m_provisionalDocumentLoader); detachDocumentLoader(m_policyDocumentLoader); m_checkTimer.stop(); @@ -1052,17 +1059,20 @@ bool FrameLoader::prepareForCommit() // we need to abandon the current load. if (pdl != m_provisionalDocumentLoader) return false; + // detachFromFrame() will abort XHRs that haven't completed, which can + // trigger event listeners for 'abort'. These event listeners might call + // window.stop(), which will in turn detach the provisional document loader. + // At this point, the provisional document loader should not detach, because + // then the FrameLoader would not have any attached DocumentLoaders. if (m_documentLoader) { FrameNavigationDisabler navigationDisabler(*m_frame); + TemporaryChange<bool> inDetachDocumentLoader(m_protectProvisionalLoader, true); detachDocumentLoader(m_documentLoader); } - // detachFromFrame() will abort XHRs that haven't completed, which can - // trigger event listeners for 'abort'. These event listeners might detach - // the frame. - // TODO(dcheng): Investigate if this can be moved above the check that - // m_provisionalDocumentLoader hasn't changed. + // 'abort' listeners can also detach the frame. if (!m_frame->client()) return false; + ASSERT(m_provisionalDocumentLoader == pdl); // No more events will be dispatched so detach the Document. if (m_frame->document()) m_frame->document()->detach(); diff --git a/chromium/third_party/WebKit/Source/core/loader/FrameLoader.h b/chromium/third_party/WebKit/Source/core/loader/FrameLoader.h index 81e75d546b5..d5528b2a658 100644 --- a/chromium/third_party/WebKit/Source/core/loader/FrameLoader.h +++ b/chromium/third_party/WebKit/Source/core/loader/FrameLoader.h @@ -277,6 +277,7 @@ private: SandboxFlags m_forcedSandboxFlags; bool m_dispatchingDidClearWindowObjectInMainWorld; + bool m_protectProvisionalLoader; }; } // namespace blink |
