diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebKit2/UIProcess/WebBackForwardList.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebKit2/UIProcess/WebBackForwardList.cpp')
-rw-r--r-- | Source/WebKit2/UIProcess/WebBackForwardList.cpp | 228 |
1 files changed, 191 insertions, 37 deletions
diff --git a/Source/WebKit2/UIProcess/WebBackForwardList.cpp b/Source/WebKit2/UIProcess/WebBackForwardList.cpp index 411ea56c4..c88e68c95 100644 --- a/Source/WebKit2/UIProcess/WebBackForwardList.cpp +++ b/Source/WebKit2/UIProcess/WebBackForwardList.cpp @@ -27,10 +27,28 @@ #include "WebBackForwardList.h" #include "APIArray.h" +#include "SessionState.h" #include "WebPageProxy.h" +#include <WebCore/DiagnosticLoggingClient.h> +#include <WebCore/DiagnosticLoggingKeys.h> namespace WebKit { +using namespace WebCore; + +// 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) @@ -58,7 +76,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,23 +93,25 @@ void WebBackForwardList::addItem(WebBackForwardListItem* newItem) if (!m_capacity || !newItem || !m_page) return; - Vector<RefPtr<API::Object>> removedItems; + Vector<RefPtr<WebBackForwardListItem>> removedItems; if (m_hasCurrentIndex) { + m_page->recordAutomaticNavigationSnapshot(); + // 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()); - removedItems.append(m_entries.last().release()); + didRemoveItem(*m_entries.last()); + removedItems.append(WTFMove(m_entries.last())); m_entries.removeLast(); } // 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()); - removedItems.append(m_entries[0].release()); + didRemoveItem(*m_entries[0]); + removedItems.append(WTFMove(m_entries[0])); m_entries.remove(0); if (m_entries.isEmpty()) @@ -108,26 +129,41 @@ void WebBackForwardList::addItem(WebBackForwardListItem* newItem) ASSERT(m_entries[i]); if (!m_entries[i]) continue; - m_page->backForwardRemovedItem(m_entries[i]->itemID()); - removedItems.append(m_entries[i].release()); + didRemoveItem(*m_entries[i]); + removedItems.append(WTFMove(m_entries[i])); } 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,16 +172,40 @@ 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->logDiagnosticMessage(WebCore::DiagnosticLoggingKeys::backNavigationDeltaKey(), deltaValue, ShouldSample::No); } - 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->recordAutomaticNavigationSnapshot(); + 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() const @@ -200,7 +260,17 @@ int WebBackForwardList::forwardListCount() const return m_page && m_hasCurrentIndex ? m_entries.size() - (m_currentIndex + 1) : 0; } -PassRefPtr<API::Array> WebBackForwardList::backListAsAPIArrayWithLimit(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()); @@ -221,10 +291,10 @@ PassRefPtr<API::Array> WebBackForwardList::backListAsAPIArrayWithLimit(unsigned vector.uncheckedAppend(m_entries[i].get()); } - return API::Array::create(std::move(vector)); + return API::Array::create(WTFMove(vector)); } -PassRefPtr<API::Array> WebBackForwardList::forwardListAsAPIArrayWithLimit(unsigned limit) const +Ref<API::Array> WebBackForwardList::forwardListAsAPIArrayWithLimit(unsigned limit) const { ASSERT(!m_hasCurrentIndex || m_currentIndex < m_entries.size()); @@ -245,7 +315,27 @@ PassRefPtr<API::Array> WebBackForwardList::forwardListAsAPIArrayWithLimit(unsign vector.uncheckedAppend(m_entries[i].get()); } - return API::Array::create(std::move(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 +347,7 @@ void WebBackForwardList::clear() return; RefPtr<WebBackForwardListItem> currentItem = this->currentItem(); - Vector<RefPtr<API::Object>> 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 +359,13 @@ void WebBackForwardList::clear() if (!m_entries[i]) continue; - m_page->backForwardRemovedItem(m_entries[i]->itemID()); - removedItems.append(m_entries[i].release()); + didRemoveItem(*m_entries[i]); + removedItems.append(WTFMove(m_entries[i])); } m_entries.clear(); m_hasCurrentIndex = false; - m_page->didChangeBackForwardList(0, &removedItems); + m_page->didChangeBackForwardList(nullptr, WTFMove(removedItems)); return; } @@ -283,26 +373,90 @@ 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); for (size_t i = 0; i < size; ++i) { if (i != m_currentIndex && m_hasCurrentIndex && m_entries[i]) - removedItems.append(m_entries[i].release()); + removedItems.append(WTFMove(m_entries[i])); } m_currentIndex = 0; if (currentItem) { m_entries.shrink(1); - m_entries[0] = currentItem.release(); + m_entries[0] = WTFMove(currentItem); } else { m_entries.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 = std::nullopt; + else if (backForwardListState.items.size() <= backForwardListState.currentIndex.value()) + backForwardListState.currentIndex = backForwardListState.items.size() - 1; + + 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.value_or(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 |