summaryrefslogtreecommitdiff
path: root/Source/WebCore/history
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/history')
-rw-r--r--Source/WebCore/history/BackForwardClient.h (renamed from Source/WebCore/history/mac/HistoryItemMac.mm)71
-rw-r--r--Source/WebCore/history/BackForwardController.cpp65
-rw-r--r--Source/WebCore/history/BackForwardController.h29
-rw-r--r--Source/WebCore/history/BackForwardList.cpp (renamed from Source/WebCore/history/BackForwardListImpl.cpp)157
-rw-r--r--Source/WebCore/history/BackForwardList.h78
-rw-r--r--Source/WebCore/history/BackForwardListImpl.h94
-rw-r--r--Source/WebCore/history/CachedFrame.cpp190
-rw-r--r--Source/WebCore/history/CachedFrame.h40
-rw-r--r--Source/WebCore/history/CachedFramePlatformData.h2
-rw-r--r--Source/WebCore/history/CachedPage.cpp104
-rw-r--r--Source/WebCore/history/CachedPage.h40
-rw-r--r--Source/WebCore/history/HistoryItem.cpp532
-rw-r--r--Source/WebCore/history/HistoryItem.h286
-rw-r--r--Source/WebCore/history/PageCache.cpp655
-rw-r--r--Source/WebCore/history/PageCache.h103
-rw-r--r--Source/WebCore/history/blackberry/HistoryItemViewState.h55
-rw-r--r--Source/WebCore/history/qt/HistoryItemQt.cpp241
17 files changed, 1004 insertions, 1738 deletions
diff --git a/Source/WebCore/history/mac/HistoryItemMac.mm b/Source/WebCore/history/BackForwardClient.h
index 9b077a1ef..778ac8ff0 100644
--- a/Source/WebCore/history/mac/HistoryItemMac.mm
+++ b/Source/WebCore/history/BackForwardClient.h
@@ -1,5 +1,7 @@
/*
- * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ * 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
@@ -10,10 +12,10 @@
* 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
+ * 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 COMPUTER, INC. OR
+ * 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
@@ -23,45 +25,42 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "config.h"
-#include "HistoryItem.h"
+#ifndef BackForwardClient_h
+#define BackForwardClient_h
-#include <wtf/text/StringHash.h>
+#include <wtf/Forward.h>
+#include <wtf/RefCounted.h>
namespace WebCore {
-id HistoryItem::viewState() const
-{
- return m_viewState.get();
-}
+class HistoryItem;
-void HistoryItem::setViewState(id statePList)
-{
- id newState = [statePList copy];
- m_viewState = newState;
- [newState release];
-}
+class BackForwardClient : public RefCounted<BackForwardClient> {
+public:
+ virtual ~BackForwardClient()
+ {
+ }
-id HistoryItem::getTransientProperty(const String& key) const
-{
- if (!m_transientProperties)
- return nil;
- return m_transientProperties->get(key).get();
-}
+ virtual void addItem(Ref<HistoryItem>&&) = 0;
-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 = adoptPtr(new HashMap<String, RetainPtr<id> >);
- m_transientProperties->set(key, value);
- }
-}
+ virtual void goToItem(HistoryItem*) = 0;
+
+ virtual HistoryItem* itemAtIndex(int) = 0;
+ virtual int backListCount() = 0;
+ virtual int forwardListCount() = 0;
+
+ virtual void close() = 0;
+
+#if PLATFORM(IOS)
+ // FIXME: These methods seem to violate the encapsulation of this class.
+ virtual unsigned current() = 0;
+ virtual void setCurrent(unsigned newCurrent) = 0;
+
+ // FIXME: Consider renaming this method once we upstream the iOS changes to WebView.mm.
+ virtual bool clearAllPageCaches() = 0;
+#endif
+};
} // namespace WebCore
+
+#endif // BackForwardClient_h
diff --git a/Source/WebCore/history/BackForwardController.cpp b/Source/WebCore/history/BackForwardController.cpp
index ca363b80a..2317ad726 100644
--- a/Source/WebCore/history/BackForwardController.cpp
+++ b/Source/WebCore/history/BackForwardController.cpp
@@ -26,52 +26,80 @@
#include "config.h"
#include "BackForwardController.h"
-#include "BackForwardListImpl.h"
+#include "BackForwardList.h"
#include "HistoryItem.h"
#include "Page.h"
namespace WebCore {
-BackForwardController::BackForwardController(Page* page, PassRefPtr<BackForwardList> client)
+BackForwardController::BackForwardController(Page& page, RefPtr<BackForwardClient>&& client)
: m_page(page)
- , m_client(client)
+ , m_client(WTFMove(client))
{
if (!m_client)
- m_client = BackForwardListImpl::create(page);
+ m_client = BackForwardList::create(&page);
}
BackForwardController::~BackForwardController()
{
}
-PassOwnPtr<BackForwardController> BackForwardController::create(Page* page, PassRefPtr<BackForwardList> client)
-{
- return adoptPtr(new BackForwardController(page, client));
-}
-
bool BackForwardController::canGoBackOrForward(int distance) const
{
- return m_page->canGoBackOrForward(distance);
+ if (!distance)
+ return true;
+ if (distance > 0 && distance <= forwardCount())
+ return true;
+ if (distance < 0 && -distance <= backCount())
+ return true;
+ return false;
}
void BackForwardController::goBackOrForward(int distance)
{
- m_page->goBackOrForward(distance);
+ if (!distance)
+ return;
+
+ HistoryItem* item = itemAtIndex(distance);
+ if (!item) {
+ if (distance > 0) {
+ if (int forwardCount = this->forwardCount())
+ item = itemAtIndex(forwardCount);
+ } else {
+ if (int backCount = this->backCount())
+ item = itemAtIndex(-backCount);
+ }
+ }
+
+ if (!item)
+ return;
+
+ m_page.goToItem(*item, FrameLoadType::IndexedBackForward);
}
bool BackForwardController::goBack()
{
- return m_page->goBack();
+ HistoryItem* item = backItem();
+ if (!item)
+ return false;
+
+ m_page.goToItem(*item, FrameLoadType::Back);
+ return true;
}
bool BackForwardController::goForward()
{
- return m_page->goForward();
+ HistoryItem* item = forwardItem();
+ if (!item)
+ return false;
+
+ m_page.goToItem(*item, FrameLoadType::Forward);
+ return true;
}
-void BackForwardController::addItem(PassRefPtr<HistoryItem> item)
+void BackForwardController::addItem(Ref<HistoryItem>&& item)
{
- m_client->addItem(item);
+ m_client->addItem(WTFMove(item));
}
void BackForwardController::setCurrentItem(HistoryItem* item)
@@ -81,7 +109,7 @@ void BackForwardController::setCurrentItem(HistoryItem* item)
int BackForwardController::count() const
{
- return m_page->getHistoryLength();
+ return m_client->backListCount() + 1 + m_client->forwardListCount();
}
int BackForwardController::backCount() const
@@ -99,11 +127,6 @@ HistoryItem* BackForwardController::itemAtIndex(int i)
return m_client->itemAtIndex(i);
}
-bool BackForwardController::isActive()
-{
- return m_client->isActive();
-}
-
void BackForwardController::close()
{
m_client->close();
diff --git a/Source/WebCore/history/BackForwardController.h b/Source/WebCore/history/BackForwardController.h
index aa2b2f8df..5a24f8ede 100644
--- a/Source/WebCore/history/BackForwardController.h
+++ b/Source/WebCore/history/BackForwardController.h
@@ -32,35 +32,32 @@
namespace WebCore {
-class BackForwardList;
+class BackForwardClient;
class HistoryItem;
class Page;
class BackForwardController {
WTF_MAKE_NONCOPYABLE(BackForwardController); WTF_MAKE_FAST_ALLOCATED;
public:
+ BackForwardController(Page&, RefPtr<BackForwardClient>&&);
~BackForwardController();
- static PassOwnPtr<BackForwardController> create(Page*, PassRefPtr<BackForwardList>);
+ BackForwardClient* client() const { return m_client.get(); }
- BackForwardList* client() const { return m_client.get(); }
-
- bool canGoBackOrForward(int distance) const;
+ WEBCORE_EXPORT bool canGoBackOrForward(int distance) const;
void goBackOrForward(int distance);
- bool goBack();
- bool goForward();
+ WEBCORE_EXPORT bool goBack();
+ WEBCORE_EXPORT bool goForward();
- void addItem(PassRefPtr<HistoryItem>);
+ void addItem(Ref<HistoryItem>&&);
void setCurrentItem(HistoryItem*);
int count() const;
- int backCount() const;
- int forwardCount() const;
-
- HistoryItem* itemAtIndex(int);
+ WEBCORE_EXPORT int backCount() const;
+ WEBCORE_EXPORT int forwardCount() const;
- bool isActive();
+ WEBCORE_EXPORT HistoryItem* itemAtIndex(int);
void close();
@@ -69,10 +66,8 @@ public:
HistoryItem* forwardItem() { return itemAtIndex(1); }
private:
- BackForwardController(Page*, PassRefPtr<BackForwardList>);
-
- Page* m_page;
- RefPtr<BackForwardList> m_client;
+ Page& m_page;
+ RefPtr<BackForwardClient> m_client;
};
} // namespace WebCore
diff --git a/Source/WebCore/history/BackForwardListImpl.cpp b/Source/WebCore/history/BackForwardList.cpp
index 05b2a0edf..5a378d75d 100644
--- a/Source/WebCore/history/BackForwardListImpl.cpp
+++ b/Source/WebCore/history/BackForwardList.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2005, 2006 Apple 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
@@ -11,10 +11,10 @@
* 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
+ * 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 COMPUTER, INC. OR
+ * 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
@@ -25,7 +25,7 @@
*/
#include "config.h"
-#include "BackForwardListImpl.h"
+#include "BackForwardList.h"
#include "Frame.h"
#include "FrameLoader.h"
@@ -36,14 +36,12 @@
#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)
+BackForwardList::BackForwardList(Page* page)
: m_page(page)
, m_current(NoCurrentItemIndex)
, m_capacity(DefaultCapacity)
@@ -52,44 +50,42 @@ BackForwardListImpl::BackForwardListImpl(Page* page)
{
}
-BackForwardListImpl::~BackForwardListImpl()
+BackForwardList::~BackForwardList()
{
ASSERT(m_closed);
}
-void BackForwardListImpl::addItem(PassRefPtr<HistoryItem> prpItem)
+void BackForwardList::addItem(Ref<HistoryItem>&& newItem)
{
- ASSERT(prpItem);
- if (m_capacity == 0 || !m_enabled)
+ if (!m_capacity || !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());
+ Ref<HistoryItem> item = m_entries.takeLast();
+ m_entryHash.remove(item.ptr());
+ PageCache::singleton().remove(item);
}
}
// 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];
+ if (m_entries.size() == m_capacity && (m_current || m_capacity == 1)) {
+ Ref<HistoryItem> item = WTFMove(m_entries[0]);
m_entries.remove(0);
- m_entryHash.remove(item);
- pageCache()->remove(item.get());
- m_current--;
+ m_entryHash.remove(item.ptr());
+ PageCache::singleton().remove(item);
+ --m_current;
}
- m_entryHash.add(prpItem.get());
- m_entries.insert(m_current + 1, prpItem);
- m_current++;
+ m_entryHash.add(newItem.ptr());
+ m_entries.insert(m_current + 1, WTFMove(newItem));
+ ++m_current;
}
-void BackForwardListImpl::goBack()
+void BackForwardList::goBack()
{
ASSERT(m_current > 0);
if (m_current > 0) {
@@ -97,7 +93,7 @@ void BackForwardListImpl::goBack()
}
}
-void BackForwardListImpl::goForward()
+void BackForwardList::goForward()
{
ASSERT(m_current < m_entries.size() - 1);
if (m_current < m_entries.size() - 1) {
@@ -105,52 +101,52 @@ void BackForwardListImpl::goForward()
}
}
-void BackForwardListImpl::goToItem(HistoryItem* item)
+void BackForwardList::goToItem(HistoryItem* item)
{
if (!m_entries.size() || !item)
return;
unsigned int index = 0;
for (; index < m_entries.size(); ++index)
- if (m_entries[index] == item)
+ if (m_entries[index].ptr() == item)
break;
if (index < m_entries.size()) {
m_current = index;
}
}
-HistoryItem* BackForwardListImpl::backItem()
+HistoryItem* BackForwardList::backItem()
{
if (m_current && m_current != NoCurrentItemIndex)
- return m_entries[m_current - 1].get();
- return 0;
+ return m_entries[m_current - 1].ptr();
+ return nullptr;
}
-HistoryItem* BackForwardListImpl::currentItem()
+HistoryItem* BackForwardList::currentItem()
{
if (m_current != NoCurrentItemIndex)
- return m_entries[m_current].get();
- return 0;
+ return m_entries[m_current].ptr();
+ return nullptr;
}
-HistoryItem* BackForwardListImpl::forwardItem()
+HistoryItem* BackForwardList::forwardItem()
{
if (m_entries.size() && m_current < m_entries.size() - 1)
- return m_entries[m_current + 1].get();
- return 0;
+ return m_entries[m_current + 1].ptr();
+ return nullptr;
}
-void BackForwardListImpl::backListWithLimit(int limit, HistoryItemVector& list)
+void BackForwardList::backListWithLimit(int limit, HistoryItemVector& list)
{
list.clear();
if (m_current != NoCurrentItemIndex) {
- unsigned first = max((int)m_current - limit, 0);
+ unsigned first = std::max(static_cast<int>(m_current) - limit, 0);
for (; first < m_current; ++first)
- list.append(m_entries[first]);
+ list.append(m_entries[first].get());
}
}
-void BackForwardListImpl::forwardListWithLimit(int limit, HistoryItemVector& list)
+void BackForwardList::forwardListWithLimit(int limit, HistoryItemVector& list)
{
ASSERT(limit > -1);
list.clear();
@@ -159,25 +155,24 @@ void BackForwardListImpl::forwardListWithLimit(int limit, HistoryItemVector& lis
unsigned lastEntry = m_entries.size() - 1;
if (m_current < lastEntry) {
- int last = min(m_current + limit, lastEntry);
+ int last = std::min(m_current + limit, lastEntry);
limit = m_current + 1;
for (; limit <= last; ++limit)
- list.append(m_entries[limit]);
+ list.append(m_entries[limit].get());
}
}
-int BackForwardListImpl::capacity()
+int BackForwardList::capacity()
{
return m_capacity;
}
-void BackForwardListImpl::setCapacity(int size)
+void BackForwardList::setCapacity(int size)
{
- while (size < (int)m_entries.size()) {
- RefPtr<HistoryItem> item = m_entries.last();
- m_entries.removeLast();
- m_entryHash.remove(item);
- pageCache()->remove(item.get());
+ while (size < static_cast<int>(m_entries.size())) {
+ Ref<HistoryItem> item = m_entries.takeLast();
+ m_entryHash.remove(item.ptr());
+ PageCache::singleton().remove(item);
}
if (!size)
@@ -188,12 +183,12 @@ void BackForwardListImpl::setCapacity(int size)
m_capacity = size;
}
-bool BackForwardListImpl::enabled()
+bool BackForwardList::enabled()
{
return m_enabled;
}
-void BackForwardListImpl::setEnabled(bool enabled)
+void BackForwardList::setEnabled(bool enabled)
{
m_enabled = enabled;
if (!enabled) {
@@ -203,56 +198,79 @@ void BackForwardListImpl::setEnabled(bool enabled)
}
}
-int BackForwardListImpl::backListCount()
+int BackForwardList::backListCount()
{
return m_current == NoCurrentItemIndex ? 0 : m_current;
}
-int BackForwardListImpl::forwardListCount()
+int BackForwardList::forwardListCount()
{
return m_current == NoCurrentItemIndex ? 0 : (int)m_entries.size() - (m_current + 1);
}
-HistoryItem* BackForwardListImpl::itemAtIndex(int index)
+HistoryItem* BackForwardList::itemAtIndex(int index)
{
// Do range checks without doing math on index to avoid overflow.
- if (index < -(int)m_current)
- return 0;
+ if (index < -static_cast<int>(m_current))
+ return nullptr;
if (index > forwardListCount())
- return 0;
+ return nullptr;
- return m_entries[index + m_current].get();
+ return m_entries[index + m_current].ptr();
}
-HistoryItemVector& BackForwardListImpl::entries()
+HistoryItemVector& BackForwardList::entries()
{
return m_entries;
}
-void BackForwardListImpl::close()
+#if PLATFORM(IOS)
+unsigned BackForwardList::current()
+{
+ return m_current;
+}
+
+void BackForwardList::setCurrent(unsigned newCurrent)
{
- int size = m_entries.size();
- for (int i = 0; i < size; ++i)
- pageCache()->remove(m_entries[i].get());
+ m_current = newCurrent;
+}
+
+bool BackForwardList::clearAllPageCaches()
+{
+ bool didRemoveAtLeastOneItem = false;
+ for (auto& item : m_entries) {
+ if (item->isInPageCache()) {
+ didRemoveAtLeastOneItem = true;
+ PageCache::singleton().remove(item);
+ }
+ }
+ return didRemoveAtLeastOneItem;
+}
+#endif
+
+void BackForwardList::close()
+{
+ for (auto& item : m_entries)
+ PageCache::singleton().remove(item);
m_entries.clear();
m_entryHash.clear();
- m_page = 0;
+ m_page = nullptr;
m_closed = true;
}
-bool BackForwardListImpl::closed()
+bool BackForwardList::closed()
{
return m_closed;
}
-void BackForwardListImpl::removeItem(HistoryItem* item)
+void BackForwardList::removeItem(HistoryItem* item)
{
if (!item)
return;
- for (unsigned i = 0; i < m_entries.size(); ++i)
- if (m_entries[i] == item) {
+ for (unsigned i = 0; i < m_entries.size(); ++i) {
+ if (m_entries[i].ptr() == item) {
m_entries.remove(i);
m_entryHash.remove(item);
if (m_current == NoCurrentItemIndex || m_current < i)
@@ -266,9 +284,10 @@ void BackForwardListImpl::removeItem(HistoryItem* item)
}
break;
}
+ }
}
-bool BackForwardListImpl::containsItem(HistoryItem* entry)
+bool BackForwardList::containsItem(HistoryItem* entry)
{
return m_entryHash.contains(entry);
}
diff --git a/Source/WebCore/history/BackForwardList.h b/Source/WebCore/history/BackForwardList.h
index 3f2881963..59292760c 100644
--- a/Source/WebCore/history/BackForwardList.h
+++ b/Source/WebCore/history/BackForwardList.h
@@ -12,10 +12,10 @@
* 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
+ * 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 COMPUTER, INC. OR
+ * 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
@@ -28,40 +28,70 @@
#ifndef BackForwardList_h
#define BackForwardList_h
-#include <wtf/Forward.h>
-#include <wtf/RefCounted.h>
+#include "BackForwardClient.h"
+#include <wtf/HashSet.h>
+#include <wtf/Vector.h>
namespace WebCore {
-class HistoryItem;
+class Page;
-// FIXME: Rename this class to BackForwardClient, and rename the
-// getter in Page accordingly.
-class BackForwardList : public RefCounted<BackForwardList> {
+typedef Vector<Ref<HistoryItem>> HistoryItemVector;
+typedef HashSet<RefPtr<HistoryItem>> HistoryItemHashSet;
+
+class BackForwardList : public BackForwardClient {
public:
- virtual ~BackForwardList()
- {
- }
+ static Ref<BackForwardList> create(Page* page) { return adoptRef(*new BackForwardList(page)); }
+ virtual ~BackForwardList();
- virtual void addItem(PassRefPtr<HistoryItem>) = 0;
+ Page* page() { return m_page; }
- virtual void goToItem(HistoryItem*) = 0;
+ virtual void addItem(Ref<HistoryItem>&&) override;
+ WEBCORE_EXPORT void goBack();
+ WEBCORE_EXPORT void goForward();
+ virtual void goToItem(HistoryItem*) override;
- virtual HistoryItem* itemAtIndex(int) = 0;
- virtual int backListCount() = 0;
- virtual int forwardListCount() = 0;
+ WEBCORE_EXPORT HistoryItem* backItem();
+ WEBCORE_EXPORT HistoryItem* currentItem();
+ WEBCORE_EXPORT HistoryItem* forwardItem();
+ virtual HistoryItem* itemAtIndex(int) override;
- virtual bool isActive() = 0;
+ WEBCORE_EXPORT void backListWithLimit(int, HistoryItemVector&);
+ WEBCORE_EXPORT void forwardListWithLimit(int, HistoryItemVector&);
- virtual void close() = 0;
+ WEBCORE_EXPORT int capacity();
+ WEBCORE_EXPORT void setCapacity(int);
+ WEBCORE_EXPORT bool enabled();
+ WEBCORE_EXPORT void setEnabled(bool);
+ virtual int backListCount() override;
+ virtual int forwardListCount() override;
+ WEBCORE_EXPORT bool containsItem(HistoryItem*);
- // 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); }
-};
+ virtual void close() override;
+ WEBCORE_EXPORT bool closed();
+
+ WEBCORE_EXPORT void removeItem(HistoryItem*);
+ WEBCORE_EXPORT HistoryItemVector& entries();
+
+#if PLATFORM(IOS)
+ virtual unsigned current() override;
+ virtual void setCurrent(unsigned newCurrent) override;
+ virtual bool clearAllPageCaches() override;
+#endif
+
+private:
+ WEBCORE_EXPORT explicit BackForwardList(Page*);
+
+ Page* m_page;
+ HistoryItemVector m_entries;
+ HistoryItemHashSet m_entryHash;
+ unsigned m_current;
+ unsigned m_capacity;
+ bool m_closed;
+ bool m_enabled;
+};
+
} // namespace WebCore
#endif // BackForwardList_h
diff --git a/Source/WebCore/history/BackForwardListImpl.h b/Source/WebCore/history/BackForwardListImpl.h
deleted file mode 100644
index 167912af5..000000000
--- a/Source/WebCore/history/BackForwardListImpl.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * 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: 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();
-
- 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();
-
-private:
- explicit BackForwardListImpl(Page*);
-
- virtual bool isActive() { return enabled() && capacity(); }
-
- Page* m_page;
- HistoryItemVector m_entries;
- HistoryItemHashSet m_entryHash;
- unsigned m_current;
- 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
index d3d7cb0d0..29dbe9a59 100644
--- a/Source/WebCore/history/CachedFrame.cpp
+++ b/Source/WebCore/history/CachedFrame.cpp
@@ -10,10 +10,10 @@
* 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
+ * 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 COMPUTER, INC. OR
+ * 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
@@ -31,64 +31,47 @@
#include "DOMWindow.h"
#include "Document.h"
#include "DocumentLoader.h"
-#include "EventHandler.h"
#include "EventNames.h"
#include "ExceptionCode.h"
-#include "FocusController.h"
-#include "Frame.h"
#include "FrameLoader.h"
#include "FrameLoaderClient.h"
#include "FrameView.h"
#include "HistoryController.h"
#include "HistoryItem.h"
#include "Logging.h"
+#include "MainFrame.h"
#include "Page.h"
+#include "PageCache.h"
#include "PageTransitionEvent.h"
+#include "SVGDocumentExtensions.h"
#include "ScriptController.h"
#include "SerializedScriptValue.h"
#include <wtf/RefCountedLeakCounter.h>
#include <wtf/text/CString.h>
-#if ENABLE(SVG)
-#include "SVGDocumentExtensions.h"
-#endif
-
-#if ENABLE(TOUCH_EVENTS)
+#if PLATFORM(IOS) || ENABLE(TOUCH_EVENTS)
#include "Chrome.h"
#include "ChromeClient.h"
#endif
-#if USE(ACCELERATED_COMPOSITING)
-#include "PageCache.h"
-#endif
-
namespace WebCore {
-#ifndef NDEBUG
-static WTF::RefCountedLeakCounter& cachedFrameCounter()
-{
- DEFINE_STATIC_LOCAL(WTF::RefCountedLeakCounter, counter, ("CachedFrame"));
- return counter;
-}
-#endif
+DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, cachedFrameCounter, ("CachedFrame"));
-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->document()->url())
- , m_isMainFrame(!frame->tree()->parent())
-#if USE(ACCELERATED_COMPOSITING)
- , m_isComposited(frame->view()->hasCompositedContent())
-#endif
+CachedFrameBase::CachedFrameBase(Frame& frame)
+ : m_document(frame.document())
+ , m_documentLoader(frame.loader().documentLoader())
+ , m_view(frame.view())
+ , m_url(frame.document()->url())
+ , m_isMainFrame(!frame.tree().parent())
+ , m_isComposited(frame.view()->hasCompositedContent())
{
}
CachedFrameBase::~CachedFrameBase()
{
#ifndef NDEBUG
- cachedFrameCounter().decrement();
+ cachedFrameCounter.decrement();
#endif
// CachedFrames should always have had destroy() called by their parent CachedPage
ASSERT(!m_document);
@@ -101,109 +84,103 @@ void CachedFrameBase::restore()
if (m_isMainFrame)
m_view->setParentVisible(true);
- Frame* frame = m_view->frame();
+ Frame& frame = m_view->frame();
m_cachedFrameScriptData->restore(frame);
-#if ENABLE(SVG)
if (m_document->svgExtensions())
- m_document->accessSVGExtensions()->unpauseAnimations();
-#endif
+ m_document->accessSVGExtensions().unpauseAnimations();
+
+ frame.animation().resumeAnimationsForDocument(m_document.get());
- frame->animation()->resumeAnimationsForDocument(m_document.get());
- frame->eventHandler()->setMousePressNode(m_mousePressNode.get());
- m_document->resumeActiveDOMObjects(ActiveDOMObject::DocumentWillBecomeInactive);
- m_document->resumeScriptedAnimationControllerCallbacks();
+ m_document->resume(ActiveDOMObject::PageCache);
// It is necessary to update any platform script objects after restoring the
// cached page.
- frame->script()->updatePlatformScriptObjects();
+ frame.script().updatePlatformScriptObjects();
-#if USE(ACCELERATED_COMPOSITING)
if (m_isComposited)
- frame->view()->restoreBackingStores();
-#endif
-
- frame->loader()->client()->didRestoreFromPageCache();
+ frame.view()->restoreBackingStores();
- // Reconstruct the FrameTree
- for (unsigned i = 0; i < m_childFrames.size(); ++i)
- frame->tree()->appendChild(m_childFrames[i]->view()->frame());
+ frame.loader().client().didRestoreFromPageCache();
- // Open the child CachedFrames in their respective FrameLoaders.
- for (unsigned i = 0; i < m_childFrames.size(); ++i)
+ // Reconstruct the FrameTree. And open the child CachedFrames in their respective FrameLoaders.
+ for (unsigned i = 0; i < m_childFrames.size(); ++i) {
+ frame.tree().appendChild(&m_childFrames[i]->view()->frame());
m_childFrames[i]->open();
+ }
+
+#if PLATFORM(IOS)
+ if (m_isMainFrame) {
+ frame.loader().client().didRestoreFrameHierarchyForCachedFrame();
+
+ if (DOMWindow* domWindow = m_document->domWindow()) {
+ // FIXME: Add SCROLL_LISTENER to the list of event types on Document, and use m_document->hasListenerType(). See <rdar://problem/9615482>.
+ // FIXME: Can use Document::hasListenerType() now.
+ if (domWindow->scrollEventListenerCount() && frame.page())
+ frame.page()->chrome().client().setNeedsScrollNotifications(&frame, true);
+ }
+ }
+#endif
// FIXME: update Page Visibility state here.
// https://bugs.webkit.org/show_bug.cgi?id=116770
-
m_document->enqueuePageshowEvent(PageshowEventPersisted);
-
- HistoryItem* historyItem = frame->loader()->history()->currentItem();
+
+ HistoryItem* historyItem = frame.loader().history().currentItem();
m_document->enqueuePopstateEvent(historyItem && historyItem->stateObject() ? historyItem->stateObject() : SerializedScriptValue::nullValue());
-
-#if ENABLE(TOUCH_EVENTS)
+
+#if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
if (m_document->hasTouchEventHandlers())
- m_document->page()->chrome().client()->needTouchEvents(true);
+ m_document->page()->chrome().client().needTouchEvents(true);
#endif
- m_document->documentDidResumeFromPageCache();
}
-CachedFrame::CachedFrame(Frame* frame)
+CachedFrame::CachedFrame(Frame& frame)
: CachedFrameBase(frame)
{
#ifndef NDEBUG
- cachedFrameCounter().increment();
+ cachedFrameCounter.increment();
#endif
ASSERT(m_document);
ASSERT(m_documentLoader);
ASSERT(m_view);
- if (frame->page()->focusController()->focusedFrame() == frame)
- frame->page()->focusController()->setFocusedFrame(frame->page()->mainFrame());
-
// Custom scrollbar renderers will get reattached when the document comes out of the page cache
m_view->detachCustomScrollbars();
- m_document->setInPageCache(true);
- frame->loader()->stopLoading(UnloadEventPolicyUnloadAndPageHide);
+ ASSERT(m_document->inPageCache());
// 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));
+ for (Frame* child = frame.tree().firstChild(); child; child = child->tree().nextSibling())
+ m_childFrames.append(std::make_unique<CachedFrame>(*child));
- // Active DOM objects must be suspended before we cache the frame script data,
- // but after we've fired the pagehide event, in case that creates more objects.
- // Suspending must also happen after we've recursed over child frames, in case
- // those create more objects.
- m_document->documentWillSuspendForPageCache();
- m_document->suspendScriptedAnimationControllerCallbacks();
- m_document->suspendActiveDOMObjects(ActiveDOMObject::DocumentWillBecomeInactive);
- m_cachedFrameScriptData = adoptPtr(new ScriptCachedFrameData(frame));
+ // Active DOM objects must be suspended before we cache the frame script data.
+ m_document->suspend(ActiveDOMObject::PageCache);
- m_document->domWindow()->suspendForPageCache();
+ m_cachedFrameScriptData = std::make_unique<ScriptCachedFrameData>(frame);
- frame->loader()->client()->savePlatformDataToCachedFrame(this);
+ m_document->domWindow()->suspendForDocumentSuspension();
-#if USE(ACCELERATED_COMPOSITING)
- if (m_isComposited && pageCache()->shouldClearBackingStores())
- frame->view()->clearBackingStores();
-#endif
+ frame.loader().client().savePlatformDataToCachedFrame(this);
+
+ if (m_isComposited && PageCache::singleton().shouldClearBackingStores())
+ frame.view()->clearBackingStores();
// documentWillSuspendForPageCache() can set up a layout timer on the FrameView, so clear timers after that.
- frame->clearTimers();
+ frame.clearTimers();
// 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());
+ frame.tree().removeChild(&m_childFrames[i]->view()->frame());
if (!m_isMainFrame)
- frame->page()->decrementSubframeCount();
+ frame.page()->decrementSubframeCount();
- frame->loader()->client()->didSaveToPageCache();
+ frame.loader().client().didSaveToPageCache();
#ifndef NDEBUG
if (m_isMainFrame)
@@ -212,15 +189,25 @@ CachedFrame::CachedFrame(Frame* frame)
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 PLATFORM(IOS)
+ if (m_isMainFrame) {
+ if (DOMWindow* domWindow = m_document->domWindow()) {
+ if (domWindow->scrollEventListenerCount() && frame.page())
+ frame.page()->chrome().client().setNeedsScrollNotifications(&frame, false);
+ }
+ }
+#endif
+
+ ASSERT_WITH_SECURITY_IMPLICATION(!m_documentLoader->isLoading());
}
void CachedFrame::open()
{
ASSERT(m_view);
- m_view->frame()->loader()->open(*this);
-
if (!m_isMainFrame)
- m_view->frame()->page()->incrementSubframeCount();
+ m_view->frame().page()->incrementSubframeCount();
+
+ m_view->frame().loader().open(*this);
}
void CachedFrame::clear()
@@ -234,18 +221,17 @@ void CachedFrame::clear()
// 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());
+ ASSERT(!m_document->frame() || 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_document = nullptr;
+ m_view = nullptr;
+ m_url = URL();
- m_cachedFramePlatformData.clear();
- m_cachedFrameScriptData.clear();
+ m_cachedFramePlatformData = nullptr;
+ m_cachedFrameScriptData = nullptr;
}
void CachedFrame::destroy()
@@ -256,13 +242,13 @@ void CachedFrame::destroy()
// 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());
+ ASSERT(m_document->frame() == &m_view->frame());
m_document->domWindow()->willDestroyCachedFrame();
if (!m_isMainFrame) {
- m_view->frame()->detachFromPage();
- m_view->frame()->loader()->detachViewsAndDocumentLoader();
+ m_view->frame().detachFromPage();
+ m_view->frame().loader().detachViewsAndDocumentLoader();
}
for (int i = m_childFrames.size() - 1; i >= 0; --i)
@@ -278,16 +264,14 @@ void CachedFrame::destroy()
m_document->removeAllEventListeners();
m_document->setInPageCache(false);
- // FIXME: We don't call willRemove here. Why is that OK?
- m_document->detach();
- m_view->clearFrame();
+ m_document->prepareForDestruction();
clear();
}
-void CachedFrame::setCachedFramePlatformData(PassOwnPtr<CachedFramePlatformData> data)
+void CachedFrame::setCachedFramePlatformData(std::unique_ptr<CachedFramePlatformData> data)
{
- m_cachedFramePlatformData = data;
+ m_cachedFramePlatformData = WTFMove(data);
}
CachedFramePlatformData* CachedFrame::cachedFramePlatformData()
diff --git a/Source/WebCore/history/CachedFrame.h b/Source/WebCore/history/CachedFrame.h
index 463fa7f8b..e65e60992 100644
--- a/Source/WebCore/history/CachedFrame.h
+++ b/Source/WebCore/history/CachedFrame.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2010, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* 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
+ * 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 COMPUTER, INC. OR
+ * 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
@@ -27,10 +27,8 @@
#define CachedFrame_h
#include "DOMWindow.h"
-#include "KURL.h"
+#include "URL.h"
#include "ScriptCachedFrameData.h"
-#include <wtf/PassOwnPtr.h>
-#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
namespace WebCore {
@@ -42,57 +40,49 @@ 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; }
+ const URL& url() const { return m_url; }
bool isMainFrame() { return m_isMainFrame; }
protected:
- CachedFrameBase(Frame*);
+ 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;
+ URL m_url;
+ std::unique_ptr<ScriptCachedFrameData> m_cachedFrameScriptData;
+ std::unique_ptr<CachedFramePlatformData> m_cachedFramePlatformData;
bool m_isMainFrame;
-#if USE(ACCELERATED_COMPOSITING)
bool m_isComposited;
-#endif
- CachedFrameVector m_childFrames;
+ Vector<std::unique_ptr<CachedFrame>> m_childFrames;
};
-class CachedFrame : public RefCounted<CachedFrame>, private CachedFrameBase {
+class CachedFrame : private CachedFrameBase {
+ WTF_MAKE_FAST_ALLOCATED;
public:
- static PassRefPtr<CachedFrame> create(Frame* frame) { return adoptRef(new CachedFrame(frame)); }
+ explicit CachedFrame(Frame&);
void open();
void clear();
void destroy();
- void setCachedFramePlatformData(PassOwnPtr<CachedFramePlatformData>);
- CachedFramePlatformData* cachedFramePlatformData();
+ WEBCORE_EXPORT void setCachedFramePlatformData(std::unique_ptr<CachedFramePlatformData>);
+ WEBCORE_EXPORT 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:
- explicit CachedFrame(Frame*);
};
} // namespace WebCore
diff --git a/Source/WebCore/history/CachedFramePlatformData.h b/Source/WebCore/history/CachedFramePlatformData.h
index 01da8e5a6..5ae7be57d 100644
--- a/Source/WebCore/history/CachedFramePlatformData.h
+++ b/Source/WebCore/history/CachedFramePlatformData.h
@@ -10,7 +10,7 @@
* 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
+ * 3. Neither the name of Apple 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.
*
diff --git a/Source/WebCore/history/CachedPage.cpp b/Source/WebCore/history/CachedPage.cpp
index 61a06da78..d4ff648e2 100644
--- a/Source/WebCore/history/CachedPage.cpp
+++ b/Source/WebCore/history/CachedPage.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008, 2014 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* 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
+ * 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 COMPUTER, INC. OR
+ * 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
@@ -29,8 +29,8 @@
#include "Document.h"
#include "Element.h"
#include "FocusController.h"
-#include "Frame.h"
#include "FrameView.h"
+#include "MainFrame.h"
#include "Node.h"
#include "Page.h"
#include "Settings.h"
@@ -39,25 +39,19 @@
#include <wtf/RefCountedLeakCounter.h>
#include <wtf/StdLibExtras.h>
+#if PLATFORM(IOS)
+#include "FrameSelection.h"
+#endif
+
using namespace JSC;
namespace WebCore {
DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, cachedPageCounter, ("CachedPage"));
-PassRefPtr<CachedPage> CachedPage::create(Page* page)
-{
- return adoptRef(new CachedPage(page));
-}
-
-CachedPage::CachedPage(Page* page)
- : m_timeStamp(currentTime())
- , m_expirationTime(m_timeStamp + page->settings()->backForwardCacheExpirationInterval())
- , m_cachedMainFrame(CachedFrame::create(page->mainFrame()))
- , m_needStyleRecalcForVisitedLinks(false)
- , m_needsFullStyleRecalc(false)
- , m_needsCaptionPreferencesChanged(false)
- , m_needsDeviceScaleChanged(false)
+CachedPage::CachedPage(Page& page)
+ : m_expirationTime(monotonicallyIncreasingTime() + page.settings().backForwardCacheExpirationInterval())
+ , m_cachedMainFrame(std::make_unique<CachedFrame>(page.mainFrame()))
{
#ifndef NDEBUG
cachedPageCounter.increment();
@@ -70,44 +64,57 @@ CachedPage::~CachedPage()
cachedPageCounter.decrement();
#endif
- destroy();
- ASSERT(!m_cachedMainFrame);
+ if (m_cachedMainFrame)
+ m_cachedMainFrame->destroy();
}
-void CachedPage::restore(Page* page)
+void CachedPage::restore(Page& page)
{
ASSERT(m_cachedMainFrame);
- ASSERT(page && page->mainFrame() && page->mainFrame() == m_cachedMainFrame->view()->frame());
- ASSERT(!page->subframeCount());
+ ASSERT(m_cachedMainFrame->view()->frame().isMainFrame());
+ ASSERT(!page.subframeCount());
+
+ page.setNeedsRecalcStyleInAllFrames();
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 (Element* element = focusedDocument->focusedElement())
- element->updateFocusAppearance(true);
-
- if (m_needStyleRecalcForVisitedLinks) {
- for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext())
- frame->document()->visitedLinkState()->invalidateStyleForAllLinks();
- }
-
-#if USE(ACCELERATED_COMPOSITING)
- if (m_needsDeviceScaleChanged) {
- if (Frame* frame = page->mainFrame())
- frame->deviceOrPageScaleFactorChanged();
- }
+ Document* focusedDocument = page.focusController().focusedOrMainFrame().document();
+ if (Element* element = focusedDocument->focusedElement()) {
+#if PLATFORM(IOS)
+ // We don't want focused nodes changing scroll position when restoring from the cache
+ // as it can cause ugly jumps before we manage to restore the cached position.
+ page.mainFrame().selection().suppressScrolling();
+
+ bool hadProhibitsScrolling = false;
+ FrameView* frameView = page.mainFrame().view();
+ if (frameView) {
+ hadProhibitsScrolling = frameView->prohibitsScrolling();
+ frameView->setProhibitsScrolling(true);
+ }
#endif
+ element->updateFocusAppearance(SelectionRestorationMode::Restore);
+#if PLATFORM(IOS)
+ if (frameView)
+ frameView->setProhibitsScrolling(hadProhibitsScrolling);
+ page.mainFrame().selection().restoreScrolling();
+#endif
+ }
- if (m_needsFullStyleRecalc)
- page->setNeedsRecalcStyleInAllFrames();
+ if (m_needsDeviceOrPageScaleChanged)
+ page.mainFrame().deviceOrPageScaleFactorChanged();
#if ENABLE(VIDEO_TRACK)
if (m_needsCaptionPreferencesChanged)
- page->captionPreferencesChanged();
+ page.captionPreferencesChanged();
#endif
+ if (m_needsUpdateContentsSize) {
+ if (FrameView* frameView = page.mainFrame().view())
+ frameView->updateContentsSize();
+ }
+
clear();
}
@@ -115,22 +122,17 @@ void CachedPage::clear()
{
ASSERT(m_cachedMainFrame);
m_cachedMainFrame->clear();
- m_cachedMainFrame = 0;
- m_needStyleRecalcForVisitedLinks = false;
- m_needsFullStyleRecalc = false;
-}
-
-void CachedPage::destroy()
-{
- if (m_cachedMainFrame)
- m_cachedMainFrame->destroy();
-
- m_cachedMainFrame = 0;
+ m_cachedMainFrame = nullptr;
+#if ENABLE(VIDEO_TRACK)
+ m_needsCaptionPreferencesChanged = false;
+#endif
+ m_needsDeviceOrPageScaleChanged = false;
+ m_needsUpdateContentsSize = false;
}
bool CachedPage::hasExpired() const
{
- return currentTime() > m_expirationTime;
+ return monotonicallyIncreasingTime() > m_expirationTime;
}
} // namespace WebCore
diff --git a/Source/WebCore/history/CachedPage.h b/Source/WebCore/history/CachedPage.h
index c804efc8b..c082bc498 100644
--- a/Source/WebCore/history/CachedPage.h
+++ b/Source/WebCore/history/CachedPage.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* 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
+ * 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 COMPUTER, INC. OR
+ * 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
@@ -27,51 +27,45 @@
#define CachedPage_h
#include "CachedFrame.h"
-#include <wtf/RefCounted.h>
namespace WebCore {
-
+
class Document;
class DocumentLoader;
class Page;
-class CachedPage : public RefCounted<CachedPage> {
+class CachedPage {
+ WTF_MAKE_FAST_ALLOCATED;
public:
- static PassRefPtr<CachedPage> create(Page*);
+ explicit CachedPage(Page&);
~CachedPage();
- void restore(Page*);
+ 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; }
bool hasExpired() const;
CachedFrame* cachedMainFrame() { return m_cachedMainFrame.get(); }
- void markForVistedLinkStyleRecalc() { m_needStyleRecalcForVisitedLinks = true; }
- void markForFullStyleRecalc() { m_needsFullStyleRecalc = true; }
#if ENABLE(VIDEO_TRACK)
void markForCaptionPreferencesChanged() { m_needsCaptionPreferencesChanged = true; }
#endif
-#if USE(ACCELERATED_COMPOSITING)
- void markForDeviceScaleChanged() { m_needsDeviceScaleChanged = true; }
-#endif
+ void markForDeviceOrPageScaleChanged() { m_needsDeviceOrPageScaleChanged = true; }
-private:
- CachedPage(Page*);
+ void markForContentsSizeChanged() { m_needsUpdateContentsSize = true; }
- double m_timeStamp;
+private:
double m_expirationTime;
- RefPtr<CachedFrame> m_cachedMainFrame;
- bool m_needStyleRecalcForVisitedLinks;
- bool m_needsFullStyleRecalc;
- bool m_needsCaptionPreferencesChanged;
- bool m_needsDeviceScaleChanged;
+ std::unique_ptr<CachedFrame> m_cachedMainFrame;
+#if ENABLE(VIDEO_TRACK)
+ bool m_needsCaptionPreferencesChanged { false };
+#endif
+ bool m_needsDeviceOrPageScaleChanged { false };
+ bool m_needsUpdateContentsSize { false };
};
} // namespace WebCore
diff --git a/Source/WebCore/history/HistoryItem.cpp b/Source/WebCore/history/HistoryItem.cpp
index a389c0328..26bb7906f 100644
--- a/Source/WebCore/history/HistoryItem.cpp
+++ b/Source/WebCore/history/HistoryItem.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005, 2006, 2008, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2006, 2008, 2011, 2014 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* 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
+ * 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 COMPUTER, INC. OR
+ * 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
@@ -29,20 +29,18 @@
#include "CachedPage.h"
#include "Document.h"
#include "IconDatabase.h"
+#include "KeyedCoding.h"
#include "PageCache.h"
#include "ResourceRequest.h"
#include "SerializedScriptValue.h"
#include "SharedBuffer.h"
#include <stdio.h>
#include <wtf/CurrentTime.h>
-#include <wtf/Decoder.h>
-#include <wtf/Encoder.h>
+#include <wtf/DateMath.h>
#include <wtf/text/CString.h>
namespace WebCore {
-const uint32_t backForwardTreeEncodingVersion = 2;
-
static long long generateSequenceNumber()
{
// Initialize to the current time to reduce the likelihood of generating
@@ -55,79 +53,62 @@ static void defaultNotifyHistoryItemChanged(HistoryItem*)
{
}
-void (*notifyHistoryItemChanged)(HistoryItem*) = defaultNotifyHistoryItemChanged;
+WEBCORE_EXPORT void (*notifyHistoryItemChanged)(HistoryItem*) = defaultNotifyHistoryItemChanged;
HistoryItem::HistoryItem()
- : m_lastVisitedTime(0)
- , m_lastVisitWasHTTPNonGet(false)
- , m_pageScaleFactor(0)
+ : m_pageScaleFactor(0)
, m_lastVisitWasFailure(false)
, m_isTargetItem(false)
- , m_visitCount(0)
, m_itemSequenceNumber(generateSequenceNumber())
, m_documentSequenceNumber(generateSequenceNumber())
- , m_next(0)
- , m_prev(0)
+ , m_pruningReason(PruningReason::None)
+#if PLATFORM(IOS)
+ , m_scale(0)
+ , m_scaleIsInitial(false)
+ , m_bookmarkID(0)
+#endif
{
}
-HistoryItem::HistoryItem(const String& urlString, const String& title, double time)
+HistoryItem::HistoryItem(const String& urlString, const String& title)
: m_urlString(urlString)
, m_originalURLString(urlString)
, m_title(title)
- , m_lastVisitedTime(time)
- , m_lastVisitWasHTTPNonGet(false)
, m_pageScaleFactor(0)
, m_lastVisitWasFailure(false)
, m_isTargetItem(false)
- , m_visitCount(0)
, m_itemSequenceNumber(generateSequenceNumber())
, m_documentSequenceNumber(generateSequenceNumber())
- , m_next(0)
- , m_prev(0)
+ , m_pruningReason(PruningReason::None)
+#if PLATFORM(IOS)
+ , m_scale(0)
+ , m_scaleIsInitial(false)
+ , m_bookmarkID(0)
+#endif
{
iconDatabase().retainIconForPageURL(m_urlString);
}
-HistoryItem::HistoryItem(const String& urlString, const String& title, const String& alternateTitle, double time)
+HistoryItem::HistoryItem(const String& urlString, const String& title, const String& alternateTitle)
: m_urlString(urlString)
, m_originalURLString(urlString)
, m_title(title)
, m_displayTitle(alternateTitle)
- , m_lastVisitedTime(time)
- , m_lastVisitWasHTTPNonGet(false)
, m_pageScaleFactor(0)
, m_lastVisitWasFailure(false)
, m_isTargetItem(false)
- , m_visitCount(0)
, m_itemSequenceNumber(generateSequenceNumber())
, m_documentSequenceNumber(generateSequenceNumber())
- , m_next(0)
- , m_prev(0)
+ , m_pruningReason(PruningReason::None)
+#if PLATFORM(IOS)
+ , m_scale(0)
+ , m_scaleIsInitial(false)
+ , m_bookmarkID(0)
+#endif
{
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_pageScaleFactor(0)
- , m_lastVisitWasFailure(false)
- , m_isTargetItem(false)
- , m_visitCount(0)
- , m_itemSequenceNumber(generateSequenceNumber())
- , m_documentSequenceNumber(generateSequenceNumber())
- , m_next(0)
- , m_prev(0)
-{
- iconDatabase().retainIconForPageURL(m_urlString);
-}
-
HistoryItem::~HistoryItem()
{
ASSERT(!m_cachedPage);
@@ -140,21 +121,22 @@ inline HistoryItem::HistoryItem(const HistoryItem& item)
, 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_scrollPosition(item.m_scrollPosition)
, m_pageScaleFactor(item.m_pageScaleFactor)
, 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)
+ , m_pruningReason(PruningReason::None)
+#if PLATFORM(IOS)
+ , m_scale(item.m_scale)
+ , m_scaleIsInitial(item.m_scaleIsInitial)
+ , m_bookmarkID(item.m_bookmarkID)
+ , m_sharedLinkUniqueIdentifier(item.m_sharedLinkUniqueIdentifier)
+#endif
{
if (item.m_formData)
m_formData = item.m_formData->copy();
@@ -165,12 +147,12 @@ inline HistoryItem::HistoryItem(const HistoryItem& item)
m_children.uncheckedAppend(item.m_children[i]->copy());
if (item.m_redirectURLs)
- m_redirectURLs = adoptPtr(new Vector<String>(*item.m_redirectURLs));
+ m_redirectURLs = std::make_unique<Vector<String>>(*item.m_redirectURLs);
}
-PassRefPtr<HistoryItem> HistoryItem::copy() const
+Ref<HistoryItem> HistoryItem::copy() const
{
- return adoptRef(new HistoryItem(*this));
+ return adoptRef(*new HistoryItem(*this));
}
void HistoryItem::reset()
@@ -181,27 +163,20 @@ void HistoryItem::reset()
m_originalURLString = String();
m_referrer = String();
m_target = String();
- m_parent = String();
m_title = String();
m_displayTitle = String();
- m_lastVisitedTime = 0;
- m_lastVisitWasHTTPNonGet = false;
-
m_lastVisitWasFailure = false;
m_isTargetItem = false;
- m_visitCount = 0;
- m_dailyVisitCounts.clear();
- m_weeklyVisitCounts.clear();
- m_redirectURLs.clear();
+ m_redirectURLs = nullptr;
m_itemSequenceNumber = generateSequenceNumber();
- m_stateObject = 0;
+ m_stateObject = nullptr;
m_documentSequenceNumber = generateSequenceNumber();
- m_formData = 0;
+ m_formData = nullptr;
m_formContentType = String();
clearChildren();
@@ -234,19 +209,14 @@ bool HistoryItem::hasCachedPageExpired() const
return m_cachedPage ? m_cachedPage->hasExpired() : false;
}
-double HistoryItem::lastVisitedTime() const
+URL HistoryItem::url() const
{
- return m_lastVisitedTime;
+ return URL(ParsedURLString, m_urlString);
}
-KURL HistoryItem::url() const
+URL HistoryItem::originalURL() const
{
- return KURL(ParsedURLString, m_urlString);
-}
-
-KURL HistoryItem::originalURL() const
-{
- return KURL(ParsedURLString, m_originalURLString);
+ return URL(ParsedURLString, m_originalURLString);
}
const String& HistoryItem::referrer() const
@@ -259,11 +229,6 @@ 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;
@@ -281,9 +246,9 @@ void HistoryItem::setURLString(const String& urlString)
notifyHistoryItemChanged(this);
}
-void HistoryItem::setURL(const KURL& url)
+void HistoryItem::setURL(const URL& url)
{
- pageCache()->remove(this);
+ PageCache::singleton().remove(*this);
setURLString(url.string());
clearDocumentState();
}
@@ -312,114 +277,19 @@ void HistoryItem::setTarget(const String& 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.insert(0, m_visitCount);
-
- int daysElapsed = timeToDay(time) - timeToDay(m_lastVisitedTime);
-
- if (daysElapsed < 0)
- daysElapsed = 0;
-
- Vector<int> padding;
- padding.fill(0, daysElapsed);
- m_dailyVisitCounts.insert(0, 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.insert(0, 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)
+const IntPoint& HistoryItem::scrollPosition() const
{
- m_title = title;
- recordVisitAtTime(time, visitCountBehavior);
+ return m_scrollPosition;
}
-int HistoryItem::visitCount() const
+void HistoryItem::setScrollPosition(const IntPoint& position)
{
- return m_visitCount;
+ m_scrollPosition = position;
}
-void HistoryItem::recordInitialVisit()
+void HistoryItem::clearScrollPosition()
{
- 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);
+ m_scrollPosition = IntPoint();
}
float HistoryItem::pageScaleFactor() const
@@ -447,6 +317,16 @@ void HistoryItem::clearDocumentState()
m_documentState.clear();
}
+void HistoryItem::setShouldOpenExternalURLsPolicy(ShouldOpenExternalURLsPolicy policy)
+{
+ m_shouldOpenExternalURLsPolicy = policy;
+}
+
+ShouldOpenExternalURLsPolicy HistoryItem::shouldOpenExternalURLsPolicy() const
+{
+ return m_shouldOpenExternalURLsPolicy;
+}
+
bool HistoryItem::isTargetItem() const
{
return m_isTargetItem;
@@ -457,68 +337,49 @@ void HistoryItem::setIsTargetItem(bool flag)
m_isTargetItem = flag;
}
-void HistoryItem::setStateObject(PassRefPtr<SerializedScriptValue> object)
+void HistoryItem::setStateObject(RefPtr<SerializedScriptValue>&& object)
{
- m_stateObject = object;
+ m_stateObject = WTFMove(object);
}
-void HistoryItem::addChildItem(PassRefPtr<HistoryItem> child)
+void HistoryItem::addChildItem(Ref<HistoryItem>&& child)
{
ASSERT(!childItemWithTarget(child->target()));
- m_children.append(child);
+ m_children.append(WTFMove(child));
}
-void HistoryItem::setChildItem(PassRefPtr<HistoryItem> child)
+void HistoryItem::setChildItem(Ref<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;
+ m_children[i] = WTFMove(child);
return;
}
}
- m_children.append(child);
+ m_children.append(WTFMove(child));
}
-HistoryItem* HistoryItem::childItemWithTarget(const String& target) const
+HistoryItem* HistoryItem::childItemWithTarget(const String& target)
{
unsigned size = m_children.size();
for (unsigned i = 0; i < size; ++i) {
if (m_children[i]->target() == target)
- return m_children[i].get();
+ return m_children[i].ptr();
}
- return 0;
+ return nullptr;
}
-HistoryItem* HistoryItem::childItemWithDocumentSequenceNumber(long long number) const
+HistoryItem* HistoryItem::childItemWithDocumentSequenceNumber(long long number)
{
unsigned size = m_children.size();
for (unsigned i = 0; i < size; ++i) {
if (m_children[i]->documentSequenceNumber() == number)
- return m_children[i].get();
+ return m_children[i].ptr();
}
- 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;
+ return nullptr;
}
const HistoryItemVector& HistoryItem::children() const
@@ -536,13 +397,13 @@ void HistoryItem::clearChildren()
m_children.clear();
}
-bool HistoryItem::isAncestorOf(const HistoryItem* item) const
+bool HistoryItem::isAncestorOf(const HistoryItem& item) const
{
for (size_t i = 0; i < m_children.size(); ++i) {
- HistoryItem* child = m_children[i].get();
- if (child == item)
+ auto& child = m_children[i].get();
+ if (&child == &item)
return true;
- if (child->isAncestorOf(item))
+ if (child.isAncestorOf(item))
return true;
}
return false;
@@ -551,34 +412,34 @@ bool HistoryItem::isAncestorOf(const HistoryItem* item) const
// 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
+bool HistoryItem::shouldDoSameDocumentNavigationTo(HistoryItem& otherItem) const
{
- if (this == otherItem)
+ if (this == &otherItem)
return false;
- if (stateObject() || otherItem->stateObject())
- return documentSequenceNumber() == otherItem->documentSequenceNumber();
+ if (stateObject() || otherItem.stateObject())
+ return documentSequenceNumber() == otherItem.documentSequenceNumber();
- if ((url().hasFragmentIdentifier() || otherItem->url().hasFragmentIdentifier()) && equalIgnoringFragmentIdentifier(url(), otherItem->url()))
- 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
+bool HistoryItem::hasSameDocumentTree(HistoryItem& otherItem) const
{
- if (documentSequenceNumber() != otherItem->documentSequenceNumber())
+ if (documentSequenceNumber() != otherItem.documentSequenceNumber())
return false;
- if (children().size() != otherItem->children().size())
+ 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))
+ auto& child = children()[i].get();
+ auto* otherChild = otherItem.childItemWithDocumentSequenceNumber(child.documentSequenceNumber());
+ if (!otherChild || !child.hasSameDocumentTree(*otherChild))
return false;
}
@@ -587,16 +448,16 @@ bool HistoryItem::hasSameDocumentTree(HistoryItem* otherItem) const
// 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
+bool HistoryItem::hasSameFrames(HistoryItem& otherItem) const
{
- if (target() != otherItem->target())
+ if (target() != otherItem.target())
return false;
- if (children().size() != otherItem->children().size())
+ if (children().size() != otherItem.children().size())
return false;
for (size_t i = 0; i < children().size(); i++) {
- if (!otherItem->childItemWithTarget(children()[i]->target()))
+ if (!otherItem.childItemWithTarget(children()[i]->target()))
return false;
}
@@ -612,20 +473,20 @@ void HistoryItem::setFormInfoFromRequest(const ResourceRequest& request)
{
m_referrer = request.httpReferrer();
- if (equalIgnoringCase(request.httpMethod(), "POST")) {
+ if (equalLettersIgnoringASCIICase(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_formData = nullptr;
m_formContentType = String();
}
}
-void HistoryItem::setFormData(PassRefPtr<FormData> formData)
+void HistoryItem::setFormData(RefPtr<FormData>&& formData)
{
- m_formData = formData;
+ m_formData = WTFMove(formData);
}
void HistoryItem::setFormContentType(const String& formContentType)
@@ -638,26 +499,16 @@ FormData* HistoryItem::formData()
return m_formData.get();
}
-bool HistoryItem::isCurrentDocument(Document* doc) const
+bool HistoryItem::isCurrentDocument(Document& document) 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;
+ return equalIgnoringFragmentIdentifier(url(), document.url());
}
void HistoryItem::addRedirectURL(const String& url)
{
if (!m_redirectURLs)
- m_redirectURLs = adoptPtr(new Vector<String>);
+ m_redirectURLs = std::make_unique<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.
@@ -670,183 +521,14 @@ Vector<String>* HistoryItem::redirectURLs() const
return m_redirectURLs.get();
}
-void HistoryItem::setRedirectURLs(PassOwnPtr<Vector<String> > redirectURLs)
+void HistoryItem::setRedirectURLs(std::unique_ptr<Vector<String>> redirectURLs)
{
- m_redirectURLs = redirectURLs;
+ m_redirectURLs = WTFMove(redirectURLs);
}
-void HistoryItem::encodeBackForwardTree(Encoder& encoder) const
+void HistoryItem::notifyChanged()
{
- 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->encode(encoder);
-
- encoder.encodeInt64(m_itemSequenceNumber);
-
- encoder.encodeString(m_referrer);
-
- encoder.encodeInt32(m_scrollPoint.x());
- encoder.encodeInt32(m_scrollPoint.y());
-
- encoder.encodeFloat(m_pageScaleFactor);
-
- encoder.encodeBool(m_stateObject);
- if (m_stateObject)
- encoder.encodeBytes(m_stateObject->data().data(), m_stateObject->data().size());
-
- 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::decode(decoder);
- if (!node->m_formData)
- return 0;
- }
-
- if (!decoder.decodeInt64(node->m_itemSequenceNumber))
- 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);
-
- if (!decoder.decodeFloat(node->m_pageScaleFactor))
- return 0;
-
- bool hasStateObject;
- if (!decoder.decodeBool(hasStateObject))
- return 0;
- if (hasStateObject) {
- Vector<uint8_t> bytes;
- if (!decoder.decodeBytes(bytes))
- return 0;
- node->m_stateObject = SerializedScriptValue::adopt(bytes);
- }
-
- 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();
+ notifyHistoryItemChanged(this);
}
#ifndef NDEBUG
diff --git a/Source/WebCore/history/HistoryItem.h b/Source/WebCore/history/HistoryItem.h
index 7fe4511e8..f94482239 100644
--- a/Source/WebCore/history/HistoryItem.h
+++ b/Source/WebCore/history/HistoryItem.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2008, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2008, 2011, 2014 Apple Inc. All rights reserved.
* Copyright (C) 2012 Research In Motion Limited. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -11,10 +11,10 @@
* 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
+ * 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 COMPUTER, INC. OR
+ * 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
@@ -27,14 +27,20 @@
#ifndef HistoryItem_h
#define HistoryItem_h
+#include "FloatRect.h"
+#include "FrameLoaderTypes.h"
#include "IntPoint.h"
+#include "IntRect.h"
#include "SerializedScriptValue.h"
-#include <wtf/OwnPtr.h>
-#include <wtf/PassOwnPtr.h>
+#include <memory>
#include <wtf/RefCounted.h>
#include <wtf/text/WTFString.h>
-#if PLATFORM(MAC)
+#if PLATFORM(IOS)
+#include "ViewportArguments.h"
+#endif
+
+#if PLATFORM(COCOA)
#import <wtf/RetainPtr.h>
typedef struct objc_object* id;
#endif
@@ -45,10 +51,6 @@ typedef struct objc_object* id;
#include <QDataStream>
#endif
-#if PLATFORM(BLACKBERRY)
-#include "HistoryItemViewState.h"
-#endif
-
namespace WebCore {
class CachedPage;
@@ -56,96 +58,80 @@ class Document;
class FormData;
class HistoryItem;
class Image;
-class KURL;
class ResourceRequest;
+class URL;
+enum class PruningReason;
-typedef Vector<RefPtr<HistoryItem> > HistoryItemVector;
-
-extern void (*notifyHistoryItemChanged)(HistoryItem*);
+typedef Vector<Ref<HistoryItem>> HistoryItemVector;
-enum VisitCountBehavior {
- IncreaseVisitCount,
- DoNotIncreaseVisitCount
-};
+WEBCORE_EXPORT extern void (*notifyHistoryItemChanged)(HistoryItem*);
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)
+ static Ref<HistoryItem> create() { return adoptRef(*new HistoryItem); }
+ static Ref<HistoryItem> create(const String& urlString, const String& title)
{
- return adoptRef(new HistoryItem(urlString, title, lastVisited));
+ return adoptRef(*new HistoryItem(urlString, title));
}
- static PassRefPtr<HistoryItem> create(const String& urlString, const String& title, const String& alternateTitle, double lastVisited)
+ static Ref<HistoryItem> create(const String& urlString, const String& title, const String& alternateTitle)
{
- 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));
+ return adoptRef(*new HistoryItem(urlString, title, alternateTitle));
}
- ~HistoryItem();
+ WEBCORE_EXPORT ~HistoryItem();
- PassRefPtr<HistoryItem> copy() const;
+ WEBCORE_EXPORT Ref<HistoryItem> copy() const;
// Resets the HistoryItem to its initial state, as returned by create().
void reset();
- 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; }
- bool hasCachedPageExpired() const;
-
- double lastVisitedTime() const;
+ WEBCORE_EXPORT const String& originalURLString() const;
+ WEBCORE_EXPORT const String& urlString() const;
+ WEBCORE_EXPORT const String& title() const;
- void setAlternateTitle(const String& alternateTitle);
- const String& alternateTitle() const;
+ bool isInPageCache() const { return m_cachedPage.get(); }
+ WEBCORE_EXPORT bool hasCachedPageExpired() const;
+
+ WEBCORE_EXPORT void setAlternateTitle(const String&);
+ WEBCORE_EXPORT const String& alternateTitle() const;
- const String& parent() const;
- KURL url() const;
- KURL originalURL() const;
- const String& referrer() const;
- const String& target() const;
- bool isTargetItem() const;
+ WEBCORE_EXPORT URL url() const;
+ WEBCORE_EXPORT URL originalURL() const;
+ WEBCORE_EXPORT const String& referrer() const;
+ WEBCORE_EXPORT const String& target() const;
+ WEBCORE_EXPORT bool isTargetItem() const;
- FormData* formData();
- String formContentType() const;
+ WEBCORE_EXPORT FormData* formData();
+ WEBCORE_EXPORT 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();
+ WEBCORE_EXPORT const IntPoint& scrollPosition() const;
+ WEBCORE_EXPORT void setScrollPosition(const IntPoint&);
+ void clearScrollPosition();
- float pageScaleFactor() const;
- void setPageScaleFactor(float);
+ WEBCORE_EXPORT float pageScaleFactor() const;
+ WEBCORE_EXPORT void setPageScaleFactor(float);
- const Vector<String>& documentState() const;
- void setDocumentState(const Vector<String>&);
+ WEBCORE_EXPORT const Vector<String>& documentState() const;
+ WEBCORE_EXPORT 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);
+ WEBCORE_EXPORT void setShouldOpenExternalURLsPolicy(ShouldOpenExternalURLsPolicy);
+ WEBCORE_EXPORT ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy() const;
+
+ void setURL(const URL&);
+ WEBCORE_EXPORT void setURLString(const String&);
+ WEBCORE_EXPORT void setOriginalURLString(const String&);
+ WEBCORE_EXPORT void setReferrer(const String&);
+ WEBCORE_EXPORT void setTarget(const String&);
+ WEBCORE_EXPORT void setTitle(const String&);
+ WEBCORE_EXPORT void setIsTargetItem(bool);
- void setStateObject(PassRefPtr<SerializedScriptValue> object);
- PassRefPtr<SerializedScriptValue> stateObject() const { return m_stateObject; }
+ WEBCORE_EXPORT void setStateObject(RefPtr<SerializedScriptValue>&&);
+ RefPtr<SerializedScriptValue> stateObject() const { return m_stateObject; }
void setItemSequenceNumber(long long number) { m_itemSequenceNumber = number; }
long long itemSequenceNumber() const { return m_itemSequenceNumber; }
@@ -154,59 +140,42 @@ public:
long long documentSequenceNumber() const { return m_documentSequenceNumber; }
void setFormInfoFromRequest(const ResourceRequest&);
- void setFormData(PassRefPtr<FormData>);
- void setFormContentType(const String&);
+ WEBCORE_EXPORT void setFormData(RefPtr<FormData>&&);
+ WEBCORE_EXPORT 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;
+
+ WEBCORE_EXPORT void addChildItem(Ref<HistoryItem>&&);
+ void setChildItem(Ref<HistoryItem>&&);
+ WEBCORE_EXPORT HistoryItem* childItemWithTarget(const String&);
+ HistoryItem* childItemWithDocumentSequenceNumber(long long number);
+ WEBCORE_EXPORT const HistoryItemVector& children() const;
+ WEBCORE_EXPORT bool hasChildren() const;
void clearChildren();
- bool isAncestorOf(const HistoryItem*) const;
+ bool isAncestorOf(const HistoryItem&) const;
- bool shouldDoSameDocumentNavigationTo(HistoryItem* otherItem) const;
- bool hasSameFrames(HistoryItem* otherItem) const;
+ 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);
+ WEBCORE_EXPORT void addRedirectURL(const String&);
+ WEBCORE_EXPORT Vector<String>* redirectURLs() const;
+ WEBCORE_EXPORT void setRedirectURLs(std::unique_ptr<Vector<String>>);
- void addRedirectURL(const String&);
- Vector<String>* redirectURLs() const;
- void setRedirectURLs(PassOwnPtr<Vector<String> >);
-
- bool isCurrentDocument(Document*) const;
+ bool isCurrentDocument(Document&) const;
-#if PLATFORM(MAC)
- id viewState() const;
- void setViewState(id);
+#if PLATFORM(COCOA)
+ WEBCORE_EXPORT id viewState() const;
+ WEBCORE_EXPORT 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);
+ WEBCORE_EXPORT id getTransientProperty(const String&) const;
+ WEBCORE_EXPORT void setTransientProperty(const String&, id);
#endif
#if PLATFORM(QT)
QVariant userData() const { return m_userData; }
void setUserData(const QVariant& userData) { m_userData = userData; }
-
- static PassRefPtr<HistoryItem> restoreState(QDataStream& buffer, int version);
- QDataStream& saveState(QDataStream& out, int version) const;
-#endif
-
-#if PLATFORM(BLACKBERRY)
- HistoryItemViewState& viewState() { return m_viewState; }
#endif
#ifndef NDEBUG
@@ -214,56 +183,71 @@ public:
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; }
+#if PLATFORM(IOS)
+ FloatRect exposedContentRect() const { return m_exposedContentRect; }
+ void setExposedContentRect(FloatRect exposedContentRect) { m_exposedContentRect = exposedContentRect; }
-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);
+ IntRect unobscuredContentRect() const { return m_unobscuredContentRect; }
+ void setUnobscuredContentRect(IntRect unobscuredContentRect) { m_unobscuredContentRect = unobscuredContentRect; }
- explicit HistoryItem(const HistoryItem&);
+ FloatSize minimumLayoutSizeInScrollViewCoordinates() const { return m_minimumLayoutSizeInScrollViewCoordinates; }
+ void setMinimumLayoutSizeInScrollViewCoordinates(FloatSize minimumLayoutSizeInScrollViewCoordinates) { m_minimumLayoutSizeInScrollViewCoordinates = minimumLayoutSizeInScrollViewCoordinates; }
- void padDailyCountsForNewVisit(double time);
- void collapseDailyVisitsToWeekly();
- void recordVisitAtTime(double, VisitCountBehavior = IncreaseVisitCount);
-
- bool hasSameDocumentTree(HistoryItem* otherItem) const;
+ IntSize contentSize() const { return m_contentSize; }
+ void setContentSize(IntSize contentSize) { m_contentSize = contentSize; }
+
+ float scale() const { return m_scale; }
+ bool scaleIsInitial() const { return m_scaleIsInitial; }
+ void setScaleIsInitial(bool scaleIsInitial) { m_scaleIsInitial = scaleIsInitial; }
+ void setScale(float newScale, bool isInitial)
+ {
+ m_scale = newScale;
+ m_scaleIsInitial = isInitial;
+ }
+
+ const ViewportArguments& viewportArguments() const { return m_viewportArguments; }
+ void setViewportArguments(const ViewportArguments& viewportArguments) { m_viewportArguments = viewportArguments; }
+
+ uint32_t bookmarkID() const { return m_bookmarkID; }
+ void setBookmarkID(uint32_t bookmarkID) { m_bookmarkID = bookmarkID; }
+ String sharedLinkUniqueIdentifier() const { return m_sharedLinkUniqueIdentifier; }
+ void setSharedLinkUniqueIdentifier(const String& sharedLinkUniqueidentifier) { m_sharedLinkUniqueIdentifier = sharedLinkUniqueidentifier; }
+#endif
+
+ void notifyChanged();
- HistoryItem* findTargetItem();
+ void setWasRestoredFromSession(bool wasRestoredFromSession) { m_wasRestoredFromSession = wasRestoredFromSession; }
+ bool wasRestoredFromSession() const { return m_wasRestoredFromSession; }
- void encodeBackForwardTreeNode(Encoder&) const;
+private:
+ WEBCORE_EXPORT HistoryItem();
+ WEBCORE_EXPORT HistoryItem(const String& urlString, const String& title);
+ WEBCORE_EXPORT HistoryItem(const String& urlString, const String& title, const String& alternateTitle);
+
+ HistoryItem(const HistoryItem&);
- /* When adding new member variables to this class, please notify the Qt team.
- * qt/HistoryItemQt.cpp contains code to serialize history items.
- */
+ bool hasSameDocumentTree(HistoryItem& otherItem) const;
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;
+ IntPoint m_scrollPosition;
float m_pageScaleFactor;
Vector<String> m_documentState;
+
+ ShouldOpenExternalURLsPolicy m_shouldOpenExternalURLsPolicy { ShouldOpenExternalURLsPolicy::ShouldNotAllow };
HistoryItemVector m_children;
bool m_lastVisitWasFailure;
bool m_isTargetItem;
- int m_visitCount;
- Vector<int> m_dailyVisitCounts;
- Vector<int> m_weeklyVisitCounts;
+ bool m_wasRestoredFromSession { false };
- OwnPtr<Vector<String> > m_redirectURLs;
+ std::unique_ptr<Vector<String>> m_redirectURLs;
// If two HistoryItems have the same item sequence number, then they are
// clones of one another. Traversing history from one such HistoryItem to
@@ -284,22 +268,30 @@ private:
String m_formContentType;
// PageCache controls these fields.
- HistoryItem* m_next;
- HistoryItem* m_prev;
- RefPtr<CachedPage> m_cachedPage;
-
-#if PLATFORM(MAC)
+ std::unique_ptr<CachedPage> m_cachedPage;
+ PruningReason m_pruningReason;
+
+#if PLATFORM(IOS)
+ FloatRect m_exposedContentRect;
+ IntRect m_unobscuredContentRect;
+ FloatSize m_minimumLayoutSizeInScrollViewCoordinates;
+ IntSize m_contentSize;
+ float m_scale;
+ bool m_scaleIsInitial;
+ ViewportArguments m_viewportArguments;
+
+ uint32_t m_bookmarkID;
+ String m_sharedLinkUniqueIdentifier;
+#endif
+
+#if PLATFORM(COCOA)
RetainPtr<id> m_viewState;
- OwnPtr<HashMap<String, RetainPtr<id> > > m_transientProperties;
+ std::unique_ptr<HashMap<String, RetainPtr<id>>> m_transientProperties;
#endif
#if PLATFORM(QT)
QVariant m_userData;
#endif
-
-#if PLATFORM(BLACKBERRY)
- HistoryItemViewState m_viewState;
-#endif
}; //class HistoryItem
} //namespace WebCore
diff --git a/Source/WebCore/history/PageCache.cpp b/Source/WebCore/history/PageCache.cpp
index c45ca8015..84ded8cce 100644
--- a/Source/WebCore/history/PageCache.cpp
+++ b/Source/WebCore/history/PageCache.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2014, 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* 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
+ * 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 COMPUTER, INC. OR
+ * 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
@@ -31,24 +31,27 @@
#include "MemoryCache.h"
#include "CachedPage.h"
#include "DOMWindow.h"
-#include "DatabaseManager.h"
#include "DeviceMotionController.h"
#include "DeviceOrientationController.h"
+#include "DiagnosticLoggingClient.h"
+#include "DiagnosticLoggingKeys.h"
#include "Document.h"
#include "DocumentLoader.h"
-#include "Frame.h"
+#include "FocusController.h"
#include "FrameLoader.h"
#include "FrameLoaderClient.h"
-#include "FrameLoaderStateMachine.h"
#include "FrameView.h"
-#include "HistogramSupport.h"
#include "HistoryController.h"
-#include "HistoryItem.h"
+#include "IgnoreOpensDuringUnloadCountIncrementer.h"
#include "Logging.h"
+#include "MainFrame.h"
+#include "MemoryPressureHandler.h"
#include "Page.h"
#include "Settings.h"
-#include "SharedWorkerRepository.h"
+#include "SubframeLoader.h"
#include <wtf/CurrentTime.h>
+#include <wtf/NeverDestroyed.h>
+#include <wtf/TemporaryChange.h>
#include <wtf/text/CString.h>
#include <wtf/text/StringConcatenate.h>
@@ -56,465 +59,419 @@
#include "DeviceProximityController.h"
#endif
-using namespace std;
-
namespace WebCore {
-#if !defined(NDEBUG)
-
#define PCLOG(...) LOG(PageCache, "%*s%s", indentLevel*4, "", makeString(__VA_ARGS__).utf8().data())
-
-// Used in histograms, please only add at the end, and do not remove elements (renaming e.g. to "FooEnumUnused1" is fine).
-// This is because statistics may be gathered from histograms between versions over time, and re-using values causes collisions.
-enum ReasonFrameCannotBeInPageCache {
- NoDocumentLoader = 0,
- MainDocumentError,
- IsErrorPage,
- HasPlugins,
- IsHttpsAndCacheControlled,
- HasUnloadListener,
- HasDatabaseHandles,
- HasSharedWorkers,
- NoHistoryItem,
- QuickRedirectComing,
- IsLoadingInAPISense,
- IsStopping,
- CannotSuspendActiveDOMObjects,
- DocumentLoaderUsesApplicationCache,
- ClientDeniesCaching,
- NumberOfReasonsFramesCannotBeInPageCache,
-};
-COMPILE_ASSERT(NumberOfReasonsFramesCannotBeInPageCache <= sizeof(unsigned)*8, ReasonFrameCannotBeInPageCacheDoesNotFitInBitmap);
-
-static unsigned logCanCacheFrameDecision(Frame* frame, int indentLevel)
+
+static inline void logPageCacheFailureDiagnosticMessage(DiagnosticLoggingClient& client, const String& reason)
+{
+ client.logDiagnosticMessageWithValue(DiagnosticLoggingKeys::pageCacheKey(), DiagnosticLoggingKeys::failureKey(), reason, ShouldSample::Yes);
+}
+
+static inline void logPageCacheFailureDiagnosticMessage(Page* page, const String& reason)
+{
+ if (!page)
+ return;
+
+ logPageCacheFailureDiagnosticMessage(page->mainFrame().diagnosticLoggingClient(), reason);
+}
+
+static bool canCacheFrame(Frame& frame, DiagnosticLoggingClient& diagnosticLoggingClient, unsigned indentLevel)
{
PCLOG("+---");
- if (!frame->loader()->documentLoader()) {
+ FrameLoader& frameLoader = frame.loader();
+
+ // Prevent page caching if a subframe is still in provisional load stage.
+ // We only do this check for subframes because the main frame is reused when navigating to a new page.
+ if (!frame.isMainFrame() && frameLoader.state() == FrameStateProvisional) {
+ PCLOG(" -Frame is in provisional load stage");
+ logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, DiagnosticLoggingKeys::provisionalLoadKey());
+ return false;
+ }
+
+ DocumentLoader* documentLoader = frameLoader.documentLoader();
+ if (!documentLoader) {
PCLOG(" -There is no DocumentLoader object");
- return 1 << NoDocumentLoader;
+ logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, DiagnosticLoggingKeys::noDocumentLoaderKey());
+ return false;
}
- KURL currentURL = frame->loader()->documentLoader()->url();
- KURL newURL = frame->loader()->provisionalDocumentLoader() ? frame->loader()->provisionalDocumentLoader()->url() : KURL();
+ URL currentURL = documentLoader->url();
+ URL newURL = frameLoader.provisionalDocumentLoader() ? frameLoader.provisionalDocumentLoader()->url() : URL();
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:");
- unsigned rejectReasons = 0;
- if (!frame->loader()->documentLoader()->mainDocumentError().isNull()) {
+ bool isCacheable = true;
+ if (!documentLoader->mainDocumentError().isNull()) {
PCLOG(" -Main document has an error");
- rejectReasons |= 1 << MainDocumentError;
+ logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, DiagnosticLoggingKeys::mainDocumentErrorKey());
+
+ if (documentLoader->mainDocumentError().isCancellation() && documentLoader->subresourceLoadersArePageCacheAcceptable())
+ PCLOG(" -But, it was a cancellation and all loaders during the cancelation were loading images or XHR.");
+ else
+ isCacheable = false;
}
- if (frame->loader()->documentLoader()->substituteData().isValid() && frame->loader()->documentLoader()->substituteData().failingURL().isEmpty()) {
+ // Do not cache error pages (these can be recognized as pages with substitute data or unreachable URLs).
+ if (documentLoader->substituteData().isValid() && !documentLoader->substituteData().failingURL().isEmpty()) {
PCLOG(" -Frame is an error page");
- rejectReasons |= 1 << IsErrorPage;
+ logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, DiagnosticLoggingKeys::isErrorPageKey());
+ isCacheable = false;
}
- if (frame->loader()->subframeLoader()->containsPlugins() && !frame->page()->settings()->pageCacheSupportsPlugins()) {
+ if (frameLoader.subframeLoader().containsPlugins() && !frame.page()->settings().pageCacheSupportsPlugins()) {
PCLOG(" -Frame contains plugins");
- rejectReasons |= 1 << HasPlugins;
- }
- if (frame->document()->url().protocolIs("https")
- && (frame->loader()->documentLoader()->response().cacheControlContainsNoCache()
- || frame->loader()->documentLoader()->response().cacheControlContainsNoStore())) {
- PCLOG(" -Frame is HTTPS, and cache control prohibits caching or storing");
- rejectReasons |= 1 << IsHttpsAndCacheControlled;
+ logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, DiagnosticLoggingKeys::hasPluginsKey());
+ isCacheable = false;
}
- if (frame->document()->domWindow() && frame->document()->domWindow()->hasEventListeners(eventNames().unloadEvent)) {
- PCLOG(" -Frame has an unload event listener");
- rejectReasons |= 1 << HasUnloadListener;
+ if (frame.isMainFrame() && frame.document() && frame.document()->url().protocolIs("https") && documentLoader->response().cacheControlContainsNoStore()) {
+ PCLOG(" -Frame is HTTPS, and cache control prohibits storing");
+ logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, DiagnosticLoggingKeys::httpsNoStoreKey());
+ isCacheable = false;
}
-#if ENABLE(SQL_DATABASE)
- if (DatabaseManager::manager().hasOpenDatabases(frame->document())) {
- PCLOG(" -Frame has open database handles");
- rejectReasons |= 1 << HasDatabaseHandles;
+ if (frame.isMainFrame() && !frameLoader.history().currentItem()) {
+ PCLOG(" -Main frame has no current history item");
+ logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, DiagnosticLoggingKeys::noCurrentHistoryItemKey());
+ isCacheable = false;
}
-#endif
-#if ENABLE(SHARED_WORKERS)
- if (SharedWorkerRepository::hasSharedWorkers(frame->document())) {
- PCLOG(" -Frame has associated SharedWorkers");
- rejectReasons |= 1 << HasSharedWorkers;
- }
-#endif
- if (!frame->loader()->history()->currentItem()) {
- PCLOG(" -No current history item");
- rejectReasons |= 1 << NoHistoryItem;
- }
- if (frame->loader()->quickRedirectComing()) {
+ if (frameLoader.quickRedirectComing()) {
PCLOG(" -Quick redirect is coming");
- rejectReasons |= 1 << QuickRedirectComing;
+ logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, DiagnosticLoggingKeys::quirkRedirectComingKey());
+ isCacheable = false;
}
- if (frame->loader()->documentLoader()->isLoadingInAPISense()) {
- PCLOG(" -DocumentLoader is still loading in API sense");
- rejectReasons |= 1 << IsLoadingInAPISense;
+ if (documentLoader->isLoading()) {
+ PCLOG(" -DocumentLoader is still loading");
+ logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, DiagnosticLoggingKeys::isLoadingKey());
+ isCacheable = false;
}
- if (frame->loader()->documentLoader()->isStopping()) {
+ if (documentLoader->isStopping()) {
PCLOG(" -DocumentLoader is in the middle of stopping");
- rejectReasons |= 1 << IsStopping;
+ logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, DiagnosticLoggingKeys::documentLoaderStoppingKey());
+ isCacheable = false;
}
- if (!frame->document()->canSuspendActiveDOMObjects()) {
- PCLOG(" -The document cannot suspect its active DOM Objects");
- rejectReasons |= 1 << CannotSuspendActiveDOMObjects;
+
+ Vector<ActiveDOMObject*> unsuspendableObjects;
+ if (frame.document() && !frame.document()->canSuspendActiveDOMObjectsForDocumentSuspension(&unsuspendableObjects)) {
+ PCLOG(" -The document cannot suspend its active DOM Objects");
+ for (auto* activeDOMObject : unsuspendableObjects) {
+ PCLOG(" - Unsuspendable: ", activeDOMObject->activeDOMObjectName());
+ diagnosticLoggingClient.logDiagnosticMessageWithValue(DiagnosticLoggingKeys::pageCacheKey(), DiagnosticLoggingKeys::unsuspendableDOMObjectKey(), activeDOMObject->activeDOMObjectName(), ShouldSample::Yes);
+ UNUSED_PARAM(activeDOMObject);
+ }
+ logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, DiagnosticLoggingKeys::cannotSuspendActiveDOMObjectsKey());
+ isCacheable = false;
}
- if (!frame->loader()->documentLoader()->applicationCacheHost()->canCacheInPageCache()) {
+ // FIXME: We should investigating caching frames that have an associated
+ // application cache. <rdar://problem/5917899> tracks that work.
+ if (!documentLoader->applicationCacheHost()->canCacheInPageCache()) {
PCLOG(" -The DocumentLoader uses an application cache");
- rejectReasons |= 1 << DocumentLoaderUsesApplicationCache;
+ logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, DiagnosticLoggingKeys::applicationCacheKey());
+ isCacheable = false;
}
- if (!frame->loader()->client()->canCachePage()) {
+ if (!frameLoader.client().canCachePage()) {
PCLOG(" -The client says this frame cannot be cached");
- rejectReasons |= 1 << ClientDeniesCaching;
+ logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, DiagnosticLoggingKeys::deniedByClientKey());
+ isCacheable = false;
}
- HistogramSupport::histogramEnumeration("PageCache.FrameCacheable", !rejectReasons, 2);
- int reasonCount = 0;
- for (int i = 0; i < NumberOfReasonsFramesCannotBeInPageCache; ++i) {
- if (rejectReasons & (1 << i)) {
- ++reasonCount;
- HistogramSupport::histogramEnumeration("PageCache.FrameRejectReason", i, NumberOfReasonsFramesCannotBeInPageCache);
- }
+ for (Frame* child = frame.tree().firstChild(); child; child = child->tree().nextSibling()) {
+ if (!canCacheFrame(*child, diagnosticLoggingClient, indentLevel + 1))
+ isCacheable = false;
}
- HistogramSupport::histogramEnumeration("PageCache.FrameRejectReasonCount", reasonCount, 1 + NumberOfReasonsFramesCannotBeInPageCache);
-
- for (Frame* child = frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
- rejectReasons |= logCanCacheFrameDecision(child, indentLevel + 1);
- PCLOG(rejectReasons ? " Frame CANNOT be cached" : " Frame CAN be cached");
+ PCLOG(isCacheable ? " Frame CAN be cached" : " Frame CANNOT be cached");
PCLOG("+---");
- return rejectReasons;
+ return isCacheable;
}
-// Used in histograms, please only add at the end, and do not remove elements (renaming e.g. to "FooEnumUnused1" is fine).
-// This is because statistics may be gathered from histograms between versions over time, and re-using values causes collisions.
-enum ReasonPageCannotBeInPageCache {
- FrameCannotBeInPageCache = 0,
- DisabledBackForwardList,
- DisabledPageCache,
- UsesDeviceMotion,
- UsesDeviceOrientation,
- IsReload,
- IsReloadFromOrigin,
- IsSameLoad,
- NumberOfReasonsPagesCannotBeInPageCache,
-};
-COMPILE_ASSERT(NumberOfReasonsPagesCannotBeInPageCache <= sizeof(unsigned)*8, ReasonPageCannotBeInPageCacheDoesNotFitInBitmap);
-
-static void logCanCachePageDecision(Page* page)
+static bool canCachePage(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;
+ unsigned indentLevel = 0;
PCLOG("--------\n Determining if page can be cached:");
- unsigned rejectReasons = 0;
- unsigned frameRejectReasons = logCanCacheFrameDecision(page->mainFrame(), indentLevel+1);
- if (frameRejectReasons)
- rejectReasons |= 1 << FrameCannotBeInPageCache;
+ MainFrame& mainFrame = page.mainFrame();
+ DiagnosticLoggingClient& diagnosticLoggingClient = mainFrame.diagnosticLoggingClient();
+ bool isCacheable = canCacheFrame(mainFrame, diagnosticLoggingClient, indentLevel + 1);
- if (!page->backForward()->isActive()) {
- PCLOG(" -The back/forward list is disabled or has 0 capacity");
- rejectReasons |= 1 << DisabledBackForwardList;
- }
- if (!page->settings()->usesPageCache()) {
+ if (!page.settings().usesPageCache()) {
PCLOG(" -Page settings says b/f cache disabled");
- rejectReasons |= 1 << DisabledPageCache;
+ logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, DiagnosticLoggingKeys::isDisabledKey());
+ isCacheable = false;
}
-#if ENABLE(DEVICE_ORIENTATION)
- if (DeviceMotionController::isActiveAt(page)) {
+#if ENABLE(DEVICE_ORIENTATION) && !PLATFORM(IOS)
+ if (DeviceMotionController::isActiveAt(&page)) {
PCLOG(" -Page is using DeviceMotion");
- rejectReasons |= 1 << UsesDeviceMotion;
+ logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, DiagnosticLoggingKeys::deviceMotionKey());
+ isCacheable = false;
}
- if (DeviceOrientationController::isActiveAt(page)) {
+ if (DeviceOrientationController::isActiveAt(&page)) {
PCLOG(" -Page is using DeviceOrientation");
- rejectReasons |= 1 << UsesDeviceOrientation;
+ logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, DiagnosticLoggingKeys::deviceOrientationKey());
+ isCacheable = false;
}
#endif
#if ENABLE(PROXIMITY_EVENTS)
if (DeviceProximityController::isActiveAt(page)) {
PCLOG(" -Page is using DeviceProximity");
- rejectReasons |= 1 << UsesDeviceMotion;
+ logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, deviceProximityKey);
+ isCacheable = false;
}
#endif
- FrameLoadType loadType = page->mainFrame()->loader()->loadType();
- if (loadType == FrameLoadTypeReload) {
+ FrameLoadType loadType = page.mainFrame().loader().loadType();
+ switch (loadType) {
+ case FrameLoadType::Reload:
+ // No point writing to the cache on a reload, since we will just write over it again when we leave that page.
PCLOG(" -Load type is: Reload");
- rejectReasons |= 1 << IsReload;
- }
- if (loadType == FrameLoadTypeReloadFromOrigin) {
- PCLOG(" -Load type is: Reload from origin");
- rejectReasons |= 1 << IsReloadFromOrigin;
- }
- if (loadType == FrameLoadTypeSame) {
+ logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, DiagnosticLoggingKeys::reloadKey());
+ isCacheable = false;
+ break;
+ case FrameLoadType::Same: // user loads same URL again (but not reload button)
+ // No point writing to the cache on a same load, since we will just write over it again when we leave that page.
PCLOG(" -Load type is: Same");
- rejectReasons |= 1 << IsSameLoad;
+ logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, DiagnosticLoggingKeys::sameLoadKey());
+ isCacheable = false;
+ break;
+ case FrameLoadType::RedirectWithLockedBackForwardList:
+ // 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.
+ PCLOG(" -Load type is: RedirectWithLockedBackForwardList");
+ logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, DiagnosticLoggingKeys::redirectKey());
+ isCacheable = false;
+ break;
+ case FrameLoadType::Replace:
+ // No point writing to the cache on a replace, since we will just write over it again when we leave that page.
+ PCLOG(" -Load type is: Replace");
+ logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, DiagnosticLoggingKeys::replaceKey());
+ isCacheable = false;
+ break;
+ case FrameLoadType::ReloadFromOrigin: {
+ // No point writing to the cache on a reload, since we will just write over it again when we leave that page.
+ PCLOG(" -Load type is: ReloadFromOrigin");
+ logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, DiagnosticLoggingKeys::reloadFromOriginKey());
+ isCacheable = false;
+ break;
+ }
+ case FrameLoadType::Standard:
+ case FrameLoadType::Back:
+ case FrameLoadType::Forward:
+ case FrameLoadType::IndexedBackForward: // a multi-item hop in the backforward list
+ // Cacheable.
+ break;
}
- PCLOG(rejectReasons ? " Page CANNOT be cached\n--------" : " Page CAN be cached\n--------");
-
- HistogramSupport::histogramEnumeration("PageCache.PageCacheable", !rejectReasons, 2);
- int reasonCount = 0;
- for (int i = 0; i < NumberOfReasonsPagesCannotBeInPageCache; ++i) {
- if (rejectReasons & (1 << i)) {
- ++reasonCount;
- HistogramSupport::histogramEnumeration("PageCache.PageRejectReason", i, NumberOfReasonsPagesCannotBeInPageCache);
- }
- }
- HistogramSupport::histogramEnumeration("PageCache.PageRejectReasonCount", reasonCount, 1 + NumberOfReasonsPagesCannotBeInPageCache);
- const bool settingsDisabledPageCache = rejectReasons & (1 << DisabledPageCache);
- HistogramSupport::histogramEnumeration("PageCache.PageRejectReasonCountExcludingSettings", reasonCount - settingsDisabledPageCache, NumberOfReasonsPagesCannotBeInPageCache);
-
- // Report also on the frame reasons by page; this is distinct from the per frame statistics since it coalesces the
- // causes from all subframes together.
- HistogramSupport::histogramEnumeration("PageCache.FrameCacheableByPage", !frameRejectReasons, 2);
- int frameReasonCount = 0;
- for (int i = 0; i <= NumberOfReasonsFramesCannotBeInPageCache; ++i) {
- if (frameRejectReasons & (1 << i)) {
- ++frameReasonCount;
- HistogramSupport::histogramEnumeration("PageCache.FrameRejectReasonByPage", i, NumberOfReasonsFramesCannotBeInPageCache);
- }
- }
-
- HistogramSupport::histogramEnumeration("PageCache.FrameRejectReasonCountByPage", frameReasonCount, 1 + NumberOfReasonsFramesCannotBeInPageCache);
-}
-
-#endif // !defined(NDEBUG)
+ if (isCacheable)
+ PCLOG(" Page CAN be cached\n--------");
+ else
+ PCLOG(" Page CANNOT be cached\n--------");
-PageCache* pageCache()
-{
- static PageCache* staticPageCache = new PageCache;
- return staticPageCache;
+ diagnosticLoggingClient.logDiagnosticMessageWithResult(DiagnosticLoggingKeys::pageCacheKey(), DiagnosticLoggingKeys::canCacheKey(), isCacheable ? DiagnosticLoggingResultPass : DiagnosticLoggingResultFail, ShouldSample::Yes);
+ return isCacheable;
}
-PageCache::PageCache()
- : m_capacity(0)
- , m_size(0)
- , m_head(0)
- , m_tail(0)
-#if USE(ACCELERATED_COMPOSITING)
- , m_shouldClearBackingStores(false)
-#endif
+PageCache& PageCache::singleton()
{
+ static NeverDestroyed<PageCache> globalPageCache;
+ return globalPageCache;
}
-bool PageCache::canCachePageContainingThisFrame(Frame* frame)
+bool PageCache::canCache(Page& page) const
{
- for (Frame* child = frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
- if (!canCachePageContainingThisFrame(child))
- return false;
+ if (!m_maxSize) {
+ logPageCacheFailureDiagnosticMessage(&page, DiagnosticLoggingKeys::isDisabledKey());
+ return false;
}
-
- FrameLoader* frameLoader = frame->loader();
- DocumentLoader* documentLoader = frameLoader->documentLoader();
- Document* document = frame->document();
-
- return documentLoader
- && documentLoader->mainDocumentError().isNull()
- // Do not cache error pages (these can be recognized as pages with substitute data or unreachable URLs).
- && !(documentLoader->substituteData().isValid() && !documentLoader->substituteData().failingURL().isEmpty())
- && (!frameLoader->subframeLoader()->containsPlugins() || frame->page()->settings()->pageCacheSupportsPlugins())
- && (!document->url().protocolIs("https") || (!documentLoader->response().cacheControlContainsNoCache() && !documentLoader->response().cacheControlContainsNoStore()))
- && (!document->domWindow() || !document->domWindow()->hasEventListeners(eventNames().unloadEvent))
-#if ENABLE(SQL_DATABASE)
- && !DatabaseManager::manager().hasOpenDatabases(document)
-#endif
-#if ENABLE(SHARED_WORKERS)
- && !SharedWorkerRepository::hasSharedWorkers(document)
-#endif
- && frameLoader->history()->currentItem()
- && !frameLoader->quickRedirectComing()
- && !documentLoader->isLoadingInAPISense()
- && !documentLoader->isStopping()
- && document->canSuspendActiveDOMObjects()
- // FIXME: We should investigating caching frames that have an associated
- // application cache. <rdar://problem/5917899> tracks that work.
- && documentLoader->applicationCacheHost()->canCacheInPageCache()
- && frameLoader->client()->canCachePage();
-}
-
-bool PageCache::canCache(Page* page) const
-{
- if (!page)
+
+ if (MemoryPressureHandler::singleton().isUnderMemoryPressure()) {
+ logPageCacheFailureDiagnosticMessage(&page, DiagnosticLoggingKeys::underMemoryPressureKey());
return false;
+ }
-#if !defined(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.
- FrameLoadType loadType = page->mainFrame()->loader()->loadType();
-
- return m_capacity > 0
- && canCachePageContainingThisFrame(page->mainFrame())
- && page->backForward()->isActive()
- && page->settings()->usesPageCache()
-#if ENABLE(DEVICE_ORIENTATION)
- && !DeviceMotionController::isActiveAt(page)
- && !DeviceOrientationController::isActiveAt(page)
-#endif
-#if ENABLE(PROXIMITY_EVENTS)
- && !DeviceProximityController::isActiveAt(page)
-#endif
- && (loadType == FrameLoadTypeStandard
- || loadType == FrameLoadTypeBack
- || loadType == FrameLoadTypeForward
- || loadType == FrameLoadTypeIndexedBackForward);
+ return canCachePage(page);
}
-void PageCache::setCapacity(int capacity)
+void PageCache::pruneToSizeNow(unsigned size, PruningReason pruningReason)
{
- ASSERT(capacity >= 0);
- m_capacity = max(capacity, 0);
+ TemporaryChange<unsigned> change(m_maxSize, size);
+ prune(pruningReason);
+}
- prune();
+void PageCache::setMaxSize(unsigned maxSize)
+{
+ m_maxSize = maxSize;
+ prune(PruningReason::None);
}
-int PageCache::frameCount() const
+unsigned 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;
+ unsigned frameCount = m_items.size();
+ for (auto& item : m_items) {
+ ASSERT(item->m_cachedPage);
+ frameCount += item->m_cachedPage->cachedMainFrame()->descendantFrameCount();
}
return frameCount;
}
-void PageCache::markPagesForVistedLinkStyleRecalc()
-{
- for (HistoryItem* current = m_head; current; current = current->m_next)
- current->m_cachedPage->markForVistedLinkStyleRecalc();
-}
-
-void PageCache::markPagesForFullStyleRecalc(Page* page)
+void PageCache::markPagesForDeviceOrPageScaleChanged(Page& page)
{
- Frame* mainFrame = page->mainFrame();
-
- for (HistoryItem* current = m_head; current; current = current->m_next) {
- CachedPage* cachedPage = current->m_cachedPage.get();
- if (cachedPage->cachedMainFrame()->view()->frame() == mainFrame)
- cachedPage->markForFullStyleRecalc();
+ for (auto& item : m_items) {
+ CachedPage& cachedPage = *item->m_cachedPage;
+ if (&page.mainFrame() == &cachedPage.cachedMainFrame()->view()->frame())
+ cachedPage.markForDeviceOrPageScaleChanged();
}
}
-
-#if USE(ACCELERATED_COMPOSITING)
-void PageCache::markPagesForDeviceScaleChanged(Page* page)
+void PageCache::markPagesForContentsSizeChanged(Page& page)
{
- Frame* mainFrame = page->mainFrame();
-
- for (HistoryItem* current = m_head; current; current = current->m_next) {
- CachedPage* cachedPage = current->m_cachedPage.get();
- if (cachedPage->cachedMainFrame()->view()->frame() == mainFrame)
- cachedPage->markForDeviceScaleChanged();
+ for (auto& item : m_items) {
+ CachedPage& cachedPage = *item->m_cachedPage;
+ if (&page.mainFrame() == &cachedPage.cachedMainFrame()->view()->frame())
+ cachedPage.markForContentsSizeChanged();
}
}
-#endif
#if ENABLE(VIDEO_TRACK)
void PageCache::markPagesForCaptionPreferencesChanged()
{
- for (HistoryItem* current = m_head; current; current = current->m_next)
- current->m_cachedPage->markForCaptionPreferencesChanged();
+ for (auto& item : m_items) {
+ ASSERT(item->m_cachedPage);
+ item->m_cachedPage->markForCaptionPreferencesChanged();
+ }
}
#endif
-void PageCache::add(PassRefPtr<HistoryItem> prpItem, Page* page)
+static String pruningReasonToDiagnosticLoggingKey(PruningReason pruningReason)
{
- ASSERT(prpItem);
- ASSERT(page);
- ASSERT(canCache(page));
-
- HistoryItem* item = prpItem.leakRef(); // Balanced in remove().
-
- // Remove stale cache entry if necessary.
- if (item->m_cachedPage)
- remove(item);
+ switch (pruningReason) {
+ case PruningReason::MemoryPressure:
+ return DiagnosticLoggingKeys::prunedDueToMemoryPressureKey();
+ case PruningReason::ProcessSuspended:
+ return DiagnosticLoggingKeys::prunedDueToProcessSuspended();
+ case PruningReason::ReachedMaxSize:
+ return DiagnosticLoggingKeys::prunedDueToMaxSizeReached();
+ case PruningReason::None:
+ break;
+ }
+ ASSERT_NOT_REACHED();
+ return emptyString();
+}
- item->m_cachedPage = CachedPage::create(page);
- addToLRUList(item);
- ++m_size;
-
- prune();
+static void setInPageCache(Page& page, bool isInPageCache)
+{
+ for (Frame* frame = &page.mainFrame(); frame; frame = frame->tree().traverseNext()) {
+ if (auto* document = frame->document())
+ document->setInPageCache(isInPageCache);
+ }
}
-CachedPage* PageCache::get(HistoryItem* item)
+static void firePageHideEventRecursively(Frame& frame)
{
- if (!item)
- return 0;
+ auto* document = frame.document();
+ if (!document)
+ return;
- if (CachedPage* cachedPage = item->m_cachedPage.get()) {
- if (!cachedPage->hasExpired())
- 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;
+ // stopLoading() will fire the pagehide event in each subframe and the HTML specification states
+ // that the parent document's ignore-opens-during-unload counter should be incremented while the
+ // pagehide event is being fired in its subframes:
+ // https://html.spec.whatwg.org/multipage/browsers.html#unload-a-document
+ IgnoreOpensDuringUnloadCountIncrementer ignoreOpensDuringUnloadCountIncrementer(document);
+
+ frame.loader().stopLoading(UnloadEventPolicyUnloadAndPageHide);
+
+ for (RefPtr<Frame> child = frame.tree().firstChild(); child; child = child->tree().nextSibling())
+ firePageHideEventRecursively(*child);
}
-void PageCache::remove(HistoryItem* item)
+void PageCache::addIfCacheable(HistoryItem& item, Page* page)
{
- // Safely ignore attempts to remove items not in the cache.
- if (!item || !item->m_cachedPage)
+ if (item.isInPageCache())
+ return;
+
+ if (!page || !canCache(*page))
return;
- item->m_cachedPage.clear();
- removeFromLRUList(item);
- --m_size;
+ // Make sure all the documents know they are being added to the PageCache.
+ setInPageCache(*page, true);
+
+ // Focus the main frame, defocusing a focused subframe (if we have one). We do this here,
+ // before the page enters the page cache, while we still can dispatch DOM blur/focus events.
+ if (page->focusController().focusedFrame())
+ page->focusController().setFocusedFrame(&page->mainFrame());
+
+ // Fire the pagehide event in all frames.
+ firePageHideEventRecursively(page->mainFrame());
+
+ // Check that the page is still page-cacheable after firing the pagehide event. The JS event handlers
+ // could have altered the page in a way that could prevent caching.
+ if (!canCache(*page)) {
+ setInPageCache(*page, false);
+ return;
+ }
+
+ // Make sure we no longer fire any JS events past this point.
+ NoEventDispatchAssertion assertNoEventDispatch;
- item->deref(); // Balanced in add().
+ item.m_cachedPage = std::make_unique<CachedPage>(*page);
+ item.m_pruningReason = PruningReason::None;
+ m_items.add(&item);
+
+ prune(PruningReason::ReachedMaxSize);
}
-void PageCache::prune()
+std::unique_ptr<CachedPage> PageCache::take(HistoryItem& item, Page* page)
{
- while (m_size > m_capacity) {
- ASSERT(m_tail && m_tail->m_cachedPage);
- remove(m_tail);
+ if (!item.m_cachedPage) {
+ if (item.m_pruningReason != PruningReason::None)
+ logPageCacheFailureDiagnosticMessage(page, pruningReasonToDiagnosticLoggingKey(item.m_pruningReason));
+ return nullptr;
+ }
+
+ m_items.remove(&item);
+ std::unique_ptr<CachedPage> cachedPage = WTFMove(item.m_cachedPage);
+
+ if (cachedPage->hasExpired()) {
+ LOG(PageCache, "Not restoring page for %s from back/forward cache because cache entry has expired", item.url().string().ascii().data());
+ logPageCacheFailureDiagnosticMessage(page, DiagnosticLoggingKeys::expiredKey());
+ return nullptr;
}
+
+ return cachedPage;
}
-void PageCache::addToLRUList(HistoryItem* item)
+CachedPage* PageCache::get(HistoryItem& item, Page* page)
{
- item->m_next = m_head;
- item->m_prev = 0;
+ CachedPage* cachedPage = item.m_cachedPage.get();
+ if (!cachedPage) {
+ if (item.m_pruningReason != PruningReason::None)
+ logPageCacheFailureDiagnosticMessage(page, pruningReasonToDiagnosticLoggingKey(item.m_pruningReason));
+ return nullptr;
+ }
- if (m_head) {
- ASSERT(m_tail);
- m_head->m_prev = item;
- } else {
- ASSERT(!m_tail);
- m_tail = item;
+ if (cachedPage->hasExpired()) {
+ LOG(PageCache, "Not restoring page for %s from back/forward cache because cache entry has expired", item.url().string().ascii().data());
+ logPageCacheFailureDiagnosticMessage(page, DiagnosticLoggingKeys::expiredKey());
+ remove(item);
+ return nullptr;
}
+ return cachedPage;
+}
+
+void PageCache::remove(HistoryItem& item)
+{
+ // Safely ignore attempts to remove items not in the cache.
+ if (!item.m_cachedPage)
+ return;
- m_head = item;
+ m_items.remove(&item);
+ item.m_cachedPage = nullptr;
}
-void PageCache::removeFromLRUList(HistoryItem* item)
+void PageCache::prune(PruningReason pruningReason)
{
- 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;
+ while (pageCount() > maxSize()) {
+ auto oldestItem = m_items.takeFirst();
+ oldestItem->m_cachedPage = nullptr;
+ oldestItem->m_pruningReason = pruningReason;
}
}
diff --git a/Source/WebCore/history/PageCache.h b/Source/WebCore/history/PageCache.h
index 24d57da12..31b630bff 100644
--- a/Source/WebCore/history/PageCache.h
+++ b/Source/WebCore/history/PageCache.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* 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
+ * 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 COMPUTER, INC. OR
+ * 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
@@ -26,75 +26,64 @@
#ifndef PageCache_h
#define PageCache_h
+#include "HistoryItem.h"
#include "Timer.h"
#include <wtf/Forward.h>
-#include <wtf/HashSet.h>
+#include <wtf/ListHashSet.h>
#include <wtf/Noncopyable.h>
namespace WebCore {
- class CachedPage;
- class Frame;
- class HistoryItem;
- class Page;
-
- class PageCache {
- WTF_MAKE_NONCOPYABLE(PageCache); WTF_MAKE_FAST_ALLOCATED;
- public:
- friend PageCache* pageCache();
-
- bool canCache(Page*) const;
-
- 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);
-
- int pageCount() const { return m_size; }
- int frameCount() const;
-
- void markPagesForVistedLinkStyleRecalc();
-
- // Will mark all cached pages associated with the given page as needing style recalc.
- void markPagesForFullStyleRecalc(Page*);
+class CachedPage;
+class Frame;
+class Page;
-#if ENABLE(VIDEO_TRACK)
- void markPagesForCaptionPreferencesChanged();
-#endif
+enum class PruningReason { None, ProcessSuspended, MemoryPressure, ReachedMaxSize };
-#if USE(ACCELERATED_COMPOSITING)
- bool shouldClearBackingStores() const { return m_shouldClearBackingStores; }
- void setShouldClearBackingStores(bool flag) { m_shouldClearBackingStores = flag; }
- void markPagesForDeviceScaleChanged(Page*);
-#endif
+class PageCache {
+ WTF_MAKE_NONCOPYABLE(PageCache); WTF_MAKE_FAST_ALLOCATED;
+public:
+ // Function to obtain the global page cache.
+ WEBCORE_EXPORT static PageCache& singleton();
- private:
- PageCache(); // Use pageCache() instead.
- ~PageCache(); // Not implemented to make sure nobody accidentally calls delete -- WebCore does not delete singletons.
-
- static bool canCachePageContainingThisFrame(Frame*);
+ bool canCache(Page&) const;
- void addToLRUList(HistoryItem*); // Adds to the head of the list.
- void removeFromLRUList(HistoryItem*);
+ // Used when memory is low to prune some cached pages.
+ WEBCORE_EXPORT void pruneToSizeNow(unsigned maxSize, PruningReason);
+ WEBCORE_EXPORT void setMaxSize(unsigned); // number of pages to cache.
+ unsigned maxSize() const { return m_maxSize; }
- void prune();
+ void addIfCacheable(HistoryItem&, Page*); // Prunes if maxSize() is exceeded.
+ WEBCORE_EXPORT void remove(HistoryItem&);
+ CachedPage* get(HistoryItem&, Page*);
+ std::unique_ptr<CachedPage> take(HistoryItem&, Page*);
- int m_capacity;
- int m_size;
+ unsigned pageCount() const { return m_items.size(); }
+ WEBCORE_EXPORT unsigned frameCount() const;
- // LRU List
- HistoryItem* m_head;
- HistoryItem* m_tail;
-
-#if USE(ACCELERATED_COMPOSITING)
- bool m_shouldClearBackingStores;
+ void markPagesForDeviceOrPageScaleChanged(Page&);
+ void markPagesForContentsSizeChanged(Page&);
+#if ENABLE(VIDEO_TRACK)
+ void markPagesForCaptionPreferencesChanged();
#endif
- };
- // Function to obtain the global page cache.
- PageCache* pageCache();
+ bool shouldClearBackingStores() const { return m_shouldClearBackingStores; }
+ void setShouldClearBackingStores(bool flag) { m_shouldClearBackingStores = flag; }
+
+private:
+ PageCache() = default; // Use singleton() instead.
+ ~PageCache() = delete; // Make sure nobody accidentally calls delete -- WebCore does not delete singletons.
+
+ static bool canCachePageContainingThisFrame(Frame&);
+
+ void prune(PruningReason);
+
+ ListHashSet<RefPtr<HistoryItem>> m_items;
+ unsigned m_maxSize {0};
+ bool m_shouldClearBackingStores {false};
+
+ friend class WTF::NeverDestroyed<PageCache>;
+};
} // namespace WebCore
diff --git a/Source/WebCore/history/blackberry/HistoryItemViewState.h b/Source/WebCore/history/blackberry/HistoryItemViewState.h
deleted file mode 100644
index f2efb5d26..000000000
--- a/Source/WebCore/history/blackberry/HistoryItemViewState.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2011 Research In Motion Limited. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef HistoryItemViewState_h
-#define HistoryItemViewState_h
-
-#include <BlackBerryPlatformString.h>
-#include <wtf/text/WTFString.h>
-
-namespace WebCore {
-
-struct HistoryItemViewState {
-
- HistoryItemViewState()
- : orientation(0)
- , scale(1)
- , minimumScale(-1.0)
- , maximumScale(-1.0)
- , isUserScalable(true)
- , isZoomToFitScale(false)
- , shouldReflowBlock(false)
- , shouldSaveViewState(true)
- {
- }
-
- int orientation;
- double scale;
- double minimumScale;
- double maximumScale;
- bool isUserScalable;
- bool isZoomToFitScale;
- bool shouldReflowBlock;
- bool shouldSaveViewState;
- String networkToken;
- BlackBerry::Platform::String webPageClientState;
-};
-
-} // namespace WebCore
-
-#endif // HistoryItemViewState_h
diff --git a/Source/WebCore/history/qt/HistoryItemQt.cpp b/Source/WebCore/history/qt/HistoryItemQt.cpp
deleted file mode 100644
index 5a54516f3..000000000
--- a/Source/WebCore/history/qt/HistoryItemQt.cpp
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- 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/Decoder.h>
-#include <wtf/Encoder.h>
-#include <wtf/text/CString.h>
-
-using namespace WTF;
-
-namespace WebCore {
-
-static QDataStream& operator<<(QDataStream& stream, const String& str)
-{
- // could be faster
- stream << QString(str);
- return stream;
-}
-
-static QDataStream& operator>>(QDataStream& stream, String& str)
-{
- // mabe not the fastest way, but really easy
- QString tmp;
- stream >> tmp;
- str = tmp;
- return stream;
-}
-
-class QDataStreamCoder : public WTF::Encoder, public WTF::Decoder {
-public:
- QDataStreamCoder(QDataStream&);
-
-private:
- virtual void encodeBytes(const uint8_t*, size_t);
- virtual void encodeBool(bool);
- virtual void encodeUInt32(uint32_t);
- virtual void encodeUInt64(uint64_t);
- virtual void encodeInt32(int32_t);
- virtual void encodeInt64(int64_t);
- virtual void encodeFloat(float);
- virtual void encodeDouble(double);
- virtual void encodeString(const String&);
-
- virtual bool decodeBytes(Vector<uint8_t>&);
- virtual bool decodeBool(bool&);
- virtual bool decodeUInt32(uint32_t&);
- virtual bool decodeUInt64(uint64_t&);
- virtual bool decodeInt32(int32_t&);
- virtual bool decodeInt64(int64_t&);
- virtual bool decodeFloat(float&);
- virtual bool decodeDouble(double&);
- virtual bool decodeString(String&);
-
- QDataStream& m_stream;
-};
-
-QDataStreamCoder::QDataStreamCoder(QDataStream& stream)
- : m_stream(stream)
-{
-}
-
-void QDataStreamCoder::encodeBytes(const uint8_t* bytes, size_t size)
-{
- m_stream << qint64(size);
- for (; size > 0; --size)
- m_stream << bytes++;
-}
-
-void QDataStreamCoder::encodeBool(bool value)
-{
- m_stream << value;
-}
-
-void QDataStreamCoder::encodeUInt32(uint32_t value)
-{
- m_stream << value;
-}
-
-void QDataStreamCoder::encodeUInt64(uint64_t value)
-{
- m_stream << static_cast<quint64>(value);
-}
-
-void QDataStreamCoder::encodeInt32(int32_t value)
-{
- m_stream << value;
-}
-
-void QDataStreamCoder::encodeInt64(int64_t value)
-{
- m_stream << static_cast<qint64>(value);
-}
-
-void QDataStreamCoder::encodeFloat(float value)
-{
- m_stream << value;
-}
-
-void QDataStreamCoder::encodeDouble(double value)
-{
- m_stream << value;
-}
-
-void QDataStreamCoder::encodeString(const String& value)
-{
- m_stream << value;
-}
-
-bool QDataStreamCoder::decodeBytes(Vector<uint8_t>& out)
-{
- out.clear();
- qint64 count;
- uint8_t byte;
- m_stream >> count;
- out.reserveCapacity(count);
- for (qint64 i = 0; i < count; ++i) {
- m_stream >> byte;
- out.append(byte);
- }
- return m_stream.status() == QDataStream::Ok;
-}
-
-bool QDataStreamCoder::decodeBool(bool& out)
-{
- m_stream >> out;
- return m_stream.status() == QDataStream::Ok;
-}
-
-bool QDataStreamCoder::decodeUInt32(uint32_t& out)
-{
- m_stream >> out;
- return m_stream.status() == QDataStream::Ok;
-}
-
-bool QDataStreamCoder::decodeUInt64(uint64_t& out)
-{
- quint64 tmp;
- m_stream >> tmp;
- // quint64 is defined to "long long unsigned", incompatible with uint64_t defined as "long unsigned" on 64bits archs.
- out = tmp;
- return m_stream.status() == QDataStream::Ok;
-}
-
-bool QDataStreamCoder::decodeInt32(int32_t& out)
-{
- m_stream >> out;
- return m_stream.status() == QDataStream::Ok;
-}
-
-bool QDataStreamCoder::decodeInt64(int64_t& out)
-{
- qint64 tmp;
- m_stream >> tmp;
- // qint64 is defined to "long long", incompatible with int64_t defined as "long" on 64bits archs.
- out = tmp;
- return m_stream.status() == QDataStream::Ok;
-}
-
-bool QDataStreamCoder::decodeFloat(float& out)
-{
- m_stream >> out;
- return m_stream.status() == QDataStream::Ok;
-}
-
-bool QDataStreamCoder::decodeDouble(double& out)
-{
- m_stream >> out;
- return m_stream.status() == QDataStream::Ok;
-}
-
-bool QDataStreamCoder::decodeString(String& out)
-{
- m_stream >> out;
- return m_stream.status() == QDataStream::Ok;
-}
-
-PassRefPtr<HistoryItem> HistoryItem::restoreState(QDataStream& in, int version)
-{
- ASSERT(version == 2);
-
- String url;
- String title;
- String originalURL;
- in >> url >> title >> originalURL;
-
- QDataStreamCoder decoder(in);
- RefPtr<HistoryItem> item = decodeBackForwardTree(url, title, originalURL, decoder);
- // decodeBackForwardTree has its own stream version. An incompatible input stream version will return null here.
- if (!item)
- return 0;
-
- // at the end load userData
- bool validUserData;
- in >> validUserData;
- if (validUserData) {
- QVariant tmp;
- in >> tmp;
- item->setUserData(tmp);
- }
-
- return item;
-}
-
-QDataStream& WebCore::HistoryItem::saveState(QDataStream& out, int version) const
-{
- ASSERT(version == 2);
-
- out << urlString() << title() << originalURLString();
-
- QDataStreamCoder encoder(out);
- encodeBackForwardTree(encoder);
-
- // save user data
- if (userData().isValid())
- out << true << userData();
- else
- out << false;
-
- return out;
-}
-
-} // namespace WebCore