Make back forward cache work with process swapping.
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 20 Apr 2018 04:55:32 +0000 (04:55 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 20 Apr 2018 04:55:32 +0000 (04:55 +0000)
<rdar://problem/38676604> and https://bugs.webkit.org/show_bug.cgi?id=184793

Reviewed by Chris Dumez.

Source/WebCore:

Covered by API tests.

* loader/FrameLoader.cpp:
(WebCore::FrameLoader::loadWithNavigationAction):
(WebCore::FrameLoader::load):
(WebCore::FrameLoader::loadWithDocumentLoader):
(WebCore::FrameLoader::reloadWithOverrideEncoding):
(WebCore::FrameLoader::reload):
(WebCore::FrameLoader::commitProvisionalLoad):
(WebCore::FrameLoader::loadDifferentDocumentItem):
* loader/FrameLoader.h:

Source/WebKit:

We previously saved old processes in "SuspendedPageProxy" objects.
Now we reuse them when going back or forward.

* Platform/Logging.h:

* Shared/WebBackForwardListItem.cpp:
(WebKit::WebBackForwardListItem::setSuspendedPage):
(WebKit::WebBackForwardListItem::loggingString):
* Shared/WebBackForwardListItem.h:
(WebKit::WebBackForwardListItem::suspendedPage const):

Teach Navigation objects their source WebBackForwardListItems:
* UIProcess/API/APINavigation.cpp:
(API::Navigation::Navigation):
(API::Navigation::loggingString const):
* UIProcess/API/APINavigation.h:
(API::Navigation::create):
(API::Navigation::targetItem const):
(API::Navigation::fromItem const):
(API::Navigation::backForwardListItem): Deleted.

* UIProcess/Cocoa/NavigationState.mm:
(WebKit::NavigationState::NavigationClient::decidePolicyForNavigationAction):

* UIProcess/SuspendedPageProxy.cpp:
(WebKit::messageNamesToIgnoreWhileSuspended):
(WebKit::SuspendedPageProxy::SuspendedPageProxy):
(WebKit::SuspendedPageProxy::~SuspendedPageProxy):
(WebKit::SuspendedPageProxy::webProcessDidClose):
(WebKit::SuspendedPageProxy::didReceiveMessage):
(WebKit::SuspendedPageProxy::loggingString const):
* UIProcess/SuspendedPageProxy.h:
(WebKit::SuspendedPageProxy::origin const):

* UIProcess/WebBackForwardList.cpp:
(WebKit::WebBackForwardList::WebBackForwardList):
(WebKit::WebBackForwardList::~WebBackForwardList):
(WebKit::WebBackForwardList::pageClosed):
(WebKit::WebBackForwardList::addItem):
(WebKit::WebBackForwardList::goToItem):
(WebKit::WebBackForwardList::removeAllItems):
(WebKit::WebBackForwardList::clear):
(WebKit::WebBackForwardList::restoreFromState):
(WebKit::WebBackForwardList::filteredItemStates const):
(WebKit::WebBackForwardList::itemStates const):
(WebKit::WebBackForwardList::loggingString):
* UIProcess/WebBackForwardList.h:

* UIProcess/WebNavigationState.cpp:
(WebKit::WebNavigationState::createLoadRequestNavigation):
(WebKit::WebNavigationState::createBackForwardNavigation):
* UIProcess/WebNavigationState.h:

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::reattachToWebProcess):
(WebKit::WebPageProxy::maybeCreateSuspendedPage):
(WebKit::WebPageProxy::reattachToWebProcessWithItem):
(WebKit::WebPageProxy::loadRequest):
(WebKit::WebPageProxy::loadFile):
(WebKit::WebPageProxy::goToBackForwardItem):
(WebKit::WebPageProxy::receivedPolicyDecision):
(WebKit::WebPageProxy::continueNavigationInNewProcess):
(WebKit::WebPageProxy::didCreateMainFrame):
(WebKit::WebPageProxy::didCreateSubframe):
(WebKit::WebPageProxy::didStartProvisionalLoadForFrame):
(WebKit::WebPageProxy::didFailProvisionalLoadForFrame):
(WebKit::WebPageProxy::didCommitLoadForFrame):
(WebKit::WebPageProxy::decidePolicyForNavigationAction):
(WebKit::WebPageProxy::connectionWillOpen):
(WebKit::WebPageProxy::attachToProcessForNavigation): Deleted.
* UIProcess/WebPageProxy.h:

* UIProcess/WebProcessLifetimeTracker.cpp:
(WebKit::WebProcessLifetimeTracker::webPageEnteringWebProcess):
(WebKit::WebProcessLifetimeTracker::connectionWillOpen): Deleted.
* UIProcess/WebProcessLifetimeTracker.h:

* UIProcess/WebProcessPool.cpp:
(WebKit::WebProcessPool::processForNavigation):
(WebKit::WebProcessPool::registerSuspendedPageProxy):
(WebKit::WebProcessPool::unregisterSuspendedPageProxy):
* UIProcess/WebProcessPool.h:

* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::suspendWebPageProxy):
(WebKit::WebProcessProxy::updateBackForwardItem):
(WebKit::WebProcessProxy::frameCreated):
* UIProcess/WebProcessProxy.h:

* WebProcess/WebPage/DrawingArea.h:
(WebKit::DrawingArea::attachDrawingArea):

* WebProcess/WebPage/WebBackForwardListProxy.cpp:
(WebKit::WebBackForwardListProxy::addItemFromUIProcess):
(WebKit::WebBackForwardListProxy::addItem):
* WebProcess/WebPage/WebBackForwardListProxy.h:

* WebProcess/WebPage/WebPage.cpp:
(WebKit::m_credentialsMessenger):
(WebKit::WebPage::reinitializeWebPage):
(WebKit::WebPage::goToBackForwardItem):
(WebKit::WebPage::restoreSessionInternal):
(WebKit::WebPage::restoreSession):
(WebKit::WebPage::updateBackForwardListForReattach):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:

* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h:
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
(WebKit::TiledCoreAnimationDrawingArea::TiledCoreAnimationDrawingArea):
(WebKit::TiledCoreAnimationDrawingArea::attachDrawingArea): Force a reattachment of the drawing
  area from a resumed WebProcess to the UIProcess (to make the page cache work)

Tools:

* TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@230834 268f45cc-cd09-0410-ab3c-d52691b4dbfc

34 files changed:
Source/WebCore/ChangeLog
Source/WebCore/loader/FrameLoader.cpp
Source/WebCore/loader/FrameLoader.h
Source/WebKit/ChangeLog
Source/WebKit/Platform/Logging.h
Source/WebKit/Shared/WebBackForwardListItem.cpp
Source/WebKit/Shared/WebBackForwardListItem.h
Source/WebKit/UIProcess/API/APINavigation.cpp
Source/WebKit/UIProcess/API/APINavigation.h
Source/WebKit/UIProcess/Cocoa/NavigationState.mm
Source/WebKit/UIProcess/SuspendedPageProxy.cpp
Source/WebKit/UIProcess/SuspendedPageProxy.h
Source/WebKit/UIProcess/WebBackForwardList.cpp
Source/WebKit/UIProcess/WebBackForwardList.h
Source/WebKit/UIProcess/WebNavigationState.cpp
Source/WebKit/UIProcess/WebNavigationState.h
Source/WebKit/UIProcess/WebPageProxy.cpp
Source/WebKit/UIProcess/WebPageProxy.h
Source/WebKit/UIProcess/WebProcessLifetimeTracker.cpp
Source/WebKit/UIProcess/WebProcessLifetimeTracker.h
Source/WebKit/UIProcess/WebProcessPool.cpp
Source/WebKit/UIProcess/WebProcessPool.h
Source/WebKit/UIProcess/WebProcessProxy.cpp
Source/WebKit/UIProcess/WebProcessProxy.h
Source/WebKit/WebProcess/WebPage/DrawingArea.h
Source/WebKit/WebProcess/WebPage/WebBackForwardListProxy.cpp
Source/WebKit/WebProcess/WebPage/WebBackForwardListProxy.h
Source/WebKit/WebProcess/WebPage/WebPage.cpp
Source/WebKit/WebProcess/WebPage/WebPage.h
Source/WebKit/WebProcess/WebPage/WebPage.messages.in
Source/WebKit/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h
Source/WebKit/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm

index 6c961c5..580bd52 100644 (file)
@@ -1,3 +1,22 @@
+2018-04-19  Brady Eidson  <beidson@apple.com>
+
+        Make back forward cache work with process swapping.
+        <rdar://problem/38676604> and https://bugs.webkit.org/show_bug.cgi?id=184793
+
+        Reviewed by Chris Dumez.
+
+        Covered by API tests.
+
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::loadWithNavigationAction):
+        (WebCore::FrameLoader::load):
+        (WebCore::FrameLoader::loadWithDocumentLoader):
+        (WebCore::FrameLoader::reloadWithOverrideEncoding):
+        (WebCore::FrameLoader::reload):
+        (WebCore::FrameLoader::commitProvisionalLoad):
+        (WebCore::FrameLoader::loadDifferentDocumentItem):
+        * loader/FrameLoader.h:
+
 2018-04-19  Chris Dumez  <cdumez@apple.com>
 
         Rename JSDOMWindowProxy to JSWindowProxy
index 8799da6..8a07152 100644 (file)
@@ -1416,7 +1416,7 @@ void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, const
     if (m_documentLoader)
         loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
 
-    loadWithDocumentLoader(loader.ptr(), type, formState, allowNavigationToInvalidURL, WTFMove(completionHandler));
+    loadWithDocumentLoader(loader.ptr(), type, formState, allowNavigationToInvalidURL, NavigationPolicyCheck::Require, WTFMove(completionHandler));
 }
 
 void FrameLoader::load(DocumentLoader* newDocumentLoader)
@@ -1455,10 +1455,10 @@ void FrameLoader::load(DocumentLoader* newDocumentLoader)
         type = FrameLoadType::Reload;
     }
 
-    loadWithDocumentLoader(newDocumentLoader, type, 0, AllowNavigationToInvalidURL::Yes, [] { });
+    loadWithDocumentLoader(newDocumentLoader, type, 0, AllowNavigationToInvalidURL::Yes, NavigationPolicyCheck::Require, [] { });
 }
 
-void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType type, FormState* formState, AllowNavigationToInvalidURL allowNavigationToInvalidURL, CompletionHandler<void()>&& completionHandler)
+void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType type, FormState* formState, AllowNavigationToInvalidURL allowNavigationToInvalidURL, NavigationPolicyCheck, CompletionHandler<void()>&& completionHandler)
 {
     // Retain because dispatchBeforeLoadEvent may release the last reference to it.
     Ref<Frame> protect(m_frame);
@@ -1643,7 +1643,7 @@ void FrameLoader::reloadWithOverrideEncoding(const String& encoding)
 
     loader->setOverrideEncoding(encoding);
 
-    loadWithDocumentLoader(loader.ptr(), FrameLoadType::Reload, 0, AllowNavigationToInvalidURL::Yes, [] { });
+    loadWithDocumentLoader(loader.ptr(), FrameLoadType::Reload, 0, AllowNavigationToInvalidURL::Yes, NavigationPolicyCheck::Require, [] { });
 }
 
 void FrameLoader::reload(OptionSet<ReloadOption> options)
@@ -1688,7 +1688,7 @@ void FrameLoader::reload(OptionSet<ReloadOption> options)
         return FrameLoadType::Reload;
     };
     
-    loadWithDocumentLoader(loader.ptr(), frameLoadTypeForReloadOptions(options), 0, AllowNavigationToInvalidURL::Yes, [] { });
+    loadWithDocumentLoader(loader.ptr(), frameLoadTypeForReloadOptions(options), 0, AllowNavigationToInvalidURL::Yes, NavigationPolicyCheck::Require, [] { });
 }
 
 void FrameLoader::stopAllLoaders(ClearProvisionalItemPolicy clearProvisionalItemPolicy)
@@ -1857,9 +1857,9 @@ void FrameLoader::commitProvisionalLoad()
     if (m_loadingFromCachedPage && history().provisionalItem())
         cachedPage = PageCache::singleton().take(*history().provisionalItem(), m_frame.page());
 
-    LOG(PageCache, "WebCoreLoading %s: About to commit provisional load from previous URL '%s' to new URL '%s'", m_frame.tree().uniqueName().string().utf8().data(),
+    LOG(PageCache, "WebCoreLoading %s: About to commit provisional load from previous URL '%s' to new URL '%s' with cached page %p", m_frame.tree().uniqueName().string().utf8().data(),
         m_frame.document() ? m_frame.document()->url().stringCenterEllipsizedToLength().utf8().data() : "",
-        pdl ? pdl->url().stringCenterEllipsizedToLength().utf8().data() : "<no provisional DocumentLoader>");
+        pdl ? pdl->url().stringCenterEllipsizedToLength().utf8().data() : "<no provisional DocumentLoader>", cachedPage.get());
 
     willTransitionToCommitted();
 
@@ -3459,12 +3459,14 @@ void FrameLoader::loadDifferentDocumentItem(HistoryItem& item, FrameLoadType loa
 
     auto initiatedByMainFrame = InitiatedByMainFrame::Unknown;
 
+    SetForScope<bool> currentLoadShouldCheckNavigationPolicyGuard(m_currentLoadShouldCheckNavigationPolicy, navigationPolicyCheck != NavigationPolicyCheck::Bypass);
+
     if (CachedPage* cachedPage = PageCache::singleton().get(item, m_frame.page())) {
         auto documentLoader = cachedPage->documentLoader();
         m_client.updateCachedDocumentLoader(*documentLoader);
         documentLoader->setTriggeringAction({ *m_frame.document(), documentLoader->request(), initiatedByMainFrame, loadType, false });
         documentLoader->setLastCheckedRequest(ResourceRequest());
-        loadWithDocumentLoader(documentLoader, loadType, 0, AllowNavigationToInvalidURL::Yes, [] { });
+        loadWithDocumentLoader(documentLoader, loadType, 0, AllowNavigationToInvalidURL::Yes, navigationPolicyCheck, [] { });
         return;
     }
 
@@ -3550,8 +3552,6 @@ void FrameLoader::loadDifferentDocumentItem(HistoryItem& item, FrameLoadType loa
         action = { *m_frame.document(), requestForOriginalURL, initiatedByMainFrame, loadType, isFormSubmission, event, shouldOpenExternalURLsPolicy };
     }
 
-    SetForScope<bool> currentLoadShouldCheckNavigationPolicyGuard(m_currentLoadShouldCheckNavigationPolicy, navigationPolicyCheck != NavigationPolicyCheck::Bypass);
-
     loadWithNavigationAction(request, action, LockHistory::No, loadType, 0, AllowNavigationToInvalidURL::Yes, [] { });
 }
 
index d007354..53faa49 100644 (file)
@@ -363,7 +363,7 @@ private:
 
     void urlSelected(FrameLoadRequest&&, Event*);
 
-    void loadWithDocumentLoader(DocumentLoader*, FrameLoadType, FormState*, AllowNavigationToInvalidURL, CompletionHandler<void()>&&); // Calls continueLoadAfterNavigationPolicy
+    void loadWithDocumentLoader(DocumentLoader*, FrameLoadType, FormState*, AllowNavigationToInvalidURL, NavigationPolicyCheck, CompletionHandler<void()>&&); // Calls continueLoadAfterNavigationPolicy
     void load(DocumentLoader*); // Calls loadWithDocumentLoader
 
     void loadWithNavigationAction(const ResourceRequest&, const NavigationAction&, LockHistory, FrameLoadType, FormState*, AllowNavigationToInvalidURL, CompletionHandler<void()>&&); // Calls loadWithDocumentLoader
index 4625c16..eda153d 100644 (file)
@@ -1,3 +1,123 @@
+2018-04-19  Brady Eidson  <beidson@apple.com>
+
+        Make back forward cache work with process swapping.
+        <rdar://problem/38676604> and https://bugs.webkit.org/show_bug.cgi?id=184793
+
+        Reviewed by Chris Dumez.
+
+        We previously saved old processes in "SuspendedPageProxy" objects.
+        Now we reuse them when going back or forward.
+
+        * Platform/Logging.h:
+
+        * Shared/WebBackForwardListItem.cpp:
+        (WebKit::WebBackForwardListItem::setSuspendedPage):
+        (WebKit::WebBackForwardListItem::loggingString):
+        * Shared/WebBackForwardListItem.h:
+        (WebKit::WebBackForwardListItem::suspendedPage const):
+
+        Teach Navigation objects their source WebBackForwardListItems:
+        * UIProcess/API/APINavigation.cpp:
+        (API::Navigation::Navigation):
+        (API::Navigation::loggingString const):
+        * UIProcess/API/APINavigation.h:
+        (API::Navigation::create):
+        (API::Navigation::targetItem const):
+        (API::Navigation::fromItem const):
+        (API::Navigation::backForwardListItem): Deleted.
+
+        * UIProcess/Cocoa/NavigationState.mm:
+        (WebKit::NavigationState::NavigationClient::decidePolicyForNavigationAction):
+
+        * UIProcess/SuspendedPageProxy.cpp:
+        (WebKit::messageNamesToIgnoreWhileSuspended):
+        (WebKit::SuspendedPageProxy::SuspendedPageProxy):
+        (WebKit::SuspendedPageProxy::~SuspendedPageProxy):
+        (WebKit::SuspendedPageProxy::webProcessDidClose):
+        (WebKit::SuspendedPageProxy::didReceiveMessage):
+        (WebKit::SuspendedPageProxy::loggingString const):
+        * UIProcess/SuspendedPageProxy.h:
+        (WebKit::SuspendedPageProxy::origin const):
+
+        * UIProcess/WebBackForwardList.cpp:
+        (WebKit::WebBackForwardList::WebBackForwardList):
+        (WebKit::WebBackForwardList::~WebBackForwardList):
+        (WebKit::WebBackForwardList::pageClosed):
+        (WebKit::WebBackForwardList::addItem):
+        (WebKit::WebBackForwardList::goToItem):
+        (WebKit::WebBackForwardList::removeAllItems):
+        (WebKit::WebBackForwardList::clear):
+        (WebKit::WebBackForwardList::restoreFromState):
+        (WebKit::WebBackForwardList::filteredItemStates const):
+        (WebKit::WebBackForwardList::itemStates const):
+        (WebKit::WebBackForwardList::loggingString):
+        * UIProcess/WebBackForwardList.h:
+
+        * UIProcess/WebNavigationState.cpp:
+        (WebKit::WebNavigationState::createLoadRequestNavigation):
+        (WebKit::WebNavigationState::createBackForwardNavigation):
+        * UIProcess/WebNavigationState.h:
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::reattachToWebProcess):
+        (WebKit::WebPageProxy::maybeCreateSuspendedPage):
+        (WebKit::WebPageProxy::reattachToWebProcessWithItem):
+        (WebKit::WebPageProxy::loadRequest):
+        (WebKit::WebPageProxy::loadFile):
+        (WebKit::WebPageProxy::goToBackForwardItem):
+        (WebKit::WebPageProxy::receivedPolicyDecision):
+        (WebKit::WebPageProxy::continueNavigationInNewProcess):
+        (WebKit::WebPageProxy::didCreateMainFrame):
+        (WebKit::WebPageProxy::didCreateSubframe):
+        (WebKit::WebPageProxy::didStartProvisionalLoadForFrame):
+        (WebKit::WebPageProxy::didFailProvisionalLoadForFrame):
+        (WebKit::WebPageProxy::didCommitLoadForFrame):
+        (WebKit::WebPageProxy::decidePolicyForNavigationAction):
+        (WebKit::WebPageProxy::connectionWillOpen):
+        (WebKit::WebPageProxy::attachToProcessForNavigation): Deleted.
+        * UIProcess/WebPageProxy.h:
+
+        * UIProcess/WebProcessLifetimeTracker.cpp:
+        (WebKit::WebProcessLifetimeTracker::webPageEnteringWebProcess):
+        (WebKit::WebProcessLifetimeTracker::connectionWillOpen): Deleted.
+        * UIProcess/WebProcessLifetimeTracker.h:
+
+        * UIProcess/WebProcessPool.cpp:
+        (WebKit::WebProcessPool::processForNavigation):
+        (WebKit::WebProcessPool::registerSuspendedPageProxy):
+        (WebKit::WebProcessPool::unregisterSuspendedPageProxy):
+        * UIProcess/WebProcessPool.h:
+
+        * UIProcess/WebProcessProxy.cpp:
+        (WebKit::WebProcessProxy::suspendWebPageProxy):
+        (WebKit::WebProcessProxy::updateBackForwardItem):
+        (WebKit::WebProcessProxy::frameCreated):
+        * UIProcess/WebProcessProxy.h:
+
+        * WebProcess/WebPage/DrawingArea.h:
+        (WebKit::DrawingArea::attachDrawingArea):
+
+        * WebProcess/WebPage/WebBackForwardListProxy.cpp:
+        (WebKit::WebBackForwardListProxy::addItemFromUIProcess):
+        (WebKit::WebBackForwardListProxy::addItem):
+        * WebProcess/WebPage/WebBackForwardListProxy.h:
+
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::m_credentialsMessenger):
+        (WebKit::WebPage::reinitializeWebPage):
+        (WebKit::WebPage::goToBackForwardItem):
+        (WebKit::WebPage::restoreSessionInternal):
+        (WebKit::WebPage::restoreSession):
+        (WebKit::WebPage::updateBackForwardListForReattach):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+
+        * WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h:
+        * WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
+        (WebKit::TiledCoreAnimationDrawingArea::TiledCoreAnimationDrawingArea):
+        (WebKit::TiledCoreAnimationDrawingArea::attachDrawingArea): Force a reattachment of the drawing
+          area from a resumed WebProcess to the UIProcess (to make the page cache work)
+
 2018-04-19  Brian Burg  <bburg@apple.com>
 
         Web Automation: add support for mouse/keyboard interaction sequences
index f55855c..9a4dab9 100644 (file)
@@ -40,6 +40,7 @@ extern "C" {
 #endif
 
 #define WEBKIT2_LOG_CHANNELS(M) \
+    M(BackForward) \
     M(CacheStorage) \
     M(ContextMenu) \
     M(DragAndDrop) \
index a738c7d..32e7c78 100644 (file)
@@ -27,6 +27,7 @@
 #include "WebBackForwardListItem.h"
 
 #include <WebCore/URL.h>
+#include <wtf/DebugUtilities.h>
 
 using namespace WebCore;
 
@@ -111,9 +112,17 @@ bool WebBackForwardListItem::itemIsInSameDocument(const WebBackForwardListItem&
     return documentTreesAreEqual(mainFrameState, otherMainFrameState);
 }
 
-void WebBackForwardListItem::setSuspendedPage(SuspendedPageProxy& page)
+void WebBackForwardListItem::setSuspendedPage(SuspendedPageProxy* page)
 {
-    m_suspendedPage = &page;
+    ASSERT(!m_suspendedPage || page == nullptr);
+    m_suspendedPage = page;
 }
 
+#if !LOG_DISABLED
+const char* WebBackForwardListItem::loggingString()
+{
+    return debugString("Back/forward item ID ", itemID().logString(), ", original URL ", originalURL(), ", current URL ", url(), m_suspendedPage ? "(has a suspended page)" : "");
+}
+#endif // !LOG_DISABLED
+
 } // namespace WebKit
index 3c1cc29..ba746be 100644 (file)
@@ -68,7 +68,12 @@ public:
     ViewSnapshot* snapshot() const { return m_itemState.snapshot.get(); }
     void setSnapshot(RefPtr<ViewSnapshot>&& snapshot) { m_itemState.snapshot = WTFMove(snapshot); }
 #endif
-    void setSuspendedPage(SuspendedPageProxy&);
+    void setSuspendedPage(SuspendedPageProxy*);
+    SuspendedPageProxy* suspendedPage() const { return m_suspendedPage; }
+
+#if !LOG_DISABLED
+    const char* loggingString();
+#endif
 
 private:
     explicit WebBackForwardListItem(BackForwardListItemState&&, uint64_t pageID);
index b95753c..53ddbb6 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "WebBackForwardListItem.h"
 #include "WebNavigationState.h"
+#include <wtf/DebugUtilities.h>
 
 using namespace WebCore;
 using namespace WebKit;
@@ -39,19 +40,21 @@ Navigation::Navigation(WebNavigationState& state)
 {
 }
 
-Navigation::Navigation(WebNavigationState& state, WebCore::ResourceRequest&& request)
+Navigation::Navigation(WebNavigationState& state, WebCore::ResourceRequest&& request, WebBackForwardListItem* fromItem)
     : m_navigationID(state.generateNavigationID())
     , m_originalRequest(WTFMove(request))
     , m_currentRequest(m_originalRequest)
+    , m_fromItem(fromItem)
 {
     m_redirectChain.append(m_originalRequest.url());
 }
 
-Navigation::Navigation(WebNavigationState& state, WebBackForwardListItem& item, FrameLoadType backForwardFrameLoadType)
+Navigation::Navigation(WebNavigationState& state, WebBackForwardListItem& targetItem, WebBackForwardListItem* fromItem, FrameLoadType backForwardFrameLoadType)
     : m_navigationID(state.generateNavigationID())
-    , m_originalRequest(item.url())
+    , m_originalRequest(targetItem.url())
     , m_currentRequest(m_originalRequest)
-    , m_backForwardListItem(&item)
+    , m_targetItem(&targetItem)
+    , m_fromItem(fromItem)
     , m_backForwardFrameLoadType(backForwardFrameLoadType)
 {
 }
@@ -73,9 +76,9 @@ void Navigation::appendRedirectionURL(const URL& url)
 }
 
 #if !LOG_DISABLED
-WTF::String Navigation::loggingString() const
+const char* Navigation::loggingString() const
 {
-    return makeString("Most recent URL: ", m_currentRequest.url().string(), " Back/forward list item URL: '", m_backForwardListItem ? m_backForwardListItem->url() : String { }, String::format("' (%p)", m_backForwardListItem.get()));
+    return debugString("Most recent URL: ", m_currentRequest.url().string(), " Back/forward list item URL: '", m_targetItem ? m_targetItem->url() : String { }, String::format("' (%p)", m_targetItem.get()));
 }
 #endif
 
index 947fb3c..9632e2b 100644 (file)
@@ -49,14 +49,14 @@ public:
         return adoptRef(*new Navigation(state));
     }
 
-    static Ref<Navigation> create(WebKit::WebNavigationState& state, WebKit::WebBackForwardListItem& item, WebCore::FrameLoadType backForwardFrameLoadType)
+    static Ref<Navigation> create(WebKit::WebNavigationState& state, WebKit::WebBackForwardListItem& targetItem, WebKit::WebBackForwardListItem* fromItem, WebCore::FrameLoadType backForwardFrameLoadType)
     {
-        return adoptRef(*new Navigation(state, item, backForwardFrameLoadType));
+        return adoptRef(*new Navigation(state, targetItem, fromItem, backForwardFrameLoadType));
     }
 
-    static Ref<Navigation> create(WebKit::WebNavigationState& state, WebCore::ResourceRequest&& request)
+    static Ref<Navigation> create(WebKit::WebNavigationState& state, WebCore::ResourceRequest&& request, WebKit::WebBackForwardListItem* fromItem)
     {
-        return adoptRef(*new Navigation(state, WTFMove(request)));
+        return adoptRef(*new Navigation(state, WTFMove(request), fromItem));
     }
 
     virtual ~Navigation();
@@ -71,7 +71,8 @@ public:
     void setCurrentRequestIsRedirect(bool isRedirect) { m_isRedirect = isRedirect; }
     bool currentRequestIsRedirect() const { return m_isRedirect; }
 
-    WebKit::WebBackForwardListItem* backForwardListItem() { return m_backForwardListItem.get(); }
+    WebKit::WebBackForwardListItem* targetItem() const { return m_targetItem.get(); }
+    WebKit::WebBackForwardListItem* fromItem() const { return m_fromItem.get(); }
     std::optional<WebCore::FrameLoadType> backForwardFrameLoadType() const { return m_backForwardFrameLoadType; }
 
     void appendRedirectionURL(const WebCore::URL&);
@@ -90,13 +91,13 @@ public:
     const std::optional<std::pair<uint64_t, uint64_t>>& opener() const { return m_opener; }
 
 #if !LOG_DISABLED
-    WTF::String loggingString() const;
+    const char* loggingString() const;
 #endif
 
 private:
     explicit Navigation(WebKit::WebNavigationState&);
-    Navigation(WebKit::WebNavigationState&, WebCore::ResourceRequest&&);
-    Navigation(WebKit::WebNavigationState&, WebKit::WebBackForwardListItem&, WebCore::FrameLoadType);
+    Navigation(WebKit::WebNavigationState&, WebCore::ResourceRequest&&, WebKit::WebBackForwardListItem* fromItem);
+    Navigation(WebKit::WebNavigationState&, WebKit::WebBackForwardListItem& targetItem, WebKit::WebBackForwardListItem* fromItem, WebCore::FrameLoadType);
 
     uint64_t m_navigationID;
     WebCore::ResourceRequest m_originalRequest;
@@ -107,7 +108,8 @@ private:
     bool m_shouldForceDownload { false };
     bool m_isRedirect { false };
 
-    RefPtr<WebKit::WebBackForwardListItem> m_backForwardListItem;
+    RefPtr<WebKit::WebBackForwardListItem> m_targetItem;
+    RefPtr<WebKit::WebBackForwardListItem> m_fromItem;
     std::optional<WebCore::FrameLoadType> m_backForwardFrameLoadType;
     bool m_isCrossOriginWindowOpenNavigation { false };
     std::optional<std::pair<uint64_t, uint64_t>> m_opener;
index 6e78e22..a09a20a 100644 (file)
@@ -476,6 +476,7 @@ static void tryAppLink(Ref<API::NavigationAction>&& navigationAction, const Stri
 
 void NavigationState::NavigationClient::decidePolicyForNavigationAction(WebPageProxy& webPageProxy, Ref<API::NavigationAction>&& navigationAction, Ref<WebFramePolicyListenerProxy>&& listener, API::Object* userInfo)
 {
+    ASSERT(webPageProxy.mainFrame());
     String mainFrameURLString = webPageProxy.mainFrame()->url();
     bool subframeNavigation = navigationAction->targetFrame() && !navigationAction->targetFrame()->isMainFrame();
 
index 4460f44..6e0653f 100644 (file)
 #include "WebPageProxy.h"
 #include "WebPageProxyMessages.h"
 #include "WebProcessMessages.h"
+#include "WebProcessPool.h"
 #include "WebProcessProxy.h"
+#include <WebCore/URL.h>
 #include <wtf/DebugUtilities.h>
 
+using namespace WebCore;
+
 namespace WebKit {
 
 #if !LOG_DISABLED
@@ -55,6 +59,7 @@ static const HashSet<IPC::StringReference>& messageNamesToIgnoreWhileSuspended()
         messageNames.get().add("DidFirstVisuallyNonEmptyLayoutForFrame");
         messageNames.get().add("DidNavigateWithNavigationData");
         messageNames.get().add("DidReachLayoutMilestone");
+        messageNames.get().add("DidRestoreScrollPosition");
         messageNames.get().add("DidSaveToPageCache");
         messageNames.get().add("DidStartProgress");
         messageNames.get().add("DidStartProvisionalLoadForFrame");
@@ -62,6 +67,7 @@ static const HashSet<IPC::StringReference>& messageNamesToIgnoreWhileSuspended()
         messageNames.get().add("PageExtendedBackgroundColorDidChange");
         messageNames.get().add("SetRenderTreeSize");
         messageNames.get().add("SetStatusText");
+        messageNames.get().add("SetNetworkRequestsInProgress");
     });
 
     return messageNames;
@@ -72,23 +78,32 @@ SuspendedPageProxy::SuspendedPageProxy(WebPageProxy& page, WebProcessProxy& proc
     : m_page(page)
     , m_process(&process)
     , m_backForwardListItem(item)
+    , m_origin(SecurityOriginData::fromURL({ ParsedURLString, item.url() }))
 {
-    m_backForwardListItem->setSuspendedPage(*this);
+    m_backForwardListItem->setSuspendedPage(this);
+    m_process->processPool().registerSuspendedPageProxy(*this);
     m_process->send(Messages::WebPage::SetIsSuspended(true), m_page.pageID());
 }
 
 SuspendedPageProxy::~SuspendedPageProxy()
 {
-    if (m_process)
+    if (m_process) {
         m_process->suspendedPageWasDestroyed(*this);
+        m_process->processPool().unregisterSuspendedPageProxy(*this);
+    }
+
+    m_backForwardListItem->setSuspendedPage(nullptr);
 }
 
 void SuspendedPageProxy::webProcessDidClose(WebProcessProxy& process)
 {
     ASSERT_UNUSED(process, &process == m_process);
+
+    m_process->processPool().unregisterSuspendedPageProxy(*this);
     m_process = nullptr;
 
     m_page.suspendedPageProcessClosed(*this);
+    m_backForwardListItem->setSuspendedPage(nullptr);
 }
 
 void SuspendedPageProxy::didFinishLoad()
@@ -110,7 +125,7 @@ void SuspendedPageProxy::didReceiveMessage(IPC::Connection&, IPC::Decoder& decod
         return;
     }
 #if !LOG_DISABLED
-    if (messageNamesToIgnoreWhileSuspended().contains(decoder.messageName()))
+    if (!messageNamesToIgnoreWhileSuspended().contains(decoder.messageName()))
         LOG(ProcessSwapping, "SuspendedPageProxy received unexpected WebPageProxy message '%s'", decoder.messageName().toString().data());
 #endif
 }
@@ -118,7 +133,7 @@ void SuspendedPageProxy::didReceiveMessage(IPC::Connection&, IPC::Decoder& decod
 #if !LOG_DISABLED
 const char* SuspendedPageProxy::loggingString() const
 {
-    return debugString("(", String::format("%p", this), "page ID ", String::number(m_page.pageID()), ", m_finishedSuspending ", String::number(m_finishedSuspending), ")");
+    return debugString("(", String::format("%p", this), " page ID ", String::number(m_page.pageID()), ", m_finishedSuspending ", String::number(m_finishedSuspending), ")");
 }
 #endif
 
index cd9cbc0..99d9b0c 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "Connection.h"
 #include "WebBackForwardListItem.h"
+#include <WebCore/SecurityOriginData.h>
 #include <wtf/RefCounted.h>
 
 namespace WebKit {
@@ -48,6 +49,7 @@ public:
     WebPageProxy& page() const { return m_page; }
     WebProcessProxy* process() const { return m_process; }
     WebBackForwardListItem& item() const { return m_backForwardListItem; }
+    const WebCore::SecurityOriginData& origin() const { return m_origin; }
 
     bool finishedSuspending() const { return m_finishedSuspending; }
 
@@ -65,6 +67,7 @@ private:
     WebPageProxy& m_page;
     WebProcessProxy* m_process;
     Ref<WebBackForwardListItem> m_backForwardListItem;
+    WebCore::SecurityOriginData m_origin;
 
     bool m_finishedSuspending { false };
 };
index f0c3941..6006a02 100644 (file)
 #include "WebBackForwardList.h"
 
 #include "APIArray.h"
+#include "Logging.h"
 #include "SessionState.h"
 #include "WebPageProxy.h"
 #include <WebCore/DiagnosticLoggingClient.h>
 #include <WebCore/DiagnosticLoggingKeys.h>
+#include <wtf/DebugUtilities.h>
+#include <wtf/text/StringBuilder.h>
 
 namespace WebKit {
 
@@ -44,10 +47,13 @@ WebBackForwardList::WebBackForwardList(WebPageProxy& page)
     , m_currentIndex(0)
     , m_capacity(DefaultCapacity)
 {
+    LOG(BackForward, "(Back/Forward) Created WebBackForwardList %p", this);
 }
 
 WebBackForwardList::~WebBackForwardList()
 {
+    LOG(BackForward, "(Back/Forward) Destroying WebBackForwardList %p", this);
+
     // A WebBackForwardList should never be destroyed unless it's associated page has been closed or is invalid.
     ASSERT((!m_page && !m_hasCurrentIndex) || !m_page->isValid());
 }
@@ -67,6 +73,8 @@ WebBackForwardListItem* WebBackForwardList::itemForID(const BackForwardItemIdent
 
 void WebBackForwardList::pageClosed()
 {
+    LOG(BackForward, "(Back/Forward) WebBackForwardList %p had its page closed with current size %zu", this, m_entries.size());
+
     // We should have always started out with an m_page and we should never close the page twice.
     ASSERT(m_page);
 
@@ -156,6 +164,7 @@ void WebBackForwardList::addItem(Ref<WebBackForwardListItem>&& newItem)
             m_entries.insert(m_currentIndex, WTFMove(newItem));
     }
 
+    LOG(BackForward, "(Back/Forward) WebBackForwardList %p added an item. Current size %zu, current index %zu, threw away %zu items", this, m_entries.size(), m_currentIndex, removedItems.size());
     m_page->didChangeBackForwardList(newItemPtr, WTFMove(removedItems));
 }
 
@@ -175,8 +184,10 @@ void WebBackForwardList::goToItem(WebBackForwardListItem& item)
     }
 
     // If the target item wasn't even in the list, there's nothing else to do.
-    if (targetIndex == notFound)
+    if (targetIndex == notFound) {
+        LOG(BackForward, "(Back/Forward) WebBackForwardList %p could not go to item %s (%s) because it was not found", this, item.itemID().logString(), item.url().utf8().data());
         return;
+    }
 
     if (targetIndex < m_currentIndex) {
         unsigned delta = m_entries.size() - targetIndex - 1;
@@ -209,6 +220,9 @@ void WebBackForwardList::goToItem(WebBackForwardListItem& item)
     }
 
     m_currentIndex = targetIndex;
+
+    LOG(BackForward, "(Back/Forward) WebBackForwardList %p going to item %s, is now at index %zu", this, item.itemID().logString(), targetIndex);
+
     m_page->didChangeBackForwardList(nullptr, WTFMove(removedItems));
 }
 
@@ -322,6 +336,8 @@ void WebBackForwardList::removeAllItems()
 {
     ASSERT(!m_hasCurrentIndex || m_currentIndex < m_entries.size());
 
+    LOG(BackForward, "(Back/Forward) WebBackForwardList %p removeAllItems (has %zu of them)", this, m_entries.size());
+
     Vector<Ref<WebBackForwardListItem>> removedItems;
 
     for (auto& entry : m_entries) {
@@ -338,6 +354,8 @@ void WebBackForwardList::clear()
 {
     ASSERT(!m_hasCurrentIndex || m_currentIndex < m_entries.size());
 
+    LOG(BackForward, "(Back/Forward) WebBackForwardList %p clear (has %zu of them)", this, m_entries.size());
+
     size_t size = m_entries.size();
     if (!m_page || size <= 1)
         return;
@@ -425,19 +443,30 @@ void WebBackForwardList::restoreFromState(BackForwardListState backForwardListSt
     m_hasCurrentIndex = !!backForwardListState.currentIndex;
     m_currentIndex = backForwardListState.currentIndex.value_or(0);
     m_entries = WTFMove(items);
+
+    LOG(BackForward, "(Back/Forward) WebBackForwardList %p restored from state (has %zu entries)", this, m_entries.size());
 }
 
-Vector<BackForwardListItemState> WebBackForwardList::itemStates() const
+Vector<BackForwardListItemState> WebBackForwardList::filteredItemStates(Function<bool(WebBackForwardListItem&)>&& functor) const
 {
     Vector<BackForwardListItemState> itemStates;
     itemStates.reserveInitialCapacity(m_entries.size());
 
-    for (const auto& entry : m_entries)
-        itemStates.uncheckedAppend(entry->itemState());
+    for (const auto& entry : m_entries) {
+        if (functor(entry))
+            itemStates.uncheckedAppend(entry->itemState());
+    }
 
     return itemStates;
 }
 
+Vector<BackForwardListItemState> WebBackForwardList::itemStates() const
+{
+    return filteredItemStates([](WebBackForwardListItem&) {
+        return true;
+    });
+}
+
 void WebBackForwardList::didRemoveItem(WebBackForwardListItem& backForwardListItem)
 {
     m_page->backForwardRemovedItem(backForwardListItem.itemID());
@@ -447,4 +476,25 @@ void WebBackForwardList::didRemoveItem(WebBackForwardListItem& backForwardListIt
 #endif
 }
 
+
+#if !LOG_DISABLED
+const char* WebBackForwardList::loggingString()
+{
+    StringBuilder builder;
+    builder.append(String::format("WebBackForwardList %p - %zu entries, has current index %s (%zu)", this, m_entries.size(), m_hasCurrentIndex ? "YES" : "NO", m_hasCurrentIndex ? m_currentIndex : 0));
+
+    for (size_t i = 0; i < m_entries.size(); ++i) {
+        builder.append("\n");
+        if (m_hasCurrentIndex && m_currentIndex == i)
+            builder.append(" * ");
+        else
+            builder.append(" - ");
+
+        builder.append(m_entries[i]->loggingString());
+    }
+
+    return debugString("\n", builder.toString());
+}
+#endif // !LOG_DISABLED
+
 } // namespace WebKit
index 28fcea3..5ea5678 100644 (file)
@@ -74,6 +74,11 @@ public:
     void restoreFromState(BackForwardListState);
 
     Vector<BackForwardListItemState> itemStates() const;
+    Vector<BackForwardListItemState> filteredItemStates(Function<bool(WebBackForwardListItem&)>&&) const;
+
+#if !LOG_DISABLED
+    const char* loggingString();
+#endif
 
 private:
     explicit WebBackForwardList(WebPageProxy&);
index 31a707b..98024a4 100644 (file)
@@ -42,18 +42,18 @@ WebNavigationState::~WebNavigationState()
 {
 }
 
-Ref<API::Navigation> WebNavigationState::createLoadRequestNavigation(ResourceRequest&& request)
+Ref<API::Navigation> WebNavigationState::createLoadRequestNavigation(ResourceRequest&& request, WebBackForwardListItem* currentItem)
 {
-    auto navigation = API::Navigation::create(*this, WTFMove(request));
+    auto navigation = API::Navigation::create(*this, WTFMove(request), currentItem);
 
     m_navigations.set(navigation->navigationID(), navigation.ptr());
 
     return navigation;
 }
 
-Ref<API::Navigation> WebNavigationState::createBackForwardNavigation(WebBackForwardListItem& item, FrameLoadType frameLoadType)
+Ref<API::Navigation> WebNavigationState::createBackForwardNavigation(WebBackForwardListItem& targetItem, WebBackForwardListItem* currentItem, FrameLoadType frameLoadType)
 {
-    auto navigation = API::Navigation::create(*this, item, frameLoadType);
+    auto navigation = API::Navigation::create(*this, targetItem, currentItem, frameLoadType);
 
     m_navigations.set(navigation->navigationID(), navigation.ptr());
 
index 0e12f3f..1366e3c 100644 (file)
@@ -48,8 +48,8 @@ public:
     explicit WebNavigationState();
     ~WebNavigationState();
 
-    Ref<API::Navigation> createBackForwardNavigation(WebBackForwardListItem&, WebCore::FrameLoadType);
-    Ref<API::Navigation> createLoadRequestNavigation(WebCore::ResourceRequest&&);
+    Ref<API::Navigation> createBackForwardNavigation(WebBackForwardListItem& targetItem, WebBackForwardListItem* currentItem, WebCore::FrameLoadType);
+    Ref<API::Navigation> createLoadRequestNavigation(WebCore::ResourceRequest&&, WebBackForwardListItem* currentItem);
     Ref<API::Navigation> createReloadNavigation();
     Ref<API::Navigation> createLoadDataNavigation();
 
index d3ad3c5..bfd3699 100644 (file)
@@ -661,25 +661,14 @@ void WebPageProxy::handleSynchronousMessage(IPC::Connection& connection, const S
 void WebPageProxy::reattachToWebProcess()
 {
     auto process = makeRef(m_process->processPool().createNewWebProcessRespectingProcessCountLimit(m_websiteDataStore.get()));
-    reattachToWebProcess(WTFMove(process), false);
+    reattachToWebProcess(WTFMove(process), nullptr, ReattachForBackForward::No);
 }
 
-void WebPageProxy::attachToProcessForNavigation(Ref<WebProcessProxy>&& process)
-{
-    // FIXME: If this WebPageProxy is the only one hosted in its WebProcess, does this make it go away?
-    // We need to be prepared to reuse it later.
-    processDidTerminate(ProcessTerminationReason::NavigationSwap);
-
-    // FIXME: this is to fix the ASSERT(isValid()) inside reattachToWebProcess, some other way to fix this is needed.
-    m_isValid = false;
-    reattachToWebProcess(WTFMove(process), true);
-}
-
-SuspendedPageProxy* WebPageProxy::maybeCreateSuspendedPage(WebProcessProxy& process)
+SuspendedPageProxy* WebPageProxy::maybeCreateSuspendedPage(WebProcessProxy& process, API::Navigation& navigation)
 {
     ASSERT(!m_suspendedPage || m_suspendedPage->process() != &process);
 
-    auto* currentItem = m_backForwardList->currentItem();
+    auto* currentItem = navigation.fromItem();
     if (!currentItem) {
         LOG(ProcessSwapping, "WebPageProxy %" PRIu64 " unable to create suspended page for process pid %i - No current back/forward item", pageID(), process.processIdentifier());
         return nullptr;
@@ -698,20 +687,36 @@ void WebPageProxy::suspendedPageProcessClosed(SuspendedPageProxy& page)
     m_suspendedPage = nullptr;
 }
 
-void WebPageProxy::reattachToWebProcess(Ref<WebProcessProxy>&& process, bool suspendInOldProcess)
+void WebPageProxy::reattachToWebProcess(Ref<WebProcessProxy>&& process, API::Navigation* navigation, ReattachForBackForward reattachForBackForward)
 {
     ASSERT(!m_isClosed);
     ASSERT(!isValid());
 
     m_isValid = true;
 
-    if (!suspendInOldProcess) {
+    // If the process we're attaching to is kept alive solely by our current suspended page,
+    // we need to maintain that by temporarily keeping the suspended page alive.
+    RefPtr<SuspendedPageProxy> currentSuspendedPage;
+    if (!navigation) {
         m_process->removeWebPage(*this, m_pageID);
         m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
-    } else
-        m_process->suspendWebPageProxy(*this);
+    } else {
+        currentSuspendedPage = m_suspendedPage;
+        m_process->suspendWebPageProxy(*this, *navigation);
+    }
 
     m_process = WTFMove(process);
+    if (m_process->state() == WebProcessProxy::State::Running)
+        m_webProcessLifetimeTracker.webPageEnteringWebProcess();
+
+    if (reattachForBackForward == ReattachForBackForward::Yes) {
+        ASSERT(!m_mainFrame);
+        ASSERT(m_mainFrameID);
+        m_mainFrame = WebFrameProxy::create(this, *m_mainFrameID);
+        m_process->frameCreated(*m_mainFrameID, *m_mainFrame);
+    }
+
+    LOG(ProcessSwapping, "(ProcessSwapping) Reattaching WebPageProxy %p to WebProcessProxy %p with pid %i\n", this, m_process.ptr(), m_process->processIdentifier());
 
     ASSERT(m_process->state() != ChildProcessProxy::State::Terminated);
     if (m_process->state() == ChildProcessProxy::State::Running)
@@ -778,7 +783,7 @@ RefPtr<API::Navigation> WebPageProxy::reattachToWebProcessWithItem(WebBackForwar
     if (&item != m_backForwardList->currentItem())
         m_backForwardList->goToItem(item);
 
-    auto navigation = m_navigationState->createBackForwardNavigation(item, FrameLoadType::IndexedBackForward);
+    auto navigation = m_navigationState->createBackForwardNavigation(item, m_backForwardList->currentItem(), FrameLoadType::IndexedBackForward);
 
     m_process->send(Messages::WebPage::GoToBackForwardItem(navigation->navigationID(), item.itemID(), FrameLoadType::IndexedBackForward, NavigationPolicyCheck::Require), m_pageID);
     m_process->responsivenessTimer().start();
@@ -930,7 +935,7 @@ RefPtr<API::Navigation> WebPageProxy::loadRequest(ResourceRequest&& request, Sho
     if (m_isClosed)
         return nullptr;
 
-    auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(request));
+    auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(request), m_backForwardList->currentItem());
     loadRequestWithNavigation(navigation.get(), WTFMove(request), shouldOpenExternalURLsPolicy, userData, NavigationPolicyCheck::Require);
     return WTFMove(navigation);
 }
@@ -983,7 +988,7 @@ RefPtr<API::Navigation> WebPageProxy::loadFile(const String& fileURLString, cons
             return nullptr;
     }
 
-    auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(fileURL));
+    auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(fileURL), m_backForwardList->currentItem());
 
     auto transaction = m_pageLoadState.transaction();
 
@@ -1244,7 +1249,7 @@ RefPtr<API::Navigation> WebPageProxy::goToBackForwardItem(WebBackForwardListItem
 
 RefPtr<API::Navigation> WebPageProxy::goToBackForwardItem(WebBackForwardListItem& item, FrameLoadType frameLoadType)
 {
-    LOG(Loading, "WebPageProxy %p goToBackForwardItem to back item URL %s", this, item.url().utf8().data());
+    LOG(Loading, "WebPageProxy %p goToBackForwardItem to item URL %s", this, item.url().utf8().data());
 
     if (!isValid())
         return reattachToWebProcessWithItem(item);
@@ -1255,7 +1260,7 @@ RefPtr<API::Navigation> WebPageProxy::goToBackForwardItem(WebBackForwardListItem
 
     RefPtr<API::Navigation> navigation;
     if (!m_backForwardList->currentItem()->itemIsInSameDocument(item))
-        navigation = m_navigationState->createBackForwardNavigation(item, frameLoadType);
+        navigation = m_navigationState->createBackForwardNavigation(item, m_backForwardList->currentItem(), frameLoadType);
 
     m_process->send(Messages::WebPage::GoToBackForwardItem(navigation ? navigation->navigationID() : 0, item.itemID(), frameLoadType, NavigationPolicyCheck::Require), m_pageID);
     m_process->responsivenessTimer().start();
@@ -2397,7 +2402,7 @@ void WebPageProxy::receivedPolicyDecision(PolicyAction action, WebFrameProxy& fr
             auto proposedProcess = process().processPool().processForNavigation(*this, *navigation, action);
 
             if (proposedProcess.ptr() != &process()) {
-                LOG(ProcessSwapping, "Switching from process %i to new process for navigation %" PRIu64 " '%s'", processIdentifier(), navigation->navigationID(), navigation->loggingString().utf8().data());
+                LOG(ProcessSwapping, "Switching from process %i to new process for navigation %" PRIu64 " '%s'", processIdentifier(), navigation->navigationID(), navigation->loggingString());
 
                 RunLoop::main().dispatch([this, protectedThis = makeRef(*this), navigation = makeRef(*navigation), proposedProcess = WTFMove(proposedProcess)]() mutable {
                     continueNavigationInNewProcess(navigation.get(), WTFMove(proposedProcess));
@@ -2416,7 +2421,7 @@ void WebPageProxy::receivedPolicyDecision(PolicyAction action, WebFrameProxy& fr
 
 void WebPageProxy::continueNavigationInNewProcess(API::Navigation& navigation, Ref<WebProcessProxy>&& process)
 {
-    LOG(Loading, "Continuing navigation %" PRIu64 " '%s' in a new web process", navigation.navigationID(), navigation.loggingString().utf8().data());
+    LOG(Loading, "Continuing navigation %" PRIu64 " '%s' in a new web process", navigation.navigationID(), navigation.loggingString());
 
     Ref<WebProcessProxy> previousProcess = m_process.copyRef();
     std::optional<uint64_t> navigatedFrameIdentifierInPreviousProcess;
@@ -2424,16 +2429,29 @@ void WebPageProxy::continueNavigationInNewProcess(API::Navigation& navigation, R
         navigatedFrameIdentifierInPreviousProcess = m_mainFrame->frameID();
 
     ASSERT(m_process.ptr() != process.ptr());
-    attachToProcessForNavigation(WTFMove(process));
 
-    if (auto* item = navigation.backForwardListItem()) {
-        if (item != m_backForwardList->currentItem())
-            m_backForwardList->goToItem(*item);
+    processDidTerminate(ProcessTerminationReason::NavigationSwap);
+
+    // FIXME: this is to fix the ASSERT(isValid()) inside reattachToWebProcess, some other way to fix this is needed.
+    m_isValid = false;
+    reattachToWebProcess(WTFMove(process), &navigation, navigation.targetItem() ? ReattachForBackForward::Yes : ReattachForBackForward::No);
+
+    if (auto* item = navigation.targetItem()) {
+        LOG(Loading, "WebPageProxy %p continueNavigationInNewProcess to back item URL %s", this, item->url().utf8().data());
 
-        ASSERT(navigation.backForwardFrameLoadType());
-        ASSERT(isBackForwardLoadType(*navigation.backForwardFrameLoadType()));
+        auto transaction = m_pageLoadState.transaction();
+        m_pageLoadState.setPendingAPIRequestURL(transaction, item->url());
 
+        auto itemStates = m_backForwardList-> filteredItemStates([this, targetItem = item](WebBackForwardListItem& item) {
+            if (auto* page = item.suspendedPage()) {
+                if (page->process() == m_process.ptr())
+                    return false;
+            }
+            return &item != targetItem;
+        });
+        m_process->send(Messages::WebPage::UpdateBackForwardListForReattach(WTFMove(itemStates)), m_pageID);
         m_process->send(Messages::WebPage::GoToBackForwardItem(navigation.navigationID(), item->itemID(), *navigation.backForwardFrameLoadType(), NavigationPolicyCheck::Bypass), m_pageID);
+        m_process->responsivenessTimer().start();
 
         return;
     }
@@ -3273,9 +3291,10 @@ void WebPageProxy::didCreateMainFrame(uint64_t frameID)
     MESSAGE_CHECK(m_process->canCreateFrame(frameID));
 
     m_mainFrame = WebFrameProxy::create(this, frameID);
+    m_mainFrameID = frameID;
 
     // Add the frame to the process wide map.
-    m_process->frameCreated(frameID, m_mainFrame.get());
+    m_process->frameCreated(frameID, *m_mainFrame);
 
     if (m_mainFrameCreationHandler) {
         m_mainFrameCreationHandler();
@@ -3293,7 +3312,7 @@ void WebPageProxy::didCreateSubframe(uint64_t frameID)
     RefPtr<WebFrameProxy> subFrame = WebFrameProxy::create(this, frameID);
 
     // Add the frame to the process wide map.
-    m_process->frameCreated(frameID, subFrame.get());
+    m_process->frameCreated(frameID, *subFrame);
 }
 
 void WebPageProxy::didCreateWindow(uint64_t frameID, GlobalWindowIdentifier&& windowIdentifier)
@@ -3382,7 +3401,7 @@ void WebPageProxy::didStartProvisionalLoadForFrame(uint64_t frameID, uint64_t na
             return;
     }
 
-    LOG(Loading, "WebPageProxy::didStartProvisionalLoadForFrame to frameID %" PRIu64 ", navigationID %" PRIu64 ", url %s", frameID, navigationID, url.string().utf8().data());
+    LOG(Loading, "WebPageProxy %" PRIu64 " in process pid %i didStartProvisionalLoadForFrame to frameID %" PRIu64 ", navigationID %" PRIu64 ", url %s", m_pageID, m_process->processIdentifier(), frameID, navigationID, url.string().utf8().data());
 
     auto transaction = m_pageLoadState.transaction();
 
@@ -3487,6 +3506,8 @@ void WebPageProxy::didChangeProvisionalURLForFrame(uint64_t frameID, uint64_t, W
 
 void WebPageProxy::didFailProvisionalLoadForFrame(uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const ResourceError& error, const UserData& userData)
 {
+    LOG(Loading, "(Loading) WebPageProxy %" PRIu64 " in web process pid %i didFailProvisionalLoadForFrame to provisionalURL %s", m_pageID, m_process->processIdentifier(), provisionalURL.utf8().data());
+
     PageClientProtector protector(m_pageClient);
 
     WebFrameProxy* frame = m_process->webFrame(frameID);
@@ -3541,6 +3562,9 @@ void WebPageProxy::clearLoadDependentCallbacks()
 
 void WebPageProxy::didCommitLoadForFrame(uint64_t frameID, uint64_t navigationID, const String& mimeType, bool frameHasCustomContentProvider, uint32_t opaqueFrameLoadType, const WebCore::CertificateInfo& certificateInfo, bool containsPluginDocument, std::optional<HasInsecureContent> hasInsecureContent, const UserData& userData)
 {
+    LOG(Loading, "(Loading) WebPageProxy %" PRIu64 " didCommitLoadForFrame in navigation %" PRIu64, m_pageID, m_navigationID);
+    LOG(BackForward, "(Back/Forward) After load commit, back/forward list is now:%s", m_backForwardList->loggingString());
+
     PageClientProtector protector(m_pageClient);
 
     WebFrameProxy* frame = m_process->webFrame(frameID);
@@ -3918,7 +3942,7 @@ void WebPageProxy::decidePolicyForNavigationAction(uint64_t frameID, const Secur
     MESSAGE_CHECK_URL(request.url());
     MESSAGE_CHECK_URL(originalRequest.url());
     
-    Ref<API::Navigation> navigation = navigationID ? makeRef(m_navigationState->navigation(navigationID)) : m_navigationState->createLoadRequestNavigation(ResourceRequest(request));
+    Ref<API::Navigation> navigation = navigationID ? makeRef(m_navigationState->navigation(navigationID)) : m_navigationState->createLoadRequestNavigation(ResourceRequest(request), m_backForwardList->currentItem());
 
     uint64_t newNavigationID = navigation->navigationID();
     navigation->setWasUserInitiated(!!navigationActionData.userGestureTokenIdentifier);
@@ -4250,9 +4274,9 @@ void WebPageProxy::mouseDidMoveOverElement(WebHitTestResultData&& hitTestResultD
 
 void WebPageProxy::connectionWillOpen(IPC::Connection& connection)
 {
-    ASSERT(&connection == m_process->connection());
+    ASSERT_UNUSED(connection, &connection == m_process->connection());
 
-    m_webProcessLifetimeTracker.connectionWillOpen(connection);
+    m_webProcessLifetimeTracker.webPageEnteringWebProcess();
 }
 
 void WebPageProxy::webProcessWillShutDown()
index e3c2c72..05808e9 100644 (file)
@@ -1295,7 +1295,7 @@ public:
 
     WebPreferencesStore preferencesStore() const;
 
-    SuspendedPageProxy* maybeCreateSuspendedPage(WebProcessProxy&);
+    SuspendedPageProxy* maybeCreateSuspendedPage(WebProcessProxy&, API::Navigation&);
     void suspendedPageProcessClosed(SuspendedPageProxy&);
 
 private:
@@ -1449,8 +1449,12 @@ private:
     void setCanShortCircuitHorizontalWheelEvents(bool canShortCircuitHorizontalWheelEvents) { m_canShortCircuitHorizontalWheelEvents = canShortCircuitHorizontalWheelEvents; }
 
     void reattachToWebProcess();
-    void attachToProcessForNavigation(Ref<WebProcessProxy>&&);
-    void reattachToWebProcess(Ref<WebProcessProxy>&&, bool suspendInOldProcess);
+
+    enum class ReattachForBackForward {
+        Yes,
+        No
+    };
+    void reattachToWebProcess(Ref<WebProcessProxy>&&, API::Navigation*, ReattachForBackForward);
 
     RefPtr<API::Navigation> reattachToWebProcessForReload();
     RefPtr<API::Navigation> reattachToWebProcessWithItem(WebBackForwardListItem&);
@@ -1785,6 +1789,7 @@ private:
     Ref<WebsiteDataStore> m_websiteDataStore;
 
     RefPtr<WebFrameProxy> m_mainFrame;
+    std::optional<uint64_t> m_mainFrameID;
     Function<void()> m_mainFrameCreationHandler;
     Function<void(const WebCore::GlobalWindowIdentifier&)> m_mainFrameWindowCreationHandler;
 
index 7f2599a..d1d7016 100644 (file)
@@ -53,7 +53,7 @@ void WebProcessLifetimeTracker::addObserver(WebProcessLifetimeObserver& observer
         observer.addWebPage(m_webPageProxy);
 }
 
-void WebProcessLifetimeTracker::connectionWillOpen(IPC::Connection&)
+void WebProcessLifetimeTracker::webPageEnteringWebProcess()
 {
     ASSERT(processIsRunning());
 
index dc85777..fdc4def 100644 (file)
@@ -44,7 +44,7 @@ public:
 
     void addObserver(WebProcessLifetimeObserver&);
 
-    void connectionWillOpen(IPC::Connection&);
+    void webPageEnteringWebProcess();
     void webPageLeavingWebProcess();
 
     void pageWasInvalidated();
index c01198c..21dcc3f 100644 (file)
@@ -44,6 +44,7 @@
 #include "LegacyCustomProtocolManagerMessages.h"
 #endif
 #include "LogInitialization.h"
+#include "Logging.h"
 #include "NetworkProcessCreationParameters.h"
 #include "NetworkProcessMessages.h"
 #include "NetworkProcessProxy.h"
@@ -1999,6 +2000,14 @@ Ref<WebProcessProxy> WebProcessPool::processForNavigation(WebPageProxy& page, co
     if (navigation.opener())
         return page.process();
 
+    if (auto* backForwardListItem = navigation.targetItem()) {
+        if (auto* suspendedPage = backForwardListItem->suspendedPage()) {
+            ASSERT(suspendedPage->process());
+            action = PolicyAction::Suspend;
+            return *suspendedPage->process();
+        }
+    }
+
     auto targetURL = navigation.currentRequest().url();
     auto url = URL { ParsedURLString, page.pageLoadState().url() };
     if (!url.isValid() || url.isEmpty() || url.isBlankURL() || protocolHostAndPortAreEqual(url, targetURL))
@@ -2008,4 +2017,30 @@ Ref<WebProcessProxy> WebProcessPool::processForNavigation(WebPageProxy& page, co
     return createNewWebProcess(page.websiteDataStore());
 }
 
+void WebProcessPool::registerSuspendedPageProxy(SuspendedPageProxy& page)
+{
+    auto& vector = m_suspendedPages.ensure(page.origin(), [] {
+        return Vector<SuspendedPageProxy*> { };
+    }).iterator->value;
+
+    vector.append(&page);
+
+#if !LOG_DISABLED
+    if (vector.size() > 5)
+        LOG(ProcessSwapping, "Security origin %s now has %zu suspended pages (this seems unexpected)", page.origin().debugString().utf8().data(), vector.size());
+#endif
+}
+
+void WebProcessPool::unregisterSuspendedPageProxy(SuspendedPageProxy& page)
+{
+    auto iterator = m_suspendedPages.find(page.origin());
+    ASSERT(iterator != m_suspendedPages.end());
+
+    auto result = iterator->value.removeFirst(&page);
+    ASSERT_UNUSED(result, result);
+
+    if (iterator->value.isEmpty())
+        m_suspendedPages.remove(iterator);
+}
+
 } // namespace WebKit
index f824f85..52d76c8 100644 (file)
@@ -447,6 +447,8 @@ public:
 #endif
 
     Ref<WebProcessProxy> processForNavigation(WebPageProxy&, const API::Navigation&, WebCore::PolicyAction&);
+    void registerSuspendedPageProxy(SuspendedPageProxy&);
+    void unregisterSuspendedPageProxy(SuspendedPageProxy&);
 
 private:
     void platformInitialize();
@@ -682,6 +684,8 @@ private:
     HashMap<WebCore::SecurityOriginData, ProcessThrottler::BackgroundActivityToken> m_backgroundTokensForServiceWorkerProcesses;
 #endif
 #endif
+
+    HashMap<WebCore::SecurityOriginData, Vector<SuspendedPageProxy*>> m_suspendedPages;
 };
 
 template<typename T>
index 493e88d..0750516 100644 (file)
@@ -396,9 +396,9 @@ void WebProcessProxy::addExistingWebPage(WebPageProxy& webPage, uint64_t pageID)
     updateBackgroundResponsivenessTimer();
 }
 
-void WebProcessProxy::suspendWebPageProxy(WebPageProxy& webPage)
+void WebProcessProxy::suspendWebPageProxy(WebPageProxy& webPage, API::Navigation& navigation)
 {
-    if (auto* suspendedPage = webPage.maybeCreateSuspendedPage(*this)) {
+    if (auto* suspendedPage = webPage.maybeCreateSuspendedPage(*this, navigation)) {
         LOG(ProcessSwapping, "WebProcessProxy pid %i added suspended page %s", processIdentifier(), suspendedPage->loggingString());
         m_suspendedPageMap.set(webPage.pageID(), suspendedPage);
     }
@@ -543,8 +543,14 @@ bool WebProcessProxy::fullKeyboardAccessEnabled()
 
 void WebProcessProxy::updateBackForwardItem(const BackForwardListItemState& itemState)
 {
-    if (auto* item = WebBackForwardListItem::itemForID(itemState.identifier))
-        item->setPageState(itemState.pageState);
+    if (auto* item = WebBackForwardListItem::itemForID(itemState.identifier)) {
+        // This update could be coming from a web process that is not the active process for
+        // the back/forward items page.
+        // e.g. The old web process is navigating to about:blank for suspension.
+        // We ignore these updates.
+        if (m_pageMap.contains(item->pageID()))
+            item->setPageState(itemState.pageState);
+    }
 }
 
 #if ENABLE(NETSCAPE_PLUGIN_API)
@@ -760,10 +766,9 @@ bool WebProcessProxy::canCreateFrame(uint64_t frameID) const
     return WebFrameProxyMap::isValidKey(frameID) && !m_frameMap.contains(frameID);
 }
 
-void WebProcessProxy::frameCreated(uint64_t frameID, WebFrameProxy* frameProxy)
+void WebProcessProxy::frameCreated(uint64_t frameID, WebFrameProxy& frameProxy)
 {
-    ASSERT(canCreateFrame(frameID));
-    m_frameMap.set(frameID, frameProxy);
+    m_frameMap.set(frameID, &frameProxy);
 }
 
 void WebProcessProxy::didDestroyFrame(uint64_t frameID)
index ed10f93..645c981 100644 (file)
@@ -51,6 +51,7 @@
 #include <wtf/RefPtr.h>
 
 namespace API {
+class Navigation;
 class PageConfiguration;
 }
 
@@ -130,7 +131,7 @@ public:
 
     WebFrameProxy* webFrame(uint64_t) const;
     bool canCreateFrame(uint64_t frameID) const;
-    void frameCreated(uint64_t, WebFrameProxy*);
+    void frameCreated(uint64_t, WebFrameProxy&);
     void disconnectFramesFromPage(WebPageProxy*); // Including main frame.
     size_t frameCountInPage(WebPageProxy*) const; // Including main frame.
 
@@ -204,7 +205,7 @@ public:
     void didCommitProvisionalLoad() { m_hasCommittedAnyProvisionalLoads = true; }
     bool hasCommittedAnyProvisionalLoads() const { return m_hasCommittedAnyProvisionalLoads; }
 
-    void suspendWebPageProxy(WebPageProxy&);
+    void suspendWebPageProxy(WebPageProxy&, API::Navigation&);
     void suspendedPageWasDestroyed(SuspendedPageProxy&);
 
 #if ENABLE(EXTRA_ZOOM_MODE)
index db1c01c..16eb440 100644 (file)
@@ -151,6 +151,8 @@ public:
     void displayWasRefreshed();
 #endif
 
+    virtual void attachDrawingArea() { };
+
 protected:
     DrawingArea(DrawingAreaType, WebPage&);
 
index e8a3cb7..c8688aa 100644 (file)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "WebBackForwardListProxy.h"
 
+#include "Logging.h"
 #include "SessionState.h"
 #include "SessionStateConversion.h"
 #include "WebCoreArgumentCoders.h"
@@ -54,11 +55,10 @@ static IDToHistoryItemMap& idToHistoryItemMap()
     return map;
 }
 
-void WebBackForwardListProxy::addItemFromUIProcess(const BackForwardItemIdentifier& itemID, Ref<HistoryItem>&& item, uint64_t pageID)
+void WebBackForwardListProxy::addItemFromUIProcess(const BackForwardItemIdentifier& itemID, Ref<HistoryItem>&& item, uint64_t pageID, OverwriteExistingItem overwriteExistingItem)
 {
     // This item/itemID pair should not already exist in our map.
-    ASSERT(!idToHistoryItemMap().contains(itemID));
-
+    ASSERT_UNUSED(overwriteExistingItem, overwriteExistingItem == OverwriteExistingItem::Yes || !idToHistoryItemMap().contains(itemID));
     idToHistoryItemMap().set(itemID, item.ptr());
 }
 
@@ -96,6 +96,7 @@ void WebBackForwardListProxy::addItem(Ref<HistoryItem>&& item)
     auto result = idToHistoryItemMap().add(item->identifier(), item.ptr());
     ASSERT_UNUSED(result, result.isNewEntry);
 
+    LOG(BackForward, "(Back/Forward) WebProcess pid %i setting item %p for id %s with url %s", getpid(), item.ptr(), item->identifier().logString(), item->urlString().utf8().data());
     m_page->send(Messages::WebPageProxy::BackForwardAddItem(toBackForwardListItemState(item.get())));
 }
 
index cad70e8..c6fe437 100644 (file)
@@ -44,8 +44,12 @@ public:
     static WebCore::HistoryItem* itemForID(const WebCore::BackForwardItemIdentifier&);
     static void removeItem(const WebCore::BackForwardItemIdentifier&);
 
-    void addItemFromUIProcess(const WebCore::BackForwardItemIdentifier&, Ref<WebCore::HistoryItem>&&, uint64_t pageID);
-    
+    enum class OverwriteExistingItem {
+        Yes,
+        No
+    };
+    void addItemFromUIProcess(const WebCore::BackForwardItemIdentifier&, Ref<WebCore::HistoryItem>&&, uint64_t pageID, OverwriteExistingItem);
+
     void clear();
 
 private:
index 9070b2e..e328b26 100644 (file)
@@ -525,7 +525,7 @@ WebPage::WebPage(uint64_t pageID, WebPageCreationParameters&& parameters)
     m_userAgent = parameters.userAgent;
     
     if (!parameters.itemStates.isEmpty())
-        restoreSessionInternal(parameters.itemStates, WasRestoredByAPIRequest::No);
+        restoreSessionInternal(parameters.itemStates, WasRestoredByAPIRequest::No, WebBackForwardListProxy::OverwriteExistingItem::No);
 
     if (parameters.sessionID.isValid())
         setSessionID(parameters.sessionID);
@@ -641,6 +641,9 @@ void WebPage::enableEnumeratingAllNetworkInterfaces()
 
 void WebPage::reinitializeWebPage(WebPageCreationParameters&& parameters)
 {
+    ASSERT(m_drawingArea);
+    m_drawingArea->attachDrawingArea();
+
     if (m_activityState != parameters.activityState)
         setActivityState(parameters.activityState, false, Vector<CallbackID>());
     if (m_layerHostingMode != parameters.layerHostingMode)
@@ -1399,7 +1402,7 @@ void WebPage::goToBackForwardItem(uint64_t navigationID, const BackForwardItemId
     if (!item)
         return;
 
-    LOG(Loading, "In WebProcess, WebPage %" PRIu64 " is navigating to back/forward URL %s", m_pageID, item->url().string().utf8().data());
+    LOG(Loading, "In WebProcess pid %i, WebPage %" PRIu64 " is navigating to back/forward URL %s", getpid(), m_pageID, item->url().string().utf8().data());
 
     ASSERT(!m_pendingNavigationID);
     m_pendingNavigationID = navigationID;
@@ -2490,18 +2493,23 @@ void WebPage::executeEditCommand(const String& commandName, const String& argume
     executeEditingCommand(commandName, argument);
 }
 
-void WebPage::restoreSessionInternal(const Vector<BackForwardListItemState>& itemStates, WasRestoredByAPIRequest restoredByAPIRequest)
+void WebPage::restoreSessionInternal(const Vector<BackForwardListItemState>& itemStates, WasRestoredByAPIRequest restoredByAPIRequest, WebBackForwardListProxy::OverwriteExistingItem overwrite)
 {
     for (const auto& itemState : itemStates) {
         auto historyItem = toHistoryItem(itemState);
         historyItem->setWasRestoredFromSession(restoredByAPIRequest == WasRestoredByAPIRequest::Yes);
-        static_cast<WebBackForwardListProxy*>(corePage()->backForward().client())->addItemFromUIProcess(itemState.identifier, WTFMove(historyItem), m_pageID);
+        static_cast<WebBackForwardListProxy*>(corePage()->backForward().client())->addItemFromUIProcess(itemState.identifier, WTFMove(historyItem), m_pageID, overwrite);
     }
 }
 
 void WebPage::restoreSession(const Vector<BackForwardListItemState>& itemStates)
 {
-    restoreSessionInternal(itemStates, WasRestoredByAPIRequest::Yes);
+    restoreSessionInternal(itemStates, WasRestoredByAPIRequest::Yes, WebBackForwardListProxy::OverwriteExistingItem::No);
+}
+
+void WebPage::updateBackForwardListForReattach(const Vector<WebKit::BackForwardListItemState>& itemStates)
+{
+    restoreSessionInternal(itemStates, WasRestoredByAPIRequest::No, WebBackForwardListProxy::OverwriteExistingItem::Yes);
 }
 
 #if ENABLE(TOUCH_EVENTS)
index 29c459b..0a81534 100644 (file)
@@ -45,6 +45,7 @@
 #include "SandboxExtension.h"
 #include "SharedMemory.h"
 #include "UserData.h"
+#include "WebBackForwardListProxy.h"
 #include "WebURLSchemeHandler.h"
 #include "WebUserContentController.h"
 #include <WebCore/ActivityState.h>
@@ -1188,9 +1189,10 @@ private:
     void loadURLInFrame(WebCore::URL&&, uint64_t frameID);
 
     enum class WasRestoredByAPIRequest { No, Yes };
-    void restoreSessionInternal(const Vector<BackForwardListItemState>&, WasRestoredByAPIRequest);
+    void restoreSessionInternal(const Vector<BackForwardListItemState>&, WasRestoredByAPIRequest, WebBackForwardListProxy::OverwriteExistingItem);
     void restoreSession(const Vector<BackForwardListItemState>&);
     void didRemoveBackForwardItem(const WebCore::BackForwardItemIdentifier&);
+    void updateBackForwardListForReattach(const Vector<WebKit::BackForwardListItemState>&);
 
 #if ENABLE(REMOTE_INSPECTOR)
     void setAllowsRemoteInspection(bool);
index b6027bd..6def3b0 100644 (file)
@@ -148,6 +148,7 @@ messages -> WebPage LegacyReceiver {
     StopLoadingFrame(uint64_t frameID)
     
     RestoreSession(Vector<WebKit::BackForwardListItemState> itemStates)
+    UpdateBackForwardListForReattach(Vector<WebKit::BackForwardListItemState> itemStates)
 
     DidRemoveBackForwardItem(struct WebCore::BackForwardItemIdentifier backForwardItemID)
 
index 6aefa0c..4ff9943 100644 (file)
@@ -103,6 +103,8 @@ private:
     void addTransactionCallbackID(CallbackID) override;
     void setShouldScaleViewToFitDocument(bool) override;
 
+    void attachDrawingArea() override;
+
     void adjustTransientZoom(double scale, WebCore::FloatPoint origin) override;
     void commitTransientZoom(double scale, WebCore::FloatPoint origin) override;
     void applyTransientZoomToPage(double scale, WebCore::FloatPoint origin);
index 73ba324..f211efd 100644 (file)
@@ -94,9 +94,7 @@ TiledCoreAnimationDrawingArea::TiledCoreAnimationDrawingArea(WebPage& webPage, c
     updateLayerHostingContext();
     setColorSpace(parameters.colorSpace);
 
-    LayerTreeContext layerTreeContext;
-    layerTreeContext.contextID = m_layerHostingContext->contextID();
-    m_webPage.send(Messages::DrawingAreaProxy::EnterAcceleratedCompositingMode(0, layerTreeContext));
+    attachDrawingArea();
 }
 
 TiledCoreAnimationDrawingArea::~TiledCoreAnimationDrawingArea()
@@ -104,6 +102,14 @@ TiledCoreAnimationDrawingArea::~TiledCoreAnimationDrawingArea()
     m_layerFlushScheduler.invalidate();
 }
 
+
+void TiledCoreAnimationDrawingArea::attachDrawingArea()
+{
+    LayerTreeContext layerTreeContext;
+    layerTreeContext.contextID = m_layerHostingContext->contextID();
+    m_webPage.send(Messages::DrawingAreaProxy::EnterAcceleratedCompositingMode(0, layerTreeContext));
+}
+
 void TiledCoreAnimationDrawingArea::setNeedsDisplay()
 {
 }
index 9d4958c..6b58fc3 100644 (file)
@@ -1,3 +1,12 @@
+2018-04-19  Brady Eidson  <beidson@apple.com>
+
+        Make back forward cache work with process swapping.
+        <rdar://problem/38676604> and https://bugs.webkit.org/show_bug.cgi?id=184793
+
+        Reviewed by Chris Dumez.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
+
 2018-04-19  David Kilzer  <ddkilzer@apple.com>
 
         Enable Objective-C weak references
index b1f1a79..7d864fe 100644 (file)
@@ -349,17 +349,13 @@ TEST(ProcessSwap, Back)
 
     EXPECT_EQ([receivedMessages count], 2u);
     EXPECT_TRUE([receivedMessages.get()[0] isEqualToString:@"PageShow called. Persisted: false, and window.history.state is: null"]);
+    EXPECT_TRUE([receivedMessages.get()[1] isEqualToString:@"PageShow called. Persisted: true, and window.history.state is: onloadCalled"]);
 
-    // FIXME: We'd like to get the page restoring from the page cache like before process swapping, which will make Persisted be "true"
-    // For now it's expected to be false"
-    EXPECT_TRUE([receivedMessages.get()[1] isEqualToString:@"PageShow called. Persisted: false, and window.history.state is: onloadCalled"]);
+    EXPECT_EQ(2u, seenPIDs.size());
 
     EXPECT_FALSE(pid1 == pid2);
     EXPECT_FALSE(pid2 == pid3);
-
-    // FIXME: Ideally we'd like to get process caching happening such that pid1 and pid3 are equal.
-    // But for now they should not be.
-    EXPECT_FALSE(pid1 == pid3);
+    EXPECT_TRUE(pid1 == pid3);
 }
 
 #if PLATFORM(MAC)
@@ -791,4 +787,84 @@ TEST(ProcessSwap, OnePreviousProcessRemains)
     EXPECT_EQ(2u, [processPool _webProcessCount]);
 }
 
+static const char* pageCache1Bytes = R"PSONRESOURCE(
+<script>
+window.addEventListener('pageshow', function(event) {
+    if (event.persisted)
+        window.webkit.messageHandlers.pson.postMessage("Was persisted");
+});
+</script>
+)PSONRESOURCE";
+
+TEST(ProcessSwap, PageCache1)
+{
+    auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
+    [processPoolConfiguration setProcessSwapsOnNavigation:YES];
+    auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
+
+    auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    [webViewConfiguration setProcessPool:processPool.get()];
+    auto handler = adoptNS([[PSONScheme alloc] init]);
+    [handler addMappingFromURLString:@"pson1://host/main.html" toData:pageCache1Bytes];
+    [handler addMappingFromURLString:@"pson2://host/main.html" toData:pageCache1Bytes];
+    [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON1"];
+    [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON2"];
+
+    auto messageHandler = adoptNS([[PSONMessageHandler alloc] init]);
+    [[webViewConfiguration userContentController] addScriptMessageHandler:messageHandler.get() name:@"pson"];
+
+    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
+    auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
+    [webView setNavigationDelegate:delegate.get()];
+
+    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson1://host/main.html"]];
+
+    [webView loadRequest:request];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    auto pidAfterLoad1 = [webView _webProcessIdentifier];
+
+    EXPECT_EQ(1u, [processPool _webProcessCount]);
+
+    request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson2://host/main.html"]];
+
+    [webView loadRequest:request];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    auto pidAfterLoad2 = [webView _webProcessIdentifier];
+
+    EXPECT_EQ(2u, [processPool _webProcessCount]);
+    EXPECT_NE(pidAfterLoad1, pidAfterLoad2);
+
+    [webView goBack];
+    TestWebKitAPI::Util::run(&receivedMessage);
+    receivedMessage = false;
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    auto pidAfterLoad3 = [webView _webProcessIdentifier];
+
+    EXPECT_EQ(2u, [processPool _webProcessCount]);
+    EXPECT_EQ(pidAfterLoad1, pidAfterLoad3);
+    EXPECT_EQ(1u, [receivedMessages count]);
+    EXPECT_TRUE([receivedMessages.get()[0] isEqualToString:@"Was persisted" ]);
+    EXPECT_EQ(2u, seenPIDs.size());
+
+    [webView goForward];
+    TestWebKitAPI::Util::run(&receivedMessage);
+    receivedMessage = false;
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    auto pidAfterLoad4 = [webView _webProcessIdentifier];
+
+    EXPECT_EQ(2u, [processPool _webProcessCount]);
+    EXPECT_EQ(pidAfterLoad2, pidAfterLoad4);
+    EXPECT_EQ(2u, [receivedMessages count]);
+    EXPECT_TRUE([receivedMessages.get()[1] isEqualToString:@"Was persisted" ]);
+    EXPECT_EQ(2u, seenPIDs.size());
+}
+
 #endif // WK_API_ENABLED