1 /*
2 * Copyright (C) 2009 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27 #include "CachedPage.h"
28
29 #include "CachedFramePlatformData.h"
30 #include "CString.h"
31 #include "DocumentLoader.h"
32 #include "Frame.h"
33 #include "FrameLoaderClient.h"
34 #include "FrameView.h"
35 #include "Logging.h"
36 #include <wtf/RefCountedLeakCounter.h>
37
38 #if ENABLE(SVG)
39 #include "SVGDocumentExtensions.h"
40 #endif
41
42 namespace WebCore {
43
44 #ifndef NDEBUG
cachedFrameCounter()45 static WTF::RefCountedLeakCounter& cachedFrameCounter()
46 {
47 DEFINE_STATIC_LOCAL(WTF::RefCountedLeakCounter, counter, ("CachedFrame"));
48 return counter;
49 }
50 #endif
51
CachedFrame(Frame * frame)52 CachedFrame::CachedFrame(Frame* frame)
53 : m_document(frame->document())
54 , m_documentLoader(frame->loader()->documentLoader())
55 , m_view(frame->view())
56 , m_mousePressNode(frame->eventHandler()->mousePressNode())
57 , m_url(frame->loader()->url())
58 {
59 #ifndef NDEBUG
60 cachedFrameCounter().increment();
61 #endif
62 ASSERT(m_document);
63 ASSERT(m_documentLoader);
64 ASSERT(m_view);
65
66 // Active DOM objects must be suspended before we cached the frame script data
67 m_document->suspendActiveDOMObjects();
68 m_cachedFrameScriptData.set(new ScriptCachedFrameData(frame));
69
70 m_document->documentWillBecomeInactive();
71 frame->clearTimers();
72 m_document->setInPageCache(true);
73
74 frame->loader()->client()->savePlatformDataToCachedFrame(this);
75
76 for (Frame* child = frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
77 m_childFrames.append(CachedFrame::create(child));
78
79 LOG(PageCache, "Finished creating CachedFrame with url %s and documentloader %p\n", m_url.string().utf8().data(), m_documentLoader.get());
80 }
81
~CachedFrame()82 CachedFrame::~CachedFrame()
83 {
84 #ifndef NDEBUG
85 cachedFrameCounter().decrement();
86 #endif
87
88 clear();
89 }
90
restore()91 void CachedFrame::restore()
92 {
93 ASSERT(m_document->view() == m_view);
94
95 Frame* frame = m_view->frame();
96 m_cachedFrameScriptData->restore(frame);
97
98 #if ENABLE(SVG)
99 if (m_document->svgExtensions())
100 m_document->accessSVGExtensions()->unpauseAnimations();
101 #endif
102
103 frame->animation()->resumeAnimations(m_document.get());
104 frame->eventHandler()->setMousePressNode(mousePressNode());
105 m_document->resumeActiveDOMObjects();
106
107 // It is necessary to update any platform script objects after restoring the
108 // cached page.
109 frame->script()->updatePlatformScriptObjects();
110 }
111
clear()112 void CachedFrame::clear()
113 {
114 if (!m_document)
115 return;
116
117 if (m_cachedFramePlatformData)
118 m_cachedFramePlatformData->clear();
119
120 ASSERT(m_view);
121 ASSERT(m_document->frame() == m_view->frame());
122
123 if (m_document->inPageCache()) {
124 Frame::clearTimers(m_view.get(), m_document.get());
125
126 // FIXME: Why do we need to call removeAllEventListeners here? When the document is in page cache, this method won't work
127 // fully anyway, because the document won't be able to access its DOMWindow object (due to being frameless).
128 m_document->removeAllEventListeners();
129
130 m_document->setInPageCache(false);
131 // FIXME: We don't call willRemove here. Why is that OK?
132 m_document->detach();
133 m_view->clearFrame();
134 }
135
136 ASSERT(!m_document->inPageCache());
137
138 m_document = 0;
139 m_view = 0;
140 m_mousePressNode = 0;
141 m_url = KURL();
142
143 m_cachedFramePlatformData.clear();
144
145 m_cachedFrameScriptData.clear();
146 }
147
setCachedFramePlatformData(CachedFramePlatformData * data)148 void CachedFrame::setCachedFramePlatformData(CachedFramePlatformData* data)
149 {
150 m_cachedFramePlatformData.set(data);
151 }
152
cachedFramePlatformData()153 CachedFramePlatformData* CachedFrame::cachedFramePlatformData()
154 {
155 return m_cachedFramePlatformData.get();
156 }
157
descendantFrameCount() const158 int CachedFrame::descendantFrameCount() const
159 {
160 int count = m_childFrames.size();
161 for (size_t i = 0; i < m_childFrames.size(); ++i)
162 count += m_childFrames[i]->descendantFrameCount();
163
164 return count;
165 }
166
167 } // namespace WebCore
168