diff options
author | Steve Block <steveblock@google.com> | 2009-10-08 17:19:54 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2009-10-20 00:41:58 +0100 |
commit | 231d4e3152a9c27a73b6ac7badbe6be673aa3ddf (patch) | |
tree | a6c7e2d6cd7bfa7011cc39abbb436142d7a4a7c8 /WebCore/history/CachedFrame.cpp | |
parent | e196732677050bd463301566a68a643b6d14b907 (diff) | |
download | external_webkit-231d4e3152a9c27a73b6ac7badbe6be673aa3ddf.zip external_webkit-231d4e3152a9c27a73b6ac7badbe6be673aa3ddf.tar.gz external_webkit-231d4e3152a9c27a73b6ac7badbe6be673aa3ddf.tar.bz2 |
Merge webkit.org at R49305 : Automatic merge by git.
Change-Id: I8968561bc1bfd72b8923b7118d3728579c6dbcc7
Diffstat (limited to 'WebCore/history/CachedFrame.cpp')
-rw-r--r-- | WebCore/history/CachedFrame.cpp | 153 |
1 files changed, 109 insertions, 44 deletions
diff --git a/WebCore/history/CachedFrame.cpp b/WebCore/history/CachedFrame.cpp index 5f4e746..16c7087 100644 --- a/WebCore/history/CachedFrame.cpp +++ b/WebCore/history/CachedFrame.cpp @@ -29,10 +29,13 @@ #include "CachedFramePlatformData.h" #include "CString.h" #include "DocumentLoader.h" +#include "ExceptionCode.h" +#include "EventNames.h" #include "Frame.h" #include "FrameLoaderClient.h" #include "FrameView.h" #include "Logging.h" +#include "PageTransitionEvent.h" #include <wtf/RefCountedLeakCounter.h> #if ENABLE(SVG) @@ -49,12 +52,58 @@ static WTF::RefCountedLeakCounter& cachedFrameCounter() } #endif -CachedFrame::CachedFrame(Frame* frame) +CachedFrameBase::CachedFrameBase(Frame* frame) : m_document(frame->document()) , m_documentLoader(frame->loader()->documentLoader()) , m_view(frame->view()) , m_mousePressNode(frame->eventHandler()->mousePressNode()) , m_url(frame->loader()->url()) + , m_isMainFrame(!frame->tree()->parent()) +{ +} + +CachedFrameBase::~CachedFrameBase() +{ +#ifndef NDEBUG + cachedFrameCounter().decrement(); +#endif + // CachedFrames should always have had destroy() called by their parent CachedPage + ASSERT(!m_document); +} + +void CachedFrameBase::restore() +{ + ASSERT(m_document->view() == m_view); + + Frame* frame = m_view->frame(); + m_cachedFrameScriptData->restore(frame); + +#if ENABLE(SVG) + if (m_document->svgExtensions()) + m_document->accessSVGExtensions()->unpauseAnimations(); +#endif + + frame->animation()->resumeAnimations(m_document.get()); + frame->eventHandler()->setMousePressNode(m_mousePressNode.get()); + m_document->resumeActiveDOMObjects(); + + // It is necessary to update any platform script objects after restoring the + // cached page. + frame->script()->updatePlatformScriptObjects(); + + // Reconstruct the FrameTree + for (unsigned i = 0; i < m_childFrames.size(); ++i) + frame->tree()->appendChild(m_childFrames[i]->view()->frame()); + + // Open the child CachedFrames in their respective FrameLoaders. + for (unsigned i = 0; i < m_childFrames.size(); ++i) + m_childFrames[i]->open(); + + m_document->dispatchWindowEvent(PageTransitionEvent::create(EventNames().pageshowEvent, true), m_document); +} + +CachedFrame::CachedFrame(Frame* frame) + : CachedFrameBase(frame) { #ifndef NDEBUG cachedFrameCounter().increment(); @@ -67,46 +116,38 @@ CachedFrame::CachedFrame(Frame* frame) m_document->suspendActiveDOMObjects(); m_cachedFrameScriptData.set(new ScriptCachedFrameData(frame)); + // Custom scrollbar renderers will get reattached when the document comes out of the page cache + m_view->detachCustomScrollbars(); + m_document->documentWillBecomeInactive(); frame->clearTimers(); m_document->setInPageCache(true); frame->loader()->client()->savePlatformDataToCachedFrame(this); + // Create the CachedFrames for all Frames in the FrameTree. for (Frame* child = frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) m_childFrames.append(CachedFrame::create(child)); - LOG(PageCache, "Finished creating CachedFrame with url %s and documentloader %p\n", m_url.string().utf8().data(), m_documentLoader.get()); -} + // Deconstruct the FrameTree, to restore it later. + // We do this for two reasons: + // 1 - We reuse the main frame, so when it navigates to a new page load it needs to start with a blank FrameTree. + // 2 - It's much easier to destroy a CachedFrame while it resides in the PageCache if it is disconnected from its parent. + for (unsigned i = 0; i < m_childFrames.size(); ++i) + frame->tree()->removeChild(m_childFrames[i]->view()->frame()); -CachedFrame::~CachedFrame() -{ #ifndef NDEBUG - cachedFrameCounter().decrement(); + if (m_isMainFrame) + LOG(PageCache, "Finished creating CachedFrame for main frame url '%s' and DocumentLoader %p\n", m_url.string().utf8().data(), m_documentLoader.get()); + else + LOG(PageCache, "Finished creating CachedFrame for child frame with url '%s' and DocumentLoader %p\n", m_url.string().utf8().data(), m_documentLoader.get()); #endif - - clear(); } -void CachedFrame::restore() +void CachedFrame::open() { - ASSERT(m_document->view() == m_view); - - Frame* frame = m_view->frame(); - m_cachedFrameScriptData->restore(frame); - -#if ENABLE(SVG) - if (m_document->svgExtensions()) - m_document->accessSVGExtensions()->unpauseAnimations(); -#endif - - frame->animation()->resumeAnimations(m_document.get()); - frame->eventHandler()->setMousePressNode(mousePressNode()); - m_document->resumeActiveDOMObjects(); - - // It is necessary to update any platform script objects after restoring the - // cached page. - frame->script()->updatePlatformScriptObjects(); + ASSERT(m_view); + m_view->frame()->loader()->open(*this); } void CachedFrame::clear() @@ -114,26 +155,16 @@ void CachedFrame::clear() if (!m_document) return; - if (m_cachedFramePlatformData) - m_cachedFramePlatformData->clear(); - + // clear() should only be called for Frames representing documents that are no longer in the page cache. + // This means the CachedFrame has been: + // 1 - Successfully restore()'d by going back/forward. + // 2 - destroy()'ed because the PageCache is pruning or the WebView was closed. + ASSERT(!m_document->inPageCache()); ASSERT(m_view); ASSERT(m_document->frame() == m_view->frame()); - if (m_document->inPageCache()) { - Frame::clearTimers(m_view.get(), m_document.get()); - - // FIXME: Why do we need to call removeAllEventListeners here? When the document is in page cache, this method won't work - // fully anyway, because the document won't be able to access its DOMWindow object (due to being frameless). - m_document->removeAllEventListeners(); - - m_document->setInPageCache(false); - // FIXME: We don't call willRemove here. Why is that OK? - m_document->detach(); - m_view->clearFrame(); - } - - ASSERT(!m_document->inPageCache()); + for (int i = m_childFrames.size() - 1; i >= 0; --i) + m_childFrames[i]->clear(); m_document = 0; m_view = 0; @@ -141,10 +172,44 @@ void CachedFrame::clear() m_url = KURL(); m_cachedFramePlatformData.clear(); - m_cachedFrameScriptData.clear(); } +void CachedFrame::destroy() +{ + if (!m_document) + return; + + // Only CachedFrames that are still in the PageCache should be destroyed in this manner + ASSERT(m_document->inPageCache()); + ASSERT(m_view); + ASSERT(m_document->frame() == m_view->frame()); + + if (!m_isMainFrame) { + m_view->frame()->detachFromPage(); + m_view->frame()->loader()->detachViewsAndDocumentLoader(); + } + + for (int i = m_childFrames.size() - 1; i >= 0; --i) + m_childFrames[i]->destroy(); + + if (m_cachedFramePlatformData) + m_cachedFramePlatformData->clear(); + + Frame::clearTimers(m_view.get(), m_document.get()); + + // FIXME: Why do we need to call removeAllEventListeners here? When the document is in page cache, this method won't work + // fully anyway, because the document won't be able to access its DOMWindow object (due to being frameless). + m_document->removeAllEventListeners(); + + m_document->setInPageCache(false); + // FIXME: We don't call willRemove here. Why is that OK? + m_document->detach(); + m_view->clearFrame(); + + clear(); +} + void CachedFrame::setCachedFramePlatformData(CachedFramePlatformData* data) { m_cachedFramePlatformData.set(data); |