diff options
author | Upstream <upstream-import@none> | 1970-01-12 13:46:40 +0000 |
---|---|---|
committer | Upstream <upstream-import@none> | 1970-01-12 13:46:40 +0000 |
commit | d8543bb6618c17b12da906afa77d216f58cf4058 (patch) | |
tree | c58dc05ed86825bd0ef8d305d58c8205106b540f /WebCore/history | |
download | external_webkit-d8543bb6618c17b12da906afa77d216f58cf4058.zip external_webkit-d8543bb6618c17b12da906afa77d216f58cf4058.tar.gz external_webkit-d8543bb6618c17b12da906afa77d216f58cf4058.tar.bz2 |
external/webkit r30707
Diffstat (limited to 'WebCore/history')
-rw-r--r-- | WebCore/history/BackForwardList.cpp | 267 | ||||
-rw-r--r-- | WebCore/history/BackForwardList.h | 90 | ||||
-rw-r--r-- | WebCore/history/CachedPage.cpp | 240 | ||||
-rw-r--r-- | WebCore/history/CachedPage.h | 88 | ||||
-rw-r--r-- | WebCore/history/CachedPagePlatformData.h | 45 | ||||
-rw-r--r-- | WebCore/history/HistoryItem.cpp | 437 | ||||
-rw-r--r-- | WebCore/history/HistoryItem.h | 195 | ||||
-rw-r--r-- | WebCore/history/PageCache.cpp | 183 | ||||
-rw-r--r-- | WebCore/history/PageCache.h | 83 | ||||
-rw-r--r-- | WebCore/history/mac/HistoryItemMac.mm | 65 |
10 files changed, 1693 insertions, 0 deletions
diff --git a/WebCore/history/BackForwardList.cpp b/WebCore/history/BackForwardList.cpp new file mode 100644 index 0000000..f912239 --- /dev/null +++ b/WebCore/history/BackForwardList.cpp @@ -0,0 +1,267 @@ +/* + * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "BackForwardList.h" + +#include "HistoryItem.h" +#include "Logging.h" +#include "PageCache.h" + +using namespace std; + +namespace WebCore { + +static const unsigned DefaultCapacity = 100; +static const unsigned NoCurrentItemIndex = UINT_MAX; + +BackForwardList::BackForwardList(Page* page) + : m_page(page) + , m_current(NoCurrentItemIndex) + , m_capacity(DefaultCapacity) + , m_closed(true) + , m_enabled(true) +{ +} + +BackForwardList::~BackForwardList() +{ + ASSERT(m_closed); +} + +void BackForwardList::addItem(PassRefPtr<HistoryItem> prpItem) +{ + ASSERT(prpItem); + if (m_capacity == 0 || !m_enabled) + return; + + // Toss anything in the forward list + if (m_current != NoCurrentItemIndex) { + unsigned targetSize = m_current + 1; + while (m_entries.size() > targetSize) { + RefPtr<HistoryItem> item = m_entries.last(); + m_entries.removeLast(); + m_entryHash.remove(item); + pageCache()->remove(item.get()); + } + } + + // Toss the first item if the list is getting too big, as long as we're not using it + // (or even if we are, if we only want 1 entry). + if (m_entries.size() == m_capacity && (m_current != 0 || m_capacity == 1)) { + RefPtr<HistoryItem> item = m_entries[0]; + m_entries.remove(0); + m_entryHash.remove(item); + pageCache()->remove(item.get()); + m_current--; + } + + m_entries.append(prpItem); + m_entryHash.add(m_entries.last()); + m_current++; +} + +void BackForwardList::goBack() +{ + ASSERT(m_current > 0); + if (m_current > 0) + m_current--; +} + +void BackForwardList::goForward() +{ + ASSERT(m_current < m_entries.size() - 1); + if (m_current < m_entries.size() - 1) + m_current++; +} + +void BackForwardList::goToItem(HistoryItem* item) +{ + if (!m_entries.size() || !item) + return; + + unsigned int index = 0; + for (; index < m_entries.size(); ++index) + if (m_entries[index] == item) + break; + if (index < m_entries.size()) + m_current = index; +} + +HistoryItem* BackForwardList::backItem() +{ + if (m_current && m_current != NoCurrentItemIndex) + return m_entries[m_current - 1].get(); + return 0; +} + +HistoryItem* BackForwardList::currentItem() +{ + if (m_current != NoCurrentItemIndex) + return m_entries[m_current].get(); + return 0; +} + +HistoryItem* BackForwardList::forwardItem() +{ + if (m_entries.size() && m_current < m_entries.size() - 1) + return m_entries[m_current + 1].get(); + return 0; +} + +void BackForwardList::backListWithLimit(int limit, HistoryItemVector& list) +{ + list.clear(); + if (m_current != NoCurrentItemIndex) { + unsigned first = max((int)m_current - limit, 0); + for (; first < m_current; ++first) + list.append(m_entries[first]); + } +} + +void BackForwardList::forwardListWithLimit(int limit, HistoryItemVector& list) +{ + ASSERT(limit > -1); + list.clear(); + if (!m_entries.size()) + return; + + unsigned lastEntry = m_entries.size() - 1; + if (m_current < lastEntry) { + int last = min(m_current + limit, lastEntry); + limit = m_current + 1; + for (; limit <= last; ++limit) + list.append(m_entries[limit]); + } +} + +int BackForwardList::capacity() +{ + return m_capacity; +} + +void BackForwardList::setCapacity(int size) +{ + while (size < (int)m_entries.size()) { + RefPtr<HistoryItem> item = m_entries.last(); + m_entries.removeLast(); + m_entryHash.remove(item); + pageCache()->remove(item.get()); + } + + if (!size) + m_current = NoCurrentItemIndex; + else if (m_current > m_entries.size() - 1) + m_current = m_entries.size() - 1; + + m_capacity = size; +} + +bool BackForwardList::enabled() +{ + return m_enabled; +} + +void BackForwardList::setEnabled(bool enabled) +{ + m_enabled = enabled; + if (!enabled) { + int capacity = m_capacity; + setCapacity(0); + setCapacity(capacity); + } +} + +int BackForwardList::backListCount() +{ + return m_current == NoCurrentItemIndex ? 0 : m_current; +} + +int BackForwardList::forwardListCount() +{ + return m_current == NoCurrentItemIndex ? 0 : (int)m_entries.size() - (m_current + 1); +} + +HistoryItem* BackForwardList::itemAtIndex(int index) +{ + // Do range checks without doing math on index to avoid overflow. + if (index < -(int)m_current) + return 0; + + if (index > forwardListCount()) + return 0; + + return m_entries[index + m_current].get(); +} + +HistoryItemVector& BackForwardList::entries() +{ + return m_entries; +} + +void BackForwardList::close() +{ + int size = m_entries.size(); + for (int i = 0; i < size; ++i) + pageCache()->remove(m_entries[i].get()); + m_entries.clear(); + m_entryHash.clear(); + m_page = 0; + m_closed = true; +} + +bool BackForwardList::closed() +{ + return m_closed; +} + +void BackForwardList::removeItem(HistoryItem* item) +{ + if (!item) + return; + + for (unsigned i = 0; i < m_entries.size(); ++i) + if (m_entries[i] == item) { + m_entries.remove(i); + m_entryHash.remove(item); + if (m_current == NoCurrentItemIndex || m_current < i) + break; + if (m_current > i) + m_current--; + else { + size_t count = m_entries.size(); + if (m_current >= count) + m_current = count ? count-1 : NoCurrentItemIndex; + } + break; + } +} + +bool BackForwardList::containsItem(HistoryItem* entry) +{ + return m_entryHash.contains(entry); +} + +}; // namespace WebCore diff --git a/WebCore/history/BackForwardList.h b/WebCore/history/BackForwardList.h new file mode 100644 index 0000000..048778b --- /dev/null +++ b/WebCore/history/BackForwardList.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BackForwardList_h +#define BackForwardList_h + +#include <wtf/RefCounted.h> +#include <wtf/PassRefPtr.h> +#include <wtf/HashSet.h> +#include <wtf/Vector.h> + +namespace WebCore { + +class HistoryItem; +class Page; + +typedef Vector<RefPtr<HistoryItem> > HistoryItemVector; +typedef HashSet<RefPtr<HistoryItem> > HistoryItemHashSet; + +class BackForwardList : public RefCounted<BackForwardList> { +public: + static PassRefPtr<BackForwardList> create(Page* page) { return adoptRef(new BackForwardList(page)); } + ~BackForwardList(); + + Page* page() { return m_page; } + + void addItem(PassRefPtr<HistoryItem>); + void goBack(); + void goForward(); + void goToItem(HistoryItem*); + + HistoryItem* backItem(); + HistoryItem* currentItem(); + HistoryItem* forwardItem(); + HistoryItem* itemAtIndex(int); + + void backListWithLimit(int, HistoryItemVector&); + void forwardListWithLimit(int, HistoryItemVector&); + + int capacity(); + void setCapacity(int); + bool enabled(); + void setEnabled(bool); + int backListCount(); + int forwardListCount(); + bool containsItem(HistoryItem*); + + void close(); + bool closed(); + + void removeItem(HistoryItem*); + HistoryItemVector& entries(); + +private: + BackForwardList(Page*); + + Page* m_page; + HistoryItemVector m_entries; + HistoryItemHashSet m_entryHash; + unsigned m_current; + unsigned m_capacity; + bool m_closed; + bool m_enabled; +}; //class BackForwardList + +}; //namespace WebCore + +#endif //BACKFORWARDLIST_H diff --git a/WebCore/history/CachedPage.cpp b/WebCore/history/CachedPage.cpp new file mode 100644 index 0000000..e28ab50 --- /dev/null +++ b/WebCore/history/CachedPage.cpp @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "CachedPage.h" + +#include "AnimationController.h" +#include "CachedPagePlatformData.h" +#include "Document.h" +#include "DocumentLoader.h" +#include "Element.h" +#include "EventHandler.h" +#include "FocusController.h" +#include "Frame.h" +#include "FrameLoader.h" +#include "FrameView.h" +#include "GCController.h" +#include "JSLocation.h" +#include "Logging.h" +#include "Page.h" +#include "PausedTimeouts.h" +#include "SystemTime.h" +#if ENABLE(SVG) +#include "SVGDocumentExtensions.h" +#endif + +#include "kjs_proxy.h" +#include "kjs_window.h" +#include <kjs/JSLock.h> +#include <kjs/SavedBuiltins.h> +#include <kjs/property_map.h> + +using namespace KJS; + +namespace WebCore { + +#ifndef NDEBUG +WTFLogChannel LogWebCoreCachedPageLeaks = { 0x00000000, "", WTFLogChannelOn }; + +struct CachedPageCounter { + static int count; + ~CachedPageCounter() + { + if (count) + LOG(WebCoreCachedPageLeaks, "LEAK: %d CachedPage\n", count); + } +}; +int CachedPageCounter::count = 0; +static CachedPageCounter cachedPageCounter; +#endif + +PassRefPtr<CachedPage> CachedPage::create(Page* page) +{ + return new CachedPage(page); +} + +CachedPage::CachedPage(Page* page) + : RefCounted<CachedPage>(0) + , m_timeStamp(0) + , m_document(page->mainFrame()->document()) + , m_view(page->mainFrame()->view()) + , m_mousePressNode(page->mainFrame()->eventHandler()->mousePressNode()) + , m_URL(page->mainFrame()->loader()->url()) + , m_windowProperties(new SavedProperties) + , m_locationProperties(new SavedProperties) + , m_windowLocalStorage(new SavedProperties) + , m_windowBuiltins(new SavedBuiltins) +{ +#ifndef NDEBUG + ++CachedPageCounter::count; +#endif + + m_document->willSaveToCache(); + + Frame* mainFrame = page->mainFrame(); + Window* window = Window::retrieveWindow(mainFrame); + + mainFrame->clearTimers(); + + JSLock lock; + + if (window) { + window->saveBuiltins(*m_windowBuiltins.get()); + window->saveProperties(*m_windowProperties.get()); + window->saveLocalStorage(*m_windowLocalStorage.get()); + window->location()->saveProperties(*m_locationProperties.get()); + m_pausedTimeouts.set(window->pauseTimeouts()); + } + + m_document->setInPageCache(true); + +#if ENABLE(SVG) + if (m_document && m_document->svgExtensions()) + m_document->accessSVGExtensions()->pauseAnimations(); +#endif +} + +CachedPage::~CachedPage() +{ +#ifndef NDEBUG + --CachedPageCounter::count; +#endif + + clear(); +} + +void CachedPage::restore(Page* page) +{ + ASSERT(m_document->view() == m_view); + + Frame* mainFrame = page->mainFrame(); + Window* window = Window::retrieveWindow(mainFrame); + + JSLock lock; + + if (window) { + window->restoreBuiltins(*m_windowBuiltins.get()); + window->restoreProperties(*m_windowProperties.get()); + window->restoreLocalStorage(*m_windowLocalStorage.get()); + window->location()->restoreProperties(*m_locationProperties.get()); + window->resumeTimeouts(m_pausedTimeouts.get()); + } + +#if ENABLE(SVG) + if (m_document && m_document->svgExtensions()) + m_document->accessSVGExtensions()->unpauseAnimations(); +#endif + + mainFrame->animationController()->resumeAnimations(); + + mainFrame->eventHandler()->setMousePressNode(mousePressNode()); + + // Restore the focus appearance for the focused element. + // 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. + Document* focusedDocument = page->focusController()->focusedOrMainFrame()->document(); + if (Node* node = focusedDocument->focusedNode()) { + if (node->isElementNode()) + static_cast<Element*>(node)->updateFocusAppearance(true); + } +} + +void CachedPage::clear() +{ + if (!m_document) + return; + + if (m_cachedPagePlatformData) + m_cachedPagePlatformData->clear(); + + ASSERT(m_view); + ASSERT(m_document->frame() == m_view->frame()); + + if (m_document->inPageCache()) { + Frame::clearTimers(m_view.get()); + + m_document->setInPageCache(false); + // FIXME: We don't call willRemove here. Why is that OK? + m_document->detach(); + m_document->removeAllEventListenersFromAllNodes(); + + m_view->clearFrame(); + } + + ASSERT(!m_document->inPageCache()); + + m_document = 0; + m_view = 0; + m_mousePressNode = 0; + m_URL = KURL(); + + JSLock lock; + + m_windowProperties.clear(); + m_locationProperties.clear(); + m_windowBuiltins.clear(); + m_pausedTimeouts.clear(); + m_cachedPagePlatformData.clear(); + m_windowLocalStorage.clear(); + + gcController().garbageCollectSoon(); +} + +void CachedPage::setDocumentLoader(PassRefPtr<DocumentLoader> loader) +{ + m_documentLoader = loader; +} + +DocumentLoader* CachedPage::documentLoader() +{ + return m_documentLoader.get(); +} + +void CachedPage::setTimeStamp(double timeStamp) +{ + m_timeStamp = timeStamp; +} + +void CachedPage::setTimeStampToNow() +{ + m_timeStamp = currentTime(); +} + +double CachedPage::timeStamp() const +{ + return m_timeStamp; +} + +void CachedPage::setCachedPagePlatformData(CachedPagePlatformData* data) +{ + m_cachedPagePlatformData.set(data); +} + +CachedPagePlatformData* CachedPage::cachedPagePlatformData() +{ + return m_cachedPagePlatformData.get(); +} + +} // namespace WebCore diff --git a/WebCore/history/CachedPage.h b/WebCore/history/CachedPage.h new file mode 100644 index 0000000..9157b0b --- /dev/null +++ b/WebCore/history/CachedPage.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CachedPage_h +#define CachedPage_h + +#include "KURL.h" +#include <wtf/OwnPtr.h> + +namespace KJS { + class SavedBuiltins; + struct SavedProperties; +} + +namespace WebCore { + + class CachedPagePlatformData; + class Document; + class DocumentLoader; + class FrameView; + class Node; + class Page; + class PausedTimeouts; + +class CachedPage : public RefCounted<CachedPage> { +public: + static PassRefPtr<CachedPage> create(Page*); + ~CachedPage(); + + void clear(); + Document* document() const { return m_document.get(); } + FrameView* view() const { return m_view.get(); } + Node* mousePressNode() const { return m_mousePressNode.get(); } + const KURL& url() const { return m_URL; } + void restore(Page*); + + void setTimeStamp(double); + void setTimeStampToNow(); + double timeStamp() const; + void setDocumentLoader(PassRefPtr<DocumentLoader>); + DocumentLoader* documentLoader(); + + void setCachedPagePlatformData(CachedPagePlatformData*); + CachedPagePlatformData* cachedPagePlatformData(); + +private: + CachedPage(Page*); + RefPtr<DocumentLoader> m_documentLoader; + double m_timeStamp; + + RefPtr<Document> m_document; + RefPtr<FrameView> m_view; + RefPtr<Node> m_mousePressNode; + KURL m_URL; + OwnPtr<KJS::SavedProperties> m_windowProperties; + OwnPtr<KJS::SavedProperties> m_locationProperties; + OwnPtr<KJS::SavedProperties> m_windowLocalStorage; + OwnPtr<KJS::SavedBuiltins> m_windowBuiltins; + OwnPtr<PausedTimeouts> m_pausedTimeouts; + OwnPtr<CachedPagePlatformData> m_cachedPagePlatformData; +}; + +} // namespace WebCore + +#endif // CachedPage_h + diff --git a/WebCore/history/CachedPagePlatformData.h b/WebCore/history/CachedPagePlatformData.h new file mode 100644 index 0000000..c623f2f --- /dev/null +++ b/WebCore/history/CachedPagePlatformData.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef CachedPagePlatformData_h +#define CachedPagePlatformData_h + +namespace WebCore { + +// The purpose of this class is to give each platform a vessel to store platform data when a page +// goes into the Back/Forward page cache, and perform some action with that data when the page comes out. +// Each platform should subclass this class as neccessary + +class CachedPagePlatformData { +public: + virtual ~CachedPagePlatformData() { } + virtual void clear() { } +}; + +} // namespace WebCore + +#endif // CachedPagePlatformData_h diff --git a/WebCore/history/HistoryItem.cpp b/WebCore/history/HistoryItem.cpp new file mode 100644 index 0000000..05ee6ec --- /dev/null +++ b/WebCore/history/HistoryItem.cpp @@ -0,0 +1,437 @@ +/* + * Copyright (C) 2005, 2006 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "HistoryItem.h" + +#include "Document.h" +#include "FrameLoader.h" +#include "IconDatabase.h" +#include "IntSize.h" +#include "KURL.h" +#include "Logging.h" +#include "PageCache.h" +#include "ResourceRequest.h" +#include <stdio.h> + +namespace WebCore { + +static void defaultNotifyHistoryItemChanged() {} +void (*notifyHistoryItemChanged)() = defaultNotifyHistoryItemChanged; + +HistoryItem::HistoryItem() + : RefCounted<HistoryItem>(0) + , m_lastVisitedTime(0) + , m_isInPageCache(false) + , m_isTargetItem(false) + , m_visitCount(0) +{ +} + +HistoryItem::HistoryItem(const String& urlString, const String& title, double time) + : RefCounted<HistoryItem>(0) + , m_urlString(urlString) + , m_originalURLString(urlString) + , m_title(title) + , m_lastVisitedTime(time) + , m_isInPageCache(false) + , m_isTargetItem(false) + , m_visitCount(0) +{ + iconDatabase()->retainIconForPageURL(m_urlString); +} + +HistoryItem::HistoryItem(const String& urlString, const String& title, const String& alternateTitle, double time) + : RefCounted<HistoryItem>(0) + , m_urlString(urlString) + , m_originalURLString(urlString) + , m_title(title) + , m_displayTitle(alternateTitle) + , m_lastVisitedTime(time) + , m_isInPageCache(false) + , m_isTargetItem(false) + , m_visitCount(0) +{ + iconDatabase()->retainIconForPageURL(m_urlString); +} + +HistoryItem::HistoryItem(const KURL& url, const String& title) + : RefCounted<HistoryItem>(0) + , m_urlString(url.string()) + , m_originalURLString(url.string()) + , m_title(title) + , m_lastVisitedTime(0) + , m_isInPageCache(false) + , m_isTargetItem(false) + , m_visitCount(0) +{ + iconDatabase()->retainIconForPageURL(m_urlString); +} + +HistoryItem::HistoryItem(const KURL& url, const String& target, const String& parent, const String& title) + : RefCounted<HistoryItem>(0) + , m_urlString(url.string()) + , m_originalURLString(url.string()) + , m_target(target) + , m_parent(parent) + , m_title(title) + , m_lastVisitedTime(0) + , m_isInPageCache(false) + , m_isTargetItem(false) + , m_visitCount(0) +{ + iconDatabase()->retainIconForPageURL(m_urlString); +} + +HistoryItem::~HistoryItem() +{ + ASSERT(!m_isInPageCache); + iconDatabase()->releaseIconForPageURL(m_urlString); +} + +HistoryItem::HistoryItem(const HistoryItem& item) + : RefCounted<HistoryItem>(0) + , m_urlString(item.m_urlString) + , m_originalURLString(item.m_originalURLString) + , m_target(item.m_target) + , m_parent(item.m_parent) + , m_title(item.m_title) + , m_displayTitle(item.m_displayTitle) + , m_lastVisitedTime(item.m_lastVisitedTime) + , m_scrollPoint(item.m_scrollPoint) + , m_isInPageCache(item.m_isInPageCache) + , m_isTargetItem(item.m_isTargetItem) + , m_visitCount(item.m_visitCount) + , m_formContentType(item.m_formContentType) + , m_formReferrer(item.m_formReferrer) + , m_rssFeedReferrer(item.m_rssFeedReferrer) +{ + if (item.m_formData) + m_formData = item.m_formData->copy(); + + unsigned size = item.m_subItems.size(); + m_subItems.reserveCapacity(size); + for (unsigned i = 0; i < size; ++i) + m_subItems.append(item.m_subItems[i]->copy()); +} + +PassRefPtr<HistoryItem> HistoryItem::copy() const +{ + return new HistoryItem(*this); +} + +const String& HistoryItem::urlString() const +{ + return m_urlString; +} + +// The first URL we loaded to get to where this history item points. Includes both client +// and server redirects. +const String& HistoryItem::originalURLString() const +{ + return m_originalURLString; +} + +const String& HistoryItem::title() const +{ + return m_title; +} + +const String& HistoryItem::alternateTitle() const +{ + return m_displayTitle; +} + +Image* HistoryItem::icon() const +{ + Image* result = iconDatabase()->iconForPageURL(m_urlString, IntSize(16,16)); + return result ? result : iconDatabase()->defaultIcon(IntSize(16,16)); +} + +double HistoryItem::lastVisitedTime() const +{ + return m_lastVisitedTime; +} + +KURL HistoryItem::url() const +{ + return KURL(m_urlString); +} + +KURL HistoryItem::originalURL() const +{ + return KURL(m_originalURLString); +} + +const String& HistoryItem::target() const +{ + return m_target; +} + +const String& HistoryItem::parent() const +{ + return m_parent; +} + +void HistoryItem::setAlternateTitle(const String& alternateTitle) +{ + m_displayTitle = alternateTitle; + notifyHistoryItemChanged(); +} + +void HistoryItem::setURLString(const String& urlString) +{ + if (m_urlString != urlString) { + iconDatabase()->releaseIconForPageURL(m_urlString); + m_urlString = urlString; + iconDatabase()->retainIconForPageURL(m_urlString); + } + + notifyHistoryItemChanged(); +} + +void HistoryItem::setURL(const KURL& url) +{ + pageCache()->remove(this); + setURLString(url.string()); + clearDocumentState(); +} + +void HistoryItem::setOriginalURLString(const String& urlString) +{ + m_originalURLString = urlString; + notifyHistoryItemChanged(); +} + +void HistoryItem::setTitle(const String& title) +{ + m_title = title; + notifyHistoryItemChanged(); +} + +void HistoryItem::setTarget(const String& target) +{ + m_target = target; + notifyHistoryItemChanged(); +} + +void HistoryItem::setParent(const String& parent) +{ + m_parent = parent; +} + +void HistoryItem::setLastVisitedTime(double time) +{ + if (m_lastVisitedTime != time) { + m_lastVisitedTime = time; + m_visitCount++; + } +} + +int HistoryItem::visitCount() const +{ + return m_visitCount; +} + +void HistoryItem::setVisitCount(int count) +{ + m_visitCount = count; +} + +const IntPoint& HistoryItem::scrollPoint() const +{ + return m_scrollPoint; +} + +void HistoryItem::setScrollPoint(const IntPoint& point) +{ + m_scrollPoint = point; +} + +void HistoryItem::clearScrollPoint() +{ + m_scrollPoint.setX(0); + m_scrollPoint.setY(0); +} + +void HistoryItem::setDocumentState(const Vector<String>& state) +{ + m_documentState = state; +} + +const Vector<String>& HistoryItem::documentState() const +{ + return m_documentState; +} + +void HistoryItem::clearDocumentState() +{ + m_documentState.clear(); +} + +bool HistoryItem::isTargetItem() const +{ + return m_isTargetItem; +} + +void HistoryItem::setIsTargetItem(bool flag) +{ + m_isTargetItem = flag; +} + +void HistoryItem::addChildItem(PassRefPtr<HistoryItem> child) +{ + m_subItems.append(child); +} + +HistoryItem* HistoryItem::childItemWithName(const String& name) const +{ + unsigned size = m_subItems.size(); + for (unsigned i = 0; i < size; ++i) + if (m_subItems[i]->target() == name) + return m_subItems[i].get(); + return 0; +} + +// <rdar://problem/4895849> HistoryItem::recurseToFindTargetItem() should be replace with a non-recursive method +HistoryItem* HistoryItem::recurseToFindTargetItem() +{ + if (m_isTargetItem) + return this; + if (!m_subItems.size()) + return 0; + + HistoryItem* match; + unsigned size = m_subItems.size(); + for (unsigned i = 0; i < size; ++i) { + match = m_subItems[i]->recurseToFindTargetItem(); + if (match) + return match; + } + + return 0; +} + +HistoryItem* HistoryItem::targetItem() +{ + if (!m_subItems.size()) + return this; + return recurseToFindTargetItem(); +} + +const HistoryItemVector& HistoryItem::children() const +{ + return m_subItems; +} + +bool HistoryItem::hasChildren() const +{ + return m_subItems.size(); +} + +String HistoryItem::formContentType() const +{ + return m_formContentType; +} + +String HistoryItem::formReferrer() const +{ + return m_formReferrer; +} + +String HistoryItem::rssFeedReferrer() const +{ + return m_rssFeedReferrer; +} + +void HistoryItem::setRSSFeedReferrer(const String& referrer) +{ + m_rssFeedReferrer = referrer; +} + +void HistoryItem::setFormInfoFromRequest(const ResourceRequest& request) +{ + if (equalIgnoringCase(request.httpMethod(), "POST")) { + // FIXME: Eventually we have to make this smart enough to handle the case where + // we have a stream for the body to handle the "data interspersed with files" feature. + m_formData = request.httpBody(); + m_formContentType = request.httpContentType(); + m_formReferrer = request.httpReferrer(); + } else { + m_formData = 0; + m_formContentType = String(); + m_formReferrer = String(); + } +} + +FormData* HistoryItem::formData() +{ + return m_formData.get(); +} + +bool HistoryItem::isCurrentDocument(Document* doc) const +{ + // FIXME: We should find a better way to check if this is the current document. + return urlString() == doc->url(); +} + +void HistoryItem::mergeAutoCompleteHints(HistoryItem* otherItem) +{ + ASSERT(otherItem); + if (otherItem != this) + m_visitCount += otherItem->m_visitCount; +} + +#ifndef NDEBUG +int HistoryItem::showTree() const +{ + return showTreeWithIndent(0); +} + +int HistoryItem::showTreeWithIndent(unsigned indentLevel) const +{ + String prefix(""); + int totalSubItems = 0; + unsigned i; + for (i = 0; i < indentLevel; ++i) + prefix.append(" "); + + fprintf(stderr, "%s+-%s (%p)\n", prefix.ascii().data(), m_urlString.ascii().data(), this); + + for (unsigned int i = 0; i < m_subItems.size(); ++i) { + totalSubItems += m_subItems[i]->showTreeWithIndent(indentLevel + 1); + } + return totalSubItems + 1; +} +#endif + +}; //namespace WebCore + +#ifndef NDEBUG +int showTree(const WebCore::HistoryItem* item) +{ + return item->showTree(); +} +#endif diff --git a/WebCore/history/HistoryItem.h b/WebCore/history/HistoryItem.h new file mode 100644 index 0000000..c0650a4 --- /dev/null +++ b/WebCore/history/HistoryItem.h @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HistoryItem_h +#define HistoryItem_h + +#include "CachedPage.h" +#include "FormData.h" +#include "IntPoint.h" +#include "PlatformString.h" +#include <wtf/RefCounted.h> +#include "StringHash.h" +#include <wtf/HashMap.h> +#include <wtf/OwnPtr.h> +#include <wtf/RefPtr.h> +#include <wtf/Vector.h> + +#if PLATFORM(MAC) +#import <wtf/RetainPtr.h> +typedef struct objc_object* id; +#endif + +namespace WebCore { + +class Document; +class Image; +class KURL; +class ResourceRequest; + +class HistoryItem; +typedef Vector<RefPtr<HistoryItem> > HistoryItemVector; + +extern void (*notifyHistoryItemChanged)(); + +class HistoryItem : public RefCounted<HistoryItem> { + friend class PageCache; + +public: + HistoryItem(); + HistoryItem(const String& urlString, const String& title, double lastVisited); + HistoryItem(const String& urlString, const String& title, const String& alternateTitle, double lastVisited); + HistoryItem(const KURL& url, const String& title); + HistoryItem(const KURL& url, const String& target, const String& parent, const String& title); + + ~HistoryItem(); + + PassRefPtr<HistoryItem> copy() const; + + const String& originalURLString() const; + const String& urlString() const; + const String& title() const; + + void setInPageCache(bool inPageCache) { m_isInPageCache = inPageCache; } + bool isInPageCache() const { return m_isInPageCache; } + + double lastVisitedTime() const; + + void setAlternateTitle(const String& alternateTitle); + const String& alternateTitle() const; + + Image* icon() const; + + const String& parent() const; + KURL url() const; + KURL originalURL() const; + const String& target() const; + bool isTargetItem() const; + + FormData* formData(); + String formContentType() const; + String formReferrer() const; + String rssFeedReferrer() const; + + int visitCount() const; + + void mergeAutoCompleteHints(HistoryItem* otherItem); + + const IntPoint& scrollPoint() const; + void setScrollPoint(const IntPoint&); + void clearScrollPoint(); + const Vector<String>& documentState() const; + void setDocumentState(const Vector<String>&); + void clearDocumentState(); + + void setURL(const KURL&); + void setURLString(const String&); + void setOriginalURLString(const String&); + void setTarget(const String&); + void setParent(const String&); + void setTitle(const String&); + void setIsTargetItem(bool); + + void setFormInfoFromRequest(const ResourceRequest&); + + void setRSSFeedReferrer(const String&); + void setVisitCount(int); + + void addChildItem(PassRefPtr<HistoryItem>); + HistoryItem* childItemWithName(const String&) const; + HistoryItem* targetItem(); + HistoryItem* recurseToFindTargetItem(); + const HistoryItemVector& children() const; + bool hasChildren() const; + + // This should not be called directly for HistoryItems that are already included + // in GlobalHistory. The WebKit api for this is to use -[WebHistory setLastVisitedTimeInterval:forItem:] instead. + void setLastVisitedTime(double); + + bool isCurrentDocument(Document*) const; + +#if PLATFORM(MAC) + id viewState() const; + void setViewState(id); + + // Transient properties may be of any ObjC type. They are intended to be used to store state per back/forward list entry. + // The properties will not be persisted; when the history item is removed, the properties will be lost. + id getTransientProperty(const String&) const; + void setTransientProperty(const String&, id); +#endif + +#ifndef NDEBUG + int showTree() const; + int showTreeWithIndent(unsigned indentLevel) const; +#endif + +private: + HistoryItem(const HistoryItem&); + + String m_urlString; + String m_originalURLString; + String m_target; + String m_parent; + String m_title; + String m_displayTitle; + + double m_lastVisitedTime; + + IntPoint m_scrollPoint; + Vector<String> m_documentState; + + HistoryItemVector m_subItems; + + bool m_isInPageCache; + bool m_isTargetItem; + int m_visitCount; + + // info used to repost form data + RefPtr<FormData> m_formData; + String m_formContentType; + String m_formReferrer; + + // info used to support RSS feeds + String m_rssFeedReferrer; + + // PageCache controls these fields. + HistoryItem* m_next; + HistoryItem* m_prev; + RefPtr<CachedPage> m_cachedPage; + +#if PLATFORM(MAC) + RetainPtr<id> m_viewState; + OwnPtr<HashMap<String, RetainPtr<id> > > m_transientProperties; +#endif +}; //class HistoryItem + +} //namespace WebCore + +#ifndef NDEBUG +// Outside the WebCore namespace for ease of invocation from gdb. +extern "C" int showTree(const WebCore::HistoryItem*); +#endif + +#endif // HISTORYITEM_H diff --git a/WebCore/history/PageCache.cpp b/WebCore/history/PageCache.cpp new file mode 100644 index 0000000..dc24fd2 --- /dev/null +++ b/WebCore/history/PageCache.cpp @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "PageCache.h" + +#include "Cache.h" +#include "CachedPage.h" +#include "FrameLoader.h" +#include "HistoryItem.h" +#include "Logging.h" +#include "SystemTime.h" + +using namespace std; + +namespace WebCore { + +static const double autoreleaseInterval = 3; + +PageCache* pageCache() +{ + static PageCache* staticPageCache = new PageCache; + return staticPageCache; +} + +PageCache::PageCache() + : m_capacity(0) + , m_size(0) + , m_head(0) + , m_tail(0) + , m_autoreleaseTimer(this, &PageCache::releaseAutoreleasedPagesNowOrReschedule) +{ +} + +void PageCache::setCapacity(int capacity) +{ + ASSERT(capacity >= 0); + m_capacity = max(capacity, 0); + + prune(); +} + +void PageCache::add(PassRefPtr<HistoryItem> prpItem, PassRefPtr<CachedPage> cachedPage) +{ + ASSERT(prpItem); + ASSERT(cachedPage); + + HistoryItem* item = prpItem.releaseRef(); // Balanced in remove(). + + // Remove stale cache entry if necessary. + if (item->m_cachedPage) + remove(item); + + item->m_cachedPage = cachedPage; + addToLRUList(item); + ++m_size; + + prune(); +} + +void PageCache::remove(HistoryItem* item) +{ + // Safely ignore attempts to remove items not in the cache. + if (!item || !item->m_cachedPage) + return; + + autorelease(item->m_cachedPage.release()); + removeFromLRUList(item); + --m_size; + + item->deref(); // Balanced in add(). +} + +void PageCache::prune() +{ + while (m_size > m_capacity) { + ASSERT(m_tail && m_tail->m_cachedPage); + remove(m_tail); + } +} + +void PageCache::addToLRUList(HistoryItem* item) +{ + item->m_next = m_head; + item->m_prev = 0; + + if (m_head) { + ASSERT(m_tail); + m_head->m_prev = item; + } else { + ASSERT(!m_tail); + m_tail = item; + } + + m_head = item; +} + +void PageCache::removeFromLRUList(HistoryItem* item) +{ + if (!item->m_next) { + ASSERT(item == m_tail); + m_tail = item->m_prev; + } else { + ASSERT(item != m_tail); + item->m_next->m_prev = item->m_prev; + } + + if (!item->m_prev) { + ASSERT(item == m_head); + m_head = item->m_next; + } else { + ASSERT(item != m_head); + item->m_prev->m_next = item->m_next; + } +} + +void PageCache::releaseAutoreleasedPagesNowOrReschedule(Timer<PageCache>* timer) +{ + double loadDelta = currentTime() - FrameLoader::timeOfLastCompletedLoad(); + float userDelta = userIdleTime(); + + // FIXME: <rdar://problem/5211190> This limit of 42 risks growing the page cache far beyond its nominal capacity. + if ((userDelta < 0.5 || loadDelta < 1.25) && m_autoreleaseSet.size() < 42) { + LOG(PageCache, "WebCorePageCache: Postponing releaseAutoreleasedPagesNowOrReschedule() - %f since last load, %f since last input, %i objects pending release", loadDelta, userDelta, m_autoreleaseSet.size()); + timer->startOneShot(autoreleaseInterval); + return; + } + + LOG(PageCache, "WebCorePageCache: Releasing page caches - %f seconds since last load, %f since last input, %i objects pending release", loadDelta, userDelta, m_autoreleaseSet.size()); + releaseAutoreleasedPagesNow(); +} + +void PageCache::releaseAutoreleasedPagesNow() +{ + m_autoreleaseTimer.stop(); + + // Postpone dead pruning until all our resources have gone dead. + cache()->setPruneEnabled(false); + + CachedPageSet tmp; + tmp.swap(m_autoreleaseSet); + + CachedPageSet::iterator end = tmp.end(); + for (CachedPageSet::iterator it = tmp.begin(); it != end; ++it) + (*it)->clear(); + + // Now do the prune. + cache()->setPruneEnabled(true); + cache()->prune(); +} + +void PageCache::autorelease(PassRefPtr<CachedPage> page) +{ + ASSERT(page); + ASSERT(!m_autoreleaseSet.contains(page.get())); + m_autoreleaseSet.add(page); + if (!m_autoreleaseTimer.isActive()) + m_autoreleaseTimer.startOneShot(autoreleaseInterval); +} + +} // namespace WebCore diff --git a/WebCore/history/PageCache.h b/WebCore/history/PageCache.h new file mode 100644 index 0000000..ad15ab6 --- /dev/null +++ b/WebCore/history/PageCache.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PageCache_h +#define PageCache_h + +#include "HistoryItem.h" +#include "Timer.h" +#include <wtf/Forward.h> +#include <wtf/HashSet.h> +#include <wtf/Noncopyable.h> + +namespace WebCore { + + class CachedPage; + class HistoryItem; + + class PageCache : Noncopyable { + public: + friend PageCache* pageCache(); + + void setCapacity(int); // number of pages to cache + int capacity() { return m_capacity; } + + void add(PassRefPtr<HistoryItem>, PassRefPtr<CachedPage>); // Prunes if capacity() is exceeded. + void remove(HistoryItem*); + CachedPage* get(HistoryItem* item) { return item ? item->m_cachedPage.get() : 0; } + + void releaseAutoreleasedPagesNow(); + + private: + typedef HashSet<RefPtr<CachedPage> > CachedPageSet; + + PageCache(); // Use pageCache() instead. + ~PageCache(); // Not implemented to make sure nobody accidentally calls delete -- WebCore does not delete singletons. + + void addToLRUList(HistoryItem*); // Adds to the head of the list. + void removeFromLRUList(HistoryItem*); + + void prune(); + + void autorelease(PassRefPtr<CachedPage>); + void releaseAutoreleasedPagesNowOrReschedule(Timer<PageCache>*); + + int m_capacity; + int m_size; + + // LRU List + HistoryItem* m_head; + HistoryItem* m_tail; + + Timer<PageCache> m_autoreleaseTimer; + CachedPageSet m_autoreleaseSet; + }; + + // Function to obtain the global page cache. + PageCache* pageCache(); + +} // namespace WebCore + +#endif // PageCache_h diff --git a/WebCore/history/mac/HistoryItemMac.mm b/WebCore/history/mac/HistoryItemMac.mm new file mode 100644 index 0000000..cac9b1b --- /dev/null +++ b/WebCore/history/mac/HistoryItemMac.mm @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "HistoryItem.h" + +namespace WebCore { + +// Notification strings. +NSString *WebHistoryItemChangedNotification = @"WebHistoryItemChangedNotification"; + +id HistoryItem::viewState() const +{ + return m_viewState.get(); +} + +void HistoryItem::setViewState(id statePList) +{ + id newState = [statePList copy]; + m_viewState = newState; + [newState release]; +} + +id HistoryItem::getTransientProperty(const String& key) const +{ + if (!m_transientProperties) + return nil; + return m_transientProperties->get(key).get(); +} + +void HistoryItem::setTransientProperty(const String& key, id value) +{ + if (!m_transientProperties) + m_transientProperties.set(new HashMap<String, RetainPtr<id> >); + if (value == nil) + m_transientProperties->remove(key); + else + m_transientProperties->set(key, value); +} + +} // namespace WebCore + + |