summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/history
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-06 11:45:16 +0100
committerSteve Block <steveblock@google.com>2011-05-12 13:44:10 +0100
commitcad810f21b803229eb11403f9209855525a25d57 (patch)
tree29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /Source/WebCore/history
parent121b0cf4517156d0ac5111caf9830c51b69bae8f (diff)
downloadexternal_webkit-cad810f21b803229eb11403f9209855525a25d57.zip
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'Source/WebCore/history')
-rw-r--r--Source/WebCore/history/BackForwardController.cpp107
-rw-r--r--Source/WebCore/history/BackForwardController.h76
-rw-r--r--Source/WebCore/history/BackForwardList.h75
-rw-r--r--Source/WebCore/history/BackForwardListChromium.cpp157
-rw-r--r--Source/WebCore/history/BackForwardListImpl.cpp306
-rw-r--r--Source/WebCore/history/BackForwardListImpl.h126
-rw-r--r--Source/WebCore/history/CachedFrame.cpp265
-rw-r--r--Source/WebCore/history/CachedFrame.h96
-rw-r--r--Source/WebCore/history/CachedFramePlatformData.h45
-rw-r--r--Source/WebCore/history/CachedPage.cpp102
-rw-r--r--Source/WebCore/history/CachedPage.h63
-rw-r--r--Source/WebCore/history/HistoryItem.cpp847
-rw-r--r--Source/WebCore/history/HistoryItem.h297
-rw-r--r--Source/WebCore/history/PageCache.cpp479
-rw-r--r--Source/WebCore/history/PageCache.h93
-rw-r--r--Source/WebCore/history/android/AndroidWebHistoryBridge.h62
-rw-r--r--Source/WebCore/history/android/HistoryItemAndroid.cpp46
-rw-r--r--Source/WebCore/history/cf/HistoryPropertyList.cpp156
-rw-r--r--Source/WebCore/history/cf/HistoryPropertyList.h69
-rw-r--r--Source/WebCore/history/mac/HistoryItemMac.mm67
-rw-r--r--Source/WebCore/history/qt/HistoryItemQt.cpp119
21 files changed, 3653 insertions, 0 deletions
diff --git a/Source/WebCore/history/BackForwardController.cpp b/Source/WebCore/history/BackForwardController.cpp
new file mode 100644
index 0000000..d388f19
--- /dev/null
+++ b/Source/WebCore/history/BackForwardController.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2010 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 INC. 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 INC. 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.
+ */
+
+#include "config.h"
+#include "BackForwardController.h"
+
+#include "BackForwardListImpl.h"
+#include "HistoryItem.h"
+#include "Page.h"
+
+namespace WebCore {
+
+BackForwardController::BackForwardController(Page* page, PassRefPtr<BackForwardList> client)
+ : m_page(page)
+ , m_client(client)
+{
+ if (!m_client)
+ m_client = BackForwardListImpl::create(page);
+}
+
+BackForwardController::~BackForwardController()
+{
+}
+
+bool BackForwardController::canGoBackOrForward(int distance) const
+{
+ return m_page->canGoBackOrForward(distance);
+}
+
+void BackForwardController::goBackOrForward(int distance)
+{
+ m_page->goBackOrForward(distance);
+}
+
+bool BackForwardController::goBack()
+{
+ return m_page->goBack();
+}
+
+bool BackForwardController::goForward()
+{
+ return m_page->goForward();
+}
+
+void BackForwardController::addItem(PassRefPtr<HistoryItem> item)
+{
+ m_client->addItem(item);
+}
+
+void BackForwardController::setCurrentItem(HistoryItem* item)
+{
+ m_client->goToItem(item);
+}
+
+int BackForwardController::count() const
+{
+ return m_page->getHistoryLength();
+}
+
+int BackForwardController::backCount() const
+{
+ return m_client->backListCount();
+}
+
+int BackForwardController::forwardCount() const
+{
+ return m_client->forwardListCount();
+}
+
+HistoryItem* BackForwardController::itemAtIndex(int i)
+{
+ return m_client->itemAtIndex(i);
+}
+
+bool BackForwardController::isActive()
+{
+ return m_client->isActive();
+}
+
+void BackForwardController::close()
+{
+ m_client->close();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/history/BackForwardController.h b/Source/WebCore/history/BackForwardController.h
new file mode 100644
index 0000000..e89e32b
--- /dev/null
+++ b/Source/WebCore/history/BackForwardController.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2010 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 INC. 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 INC. 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 BackForwardController_h
+#define BackForwardController_h
+
+#include <wtf/Noncopyable.h>
+#include <wtf/Forward.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class BackForwardList;
+class HistoryItem;
+class Page;
+
+class BackForwardController : public Noncopyable {
+public:
+ BackForwardController(Page*, PassRefPtr<BackForwardList>);
+ ~BackForwardController();
+
+ BackForwardList* client() const { return m_client.get(); }
+
+ bool canGoBackOrForward(int distance) const;
+ void goBackOrForward(int distance);
+
+ bool goBack();
+ bool goForward();
+
+ void addItem(PassRefPtr<HistoryItem>);
+ void setCurrentItem(HistoryItem*);
+
+ int count() const;
+ int backCount() const;
+ int forwardCount() const;
+
+ HistoryItem* itemAtIndex(int);
+
+ bool isActive();
+
+ void close();
+
+ HistoryItem* backItem() { return itemAtIndex(-1); }
+ HistoryItem* currentItem() { return itemAtIndex(0); }
+ HistoryItem* forwardItem() { return itemAtIndex(1); }
+
+private:
+ Page* m_page;
+ RefPtr<BackForwardList> m_client;
+};
+
+} // namespace WebCore
+
+#endif // BackForwardController_h
diff --git a/Source/WebCore/history/BackForwardList.h b/Source/WebCore/history/BackForwardList.h
new file mode 100644
index 0000000..212eadd
--- /dev/null
+++ b/Source/WebCore/history/BackForwardList.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2006, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2009 Google, 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/Forward.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class HistoryItem;
+
+// FIXME: Rename this class to BackForwardClient, and rename the
+// getter in Page accordingly.
+class BackForwardList : public RefCounted<BackForwardList> {
+public:
+ virtual ~BackForwardList()
+ {
+ }
+
+ virtual void addItem(PassRefPtr<HistoryItem>) = 0;
+
+ virtual void goToItem(HistoryItem*) = 0;
+
+ virtual HistoryItem* itemAtIndex(int) = 0;
+ virtual int backListCount() = 0;
+ virtual int forwardListCount() = 0;
+
+ virtual bool isActive() = 0;
+
+ virtual void close() = 0;
+
+#if ENABLE(WML)
+ // FIXME: Rename this to just "clear" and change it so it's not
+ // WML-specific. This is the same operation as clearBackForwardList
+ // in the layout test controller; it would be reasonable to have it
+ // here even though HTML DOM interfaces don't require it.
+ virtual void clearWMLPageHistory() = 0;
+#endif
+
+ // FIXME: Delete these once all callers are using BackForwardController
+ // instead of calling this directly.
+ HistoryItem* backItem() { return itemAtIndex(-1); }
+ HistoryItem* currentItem() { return itemAtIndex(0); }
+ HistoryItem* forwardItem() { return itemAtIndex(1); }
+};
+
+} // namespace WebCore
+
+#endif // BackForwardList_h
diff --git a/Source/WebCore/history/BackForwardListChromium.cpp b/Source/WebCore/history/BackForwardListChromium.cpp
new file mode 100644
index 0000000..a22a147
--- /dev/null
+++ b/Source/WebCore/history/BackForwardListChromium.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (c) 2009, Google 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 "BackForwardListImpl.h"
+
+#include "HistoryItem.h"
+#include "Logging.h"
+
+namespace WebCore {
+
+static const unsigned DefaultCapacity = 100;
+static const unsigned NoCurrentItemIndex = UINT_MAX;
+
+BackForwardListImpl::BackForwardListImpl(Page* page)
+ : m_page(page)
+ , m_client(0)
+ , m_capacity(DefaultCapacity)
+ , m_closed(true)
+ , m_enabled(true)
+{
+}
+
+BackForwardListImpl::~BackForwardListImpl()
+{
+ ASSERT(m_closed);
+}
+
+void BackForwardListImpl::addItem(PassRefPtr<HistoryItem> prpItem)
+{
+ ASSERT(prpItem);
+ if (m_capacity == 0 || !m_enabled)
+ return;
+
+ m_client->addItem(prpItem);
+}
+
+void BackForwardListImpl::goToItem(HistoryItem* item)
+{
+ m_client->goToItem(item);
+}
+
+int BackForwardListImpl::capacity()
+{
+ return m_capacity;
+}
+
+void BackForwardListImpl::setCapacity(int size)
+{
+ m_capacity = size;
+}
+
+bool BackForwardListImpl::enabled()
+{
+ return m_enabled;
+}
+
+void BackForwardListImpl::setEnabled(bool enabled)
+{
+ m_enabled = enabled;
+ if (!enabled) {
+ int capacity = m_capacity;
+ setCapacity(0);
+ setCapacity(capacity);
+ }
+}
+
+int BackForwardListImpl::backListCount()
+{
+ return m_client->backListCount();
+}
+
+int BackForwardListImpl::forwardListCount()
+{
+ return m_client->forwardListCount();
+}
+
+HistoryItem* BackForwardListImpl::itemAtIndex(int index)
+{
+ return m_client->itemAtIndex(index);
+}
+
+HistoryItemVector& BackForwardListImpl::entries()
+{
+ static HistoryItemVector noEntries;
+ return noEntries;
+}
+
+void BackForwardListImpl::close()
+{
+ if (m_client)
+ m_client->close();
+ m_page = 0;
+ m_closed = true;
+}
+
+bool BackForwardListImpl::closed()
+{
+ return m_closed;
+}
+
+void BackForwardListImpl::goBack()
+{
+ ASSERT_NOT_REACHED();
+}
+
+void BackForwardListImpl::goForward()
+{
+ ASSERT_NOT_REACHED();
+}
+
+void BackForwardListImpl::backListWithLimit(int, HistoryItemVector&)
+{
+ ASSERT_NOT_REACHED();
+}
+
+void BackForwardListImpl::forwardListWithLimit(int, HistoryItemVector&)
+{
+ ASSERT_NOT_REACHED();
+}
+
+bool BackForwardListImpl::containsItem(HistoryItem*)
+{
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+void BackForwardListImpl::removeItem(HistoryItem*)
+{
+ ASSERT_NOT_REACHED();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/history/BackForwardListImpl.cpp b/Source/WebCore/history/BackForwardListImpl.cpp
new file mode 100644
index 0000000..cdb888c
--- /dev/null
+++ b/Source/WebCore/history/BackForwardListImpl.cpp
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ *
+ * 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 "BackForwardListImpl.h"
+
+#include "Frame.h"
+#include "FrameLoader.h"
+#include "FrameLoaderClient.h"
+#include "HistoryItem.h"
+#include "Logging.h"
+#include "Page.h"
+#include "PageCache.h"
+#include "SerializedScriptValue.h"
+
+using namespace std;
+
+namespace WebCore {
+
+static const unsigned DefaultCapacity = 100;
+static const unsigned NoCurrentItemIndex = UINT_MAX;
+
+BackForwardListImpl::BackForwardListImpl(Page* page)
+ : m_page(page)
+ , m_current(NoCurrentItemIndex)
+ , m_capacity(DefaultCapacity)
+ , m_closed(true)
+ , m_enabled(true)
+{
+}
+
+BackForwardListImpl::~BackForwardListImpl()
+{
+ ASSERT(m_closed);
+}
+
+void BackForwardListImpl::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--;
+ if (m_page)
+ m_page->mainFrame()->loader()->client()->dispatchDidRemoveBackForwardItem(item.get());
+ }
+
+ m_entryHash.add(prpItem.get());
+ m_entries.insert(m_current + 1, prpItem);
+ m_current++;
+ if (m_page)
+ m_page->mainFrame()->loader()->client()->dispatchDidAddBackForwardItem(currentItem());
+}
+
+void BackForwardListImpl::goBack()
+{
+ ASSERT(m_current > 0);
+ if (m_current > 0) {
+ m_current--;
+ if (m_page)
+ m_page->mainFrame()->loader()->client()->dispatchDidChangeBackForwardIndex();
+ }
+}
+
+void BackForwardListImpl::goForward()
+{
+ ASSERT(m_current < m_entries.size() - 1);
+ if (m_current < m_entries.size() - 1) {
+ m_current++;
+ if (m_page)
+ m_page->mainFrame()->loader()->client()->dispatchDidChangeBackForwardIndex();
+ }
+}
+
+void BackForwardListImpl::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;
+ if (m_page)
+ m_page->mainFrame()->loader()->client()->dispatchDidChangeBackForwardIndex();
+ }
+}
+
+HistoryItem* BackForwardListImpl::backItem()
+{
+ if (m_current && m_current != NoCurrentItemIndex)
+ return m_entries[m_current - 1].get();
+ return 0;
+}
+
+HistoryItem* BackForwardListImpl::currentItem()
+{
+ if (m_current != NoCurrentItemIndex)
+ return m_entries[m_current].get();
+ return 0;
+}
+
+HistoryItem* BackForwardListImpl::forwardItem()
+{
+ if (m_entries.size() && m_current < m_entries.size() - 1)
+ return m_entries[m_current + 1].get();
+ return 0;
+}
+
+void BackForwardListImpl::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 BackForwardListImpl::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 BackForwardListImpl::capacity()
+{
+ return m_capacity;
+}
+
+void BackForwardListImpl::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;
+ if (m_page)
+ m_page->mainFrame()->loader()->client()->dispatchDidChangeBackForwardIndex();
+ }
+ m_capacity = size;
+}
+
+bool BackForwardListImpl::enabled()
+{
+ return m_enabled;
+}
+
+void BackForwardListImpl::setEnabled(bool enabled)
+{
+ m_enabled = enabled;
+ if (!enabled) {
+ int capacity = m_capacity;
+ setCapacity(0);
+ setCapacity(capacity);
+ }
+}
+
+int BackForwardListImpl::backListCount()
+{
+ return m_current == NoCurrentItemIndex ? 0 : m_current;
+}
+
+int BackForwardListImpl::forwardListCount()
+{
+ return m_current == NoCurrentItemIndex ? 0 : (int)m_entries.size() - (m_current + 1);
+}
+
+HistoryItem* BackForwardListImpl::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& BackForwardListImpl::entries()
+{
+ return m_entries;
+}
+
+void BackForwardListImpl::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 BackForwardListImpl::closed()
+{
+ return m_closed;
+}
+
+void BackForwardListImpl::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 BackForwardListImpl::containsItem(HistoryItem* entry)
+{
+ return m_entryHash.contains(entry);
+}
+
+#if ENABLE(WML)
+void BackForwardListImpl::clearWMLPageHistory()
+{
+ RefPtr<HistoryItem> currentItem = this->currentItem();
+
+ 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_current = NoCurrentItemIndex;
+
+ // Spec: The history stack may be reset to a state where it only contains the current card.
+ addItem(currentItem);
+}
+#endif
+
+}; // namespace WebCore
diff --git a/Source/WebCore/history/BackForwardListImpl.h b/Source/WebCore/history/BackForwardListImpl.h
new file mode 100644
index 0000000..30043fa
--- /dev/null
+++ b/Source/WebCore/history/BackForwardListImpl.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2006, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2009 Google, 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 BackForwardListImpl_h
+#define BackForwardListImpl_h
+
+#include "BackForwardList.h"
+#include <wtf/HashSet.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class Page;
+
+typedef Vector<RefPtr<HistoryItem> > HistoryItemVector;
+typedef HashSet<RefPtr<HistoryItem> > HistoryItemHashSet;
+
+// FIXME: Change Chromium to use its own BackForwardList implementation
+// and not use BackForwardListImpl at all, then remove this
+// BackForwardListClient feature entirely and just don't use this
+// class on Chromium.
+#if PLATFORM(CHROMIUM)
+// In the Chromium port, the back/forward list is managed externally.
+// See BackForwardListChromium.cpp
+class BackForwardListClient {
+public:
+ virtual ~BackForwardListClient() { }
+ virtual void addItem(PassRefPtr<HistoryItem>) = 0;
+ virtual void goToItem(HistoryItem*) = 0;
+ virtual HistoryItem* itemAtIndex(int) = 0;
+ virtual int backListCount() = 0;
+ virtual int forwardListCount() = 0;
+ virtual void close() = 0;
+};
+#endif
+
+// FIXME: After renaming BackForwardList to BackForwardClient,
+// rename this to BackForwardList.
+class BackForwardListImpl : public BackForwardList {
+public:
+ static PassRefPtr<BackForwardListImpl> create(Page* page) { return adoptRef(new BackForwardListImpl(page)); }
+ virtual ~BackForwardListImpl();
+
+#if PLATFORM(CHROMIUM)
+ // Must be called before any other methods.
+ void setClient(BackForwardListClient* client) { m_client = client; }
+#endif
+
+ Page* page() { return m_page; }
+
+ virtual void addItem(PassRefPtr<HistoryItem>);
+ void goBack();
+ void goForward();
+ virtual void goToItem(HistoryItem*);
+
+ HistoryItem* backItem();
+ HistoryItem* currentItem();
+ HistoryItem* forwardItem();
+ virtual HistoryItem* itemAtIndex(int);
+
+ void backListWithLimit(int, HistoryItemVector&);
+ void forwardListWithLimit(int, HistoryItemVector&);
+
+ int capacity();
+ void setCapacity(int);
+ bool enabled();
+ void setEnabled(bool);
+ virtual int backListCount();
+ virtual int forwardListCount();
+ bool containsItem(HistoryItem*);
+
+ virtual void close();
+ bool closed();
+
+ void removeItem(HistoryItem*);
+ HistoryItemVector& entries();
+
+#if ENABLE(WML)
+ virtual void clearWMLPageHistory();
+#endif
+
+private:
+ BackForwardListImpl(Page*);
+
+ virtual bool isActive() { return enabled() && capacity(); }
+
+ Page* m_page;
+#if PLATFORM(CHROMIUM)
+ BackForwardListClient* m_client;
+#else
+ HistoryItemVector m_entries;
+ HistoryItemHashSet m_entryHash;
+ unsigned m_current;
+#endif
+ unsigned m_capacity;
+ bool m_closed;
+ bool m_enabled;
+};
+
+} // namespace WebCore
+
+#endif // BackForwardListImpl_h
diff --git a/Source/WebCore/history/CachedFrame.cpp b/Source/WebCore/history/CachedFrame.cpp
new file mode 100644
index 0000000..d21f958
--- /dev/null
+++ b/Source/WebCore/history/CachedFrame.cpp
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2009 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 "CachedFramePlatformData.h"
+#include "DocumentLoader.h"
+#include "ExceptionCode.h"
+#include "EventNames.h"
+#include "Frame.h"
+#include "FrameLoaderClient.h"
+#include "FrameView.h"
+#include "HistoryItem.h"
+#include "Logging.h"
+#include "PageTransitionEvent.h"
+#include <wtf/text/CString.h>
+#include <wtf/RefCountedLeakCounter.h>
+
+#if ENABLE(SVG)
+#include "SVGDocumentExtensions.h"
+#endif
+
+#if ENABLE(TOUCH_EVENTS)
+#include "Chrome.h"
+#include "ChromeClient.h"
+#include "Page.h"
+#endif
+
+namespace WebCore {
+
+#ifndef NDEBUG
+static WTF::RefCountedLeakCounter& cachedFrameCounter()
+{
+ DEFINE_STATIC_LOCAL(WTF::RefCountedLeakCounter, counter, ("CachedFrame"));
+ return counter;
+}
+#endif
+
+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()->resumeAnimationsForDocument(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();
+
+ frame->loader()->client()->didRestoreFromPageCache();
+
+ // 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->enqueuePageshowEvent(PageshowEventPersisted);
+
+ HistoryItem* historyItem = frame->loader()->history()->currentItem();
+ m_document->enqueuePopstateEvent(historyItem && historyItem->stateObject() ? historyItem->stateObject() : SerializedScriptValue::nullValue());
+
+#if ENABLE(TOUCH_EVENTS)
+ if (m_document->hasListenerType(Document::TOUCH_LISTENER))
+ m_document->page()->chrome()->client()->needTouchEvents(true);
+#endif
+
+ m_document->documentDidBecomeActive();
+}
+
+CachedFrame::CachedFrame(Frame* frame)
+ : CachedFrameBase(frame)
+{
+#ifndef NDEBUG
+ cachedFrameCounter().increment();
+#endif
+ ASSERT(m_document);
+ ASSERT(m_documentLoader);
+ ASSERT(m_view);
+
+ // Active DOM objects must be suspended before we cached the frame script data
+ m_document->suspendActiveDOMObjects(ActiveDOMObject::DocumentWillBecomeInactive);
+ m_cachedFrameScriptData = adoptPtr(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()->stopLoading(UnloadEventPolicyUnloadAndPageHide);
+
+ 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));
+
+ // 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());
+
+ if (!m_isMainFrame)
+ frame->page()->decrementFrameCount();
+
+ frame->loader()->client()->didSaveToPageCache();
+
+#ifndef NDEBUG
+ 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
+
+#if ENABLE(TOUCH_EVENTS)
+ if (m_document->hasListenerType(Document::TOUCH_LISTENER))
+ m_document->page()->chrome()->client()->needTouchEvents(false);
+#endif
+}
+
+void CachedFrame::open()
+{
+ ASSERT(m_view);
+ m_view->frame()->loader()->open(*this);
+
+ if (!m_isMainFrame)
+ m_view->frame()->page()->incrementFrameCount();
+}
+
+void CachedFrame::clear()
+{
+ if (!m_document)
+ return;
+
+ // 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());
+
+ for (int i = m_childFrames.size() - 1; i >= 0; --i)
+ m_childFrames[i]->clear();
+
+ m_document = 0;
+ m_view = 0;
+ m_mousePressNode = 0;
+ 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(PassOwnPtr<CachedFramePlatformData> data)
+{
+ m_cachedFramePlatformData = data;
+}
+
+CachedFramePlatformData* CachedFrame::cachedFramePlatformData()
+{
+ return m_cachedFramePlatformData.get();
+}
+
+int CachedFrame::descendantFrameCount() const
+{
+ int count = m_childFrames.size();
+ for (size_t i = 0; i < m_childFrames.size(); ++i)
+ count += m_childFrames[i]->descendantFrameCount();
+
+ return count;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/history/CachedFrame.h b/Source/WebCore/history/CachedFrame.h
new file mode 100644
index 0000000..b0d0d29
--- /dev/null
+++ b/Source/WebCore/history/CachedFrame.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2009, 2010 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 CachedFrame_h
+#define CachedFrame_h
+
+#include "KURL.h"
+#include "ScriptCachedFrameData.h"
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class CachedFrame;
+class CachedFramePlatformData;
+class Document;
+class DocumentLoader;
+class FrameView;
+class Node;
+
+typedef Vector<RefPtr<CachedFrame> > CachedFrameVector;
+
+class CachedFrameBase {
+public:
+ void restore();
+
+ Document* document() const { return m_document.get(); }
+ FrameView* view() const { return m_view.get(); }
+ const KURL& url() const { return m_url; }
+ DOMWindow* domWindow() const { return m_cachedFrameScriptData->domWindow(); }
+ bool isMainFrame() { return m_isMainFrame; }
+
+protected:
+ CachedFrameBase(Frame*);
+ ~CachedFrameBase();
+
+ RefPtr<Document> m_document;
+ RefPtr<DocumentLoader> m_documentLoader;
+ RefPtr<FrameView> m_view;
+ RefPtr<Node> m_mousePressNode;
+ KURL m_url;
+ OwnPtr<ScriptCachedFrameData> m_cachedFrameScriptData;
+ OwnPtr<CachedFramePlatformData> m_cachedFramePlatformData;
+ bool m_isMainFrame;
+
+ CachedFrameVector m_childFrames;
+};
+
+class CachedFrame : public RefCounted<CachedFrame>, private CachedFrameBase {
+public:
+ static PassRefPtr<CachedFrame> create(Frame* frame) { return adoptRef(new CachedFrame(frame)); }
+
+ void open();
+ void clear();
+ void destroy();
+
+ void setCachedFramePlatformData(PassOwnPtr<CachedFramePlatformData>);
+ CachedFramePlatformData* cachedFramePlatformData();
+
+ using CachedFrameBase::document;
+ using CachedFrameBase::view;
+ using CachedFrameBase::url;
+ DocumentLoader* documentLoader() const { return m_documentLoader.get(); }
+ Node* mousePressNode() const { return m_mousePressNode.get(); }
+
+ int descendantFrameCount() const;
+
+private:
+ CachedFrame(Frame*);
+};
+
+} // namespace WebCore
+
+#endif // CachedFrame_h
diff --git a/Source/WebCore/history/CachedFramePlatformData.h b/Source/WebCore/history/CachedFramePlatformData.h
new file mode 100644
index 0000000..01da8e5
--- /dev/null
+++ b/Source/WebCore/history/CachedFramePlatformData.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 CachedFramePlatformData_h
+#define CachedFramePlatformData_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 CachedFramePlatformData {
+public:
+ virtual ~CachedFramePlatformData() { }
+ virtual void clear() { }
+};
+
+} // namespace WebCore
+
+#endif // CachedFramePlatformData_h
diff --git a/Source/WebCore/history/CachedPage.cpp b/Source/WebCore/history/CachedPage.cpp
new file mode 100644
index 0000000..acbfd31
--- /dev/null
+++ b/Source/WebCore/history/CachedPage.cpp
@@ -0,0 +1,102 @@
+/*
+ * 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 "FocusController.h"
+#include "Frame.h"
+#include "FrameView.h"
+#include "Page.h"
+#include <wtf/CurrentTime.h>
+#include <wtf/RefCountedLeakCounter.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+#ifndef NDEBUG
+static WTF::RefCountedLeakCounter cachedPageCounter("CachedPage");
+#endif
+
+PassRefPtr<CachedPage> CachedPage::create(Page* page)
+{
+ return adoptRef(new CachedPage(page));
+}
+
+CachedPage::CachedPage(Page* page)
+ : m_timeStamp(currentTime())
+ , m_cachedMainFrame(CachedFrame::create(page->mainFrame()))
+{
+#ifndef NDEBUG
+ cachedPageCounter.increment();
+#endif
+}
+
+CachedPage::~CachedPage()
+{
+#ifndef NDEBUG
+ cachedPageCounter.decrement();
+#endif
+
+ destroy();
+ ASSERT(!m_cachedMainFrame);
+}
+
+void CachedPage::restore(Page* page)
+{
+ ASSERT(m_cachedMainFrame);
+ ASSERT(page && page->mainFrame() && page->mainFrame() == m_cachedMainFrame->view()->frame());
+ ASSERT(!page->frameCount());
+
+ m_cachedMainFrame->open();
+
+ // 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);
+ }
+
+ clear();
+}
+
+void CachedPage::clear()
+{
+ ASSERT(m_cachedMainFrame);
+ m_cachedMainFrame->clear();
+ m_cachedMainFrame = 0;
+}
+
+void CachedPage::destroy()
+{
+ if (m_cachedMainFrame)
+ m_cachedMainFrame->destroy();
+
+ m_cachedMainFrame = 0;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/history/CachedPage.h b/Source/WebCore/history/CachedPage.h
new file mode 100644
index 0000000..4741c79
--- /dev/null
+++ b/Source/WebCore/history/CachedPage.h
@@ -0,0 +1,63 @@
+/*
+ * 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 "CachedFrame.h"
+
+namespace WebCore {
+
+class Document;
+class DocumentLoader;
+class Page;
+
+class CachedPage : public RefCounted<CachedPage> {
+public:
+ static PassRefPtr<CachedPage> create(Page*);
+ ~CachedPage();
+
+ void restore(Page*);
+ void clear();
+ void destroy();
+
+ Document* document() const { return m_cachedMainFrame->document(); }
+ DocumentLoader* documentLoader() const { return m_cachedMainFrame->documentLoader(); }
+
+ double timeStamp() const { return m_timeStamp; }
+
+ CachedFrame* cachedMainFrame() { return m_cachedMainFrame.get(); }
+
+private:
+ CachedPage(Page*);
+
+ double m_timeStamp;
+ RefPtr<CachedFrame> m_cachedMainFrame;
+};
+
+} // namespace WebCore
+
+#endif // CachedPage_h
+
diff --git a/Source/WebCore/history/HistoryItem.cpp b/Source/WebCore/history/HistoryItem.cpp
new file mode 100644
index 0000000..0995913
--- /dev/null
+++ b/Source/WebCore/history/HistoryItem.cpp
@@ -0,0 +1,847 @@
+/*
+ * Copyright (C) 2005, 2006, 2008, 2011 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 "CachedPage.h"
+#include "Document.h"
+#include "IconDatabase.h"
+#include "PageCache.h"
+#include "ResourceRequest.h"
+#include <stdio.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/Decoder.h>
+#include <wtf/Encoder.h>
+#include <wtf/MathExtras.h>
+#include <wtf/text/CString.h>
+
+namespace WebCore {
+
+const uint32_t backForwardTreeEncodingVersion = 0;
+
+static long long generateSequenceNumber()
+{
+ // Initialize to the current time to reduce the likelihood of generating
+ // identifiers that overlap with those from past/future browser sessions.
+ static long long next = static_cast<long long>(currentTime() * 1000000.0);
+ return ++next;
+}
+
+static void defaultNotifyHistoryItemChanged(HistoryItem*)
+{
+}
+
+void (*notifyHistoryItemChanged)(HistoryItem*) = defaultNotifyHistoryItemChanged;
+
+HistoryItem::HistoryItem()
+ : m_lastVisitedTime(0)
+ , m_lastVisitWasHTTPNonGet(false)
+ , m_lastVisitWasFailure(false)
+ , m_isTargetItem(false)
+ , m_visitCount(0)
+ , m_itemSequenceNumber(generateSequenceNumber())
+ , m_documentSequenceNumber(generateSequenceNumber())
+{
+}
+
+HistoryItem::HistoryItem(const String& urlString, const String& title, double time)
+ : m_urlString(urlString)
+ , m_originalURLString(urlString)
+ , m_title(title)
+ , m_lastVisitedTime(time)
+ , m_lastVisitWasHTTPNonGet(false)
+ , m_lastVisitWasFailure(false)
+ , m_isTargetItem(false)
+ , m_visitCount(0)
+ , m_itemSequenceNumber(generateSequenceNumber())
+ , m_documentSequenceNumber(generateSequenceNumber())
+{
+ iconDatabase()->retainIconForPageURL(m_urlString);
+}
+
+HistoryItem::HistoryItem(const String& urlString, const String& title, const String& alternateTitle, double time)
+ : m_urlString(urlString)
+ , m_originalURLString(urlString)
+ , m_title(title)
+ , m_displayTitle(alternateTitle)
+ , m_lastVisitedTime(time)
+ , m_lastVisitWasHTTPNonGet(false)
+ , m_lastVisitWasFailure(false)
+ , m_isTargetItem(false)
+ , m_visitCount(0)
+ , m_itemSequenceNumber(generateSequenceNumber())
+ , m_documentSequenceNumber(generateSequenceNumber())
+{
+ iconDatabase()->retainIconForPageURL(m_urlString);
+}
+
+HistoryItem::HistoryItem(const KURL& url, const String& target, const String& parent, const String& title)
+ : m_urlString(url.string())
+ , m_originalURLString(url.string())
+ , m_target(target)
+ , m_parent(parent)
+ , m_title(title)
+ , m_lastVisitedTime(0)
+ , m_lastVisitWasHTTPNonGet(false)
+ , m_lastVisitWasFailure(false)
+ , m_isTargetItem(false)
+ , m_visitCount(0)
+ , m_itemSequenceNumber(generateSequenceNumber())
+ , m_documentSequenceNumber(generateSequenceNumber())
+{
+ iconDatabase()->retainIconForPageURL(m_urlString);
+}
+
+HistoryItem::~HistoryItem()
+{
+ ASSERT(!m_cachedPage);
+ iconDatabase()->releaseIconForPageURL(m_urlString);
+#if PLATFORM(ANDROID)
+ if (m_bridge)
+ m_bridge->detachHistoryItem();
+#endif
+}
+
+inline HistoryItem::HistoryItem(const HistoryItem& item)
+ : RefCounted<HistoryItem>()
+ , m_urlString(item.m_urlString)
+ , m_originalURLString(item.m_originalURLString)
+ , m_referrer(item.m_referrer)
+ , 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_lastVisitWasHTTPNonGet(item.m_lastVisitWasHTTPNonGet)
+ , m_scrollPoint(item.m_scrollPoint)
+ , m_lastVisitWasFailure(item.m_lastVisitWasFailure)
+ , m_isTargetItem(item.m_isTargetItem)
+ , m_visitCount(item.m_visitCount)
+ , m_dailyVisitCounts(item.m_dailyVisitCounts)
+ , m_weeklyVisitCounts(item.m_weeklyVisitCounts)
+ , m_itemSequenceNumber(item.m_itemSequenceNumber)
+ , m_documentSequenceNumber(item.m_documentSequenceNumber)
+ , m_formContentType(item.m_formContentType)
+{
+ if (item.m_formData)
+ m_formData = item.m_formData->copy();
+
+ unsigned size = item.m_children.size();
+ m_children.reserveInitialCapacity(size);
+ for (unsigned i = 0; i < size; ++i)
+ m_children.uncheckedAppend(item.m_children[i]->copy());
+
+ if (item.m_redirectURLs)
+ m_redirectURLs = adoptPtr(new Vector<String>(*item.m_redirectURLs));
+}
+
+PassRefPtr<HistoryItem> HistoryItem::copy() const
+{
+ return adoptRef(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(ParsedURLString, m_urlString);
+}
+
+KURL HistoryItem::originalURL() const
+{
+ return KURL(ParsedURLString, m_originalURLString);
+}
+
+const String& HistoryItem::referrer() const
+{
+ return m_referrer;
+}
+
+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(this);
+}
+
+void HistoryItem::setURLString(const String& urlString)
+{
+ if (m_urlString != urlString) {
+ iconDatabase()->releaseIconForPageURL(m_urlString);
+ m_urlString = urlString;
+ iconDatabase()->retainIconForPageURL(m_urlString);
+ }
+
+ notifyHistoryItemChanged(this);
+}
+
+void HistoryItem::setURL(const KURL& url)
+{
+ pageCache()->remove(this);
+ setURLString(url.string());
+ clearDocumentState();
+}
+
+void HistoryItem::setOriginalURLString(const String& urlString)
+{
+ m_originalURLString = urlString;
+ notifyHistoryItemChanged(this);
+}
+
+void HistoryItem::setReferrer(const String& referrer)
+{
+ m_referrer = referrer;
+ notifyHistoryItemChanged(this);
+}
+
+void HistoryItem::setTitle(const String& title)
+{
+ m_title = title;
+ notifyHistoryItemChanged(this);
+}
+
+void HistoryItem::setTarget(const String& target)
+{
+ m_target = target;
+ notifyHistoryItemChanged(this);
+}
+
+void HistoryItem::setParent(const String& parent)
+{
+ m_parent = parent;
+}
+
+static inline int timeToDay(double time)
+{
+ static const double secondsPerDay = 60 * 60 * 24;
+ return static_cast<int>(ceil(time / secondsPerDay));
+}
+
+void HistoryItem::padDailyCountsForNewVisit(double time)
+{
+ if (m_dailyVisitCounts.isEmpty())
+ m_dailyVisitCounts.prepend(m_visitCount);
+
+ int daysElapsed = timeToDay(time) - timeToDay(m_lastVisitedTime);
+
+ if (daysElapsed < 0)
+ daysElapsed = 0;
+
+ Vector<int> padding;
+ padding.fill(0, daysElapsed);
+ m_dailyVisitCounts.prepend(padding);
+}
+
+static const size_t daysPerWeek = 7;
+static const size_t maxDailyCounts = 2 * daysPerWeek - 1;
+static const size_t maxWeeklyCounts = 5;
+
+void HistoryItem::collapseDailyVisitsToWeekly()
+{
+ while (m_dailyVisitCounts.size() > maxDailyCounts) {
+ int oldestWeekTotal = 0;
+ for (size_t i = 0; i < daysPerWeek; i++)
+ oldestWeekTotal += m_dailyVisitCounts[m_dailyVisitCounts.size() - daysPerWeek + i];
+ m_dailyVisitCounts.shrink(m_dailyVisitCounts.size() - daysPerWeek);
+ m_weeklyVisitCounts.prepend(oldestWeekTotal);
+ }
+
+ if (m_weeklyVisitCounts.size() > maxWeeklyCounts)
+ m_weeklyVisitCounts.shrink(maxWeeklyCounts);
+}
+
+void HistoryItem::recordVisitAtTime(double time, VisitCountBehavior visitCountBehavior)
+{
+ padDailyCountsForNewVisit(time);
+
+ m_lastVisitedTime = time;
+
+ if (visitCountBehavior == IncreaseVisitCount) {
+ ++m_visitCount;
+ ++m_dailyVisitCounts[0];
+ }
+
+ collapseDailyVisitsToWeekly();
+}
+
+void HistoryItem::setLastVisitedTime(double time)
+{
+ if (m_lastVisitedTime != time)
+ recordVisitAtTime(time);
+}
+
+void HistoryItem::visited(const String& title, double time, VisitCountBehavior visitCountBehavior)
+{
+ m_title = title;
+ recordVisitAtTime(time, visitCountBehavior);
+}
+
+int HistoryItem::visitCount() const
+{
+ return m_visitCount;
+}
+
+void HistoryItem::recordInitialVisit()
+{
+ ASSERT(!m_visitCount);
+ recordVisitAtTime(m_lastVisitedTime);
+}
+
+void HistoryItem::setVisitCount(int count)
+{
+ m_visitCount = count;
+}
+
+void HistoryItem::adoptVisitCounts(Vector<int>& dailyCounts, Vector<int>& weeklyCounts)
+{
+ m_dailyVisitCounts.clear();
+ m_dailyVisitCounts.swap(dailyCounts);
+ m_weeklyVisitCounts.clear();
+ m_weeklyVisitCounts.swap(weeklyCounts);
+}
+
+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;
+#if PLATFORM(ANDROID)
+ notifyHistoryItemChanged(this);
+#endif
+}
+
+const Vector<String>& HistoryItem::documentState() const
+{
+ return m_documentState;
+}
+
+void HistoryItem::clearDocumentState()
+{
+ m_documentState.clear();
+#if PLATFORM(ANDROID)
+ notifyHistoryItemChanged(this);
+#endif
+}
+
+bool HistoryItem::isTargetItem() const
+{
+ return m_isTargetItem;
+}
+
+void HistoryItem::setIsTargetItem(bool flag)
+{
+ m_isTargetItem = flag;
+#if PLATFORM(ANDROID)
+ notifyHistoryItemChanged(this);
+#endif
+}
+
+void HistoryItem::setStateObject(PassRefPtr<SerializedScriptValue> object)
+{
+ m_stateObject = object;
+}
+
+void HistoryItem::addChildItem(PassRefPtr<HistoryItem> child)
+{
+ ASSERT(!childItemWithTarget(child->target()));
+ m_children.append(child);
+#if PLATFORM(ANDROID)
+ notifyHistoryItemChanged(this);
+#endif
+}
+
+void HistoryItem::setChildItem(PassRefPtr<HistoryItem> child)
+{
+ ASSERT(!child->isTargetItem());
+ unsigned size = m_children.size();
+ for (unsigned i = 0; i < size; ++i) {
+ if (m_children[i]->target() == child->target()) {
+ child->setIsTargetItem(m_children[i]->isTargetItem());
+ m_children[i] = child;
+ return;
+ }
+ }
+ m_children.append(child);
+}
+
+HistoryItem* HistoryItem::childItemWithTarget(const String& target) const
+{
+ unsigned size = m_children.size();
+ for (unsigned i = 0; i < size; ++i) {
+ if (m_children[i]->target() == target)
+ return m_children[i].get();
+ }
+ return 0;
+}
+
+HistoryItem* HistoryItem::childItemWithDocumentSequenceNumber(long long number) const
+{
+ unsigned size = m_children.size();
+ for (unsigned i = 0; i < size; ++i) {
+ if (m_children[i]->documentSequenceNumber() == number)
+ return m_children[i].get();
+ }
+ return 0;
+}
+
+// <rdar://problem/4895849> HistoryItem::findTargetItem() should be replaced with a non-recursive method.
+HistoryItem* HistoryItem::findTargetItem()
+{
+ if (m_isTargetItem)
+ return this;
+ unsigned size = m_children.size();
+ for (unsigned i = 0; i < size; ++i) {
+ if (HistoryItem* match = m_children[i]->targetItem())
+ return match;
+ }
+ return 0;
+}
+
+HistoryItem* HistoryItem::targetItem()
+{
+ HistoryItem* foundItem = findTargetItem();
+ return foundItem ? foundItem : this;
+}
+
+const HistoryItemVector& HistoryItem::children() const
+{
+ return m_children;
+}
+
+bool HistoryItem::hasChildren() const
+{
+ return !m_children.isEmpty();
+}
+
+void HistoryItem::clearChildren()
+{
+ m_children.clear();
+}
+
+// We do same-document navigation if going to a different item and if either of the following is true:
+// - The other item corresponds to the same document (for history entries created via pushState or fragment changes).
+// - The other item corresponds to the same set of documents, including frames (for history entries created via regular navigation)
+bool HistoryItem::shouldDoSameDocumentNavigationTo(HistoryItem* otherItem) const
+{
+ if (this == otherItem)
+ return false;
+
+ if (stateObject() || otherItem->stateObject())
+ return documentSequenceNumber() == otherItem->documentSequenceNumber();
+
+ if ((url().hasFragmentIdentifier() || otherItem->url().hasFragmentIdentifier()) && equalIgnoringFragmentIdentifier(url(), otherItem->url()))
+ return documentSequenceNumber() == otherItem->documentSequenceNumber();
+
+ return hasSameDocumentTree(otherItem);
+}
+
+// Does a recursive check that this item and its descendants have the same
+// document sequence numbers as the other item.
+bool HistoryItem::hasSameDocumentTree(HistoryItem* otherItem) const
+{
+ if (documentSequenceNumber() != otherItem->documentSequenceNumber())
+ return false;
+
+ if (children().size() != otherItem->children().size())
+ return false;
+
+ for (size_t i = 0; i < children().size(); i++) {
+ HistoryItem* child = children()[i].get();
+ HistoryItem* otherChild = otherItem->childItemWithDocumentSequenceNumber(child->documentSequenceNumber());
+ if (!otherChild || !child->hasSameDocumentTree(otherChild))
+ return false;
+ }
+
+ return true;
+}
+
+// Does a non-recursive check that this item and its immediate children have the
+// same frames as the other item.
+bool HistoryItem::hasSameFrames(HistoryItem* otherItem) const
+{
+ if (target() != otherItem->target())
+ return false;
+
+ if (children().size() != otherItem->children().size())
+ return false;
+
+ for (size_t i = 0; i < children().size(); i++) {
+ if (!otherItem->childItemWithTarget(children()[i]->target()))
+ return false;
+ }
+
+ return true;
+}
+
+String HistoryItem::formContentType() const
+{
+ return m_formContentType;
+}
+
+void HistoryItem::setFormInfoFromRequest(const ResourceRequest& request)
+{
+ m_referrer = request.httpReferrer();
+
+ 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();
+ } else {
+ m_formData = 0;
+ m_formContentType = String();
+ }
+#if PLATFORM(ANDROID)
+ notifyHistoryItemChanged(this);
+#endif
+}
+
+void HistoryItem::setFormData(PassRefPtr<FormData> formData)
+{
+ m_formData = formData;
+}
+
+void HistoryItem::setFormContentType(const String& formContentType)
+{
+ m_formContentType = formContentType;
+}
+
+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 equalIgnoringFragmentIdentifier(url(), doc->url());
+}
+
+void HistoryItem::mergeAutoCompleteHints(HistoryItem* otherItem)
+{
+ // FIXME: this is broken - we should be merging the daily counts
+ // somehow. but this is to support API that's not really used in
+ // practice so leave it broken for now.
+ ASSERT(otherItem);
+ if (otherItem != this)
+ m_visitCount += otherItem->m_visitCount;
+}
+
+void HistoryItem::addRedirectURL(const String& url)
+{
+ if (!m_redirectURLs)
+ m_redirectURLs = adoptPtr(new Vector<String>);
+
+ // Our API allows us to store all the URLs in the redirect chain, but for
+ // now we only have a use for the final URL.
+ (*m_redirectURLs).resize(1);
+ (*m_redirectURLs)[0] = url;
+}
+
+Vector<String>* HistoryItem::redirectURLs() const
+{
+ return m_redirectURLs.get();
+}
+
+void HistoryItem::setRedirectURLs(PassOwnPtr<Vector<String> > redirectURLs)
+{
+ m_redirectURLs = redirectURLs;
+}
+
+void HistoryItem::encodeBackForwardTree(Encoder& encoder) const
+{
+ encoder.encodeUInt32(backForwardTreeEncodingVersion);
+
+ encodeBackForwardTreeNode(encoder);
+}
+
+void HistoryItem::encodeBackForwardTreeNode(Encoder& encoder) const
+{
+ size_t size = m_children.size();
+ encoder.encodeUInt64(size);
+ for (size_t i = 0; i < size; ++i) {
+ const HistoryItem& child = *m_children[i];
+
+ encoder.encodeString(child.m_originalURLString);
+
+ encoder.encodeString(child.m_urlString);
+
+ child.encodeBackForwardTreeNode(encoder);
+ }
+
+ encoder.encodeInt64(m_documentSequenceNumber);
+
+ size = m_documentState.size();
+ encoder.encodeUInt64(size);
+ for (size_t i = 0; i < size; ++i)
+ encoder.encodeString(m_documentState[i]);
+
+ encoder.encodeString(m_formContentType);
+
+ encoder.encodeBool(m_formData);
+ if (m_formData)
+ m_formData->encodeForBackForward(encoder);
+
+ encoder.encodeInt64(m_itemSequenceNumber);
+
+ encoder.encodeString(m_originalURLString);
+
+ encoder.encodeString(m_referrer);
+
+ encoder.encodeInt32(m_scrollPoint.x());
+ encoder.encodeInt32(m_scrollPoint.y());
+
+ encoder.encodeBool(m_stateObject);
+ if (m_stateObject) {
+#if !USE(V8)
+ encoder.encodeBytes(m_stateObject->data().data(), m_stateObject->data().size());
+#else
+ encoder.encodeString(m_stateObject->toWireString());
+#endif
+ }
+
+ encoder.encodeString(m_target);
+}
+
+struct DecodeRecursionStackElement {
+ RefPtr<HistoryItem> node;
+ size_t i;
+ uint64_t size;
+
+ DecodeRecursionStackElement(PassRefPtr<HistoryItem> node, size_t i, uint64_t size)
+ : node(node)
+ , i(i)
+ , size(size)
+ {
+ }
+};
+
+PassRefPtr<HistoryItem> HistoryItem::decodeBackForwardTree(const String& topURLString, const String& topTitle, const String& topOriginalURLString, Decoder& decoder)
+{
+ // Since the data stream is not trusted, the decode has to be non-recursive.
+ // We don't want bad data to cause a stack overflow.
+
+ uint32_t version;
+ if (!decoder.decodeUInt32(version))
+ return 0;
+ if (version != backForwardTreeEncodingVersion)
+ return 0;
+
+ String urlString = topURLString;
+ String title = topTitle;
+ String originalURLString = topOriginalURLString;
+
+ Vector<DecodeRecursionStackElement, 16> recursionStack;
+
+recurse:
+ RefPtr<HistoryItem> node = create(urlString, title, 0);
+
+ node->setOriginalURLString(originalURLString);
+
+ title = String();
+
+ uint64_t size;
+ if (!decoder.decodeUInt64(size))
+ return 0;
+ size_t i;
+ RefPtr<HistoryItem> child;
+ for (i = 0; i < size; ++i) {
+ if (!decoder.decodeString(originalURLString))
+ return 0;
+
+ if (!decoder.decodeString(urlString))
+ return 0;
+
+ recursionStack.append(DecodeRecursionStackElement(node.release(), i, size));
+ goto recurse;
+
+resume:
+ node->m_children.append(child.release());
+ }
+
+ if (!decoder.decodeInt64(node->m_documentSequenceNumber))
+ return 0;
+
+ if (!decoder.decodeUInt64(size))
+ return 0;
+ for (i = 0; i < size; ++i) {
+ String state;
+ if (!decoder.decodeString(state))
+ return 0;
+ node->m_documentState.append(state);
+ }
+
+ if (!decoder.decodeString(node->m_formContentType))
+ return 0;
+
+ bool hasFormData;
+ if (!decoder.decodeBool(hasFormData))
+ return 0;
+ if (hasFormData) {
+ node->m_formData = FormData::decodeForBackForward(decoder);
+ if (!node->m_formData)
+ return 0;
+ }
+
+ if (!decoder.decodeInt64(node->m_itemSequenceNumber))
+ return 0;
+
+ if (!decoder.decodeString(node->m_originalURLString))
+ return 0;
+
+ if (!decoder.decodeString(node->m_referrer))
+ return 0;
+
+ int32_t x;
+ if (!decoder.decodeInt32(x))
+ return 0;
+ int32_t y;
+ if (!decoder.decodeInt32(y))
+ return 0;
+ node->m_scrollPoint = IntPoint(x, y);
+
+ bool hasStateObject;
+ if (!decoder.decodeBool(hasStateObject))
+ return 0;
+ if (hasStateObject) {
+#if !USE(V8)
+ Vector<uint8_t> bytes;
+ if (!decoder.decodeBytes(bytes))
+ return 0;
+ node->m_stateObject = SerializedScriptValue::adopt(bytes);
+#else
+ String string;
+ if (!decoder.decodeString(string))
+ return 0;
+ node->m_stateObject = SerializedScriptValue::createFromWire(string);
+#endif
+ }
+
+ if (!decoder.decodeString(node->m_target))
+ return 0;
+
+ // Simulate recursion with our own stack.
+ if (!recursionStack.isEmpty()) {
+ DecodeRecursionStackElement& element = recursionStack.last();
+ child = node.release();
+ node = element.node.release();
+ i = element.i;
+ size = element.size;
+ recursionStack.removeLast();
+ goto resume;
+ }
+
+ return node.release();
+}
+
+#ifndef NDEBUG
+
+int HistoryItem::showTree() const
+{
+ return showTreeWithIndent(0);
+}
+
+int HistoryItem::showTreeWithIndent(unsigned indentLevel) const
+{
+ Vector<char> prefix;
+ for (unsigned i = 0; i < indentLevel; ++i)
+ prefix.append(" ", 2);
+ prefix.append("\0", 1);
+
+ fprintf(stderr, "%s+-%s (%p)\n", prefix.data(), m_urlString.utf8().data(), this);
+
+ int totalSubItems = 0;
+ for (unsigned i = 0; i < m_children.size(); ++i)
+ totalSubItems += m_children[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/Source/WebCore/history/HistoryItem.h b/Source/WebCore/history/HistoryItem.h
new file mode 100644
index 0000000..19b33ad
--- /dev/null
+++ b/Source/WebCore/history/HistoryItem.h
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2006, 2008, 2011 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 HistoryItem_h
+#define HistoryItem_h
+
+#include "IntPoint.h"
+#include "PlatformString.h"
+#include "SerializedScriptValue.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+
+#if PLATFORM(MAC)
+#import <wtf/RetainPtr.h>
+typedef struct objc_object* id;
+#endif
+
+#if PLATFORM(QT)
+#include <QVariant>
+#include <QByteArray>
+#include <QDataStream>
+#endif
+
+#if PLATFORM(ANDROID)
+#include "AndroidWebHistoryBridge.h"
+#endif
+
+namespace WebCore {
+
+class CachedPage;
+class Document;
+class FormData;
+class HistoryItem;
+class Image;
+class KURL;
+class ResourceRequest;
+
+typedef Vector<RefPtr<HistoryItem> > HistoryItemVector;
+
+extern void (*notifyHistoryItemChanged)(HistoryItem*);
+
+enum VisitCountBehavior {
+ IncreaseVisitCount,
+ DoNotIncreaseVisitCount
+};
+
+class HistoryItem : public RefCounted<HistoryItem> {
+ friend class PageCache;
+
+public:
+ static PassRefPtr<HistoryItem> create() { return adoptRef(new HistoryItem); }
+ static PassRefPtr<HistoryItem> create(const String& urlString, const String& title, double lastVisited)
+ {
+ return adoptRef(new HistoryItem(urlString, title, lastVisited));
+ }
+ static PassRefPtr<HistoryItem> create(const String& urlString, const String& title, const String& alternateTitle, double lastVisited)
+ {
+ return adoptRef(new HistoryItem(urlString, title, alternateTitle, lastVisited));
+ }
+ static PassRefPtr<HistoryItem> create(const KURL& url, const String& target, const String& parent, const String& title)
+ {
+ return adoptRef(new HistoryItem(url, target, parent, title));
+ }
+
+ ~HistoryItem();
+
+ PassRefPtr<HistoryItem> copy() const;
+
+ void encodeBackForwardTree(Encoder&) const;
+ static PassRefPtr<HistoryItem> decodeBackForwardTree(const String& urlString, const String& title, const String& originalURLString, Decoder&);
+
+ const String& originalURLString() const;
+ const String& urlString() const;
+ const String& title() const;
+
+ bool isInPageCache() const { return m_cachedPage; }
+
+ 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& referrer() const;
+ const String& target() const;
+ bool isTargetItem() const;
+
+ FormData* formData();
+ String formContentType() const;
+
+ int visitCount() const;
+ bool lastVisitWasFailure() const { return m_lastVisitWasFailure; }
+ bool lastVisitWasHTTPNonGet() const { return m_lastVisitWasHTTPNonGet; }
+
+ 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 setReferrer(const String&);
+ void setTarget(const String&);
+ void setParent(const String&);
+ void setTitle(const String&);
+ void setIsTargetItem(bool);
+
+ void setStateObject(PassRefPtr<SerializedScriptValue> object);
+ SerializedScriptValue* stateObject() const { return m_stateObject.get(); }
+
+ void setItemSequenceNumber(long long number) { m_itemSequenceNumber = number; }
+ long long itemSequenceNumber() const { return m_itemSequenceNumber; }
+
+ void setDocumentSequenceNumber(long long number) { m_documentSequenceNumber = number; }
+ long long documentSequenceNumber() const { return m_documentSequenceNumber; }
+
+ void setFormInfoFromRequest(const ResourceRequest&);
+ void setFormData(PassRefPtr<FormData>);
+ void setFormContentType(const String&);
+
+ void recordInitialVisit();
+
+ void setVisitCount(int);
+ void setLastVisitWasFailure(bool wasFailure) { m_lastVisitWasFailure = wasFailure; }
+ void setLastVisitWasHTTPNonGet(bool wasNotGet) { m_lastVisitWasHTTPNonGet = wasNotGet; }
+
+ void addChildItem(PassRefPtr<HistoryItem>);
+ void setChildItem(PassRefPtr<HistoryItem>);
+ HistoryItem* childItemWithTarget(const String&) const;
+ HistoryItem* childItemWithDocumentSequenceNumber(long long number) const;
+ HistoryItem* targetItem();
+ const HistoryItemVector& children() const;
+ bool hasChildren() const;
+ void clearChildren();
+
+ bool shouldDoSameDocumentNavigationTo(HistoryItem* otherItem) const;
+ bool hasSameFrames(HistoryItem* otherItem) 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);
+ void visited(const String& title, double time, VisitCountBehavior);
+
+ void addRedirectURL(const String&);
+ Vector<String>* redirectURLs() const;
+ void setRedirectURLs(PassOwnPtr<Vector<String> >);
+
+ 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
+
+#if PLATFORM(QT)
+ QVariant userData() const { return m_userData; }
+ void setUserData(const QVariant& userData) { m_userData = userData; }
+
+ bool restoreState(QDataStream& buffer, int version);
+ QDataStream& saveState(QDataStream& out, int version) const;
+#endif
+
+#if PLATFORM(ANDROID)
+ void setBridge(AndroidWebHistoryBridge* bridge);
+ AndroidWebHistoryBridge* bridge() const;
+#endif
+
+#ifndef NDEBUG
+ int showTree() const;
+ int showTreeWithIndent(unsigned indentLevel) const;
+#endif
+
+ void adoptVisitCounts(Vector<int>& dailyCounts, Vector<int>& weeklyCounts);
+ const Vector<int>& dailyVisitCounts() const { return m_dailyVisitCounts; }
+ const Vector<int>& weeklyVisitCounts() const { return m_weeklyVisitCounts; }
+
+private:
+ 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& frameName, const String& parent, const String& title);
+
+ HistoryItem(const HistoryItem&);
+
+ void padDailyCountsForNewVisit(double time);
+ void collapseDailyVisitsToWeekly();
+ void recordVisitAtTime(double, VisitCountBehavior = IncreaseVisitCount);
+
+ bool hasSameDocumentTree(HistoryItem* otherItem) const;
+
+ HistoryItem* findTargetItem();
+
+ void encodeBackForwardTreeNode(Encoder&) const;
+ static PassRefPtr<HistoryItem> decodeBackForwardTreeNode(const String& urlString, const String& title, const String& originalURLString, Decoder&);
+
+ /* When adding new member variables to this class, please notify the Qt team.
+ * qt/HistoryItemQt.cpp contains code to serialize history items.
+ */
+
+ String m_urlString;
+ String m_originalURLString;
+ String m_referrer;
+ String m_target;
+ String m_parent;
+ String m_title;
+ String m_displayTitle;
+
+ double m_lastVisitedTime;
+ bool m_lastVisitWasHTTPNonGet;
+
+ IntPoint m_scrollPoint;
+ Vector<String> m_documentState;
+
+ HistoryItemVector m_children;
+
+ bool m_lastVisitWasFailure;
+ bool m_isTargetItem;
+ int m_visitCount;
+ Vector<int> m_dailyVisitCounts;
+ Vector<int> m_weeklyVisitCounts;
+
+ OwnPtr<Vector<String> > m_redirectURLs;
+
+ int64_t m_itemSequenceNumber;
+
+ // Support for HTML5 History
+ RefPtr<SerializedScriptValue> m_stateObject;
+ int64_t m_documentSequenceNumber;
+
+ // info used to repost form data
+ RefPtr<FormData> m_formData;
+ String m_formContentType;
+
+ // 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
+
+#if PLATFORM(QT)
+ QVariant m_userData;
+#endif
+
+#if PLATFORM(ANDROID)
+ RefPtr<AndroidWebHistoryBridge> m_bridge;
+#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/Source/WebCore/history/PageCache.cpp b/Source/WebCore/history/PageCache.cpp
new file mode 100644
index 0000000..7375a9c
--- /dev/null
+++ b/Source/WebCore/history/PageCache.cpp
@@ -0,0 +1,479 @@
+/*
+ * 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 "ApplicationCacheHost.h"
+#include "BackForwardController.h"
+#include "MemoryCache.h"
+#include "CachedPage.h"
+#include "DOMWindow.h"
+#include "DeviceMotionController.h"
+#include "DeviceOrientationController.h"
+#include "Document.h"
+#include "DocumentLoader.h"
+#include "Frame.h"
+#include "FrameLoader.h"
+#include "FrameLoaderClient.h"
+#include "FrameLoaderStateMachine.h"
+#include "HistoryItem.h"
+#include "Logging.h"
+#include "Page.h"
+#include "Settings.h"
+#include "SharedWorkerRepository.h"
+#include "SystemTime.h"
+#include <wtf/CurrentTime.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/StringConcatenate.h>
+
+using namespace std;
+
+namespace WebCore {
+
+static const double autoreleaseInterval = 3;
+
+#ifndef NDEBUG
+
+static String& pageCacheLogPrefix(int indentLevel)
+{
+ static int previousIndent = -1;
+ DEFINE_STATIC_LOCAL(String, prefix, ());
+
+ if (indentLevel != previousIndent) {
+ previousIndent = indentLevel;
+ prefix.truncate(0);
+ for (int i = 0; i < previousIndent; ++i)
+ prefix += " ";
+ }
+
+ return prefix;
+}
+
+static void pageCacheLog(const String& prefix, const String& message)
+{
+ LOG(PageCache, "%s%s", prefix.utf8().data(), message.utf8().data());
+}
+
+#define PCLOG(...) pageCacheLog(pageCacheLogPrefix(indentLevel), makeString(__VA_ARGS__))
+
+static bool logCanCacheFrameDecision(Frame* frame, int indentLevel)
+{
+ // Only bother logging for frames that have actually loaded and have content.
+ if (frame->loader()->stateMachine()->creatingInitialEmptyDocument())
+ return false;
+ KURL currentURL = frame->loader()->documentLoader() ? frame->loader()->documentLoader()->url() : KURL();
+ if (currentURL.isEmpty())
+ return false;
+
+ PCLOG("+---");
+ KURL newURL = frame->loader()->provisionalDocumentLoader() ? frame->loader()->provisionalDocumentLoader()->url() : KURL();
+ if (!newURL.isEmpty())
+ PCLOG(" Determining if frame can be cached navigating from (", currentURL.string(), ") to (", newURL.string(), "):");
+ else
+ PCLOG(" Determining if subframe with URL (", currentURL.string(), ") can be cached:");
+
+ bool cannotCache = false;
+
+ do {
+ if (!frame->loader()->documentLoader()) {
+ PCLOG(" -There is no DocumentLoader object");
+ cannotCache = true;
+ break;
+ }
+ if (!frame->loader()->documentLoader()->mainDocumentError().isNull()) {
+ PCLOG(" -Main document has an error");
+ cannotCache = true;
+ }
+ if (frame->loader()->subframeLoader()->containsPlugins()) {
+ PCLOG(" -Frame contains plugins");
+ cannotCache = true;
+ }
+ if (frame->loader()->url().protocolIs("https")) {
+ PCLOG(" -Frame is HTTPS");
+ cannotCache = true;
+ }
+ if (frame->domWindow() && frame->domWindow()->hasEventListeners(eventNames().unloadEvent)) {
+ PCLOG(" -Frame has an unload event listener");
+ cannotCache = true;
+ }
+#if ENABLE(DATABASE)
+ if (frame->document()->hasOpenDatabases()) {
+ PCLOG(" -Frame has open database handles");
+ cannotCache = true;
+ }
+#endif
+#if ENABLE(SHARED_WORKERS)
+ if (SharedWorkerRepository::hasSharedWorkers(frame->document())) {
+ PCLOG(" -Frame has associated SharedWorkers");
+ cannotCache = true;
+ }
+#endif
+ if (frame->document()->usingGeolocation()) {
+ PCLOG(" -Frame uses Geolocation");
+ cannotCache = true;
+ }
+ if (!frame->loader()->history()->currentItem()) {
+ PCLOG(" -No current history item");
+ cannotCache = true;
+ }
+ if (frame->loader()->quickRedirectComing()) {
+ PCLOG(" -Quick redirect is coming");
+ cannotCache = true;
+ }
+ if (frame->loader()->documentLoader()->isLoadingInAPISense()) {
+ PCLOG(" -DocumentLoader is still loading in API sense");
+ cannotCache = true;
+ }
+ if (frame->loader()->documentLoader()->isStopping()) {
+ PCLOG(" -DocumentLoader is in the middle of stopping");
+ cannotCache = true;
+ }
+ if (!frame->document()->canSuspendActiveDOMObjects()) {
+ PCLOG(" -The document cannot suspect its active DOM Objects");
+ cannotCache = true;
+ }
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+ if (!frame->loader()->documentLoader()->applicationCacheHost()->canCacheInPageCache()) {
+ PCLOG(" -The DocumentLoader uses an application cache");
+ cannotCache = true;
+ }
+#endif
+ if (!frame->loader()->client()->canCachePage()) {
+ PCLOG(" -The client says this frame cannot be cached");
+ cannotCache = true;
+ }
+ } while (false);
+
+ for (Frame* child = frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
+ if (!logCanCacheFrameDecision(child, indentLevel + 1))
+ cannotCache = true;
+
+ PCLOG(cannotCache ? " Frame CANNOT be cached" : " Frame CAN be cached");
+ PCLOG("+---");
+
+ return !cannotCache;
+}
+
+static void logCanCachePageDecision(Page* page)
+{
+ // Only bother logging for main frames that have actually loaded and have content.
+ if (page->mainFrame()->loader()->stateMachine()->creatingInitialEmptyDocument())
+ return;
+ KURL currentURL = page->mainFrame()->loader()->documentLoader() ? page->mainFrame()->loader()->documentLoader()->url() : KURL();
+ if (currentURL.isEmpty())
+ return;
+
+ int indentLevel = 0;
+ PCLOG("--------\n Determining if page can be cached:");
+
+ bool cannotCache = !logCanCacheFrameDecision(page->mainFrame(), 1);
+
+ FrameLoadType loadType = page->mainFrame()->loader()->loadType();
+ if (!page->backForward()->isActive()) {
+ PCLOG(" -The back/forward list is disabled or has 0 capacity");
+ cannotCache = true;
+ }
+ if (!page->settings()->usesPageCache()) {
+ PCLOG(" -Page settings says b/f cache disabled");
+ cannotCache = true;
+ }
+#if ENABLE(DEVICE_ORIENTATION)
+ if (page->deviceMotionController() && page->deviceMotionController()->isActive()) {
+ PCLOG(" -Page is using DeviceMotion");
+ cannotCache = true;
+ }
+ if (page->deviceOrientationController() && page->deviceOrientationController()->isActive()) {
+ PCLOG(" -Page is using DeviceOrientation");
+ cannotCache = true;
+ }
+#endif
+ if (loadType == FrameLoadTypeReload) {
+ PCLOG(" -Load type is: Reload");
+ cannotCache = true;
+ }
+ if (loadType == FrameLoadTypeReloadFromOrigin) {
+ PCLOG(" -Load type is: Reload from origin");
+ cannotCache = true;
+ }
+ if (loadType == FrameLoadTypeSame) {
+ PCLOG(" -Load type is: Same");
+ cannotCache = true;
+ }
+
+ PCLOG(cannotCache ? " Page CANNOT be cached\n--------" : " Page CAN be cached\n--------");
+}
+
+#endif
+
+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)
+{
+}
+
+bool PageCache::canCachePageContainingThisFrame(Frame* frame)
+{
+ for (Frame* child = frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
+ if (!canCachePageContainingThisFrame(child))
+ return false;
+ }
+
+ return frame->loader()->documentLoader()
+ && frame->loader()->documentLoader()->mainDocumentError().isNull()
+ // FIXME: If we ever change this so that frames with plug-ins will be cached,
+ // we need to make sure that we don't cache frames that have outstanding NPObjects
+ // (objects created by the plug-in). Since there is no way to pause/resume a Netscape plug-in,
+ // they would need to be destroyed and then recreated, and there is no way that we can recreate
+ // the right NPObjects. See <rdar://problem/5197041> for more information.
+ && !frame->loader()->subframeLoader()->containsPlugins()
+ && !frame->loader()->url().protocolIs("https")
+ && (!frame->domWindow() || !frame->domWindow()->hasEventListeners(eventNames().unloadEvent))
+#if ENABLE(DATABASE)
+ && !frame->document()->hasOpenDatabases()
+#endif
+#if ENABLE(SHARED_WORKERS)
+ && !SharedWorkerRepository::hasSharedWorkers(frame->document())
+#endif
+ && !frame->document()->usingGeolocation()
+ && frame->loader()->history()->currentItem()
+ && !frame->loader()->quickRedirectComing()
+ && !frame->loader()->documentLoader()->isLoadingInAPISense()
+ && !frame->loader()->documentLoader()->isStopping()
+ && frame->document()->canSuspendActiveDOMObjects()
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+ // FIXME: We should investigating caching frames that have an associated
+ // application cache. <rdar://problem/5917899> tracks that work.
+ && frame->loader()->documentLoader()->applicationCacheHost()->canCacheInPageCache()
+#endif
+#if ENABLE(WML)
+ && !frame->document()->containsWMLContent()
+ && !frame->document()->isWMLDocument()
+#endif
+ && frame->loader()->client()->canCachePage();
+}
+
+bool PageCache::canCache(Page* page)
+{
+ if (!page)
+ return false;
+
+#ifndef NDEBUG
+ logCanCachePageDecision(page);
+#endif
+
+ // Cache the page, if possible.
+ // Don't write to the cache if in the middle of a redirect, since we will want to
+ // store the final page we end up on.
+ // No point writing to the cache on a reload or loadSame, since we will just write
+ // over it again when we leave that page.
+ // FIXME: <rdar://problem/4886592> - We should work out the complexities of caching pages with frames as they
+ // are the most interesting pages on the web, and often those that would benefit the most from caching!
+ FrameLoadType loadType = page->mainFrame()->loader()->loadType();
+
+ return canCachePageContainingThisFrame(page->mainFrame())
+ && page->backForward()->isActive()
+ && page->settings()->usesPageCache()
+#if ENABLE(DEVICE_ORIENTATION)
+ && !(page->deviceMotionController() && page->deviceMotionController()->isActive())
+ && !(page->deviceOrientationController() && page->deviceOrientationController()->isActive())
+#endif
+ && loadType != FrameLoadTypeReload
+ && loadType != FrameLoadTypeReloadFromOrigin
+ && loadType != FrameLoadTypeSame;
+}
+
+void PageCache::setCapacity(int capacity)
+{
+ ASSERT(capacity >= 0);
+ m_capacity = max(capacity, 0);
+
+ prune();
+}
+
+int PageCache::frameCount() const
+{
+ int frameCount = 0;
+ for (HistoryItem* current = m_head; current; current = current->m_next) {
+ ++frameCount;
+ ASSERT(current->m_cachedPage);
+ frameCount += current->m_cachedPage ? current->m_cachedPage->cachedMainFrame()->descendantFrameCount() : 0;
+ }
+
+ return frameCount;
+}
+
+int PageCache::autoreleasedPageCount() const
+{
+ return m_autoreleaseSet.size();
+}
+
+void PageCache::add(PassRefPtr<HistoryItem> prpItem, Page* page)
+{
+ ASSERT(prpItem);
+ ASSERT(page);
+ ASSERT(canCache(page));
+
+ HistoryItem* item = prpItem.releaseRef(); // Balanced in remove().
+
+ // Remove stale cache entry if necessary.
+ if (item->m_cachedPage)
+ remove(item);
+
+ item->m_cachedPage = CachedPage::create(page);
+ addToLRUList(item);
+ ++m_size;
+
+ prune();
+}
+
+CachedPage* PageCache::get(HistoryItem* item)
+{
+ if (!item)
+ return 0;
+
+ if (CachedPage* cachedPage = item->m_cachedPage.get()) {
+ // FIXME: 1800 should not be hardcoded, it should come from
+ // WebKitBackForwardCacheExpirationIntervalKey in WebKit.
+ // Or we should remove WebKitBackForwardCacheExpirationIntervalKey.
+ if (currentTime() - cachedPage->timeStamp() <= 1800)
+ return cachedPage;
+
+ LOG(PageCache, "Not restoring page for %s from back/forward cache because cache entry has expired", item->url().string().ascii().data());
+ pageCache()->remove(item);
+ }
+ return 0;
+}
+
+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)->destroy();
+
+ // 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/Source/WebCore/history/PageCache.h b/Source/WebCore/history/PageCache.h
new file mode 100644
index 0000000..71ae5ad
--- /dev/null
+++ b/Source/WebCore/history/PageCache.h
@@ -0,0 +1,93 @@
+/*
+ * 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 Frame;
+ class HistoryItem;
+ class Page;
+
+ class PageCache : public Noncopyable {
+ public:
+ friend PageCache* pageCache();
+
+ static bool canCache(Page*);
+
+ void setCapacity(int); // number of pages to cache
+ int capacity() { return m_capacity; }
+
+ void add(PassRefPtr<HistoryItem>, Page*); // Prunes if capacity() is exceeded.
+ void remove(HistoryItem*);
+ CachedPage* get(HistoryItem* item);
+
+ void releaseAutoreleasedPagesNow();
+
+ int pageCount() const { return m_size; }
+ int frameCount() const;
+ int autoreleasedPageCount() const;
+
+ 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.
+
+ static bool canCachePageContainingThisFrame(Frame*);
+
+ 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/Source/WebCore/history/android/AndroidWebHistoryBridge.h b/Source/WebCore/history/android/AndroidWebHistoryBridge.h
new file mode 100644
index 0000000..a827b4a
--- /dev/null
+++ b/Source/WebCore/history/android/AndroidWebHistoryBridge.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2009, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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 AndroidWebHistoryBridge_h
+#define AndroidWebHistoryBridge_h
+
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class HistoryItem;
+
+class AndroidWebHistoryBridge : public RefCounted<AndroidWebHistoryBridge> {
+public:
+ AndroidWebHistoryBridge(HistoryItem* item)
+ : m_scale(0)
+ , m_textWrapScale(0)
+ , m_active(false)
+ , m_historyItem(item) { }
+ virtual ~AndroidWebHistoryBridge() { }
+ virtual void updateHistoryItem(HistoryItem* item) = 0;
+
+ void setScale(float s) { m_scale = s; }
+ void setTextWrapScale(float s) { m_textWrapScale = s; }
+ float scale() const { return m_scale; }
+ float textWrapScale() const { return m_textWrapScale; }
+ void detachHistoryItem() { m_historyItem = 0; }
+ HistoryItem* historyItem() const { return m_historyItem; }
+ void setActive() { m_active = true; }
+
+protected:
+ float m_scale;
+ float m_textWrapScale;
+ bool m_active;
+ HistoryItem* m_historyItem;
+};
+
+} // namespace WebCore
+
+#endif // AndroidWebHistoryBridge_h
diff --git a/Source/WebCore/history/android/HistoryItemAndroid.cpp b/Source/WebCore/history/android/HistoryItemAndroid.cpp
new file mode 100644
index 0000000..7c0f4ba
--- /dev/null
+++ b/Source/WebCore/history/android/HistoryItemAndroid.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2009, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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 {
+
+class AndroidWebHistoryBridge;
+
+AndroidWebHistoryBridge* HistoryItem::bridge() const
+{
+ if (!m_bridge)
+ return 0;
+ return m_bridge.get();
+}
+
+void HistoryItem::setBridge(AndroidWebHistoryBridge* bridge)
+{
+ m_bridge = adoptRef(bridge);
+}
+
+} // namespace WebCore
+
diff --git a/Source/WebCore/history/cf/HistoryPropertyList.cpp b/Source/WebCore/history/cf/HistoryPropertyList.cpp
new file mode 100644
index 0000000..fd28237
--- /dev/null
+++ b/Source/WebCore/history/cf/HistoryPropertyList.cpp
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2009 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 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 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 "HistoryPropertyList.h"
+
+#include "HistoryItem.h"
+#include <wtf/StringExtras.h>
+
+namespace WebCore {
+
+static const int currentFileVersion = 1;
+
+HistoryPropertyListWriter::HistoryPropertyListWriter()
+ : m_dailyVisitCountsKey("D")
+ , m_displayTitleKey("displayTitle")
+ , m_lastVisitWasFailureKey("lastVisitWasFailure")
+ , m_lastVisitWasHTTPNonGetKey("lastVisitWasHTTPNonGet")
+ , m_lastVisitedDateKey("lastVisitedDate")
+ , m_redirectURLsKey("redirectURLs")
+ , m_titleKey("title")
+ , m_urlKey("")
+ , m_visitCountKey("visitCount")
+ , m_weeklyVisitCountsKey("W")
+ , m_buffer(0)
+{
+}
+
+UInt8* HistoryPropertyListWriter::buffer(size_t size)
+{
+ ASSERT(!m_buffer);
+ m_buffer = static_cast<UInt8*>(CFAllocatorAllocate(0, size, 0));
+ m_bufferSize = size;
+ return m_buffer;
+}
+
+RetainPtr<CFDataRef> HistoryPropertyListWriter::releaseData()
+{
+ UInt8* buffer = m_buffer;
+ if (!buffer)
+ return 0;
+ m_buffer = 0;
+ RetainPtr<CFDataRef> data(AdoptCF, CFDataCreateWithBytesNoCopy(0, buffer, m_bufferSize, 0));
+ if (!data) {
+ CFAllocatorDeallocate(0, buffer);
+ return 0;
+ }
+ return data;
+}
+
+void HistoryPropertyListWriter::writeObjects(BinaryPropertyListObjectStream& stream)
+{
+ size_t outerDictionaryStart = stream.writeDictionaryStart();
+
+ stream.writeString("WebHistoryFileVersion");
+ stream.writeString("WebHistoryDates");
+
+ stream.writeInteger(currentFileVersion);
+ size_t outerDateArrayStart = stream.writeArrayStart();
+ writeHistoryItems(stream);
+ stream.writeArrayEnd(outerDateArrayStart);
+
+ stream.writeDictionaryEnd(outerDictionaryStart);
+}
+
+void HistoryPropertyListWriter::writeHistoryItem(BinaryPropertyListObjectStream& stream, HistoryItem* item)
+{
+ size_t itemDictionaryStart = stream.writeDictionaryStart();
+
+ const String& title = item->title();
+ const String& displayTitle = item->alternateTitle();
+ double lastVisitedDate = item->lastVisitedTime();
+ int visitCount = item->visitCount();
+ Vector<String>* redirectURLs = item->redirectURLs();
+ const Vector<int>& dailyVisitCounts = item->dailyVisitCounts();
+ const Vector<int>& weeklyVisitCounts = item->weeklyVisitCounts();
+
+ // keys
+ stream.writeString(m_urlKey);
+ if (!title.isEmpty())
+ stream.writeString(m_titleKey);
+ if (!displayTitle.isEmpty())
+ stream.writeString(m_displayTitleKey);
+ if (lastVisitedDate)
+ stream.writeString(m_lastVisitedDateKey);
+ if (visitCount)
+ stream.writeString(m_visitCountKey);
+ if (item->lastVisitWasFailure())
+ stream.writeString(m_lastVisitWasFailureKey);
+ if (item->lastVisitWasHTTPNonGet())
+ stream.writeString(m_lastVisitWasHTTPNonGetKey);
+ if (redirectURLs)
+ stream.writeString(m_redirectURLsKey);
+ if (!dailyVisitCounts.isEmpty())
+ stream.writeString(m_dailyVisitCountsKey);
+ if (!weeklyVisitCounts.isEmpty())
+ stream.writeString(m_weeklyVisitCountsKey);
+
+ // values
+ stream.writeUniqueString(item->urlString());
+ if (!title.isEmpty())
+ stream.writeString(title);
+ if (!displayTitle.isEmpty())
+ stream.writeString(displayTitle);
+ if (lastVisitedDate) {
+ char buffer[32];
+ snprintf(buffer, sizeof(buffer), "%.1lf", lastVisitedDate);
+ stream.writeUniqueString(buffer);
+ }
+ if (visitCount)
+ stream.writeInteger(visitCount);
+ if (item->lastVisitWasFailure())
+ stream.writeBooleanTrue();
+ if (item->lastVisitWasHTTPNonGet()) {
+ ASSERT(item->urlString().startsWith("http:", false) || item->urlString().startsWith("https:", false));
+ stream.writeBooleanTrue();
+ }
+ if (redirectURLs) {
+ size_t redirectArrayStart = stream.writeArrayStart();
+ size_t size = redirectURLs->size();
+ ASSERT(size);
+ for (size_t i = 0; i < size; ++i)
+ stream.writeUniqueString(redirectURLs->at(i));
+ stream.writeArrayEnd(redirectArrayStart);
+ }
+ if (size_t size = dailyVisitCounts.size())
+ stream.writeIntegerArray(dailyVisitCounts.data(), size);
+ if (size_t size = weeklyVisitCounts.size())
+ stream.writeIntegerArray(weeklyVisitCounts.data(), size);
+
+ stream.writeDictionaryEnd(itemDictionaryStart);
+}
+
+}
diff --git a/Source/WebCore/history/cf/HistoryPropertyList.h b/Source/WebCore/history/cf/HistoryPropertyList.h
new file mode 100644
index 0000000..fcb8c47
--- /dev/null
+++ b/Source/WebCore/history/cf/HistoryPropertyList.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2009 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 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 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 HistoryPropertyList_h
+#define HistoryPropertyList_h
+
+#include "BinaryPropertyList.h"
+#include "PlatformString.h"
+#include <wtf/RetainPtr.h>
+
+namespace WebCore {
+
+class HistoryItem;
+
+class HistoryPropertyListWriter : public BinaryPropertyListWriter {
+public:
+ RetainPtr<CFDataRef> releaseData();
+
+protected:
+ HistoryPropertyListWriter();
+
+ void writeHistoryItem(BinaryPropertyListObjectStream&, HistoryItem*);
+
+private:
+ virtual void writeHistoryItems(BinaryPropertyListObjectStream&) = 0;
+
+ virtual void writeObjects(BinaryPropertyListObjectStream&);
+ virtual UInt8* buffer(size_t);
+
+ const String m_dailyVisitCountsKey;
+ const String m_displayTitleKey;
+ const String m_lastVisitWasFailureKey;
+ const String m_lastVisitWasHTTPNonGetKey;
+ const String m_lastVisitedDateKey;
+ const String m_redirectURLsKey;
+ const String m_titleKey;
+ const String m_urlKey;
+ const String m_visitCountKey;
+ const String m_weeklyVisitCountsKey;
+
+ UInt8* m_buffer;
+ size_t m_bufferSize;
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/history/mac/HistoryItemMac.mm b/Source/WebCore/history/mac/HistoryItemMac.mm
new file mode 100644
index 0000000..09bf78d
--- /dev/null
+++ b/Source/WebCore/history/mac/HistoryItemMac.mm
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2006, 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 "HistoryItem.h"
+
+#include <wtf/text/StringHash.h>
+
+namespace WebCore {
+
+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 (!value) {
+ if (m_transientProperties) {
+ m_transientProperties->remove(key);
+ if (m_transientProperties->isEmpty())
+ m_transientProperties.clear();
+ }
+ } else {
+ if (!m_transientProperties)
+ m_transientProperties.set(new HashMap<String, RetainPtr<id> >);
+ m_transientProperties->set(key, value);
+ }
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/history/qt/HistoryItemQt.cpp b/Source/WebCore/history/qt/HistoryItemQt.cpp
new file mode 100644
index 0000000..b3c7ba1
--- /dev/null
+++ b/Source/WebCore/history/qt/HistoryItemQt.cpp
@@ -0,0 +1,119 @@
+/*
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "HistoryItem.h"
+
+#include "FormData.h"
+#include <wtf/text/CString.h>
+
+bool WebCore::HistoryItem::restoreState(QDataStream& in, int version)
+{
+ // we only support version 1 for now
+
+ if (version != 1)
+ return false;
+
+ WTF::String url;
+ WTF::String title;
+ WTF::String altTitle;
+ WTF::String orginalUrl;
+ WTF::String referrer;
+ WTF::String target;
+ WTF::String parrent;
+ double lastVisitedTime;
+ bool validUserData;
+ WTF::String parent;
+ bool lastVisitWasHTTPNonGet;
+ bool lastVisitWasFailure;
+ bool isTargetItem;
+ int visitCount;
+ WTF::Vector<WTF::String> documentState;
+ WebCore::IntPoint scrollPoint;
+ WTF::Vector<int> weeklyVisitCounts;
+ WTF::Vector<int> dailyVisitCounts;
+ // bool loadFormdata;
+ // WTF::String formContentType;
+ // WTF::Vector<char> formData;
+
+ in >> url >> title >> altTitle >> lastVisitedTime >> orginalUrl >> referrer >> target >> parent;
+ in >> lastVisitWasHTTPNonGet >> lastVisitWasFailure >> isTargetItem >> visitCount >> documentState;
+ in >> scrollPoint >> dailyVisitCounts >> weeklyVisitCounts;
+ /*in >> loadFormdata;
+ if (loadFormdata) {
+ in >> formContentType >> formData;
+ // direct assigned (!)
+ m_formContentType = formContentType;
+ m_formData = FormData::create(CString(formData));
+ }*/
+ // use setters
+ adoptVisitCounts(dailyVisitCounts, weeklyVisitCounts);
+ setScrollPoint(scrollPoint);
+ setDocumentState(documentState);
+ setVisitCount(visitCount);
+ setIsTargetItem(isTargetItem);
+ setLastVisitWasFailure(lastVisitWasFailure);
+ setLastVisitWasHTTPNonGet(lastVisitWasHTTPNonGet);
+ setParent(parent);
+ setTarget(target);
+ setReferrer(referrer);
+ setOriginalURLString(orginalUrl);
+ setURLString(url);
+ setLastVisitedTime(lastVisitedTime);
+ setTitle(title);
+ setAlternateTitle(altTitle);
+
+ // at the end load userData
+ in >> validUserData;
+ if (validUserData) {
+ QVariant tmp;
+ in >> tmp;
+ setUserData(tmp);
+ }
+
+ return in.status() == QDataStream::Ok;
+}
+
+QDataStream& WebCore::HistoryItem::saveState(QDataStream& out, int version) const
+{
+ // we only support version 1 for now.
+ if (version != 1)
+ return out;
+
+ out << urlString() << title() << alternateTitle() << lastVisitedTime();
+ out << originalURLString() << referrer() << target() << parent();
+ out << lastVisitWasHTTPNonGet() << lastVisitWasFailure() << isTargetItem();
+ out << visitCount() << documentState() << scrollPoint();
+ out << dailyVisitCounts() << weeklyVisitCounts();
+ /*if (m_formData) {
+ out << true;
+ out << formContentType();
+ out << m_formData->flatten();
+ } else {
+ out << false;
+ }*/
+ // save user data
+ if (userData().isValid())
+ out << true << userData();
+ else
+ out << false;
+
+ return out;
+}
+