summaryrefslogtreecommitdiff
path: root/Source/WebKit2/UIProcess/WebBackForwardList.cpp
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@qt.io>2017-05-30 12:48:17 +0200
committerOswald Buddenhagen <oswald.buddenhagen@qt.io>2017-05-30 12:48:17 +0200
commit881da28418d380042aa95a97f0cbd42560a64f7c (patch)
treea794dff3274695e99c651902dde93d934ea7a5af /Source/WebKit2/UIProcess/WebBackForwardList.cpp
parent7e104c57a70fdf551bb3d22a5d637cdcbc69dbea (diff)
parent0fcedcd17cc00d3dd44c718b3cb36c1033319671 (diff)
downloadqtwebkit-881da28418d380042aa95a97f0cbd42560a64f7c.tar.gz
Merge 'wip/next' into dev
Change-Id: Iff9ee5e23bb326c4371ec8ed81d56f2f05d680e9
Diffstat (limited to 'Source/WebKit2/UIProcess/WebBackForwardList.cpp')
-rw-r--r--Source/WebKit2/UIProcess/WebBackForwardList.cpp249
1 files changed, 199 insertions, 50 deletions
diff --git a/Source/WebKit2/UIProcess/WebBackForwardList.cpp b/Source/WebKit2/UIProcess/WebBackForwardList.cpp
index 763023d07..273431232 100644
--- a/Source/WebKit2/UIProcess/WebBackForwardList.cpp
+++ b/Source/WebKit2/UIProcess/WebBackForwardList.cpp
@@ -26,19 +26,34 @@
#include "config.h"
#include "WebBackForwardList.h"
+#include "APIArray.h"
+#include "SessionState.h"
#include "WebPageProxy.h"
+#include <WebCore/DiagnosticLoggingKeys.h>
namespace WebKit {
+// FIXME: Make this static once WebBackForwardListCF.cpp is no longer using it.
+uint64_t generateWebBackForwardItemID();
+
+uint64_t generateWebBackForwardItemID()
+{
+ // These IDs exist in the UIProcess for items created by the UIProcess.
+ // The IDs generated here need to never collide with the IDs created in WebBackForwardListProxy in the WebProcess.
+ // We accomplish this by starting from 2, and only ever using even ids.
+ static uint64_t uniqueHistoryItemID = 0;
+ uniqueHistoryItemID += 2;
+ return uniqueHistoryItemID;
+}
+
static const unsigned DefaultCapacity = 100;
-WebBackForwardList::WebBackForwardList(WebPageProxy* page)
- : m_page(page)
+WebBackForwardList::WebBackForwardList(WebPageProxy& page)
+ : m_page(&page)
, m_hasCurrentIndex(false)
, m_currentIndex(0)
, m_capacity(DefaultCapacity)
{
- ASSERT(m_page);
}
WebBackForwardList::~WebBackForwardList()
@@ -58,7 +73,8 @@ void WebBackForwardList::pageClosed()
ASSERT(m_entries[i]);
if (!m_entries[i])
continue;
- m_page->backForwardRemovedItem(m_entries[i]->itemID());
+
+ didRemoveItem(*m_entries[i]);
}
}
@@ -74,14 +90,16 @@ void WebBackForwardList::addItem(WebBackForwardListItem* newItem)
if (!m_capacity || !newItem || !m_page)
return;
- Vector<RefPtr<APIObject> > removedItems;
+ Vector<RefPtr<WebBackForwardListItem>> removedItems;
if (m_hasCurrentIndex) {
+ m_page->recordNavigationSnapshot();
+
// Toss everything in the forward list.
unsigned targetSize = m_currentIndex + 1;
removedItems.reserveCapacity(m_entries.size() - targetSize);
while (m_entries.size() > targetSize) {
- m_page->backForwardRemovedItem(m_entries.last()->itemID());
+ didRemoveItem(*m_entries.last());
removedItems.append(m_entries.last().release());
m_entries.removeLast();
}
@@ -89,7 +107,7 @@ void WebBackForwardList::addItem(WebBackForwardListItem* newItem)
// 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_currentIndex || m_capacity == 1)) {
- m_page->backForwardRemovedItem(m_entries[0]->itemID());
+ didRemoveItem(*m_entries[0]);
removedItems.append(m_entries[0].release());
m_entries.remove(0);
@@ -108,26 +126,41 @@ void WebBackForwardList::addItem(WebBackForwardListItem* newItem)
ASSERT(m_entries[i]);
if (!m_entries[i])
continue;
- m_page->backForwardRemovedItem(m_entries[i]->itemID());
+ didRemoveItem(*m_entries[i]);
removedItems.append(m_entries[i].release());
}
m_entries.clear();
}
-
+
+ bool shouldKeepCurrentItem = true;
+
if (!m_hasCurrentIndex) {
ASSERT(m_entries.isEmpty());
m_currentIndex = 0;
m_hasCurrentIndex = true;
- } else
- m_currentIndex++;
+ } else {
+ shouldKeepCurrentItem = m_page->shouldKeepCurrentBackForwardListItemInList(m_entries[m_currentIndex].get());
+ if (shouldKeepCurrentItem)
+ m_currentIndex++;
+ }
- // m_current never be pointing more than 1 past the end of the entries Vector.
- // If it is, something has gone wrong and we should not try to insert the new item.
- ASSERT(m_currentIndex <= m_entries.size());
- if (m_currentIndex <= m_entries.size())
- m_entries.insert(m_currentIndex, newItem);
+ if (!shouldKeepCurrentItem) {
+ // m_current should never be pointing past the end of the entries Vector.
+ // If it is, something has gone wrong and we should not try to swap in the new item.
+ ASSERT(m_currentIndex < m_entries.size());
+
+ removedItems.append(m_entries[m_currentIndex]);
+ m_entries[m_currentIndex] = newItem;
+ } else {
+ // m_current should never be pointing more than 1 past the end of the entries Vector.
+ // If it is, something has gone wrong and we should not try to insert the new item.
+ ASSERT(m_currentIndex <= m_entries.size());
- m_page->didChangeBackForwardList(newItem, &removedItems);
+ if (m_currentIndex <= m_entries.size())
+ m_entries.insert(m_currentIndex, newItem);
+ }
+
+ m_page->didChangeBackForwardList(newItem, WTFMove(removedItems));
}
void WebBackForwardList::goToItem(WebBackForwardListItem* item)
@@ -136,52 +169,76 @@ void WebBackForwardList::goToItem(WebBackForwardListItem* item)
if (!m_entries.size() || !item || !m_page || !m_hasCurrentIndex)
return;
-
- unsigned index = 0;
- for (; index < m_entries.size(); ++index) {
- if (m_entries[index] == item)
- break;
+
+ size_t targetIndex = m_entries.find(item);
+
+ // If the target item wasn't even in the list, there's nothing else to do.
+ if (targetIndex == notFound)
+ return;
+
+ if (targetIndex < m_currentIndex) {
+ unsigned delta = m_entries.size() - targetIndex - 1;
+ String deltaValue = delta > 10 ? ASCIILiteral("over10") : String::number(delta);
+ m_page->logDiagnosticMessageWithValue(WebCore::DiagnosticLoggingKeys::backNavigationKey(), WebCore::DiagnosticLoggingKeys::deltaKey(), deltaValue, false /* shouldSample */);
}
- if (index < m_entries.size()) {
- m_currentIndex = index;
- m_page->didChangeBackForwardList(0, 0);
+
+ // If we're going to an item different from the current item, ask the client if the current
+ // item should remain in the list.
+ WebBackForwardListItem* currentItem = m_entries[m_currentIndex].get();
+ bool shouldKeepCurrentItem = true;
+ if (currentItem != item) {
+ m_page->recordNavigationSnapshot();
+ shouldKeepCurrentItem = m_page->shouldKeepCurrentBackForwardListItemInList(m_entries[m_currentIndex].get());
}
+
+ // If the client said to remove the current item, remove it and then update the target index.
+ Vector<RefPtr<WebBackForwardListItem>> removedItems;
+ if (!shouldKeepCurrentItem) {
+ removedItems.append(currentItem);
+ m_entries.remove(m_currentIndex);
+ targetIndex = m_entries.find(item);
+
+ ASSERT(targetIndex != notFound);
+ }
+
+ m_currentIndex = targetIndex;
+ m_page->didChangeBackForwardList(nullptr, removedItems);
}
-WebBackForwardListItem* WebBackForwardList::currentItem()
+WebBackForwardListItem* WebBackForwardList::currentItem() const
{
ASSERT(!m_hasCurrentIndex || m_currentIndex < m_entries.size());
- return m_page && m_hasCurrentIndex ? m_entries[m_currentIndex].get() : 0;
+ return m_page && m_hasCurrentIndex ? m_entries[m_currentIndex].get() : nullptr;
}
-WebBackForwardListItem* WebBackForwardList::backItem()
+WebBackForwardListItem* WebBackForwardList::backItem() const
{
ASSERT(!m_hasCurrentIndex || m_currentIndex < m_entries.size());
- return m_page && m_hasCurrentIndex && m_currentIndex ? m_entries[m_currentIndex - 1].get() : 0;
+ return m_page && m_hasCurrentIndex && m_currentIndex ? m_entries[m_currentIndex - 1].get() : nullptr;
}
-WebBackForwardListItem* WebBackForwardList::forwardItem()
+WebBackForwardListItem* WebBackForwardList::forwardItem() const
{
ASSERT(!m_hasCurrentIndex || m_currentIndex < m_entries.size());
- return m_page && m_hasCurrentIndex && m_entries.size() && m_currentIndex < m_entries.size() - 1 ? m_entries[m_currentIndex + 1].get() : 0;
+ return m_page && m_hasCurrentIndex && m_entries.size() && m_currentIndex < m_entries.size() - 1 ? m_entries[m_currentIndex + 1].get() : nullptr;
}
-WebBackForwardListItem* WebBackForwardList::itemAtIndex(int index)
+WebBackForwardListItem* WebBackForwardList::itemAtIndex(int index) const
{
ASSERT(!m_hasCurrentIndex || m_currentIndex < m_entries.size());
if (!m_hasCurrentIndex || !m_page)
- return 0;
+ return nullptr;
// Do range checks without doing math on index to avoid overflow.
if (index < -backListCount())
- return 0;
+ return nullptr;
if (index > forwardListCount())
- return 0;
+ return nullptr;
return m_entries[index + m_currentIndex].get();
}
@@ -200,19 +257,29 @@ int WebBackForwardList::forwardListCount() const
return m_page && m_hasCurrentIndex ? m_entries.size() - (m_currentIndex + 1) : 0;
}
-PassRefPtr<ImmutableArray> WebBackForwardList::backListAsImmutableArrayWithLimit(unsigned limit) const
+Ref<API::Array> WebBackForwardList::backList() const
+{
+ return backListAsAPIArrayWithLimit(backListCount());
+}
+
+Ref<API::Array> WebBackForwardList::forwardList() const
+{
+ return forwardListAsAPIArrayWithLimit(forwardListCount());
+}
+
+Ref<API::Array> WebBackForwardList::backListAsAPIArrayWithLimit(unsigned limit) const
{
ASSERT(!m_hasCurrentIndex || m_currentIndex < m_entries.size());
if (!m_page || !m_hasCurrentIndex)
- return ImmutableArray::create();
+ return API::Array::create();
unsigned backListSize = static_cast<unsigned>(backListCount());
unsigned size = std::min(backListSize, limit);
if (!size)
- return ImmutableArray::create();
+ return API::Array::create();
- Vector<RefPtr<APIObject> > vector;
+ Vector<RefPtr<API::Object>> vector;
vector.reserveInitialCapacity(size);
ASSERT(backListSize >= size);
@@ -221,21 +288,21 @@ PassRefPtr<ImmutableArray> WebBackForwardList::backListAsImmutableArrayWithLimit
vector.uncheckedAppend(m_entries[i].get());
}
- return ImmutableArray::adopt(vector);
+ return API::Array::create(WTFMove(vector));
}
-PassRefPtr<ImmutableArray> WebBackForwardList::forwardListAsImmutableArrayWithLimit(unsigned limit) const
+Ref<API::Array> WebBackForwardList::forwardListAsAPIArrayWithLimit(unsigned limit) const
{
ASSERT(!m_hasCurrentIndex || m_currentIndex < m_entries.size());
if (!m_page || !m_hasCurrentIndex)
- return ImmutableArray::create();
+ return API::Array::create();
unsigned size = std::min(static_cast<unsigned>(forwardListCount()), limit);
if (!size)
- return ImmutableArray::create();
+ return API::Array::create();
- Vector<RefPtr<APIObject> > vector;
+ Vector<RefPtr<API::Object>> vector;
vector.reserveInitialCapacity(size);
unsigned last = m_currentIndex + size;
@@ -245,7 +312,27 @@ PassRefPtr<ImmutableArray> WebBackForwardList::forwardListAsImmutableArrayWithLi
vector.uncheckedAppend(m_entries[i].get());
}
- return ImmutableArray::adopt(vector);
+ return API::Array::create(WTFMove(vector));
+}
+
+void WebBackForwardList::removeAllItems()
+{
+ ASSERT(!m_hasCurrentIndex || m_currentIndex < m_entries.size());
+
+ Vector<RefPtr<WebBackForwardListItem>> removedItems;
+
+ for (auto& entry : m_entries) {
+ ASSERT(entry);
+ if (!entry)
+ continue;
+
+ didRemoveItem(*entry);
+ removedItems.append(WTFMove(entry));
+ }
+
+ m_entries.clear();
+ m_hasCurrentIndex = false;
+ m_page->didChangeBackForwardList(nullptr, WTFMove(removedItems));
}
void WebBackForwardList::clear()
@@ -257,7 +344,7 @@ void WebBackForwardList::clear()
return;
RefPtr<WebBackForwardListItem> currentItem = this->currentItem();
- Vector<RefPtr<APIObject> > removedItems;
+ Vector<RefPtr<WebBackForwardListItem>> removedItems;
if (!currentItem) {
// We should only ever have no current item if we also have no current item index.
@@ -269,13 +356,13 @@ void WebBackForwardList::clear()
if (!m_entries[i])
continue;
- m_page->backForwardRemovedItem(m_entries[i]->itemID());
+ didRemoveItem(*m_entries[i]);
removedItems.append(m_entries[i].release());
}
m_entries.clear();
m_hasCurrentIndex = false;
- m_page->didChangeBackForwardList(0, &removedItems);
+ m_page->didChangeBackForwardList(nullptr, WTFMove(removedItems));
return;
}
@@ -283,7 +370,7 @@ void WebBackForwardList::clear()
for (size_t i = 0; i < size; ++i) {
ASSERT(m_entries[i]);
if (m_entries[i] && m_entries[i] != currentItem)
- m_page->backForwardRemovedItem(m_entries[i]->itemID());
+ didRemoveItem(*m_entries[i]);
}
removedItems.reserveCapacity(size - 1);
@@ -302,7 +389,69 @@ void WebBackForwardList::clear()
m_hasCurrentIndex = false;
}
- m_page->didChangeBackForwardList(0, &removedItems);
+ m_page->didChangeBackForwardList(nullptr, WTFMove(removedItems));
+}
+
+BackForwardListState WebBackForwardList::backForwardListState(const std::function<bool (WebBackForwardListItem&)>& filter) const
+{
+ ASSERT(!m_hasCurrentIndex || m_currentIndex < m_entries.size());
+
+ BackForwardListState backForwardListState;
+ if (m_hasCurrentIndex)
+ backForwardListState.currentIndex = m_currentIndex;
+
+ for (size_t i = 0; i < m_entries.size(); ++i) {
+ auto& entry = *m_entries[i];
+
+ if (filter && !filter(entry)) {
+ auto& currentIndex = backForwardListState.currentIndex;
+ if (currentIndex && i <= currentIndex.value() && currentIndex.value())
+ --currentIndex.value();
+
+ continue;
+ }
+
+ backForwardListState.items.append(entry.itemState());
+ }
+
+ if (backForwardListState.items.isEmpty())
+ backForwardListState.currentIndex = Nullopt;
+
+ return backForwardListState;
+}
+
+void WebBackForwardList::restoreFromState(BackForwardListState backForwardListState)
+{
+ Vector<RefPtr<WebBackForwardListItem>> items;
+ items.reserveInitialCapacity(backForwardListState.items.size());
+
+ for (auto& backForwardListItemState : backForwardListState.items) {
+ backForwardListItemState.identifier = generateWebBackForwardItemID();
+ items.uncheckedAppend(WebBackForwardListItem::create(WTFMove(backForwardListItemState), m_page->pageID()));
+ }
+ m_hasCurrentIndex = !!backForwardListState.currentIndex;
+ m_currentIndex = backForwardListState.currentIndex.valueOr(0);
+ m_entries = WTFMove(items);
+}
+
+Vector<BackForwardListItemState> WebBackForwardList::itemStates() const
+{
+ Vector<BackForwardListItemState> itemStates;
+ itemStates.reserveInitialCapacity(m_entries.size());
+
+ for (const auto& entry : m_entries)
+ itemStates.uncheckedAppend(entry->itemState());
+
+ return itemStates;
+}
+
+void WebBackForwardList::didRemoveItem(WebBackForwardListItem& backForwardListItem)
+{
+ m_page->backForwardRemovedItem(backForwardListItem.itemID());
+
+#if PLATFORM(COCOA)
+ backForwardListItem.setSnapshot(nullptr);
+#endif
}
} // namespace WebKit