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 "Document.h"
30#include "Element.h"
31#include "FocusController.h"
32#include "Frame.h"
33#include "FrameView.h"
34#include "Node.h"
35#include "Page.h"
36#include "Settings.h"
37#include "VisitedLinkState.h"
38#include <wtf/CurrentTime.h>
39#include <wtf/RefCountedLeakCounter.h>
40#include <wtf/StdLibExtras.h>
41
42using namespace JSC;
43
44namespace WebCore {
45
46DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, cachedPageCounter, ("CachedPage"));
47
48PassRefPtr<CachedPage> CachedPage::create(Page* page)
49{
50    return adoptRef(new CachedPage(page));
51}
52
53CachedPage::CachedPage(Page* page)
54    : m_timeStamp(currentTime())
55    , m_expirationTime(m_timeStamp + page->settings()->backForwardCacheExpirationInterval())
56    , m_cachedMainFrame(CachedFrame::create(page->mainFrame()))
57    , m_needStyleRecalcForVisitedLinks(false)
58    , m_needsFullStyleRecalc(false)
59    , m_needsCaptionPreferencesChanged(false)
60    , m_needsDeviceScaleChanged(false)
61{
62#ifndef NDEBUG
63    cachedPageCounter.increment();
64#endif
65}
66
67CachedPage::~CachedPage()
68{
69#ifndef NDEBUG
70    cachedPageCounter.decrement();
71#endif
72
73    destroy();
74    ASSERT(!m_cachedMainFrame);
75}
76
77void CachedPage::restore(Page* page)
78{
79    ASSERT(m_cachedMainFrame);
80    ASSERT(page && page->mainFrame() && page->mainFrame() == m_cachedMainFrame->view()->frame());
81    ASSERT(!page->subframeCount());
82
83    m_cachedMainFrame->open();
84
85    // Restore the focus appearance for the focused element.
86    // 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.
87    Document* focusedDocument = page->focusController()->focusedOrMainFrame()->document();
88    if (Element* element = focusedDocument->focusedElement())
89        element->updateFocusAppearance(true);
90
91    if (m_needStyleRecalcForVisitedLinks) {
92        for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext())
93            frame->document()->visitedLinkState()->invalidateStyleForAllLinks();
94    }
95
96#if USE(ACCELERATED_COMPOSITING)
97    if (m_needsDeviceScaleChanged) {
98        if (Frame* frame = page->mainFrame())
99            frame->deviceOrPageScaleFactorChanged();
100    }
101#endif
102
103    if (m_needsFullStyleRecalc)
104        page->setNeedsRecalcStyleInAllFrames();
105
106#if ENABLE(VIDEO_TRACK)
107    if (m_needsCaptionPreferencesChanged)
108        page->captionPreferencesChanged();
109#endif
110
111    clear();
112}
113
114void CachedPage::clear()
115{
116    ASSERT(m_cachedMainFrame);
117    m_cachedMainFrame->clear();
118    m_cachedMainFrame = 0;
119    m_needStyleRecalcForVisitedLinks = false;
120    m_needsFullStyleRecalc = false;
121}
122
123void CachedPage::destroy()
124{
125    if (m_cachedMainFrame)
126        m_cachedMainFrame->destroy();
127
128    m_cachedMainFrame = 0;
129}
130
131bool CachedPage::hasExpired() const
132{
133    return currentTime() > m_expirationTime;
134}
135
136} // namespace WebCore
137