JavaScriptCore:
[WebKit-https.git] / WebCore / history / CachedPage.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2008 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 "AnimationController.h"
30 #include "CachedPagePlatformData.h"
31 #include "Document.h"
32 #include "DocumentLoader.h"
33 #include "Element.h"
34 #include "EventHandler.h"
35 #include "FocusController.h"
36 #include "Frame.h"
37 #include "FrameLoader.h"
38 #include "FrameView.h"
39 #include "GCController.h"
40 #include "JSLocation.h"
41 #include "Logging.h"
42 #include "Page.h"
43 #include "PausedTimeouts.h"
44 #include "SystemTime.h"
45 #if ENABLE(SVG)
46 #include "SVGDocumentExtensions.h"
47 #endif
48
49 #include "kjs_proxy.h"
50 #include "kjs_window.h"
51 #include <kjs/JSLock.h>
52 #include <kjs/SavedBuiltins.h>
53 #include <kjs/property_map.h>
54
55 using namespace KJS;
56
57 namespace WebCore {
58
59 #ifndef NDEBUG
60 WTFLogChannel LogWebCoreCachedPageLeaks =  { 0x00000000, "", WTFLogChannelOn };
61
62 struct CachedPageCounter { 
63     static int count; 
64     ~CachedPageCounter() 
65     { 
66         if (count)
67             LOG(WebCoreCachedPageLeaks, "LEAK: %d CachedPage\n", count);
68     }
69 };
70 int CachedPageCounter::count = 0;
71 static CachedPageCounter cachedPageCounter;
72 #endif
73
74 PassRefPtr<CachedPage> CachedPage::create(Page* page)
75 {
76     return new CachedPage(page);
77 }
78
79 CachedPage::CachedPage(Page* page)
80     : m_timeStamp(0)
81     , m_document(page->mainFrame()->document())
82     , m_view(page->mainFrame()->view())
83     , m_mousePressNode(page->mainFrame()->eventHandler()->mousePressNode())
84     , m_URL(page->mainFrame()->loader()->url())
85     , m_windowProperties(new SavedProperties)
86     , m_locationProperties(new SavedProperties)
87     , m_windowLocalStorage(new SavedProperties)
88     , m_windowBuiltins(new SavedBuiltins)
89 {
90 #ifndef NDEBUG
91     ++CachedPageCounter::count;
92 #endif
93     
94     m_document->willSaveToCache(); 
95     
96     Frame* mainFrame = page->mainFrame();
97     Window* window = Window::retrieveWindow(mainFrame);
98
99     mainFrame->clearTimers();
100
101     JSLock lock;
102
103     if (window) {
104         window->saveBuiltins(*m_windowBuiltins.get());
105         window->saveProperties(*m_windowProperties.get());
106         window->saveLocalStorage(*m_windowLocalStorage.get());
107         window->location()->saveProperties(*m_locationProperties.get());
108         m_pausedTimeouts.set(window->pauseTimeouts());
109     }
110
111     m_document->setInPageCache(true);
112
113 #if ENABLE(SVG)
114     if (m_document && m_document->svgExtensions())
115         m_document->accessSVGExtensions()->pauseAnimations();
116 #endif
117 }
118
119 CachedPage::~CachedPage()
120 {
121 #ifndef NDEBUG
122     --CachedPageCounter::count;
123 #endif
124
125     clear();
126 }
127
128 void CachedPage::restore(Page* page)
129 {
130     ASSERT(m_document->view() == m_view);
131
132     Frame* mainFrame = page->mainFrame();
133     Window* window = Window::retrieveWindow(mainFrame);
134
135     JSLock lock;
136
137     if (window) {
138         window->restoreBuiltins(*m_windowBuiltins.get());
139         window->restoreProperties(*m_windowProperties.get());
140         window->restoreLocalStorage(*m_windowLocalStorage.get());
141         window->location()->restoreProperties(*m_locationProperties.get());
142         window->resumeTimeouts(m_pausedTimeouts.get());
143     }
144
145 #if ENABLE(SVG)
146     if (m_document && m_document->svgExtensions())
147         m_document->accessSVGExtensions()->unpauseAnimations();
148 #endif
149
150     mainFrame->animationController()->resumeAnimations();
151
152     mainFrame->eventHandler()->setMousePressNode(mousePressNode());
153         
154     // Restore the focus appearance for the focused element.
155     // FIXME: Right now we don't support pages w/ frames in the b/f cache.  This may need to be tweaked when we add support for that.
156     Document* focusedDocument = page->focusController()->focusedOrMainFrame()->document();
157     if (Node* node = focusedDocument->focusedNode()) {
158         if (node->isElementNode())
159             static_cast<Element*>(node)->updateFocusAppearance(true);
160     }
161 }
162
163 void CachedPage::clear()
164 {
165     if (!m_document)
166         return;
167
168     if (m_cachedPagePlatformData)
169         m_cachedPagePlatformData->clear();
170         
171     ASSERT(m_view);
172     ASSERT(m_document->frame() == m_view->frame());
173
174     if (m_document->inPageCache()) {
175         Frame::clearTimers(m_view.get());
176
177         m_document->setInPageCache(false);
178         // FIXME: We don't call willRemove here. Why is that OK?
179         m_document->detach();
180         m_document->removeAllEventListenersFromAllNodes();
181
182         m_view->clearFrame();
183     }
184
185     ASSERT(!m_document->inPageCache());
186
187     m_document = 0;
188     m_view = 0;
189     m_mousePressNode = 0;
190     m_URL = KURL();
191
192     JSLock lock;
193
194     m_windowProperties.clear();
195     m_locationProperties.clear();
196     m_windowBuiltins.clear();
197     m_pausedTimeouts.clear();
198     m_cachedPagePlatformData.clear();
199     m_windowLocalStorage.clear();
200
201     gcController().garbageCollectSoon();
202 }
203
204 void CachedPage::setDocumentLoader(PassRefPtr<DocumentLoader> loader)
205 {
206     m_documentLoader = loader;
207 }
208
209 DocumentLoader* CachedPage::documentLoader()
210 {
211     return m_documentLoader.get();
212 }
213
214 void CachedPage::setTimeStamp(double timeStamp)
215 {
216     m_timeStamp = timeStamp;
217 }
218
219 void CachedPage::setTimeStampToNow()
220 {
221     m_timeStamp = currentTime();
222 }
223
224 double CachedPage::timeStamp() const
225 {
226     return m_timeStamp;
227 }
228
229 void CachedPage::setCachedPagePlatformData(CachedPagePlatformData* data)
230 {
231     m_cachedPagePlatformData.set(data);
232 }
233
234 CachedPagePlatformData* CachedPage::cachedPagePlatformData()
235 {
236     return m_cachedPagePlatformData.get();
237 }
238
239 } // namespace WebCore