Go to back/forward list items after a process-swapped navigation.
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 23 Mar 2018 22:15:23 +0000 (22:15 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 23 Mar 2018 22:15:23 +0000 (22:15 +0000)
<rdar://problem/38690544> and https://bugs.webkit.org/show_bug.cgi?id=183920

Reviewed by Andy Estes.

Source/WebCore:

Covered by new API test.

Most of the changes to WebCore are teaching HistoryItem navigations to know when they should
do a policy check or not.

* WebCore.xcodeproj/project.pbxproj:

* history/BackForwardController.cpp:
(WebCore::BackForwardController::goBackOrForward):
(WebCore::BackForwardController::goBack):
(WebCore::BackForwardController::goForward):

* history/HistoryItem.cpp:
(WebCore::HistoryItem::setStateObject): Actually push state object changes to the UIProcess.
  This was a long standing bug that made it difficult to effectively test this change.

* loader/FrameLoader.cpp:
(WebCore::FrameLoader::loadURLIntoChildFrame):
(WebCore::FrameLoader::loadDifferentDocumentItem):
(WebCore::FrameLoader::loadItem):
(WebCore::FrameLoader::retryAfterFailedCacheOnlyMainResourceLoad):
* loader/FrameLoader.h:
* loader/FrameLoaderTypes.h:

* loader/HistoryController.cpp:
(WebCore::HistoryController::goToItem):
(WebCore::HistoryController::setDefersLoading):
(WebCore::HistoryController::recursiveGoToItem):
* loader/HistoryController.h:

* loader/NavigationPolicyCheck.h:

* page/Page.cpp:
(WebCore::Page::goToItem):
* page/Page.h:

Source/WebKit:

This takes the initial work of "process swap a normal navigation" and extends it to
process swapping for back/forward item navigations.

* Scripts/webkit/messages.py:

Make sure state objects are serialized to the UI Process back/forward list items, as otherwise
they will be lost in process-swap scenarios:
* Shared/SessionState.cpp:
(WebKit::PageState::encode const):
(WebKit::PageState::decode):
* Shared/SessionState.h:

Make a new variant of APINavigation specifically for back/forward list items.
* UIProcess/API/APINavigation.cpp:
(API::Navigation::Navigation):
(API::Navigation::loggingURL const):
* UIProcess/API/APINavigation.h:
(API::Navigation::create):
(API::Navigation::backForwardListItem):
(API::Navigation::backForwardFrameLoadType const):

* UIProcess/API/C/WKPage.cpp:
(WKPageGoToBackForwardListItem):

* UIProcess/API/Cocoa/WKBrowsingContextController.mm:
(-[WKBrowsingContextController goToBackForwardListItem:]):

* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView goToBackForwardListItem:]):

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

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::reattachToWebProcessForReload):
(WebKit::WebPageProxy::reattachToWebProcessWithItem):
(WebKit::WebPageProxy::goForward):
(WebKit::WebPageProxy::goBack):
(WebKit::WebPageProxy::goToBackForwardItem):
(WebKit::WebPageProxy::receivedPolicyDecision):
(WebKit::WebPageProxy::continueNavigationInNewProcess): Handle back/forward navigations differently than others.
(WebKit::WebPageProxy::restoreFromSessionState):
* UIProcess/WebPageProxy.h:

* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::addOrUpdateBackForwardItem): Renamed from "addBackForwardItem" for clarity
(WebKit::WebProcessProxy::addBackForwardItem): Deleted.
* UIProcess/WebProcessProxy.h:
* UIProcess/WebProcessProxy.messages.in:

* UIProcess/ios/ViewGestureControllerIOS.mm:
(WebKit::ViewGestureController::endSwipeGesture):

* UIProcess/mac/ViewGestureControllerMac.mm:
(WebKit::ViewGestureController::endSwipeGesture):

* WebProcess/WebCoreSupport/SessionStateConversion.cpp:
(WebKit::toPageState):
(WebKit::toHistoryItem):

* WebProcess/WebPage/WebBackForwardListProxy.cpp:
(WebKit::updateBackForwardItem):

* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::goToBackForwardItem): Combined "goBack" and "goForward" with this method,
  passing the appropriate FrameLoadType around as needed to remember the specific type.
(WebKit::WebPage::goForward): Deleted.
(WebKit::WebPage::goBack): Deleted.
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:

Source/WebKitLegacy/mac:

* WebView/WebView.mm:
(-[WebView _loadBackForwardListFromOtherView:]):
(-[WebView goToBackForwardItem:]):

Source/WebKitLegacy/win:

* WebView.cpp:
(WebView::goToBackForwardItem):
(WebView::loadBackForwardListFromOtherView):

Tools:

Add a new API test that does some process-swapping navigations (including a back navigation)
and verifies the state of the engine afterwards.

* TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
(-[PSONMessageHandler userContentController:didReceiveScriptMessage:]):
(-[PSONScheme initWithBytes:]):
(-[PSONScheme webView:startURLSchemeTask:]):
(log):
(function):
(TEST): Deleted.

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

42 files changed:
Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/history/BackForwardController.cpp
Source/WebCore/history/HistoryItem.cpp
Source/WebCore/loader/FrameLoader.cpp
Source/WebCore/loader/FrameLoader.h
Source/WebCore/loader/FrameLoaderTypes.h
Source/WebCore/loader/HistoryController.cpp
Source/WebCore/loader/HistoryController.h
Source/WebCore/loader/NavigationPolicyCheck.h [new file with mode: 0644]
Source/WebCore/page/Page.cpp
Source/WebCore/page/Page.h
Source/WebKit/ChangeLog
Source/WebKit/Scripts/webkit/messages.py
Source/WebKit/Shared/SessionState.cpp
Source/WebKit/Shared/SessionState.h
Source/WebKit/UIProcess/API/APINavigation.cpp
Source/WebKit/UIProcess/API/APINavigation.h
Source/WebKit/UIProcess/API/C/WKPage.cpp
Source/WebKit/UIProcess/API/Cocoa/WKBrowsingContextController.mm
Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm
Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp
Source/WebKit/UIProcess/WebNavigationState.cpp
Source/WebKit/UIProcess/WebNavigationState.h
Source/WebKit/UIProcess/WebPageProxy.cpp
Source/WebKit/UIProcess/WebPageProxy.h
Source/WebKit/UIProcess/WebProcessProxy.cpp
Source/WebKit/UIProcess/WebProcessProxy.h
Source/WebKit/UIProcess/WebProcessProxy.messages.in
Source/WebKit/UIProcess/ios/ViewGestureControllerIOS.mm
Source/WebKit/UIProcess/mac/ViewGestureControllerMac.mm
Source/WebKit/WebProcess/WebCoreSupport/SessionStateConversion.cpp
Source/WebKit/WebProcess/WebPage/WebBackForwardListProxy.cpp
Source/WebKit/WebProcess/WebPage/WebPage.cpp
Source/WebKit/WebProcess/WebPage/WebPage.h
Source/WebKit/WebProcess/WebPage/WebPage.messages.in
Source/WebKitLegacy/mac/ChangeLog
Source/WebKitLegacy/mac/WebView/WebView.mm
Source/WebKitLegacy/win/ChangeLog
Source/WebKitLegacy/win/WebView.cpp
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm

index 75bab23..691fb12 100644 (file)
@@ -1,3 +1,46 @@
+2018-03-23  Brady Eidson  <beidson@apple.com>
+
+        Go to back/forward list items after a process-swapped navigation.
+        <rdar://problem/38690544> and https://bugs.webkit.org/show_bug.cgi?id=183920
+
+        Reviewed by Andy Estes.
+
+        Covered by new API test.
+
+        Most of the changes to WebCore are teaching HistoryItem navigations to know when they should
+        do a policy check or not.
+
+        * WebCore.xcodeproj/project.pbxproj:
+
+        * history/BackForwardController.cpp:
+        (WebCore::BackForwardController::goBackOrForward):
+        (WebCore::BackForwardController::goBack):
+        (WebCore::BackForwardController::goForward):
+
+        * history/HistoryItem.cpp:
+        (WebCore::HistoryItem::setStateObject): Actually push state object changes to the UIProcess.
+          This was a long standing bug that made it difficult to effectively test this change.
+
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::loadURLIntoChildFrame):
+        (WebCore::FrameLoader::loadDifferentDocumentItem):
+        (WebCore::FrameLoader::loadItem):
+        (WebCore::FrameLoader::retryAfterFailedCacheOnlyMainResourceLoad):
+        * loader/FrameLoader.h:
+        * loader/FrameLoaderTypes.h:
+
+        * loader/HistoryController.cpp:
+        (WebCore::HistoryController::goToItem):
+        (WebCore::HistoryController::setDefersLoading):
+        (WebCore::HistoryController::recursiveGoToItem):
+        * loader/HistoryController.h:
+
+        * loader/NavigationPolicyCheck.h:
+
+        * page/Page.cpp:
+        (WebCore::Page::goToItem):
+        * page/Page.h:
+
 2018-03-23  John Wilander  <wilander@apple.com>
 
         Resource Load Statistics: Fix decoder key isPrevalentResource->isVeryPrevalentResource
index c336fda..1574435 100644 (file)
                510D4A37103165EE0049EA54 /* SocketStreamHandle.h in Headers */ = {isa = PBXBuildFile; fileRef = 510D4A31103165EE0049EA54 /* SocketStreamHandle.h */; settings = {ATTRIBUTES = (Private, ); }; };
                510D4A38103165EE0049EA54 /* SocketStreamHandleClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 510D4A32103165EE0049EA54 /* SocketStreamHandleClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
                5110FCFC1E03641D006F8D0B /* IDBCursorRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 5110FCFB1E0362A5006F8D0B /* IDBCursorRecord.h */; };
+               511E97A32063074600AD4599 /* NavigationPolicyCheck.h in Headers */ = {isa = PBXBuildFile; fileRef = 511E97A12063072A00AD4599 /* NavigationPolicyCheck.h */; settings = {ATTRIBUTES = (Private, ); }; };
                511EC1281C50AACA0032F983 /* IDBSerialization.h in Headers */ = {isa = PBXBuildFile; fileRef = 511EC1261C50AA570032F983 /* IDBSerialization.h */; };
                511EC12C1C50ABBF0032F983 /* SQLiteIDBTransaction.h in Headers */ = {isa = PBXBuildFile; fileRef = 511EC12A1C50ABBA0032F983 /* SQLiteIDBTransaction.h */; };
                511EC1301C50ABF50032F983 /* SQLiteIDBCursor.h in Headers */ = {isa = PBXBuildFile; fileRef = 511EC12E1C50ABEC0032F983 /* SQLiteIDBCursor.h */; };
                510D4A31103165EE0049EA54 /* SocketStreamHandle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SocketStreamHandle.h; sourceTree = "<group>"; };
                510D4A32103165EE0049EA54 /* SocketStreamHandleClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SocketStreamHandleClient.h; sourceTree = "<group>"; };
                5110FCFB1E0362A5006F8D0B /* IDBCursorRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBCursorRecord.h; sourceTree = "<group>"; };
+               511E97A12063072A00AD4599 /* NavigationPolicyCheck.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NavigationPolicyCheck.h; sourceTree = "<group>"; };
                511EC1251C50AA570032F983 /* IDBSerialization.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IDBSerialization.cpp; sourceTree = "<group>"; };
                511EC1261C50AA570032F983 /* IDBSerialization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBSerialization.h; sourceTree = "<group>"; };
                511EC1291C50ABBA0032F983 /* SQLiteIDBTransaction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SQLiteIDBTransaction.cpp; sourceTree = "<group>"; };
                                93CCF05F0AF6CA7600018E89 /* NavigationAction.cpp */,
                                93CCF0260AF6C52900018E89 /* NavigationAction.h */,
                                9BA827781F06156500F71E75 /* NavigationDisabler.h */,
+                               511E97A12063072A00AD4599 /* NavigationPolicyCheck.h */,
                                979F43D11075E44A0000F83B /* NavigationScheduler.cpp */,
                                979F43D21075E44A0000F83B /* NavigationScheduler.h */,
                                93E227DD0AF589AD00D48324 /* NetscapePlugInStreamLoader.cpp */,
                                83B2D1751B8BCD6A00A02E47 /* NativeNodeFilter.h in Headers */,
                                E10B9B6C0B747599003ED890 /* NativeXPathNSResolver.h in Headers */,
                                93CCF0270AF6C52900018E89 /* NavigationAction.h in Headers */,
+                               511E97A32063074600AD4599 /* NavigationPolicyCheck.h in Headers */,
                                979F43D41075E44A0000F83B /* NavigationScheduler.h in Headers */,
                                A9C6E5A60D746458006442E9 /* Navigator.h in Headers */,
                                E12719C70EEEC16800F61213 /* NavigatorBase.h in Headers */,
index f450926..0f05bf6 100644 (file)
@@ -27,6 +27,7 @@
 #include "BackForwardController.h"
 
 #include "BackForwardClient.h"
+#include "NavigationPolicyCheck.h"
 #include "Page.h"
 
 namespace WebCore {
@@ -69,7 +70,7 @@ void BackForwardController::goBackOrForward(int distance)
     if (!item)
         return;
 
-    m_page.goToItem(*item, FrameLoadType::IndexedBackForward);
+    m_page.goToItem(*item, FrameLoadType::IndexedBackForward, NavigationPolicyCheck::Require);
 }
 
 bool BackForwardController::goBack()
@@ -78,7 +79,7 @@ bool BackForwardController::goBack()
     if (!item)
         return false;
 
-    m_page.goToItem(*item, FrameLoadType::Back);
+    m_page.goToItem(*item, FrameLoadType::Back, NavigationPolicyCheck::Require);
     return true;
 }
 
@@ -88,7 +89,7 @@ bool BackForwardController::goForward()
     if (!item)
         return false;
 
-    m_page.goToItem(*item, FrameLoadType::Forward);
+    m_page.goToItem(*item, FrameLoadType::Forward, NavigationPolicyCheck::Require);
     return true;
 }
 
index 6c3034c..9d86898 100644 (file)
@@ -311,6 +311,7 @@ void HistoryItem::setIsTargetItem(bool flag)
 void HistoryItem::setStateObject(RefPtr<SerializedScriptValue>&& object)
 {
     m_stateObject = WTFMove(object);
+    notifyHistoryItemChanged(this);
 }
 
 void HistoryItem::addChildItem(Ref<HistoryItem>&& child)
index 6de2d7b..d259e7f 100644 (file)
@@ -87,6 +87,7 @@
 #include "MemoryCache.h"
 #include "MemoryRelease.h"
 #include "NavigationDisabler.h"
+#include "NavigationPolicyCheck.h"
 #include "NavigationScheduler.h"
 #include "Page.h"
 #include "PageCache.h"
@@ -927,7 +928,7 @@ void FrameLoader::loadURLIntoChildFrame(const URL& url, const String& referer, F
     if (parentItem && parentItem->children().size() && isBackForwardLoadType(loadType()) && !m_frame.document()->loadEventFinished()) {
         if (auto* childItem = parentItem->childItemWithTarget(childFrame->tree().uniqueName())) {
             childFrame->loader().m_requestedHistoryItem = childItem;
-            childFrame->loader().loadDifferentDocumentItem(*childItem, loadType(), MayAttemptCacheOnlyLoadForFormSubmissionItem);
+            childFrame->loader().loadDifferentDocumentItem(*childItem, loadType(), MayAttemptCacheOnlyLoadForFormSubmissionItem, NavigationPolicyCheck::Require);
             return;
         }
     }
@@ -3467,7 +3468,7 @@ void FrameLoader::loadSameDocumentItem(HistoryItem& item)
 // FIXME: This function should really be split into a couple pieces, some of
 // which should be methods of HistoryController and some of which should be
 // methods of FrameLoader.
-void FrameLoader::loadDifferentDocumentItem(HistoryItem& item, FrameLoadType loadType, FormSubmissionCacheLoadPolicy cacheLoadPolicy)
+void FrameLoader::loadDifferentDocumentItem(HistoryItem& item, FrameLoadType loadType, FormSubmissionCacheLoadPolicy cacheLoadPolicy, NavigationPolicyCheck navigationPolicyCheck)
 {
     // Remember this item so we can traverse any child items as child frames load
     history().setProvisionalItem(&item);
@@ -3565,11 +3566,13 @@ 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, [] { });
 }
 
 // Loads content into this frame, as specified by history item
-void FrameLoader::loadItem(HistoryItem& item, FrameLoadType loadType)
+void FrameLoader::loadItem(HistoryItem& item, FrameLoadType loadType, NavigationPolicyCheck navigationPolicyCheck)
 {
     m_requestedHistoryItem = &item;
     HistoryItem* currentItem = history().currentItem();
@@ -3578,7 +3581,7 @@ void FrameLoader::loadItem(HistoryItem& item, FrameLoadType loadType)
     if (sameDocumentNavigation)
         loadSameDocumentItem(item);
     else
-        loadDifferentDocumentItem(item, loadType, MayAttemptCacheOnlyLoadForFormSubmissionItem);
+        loadDifferentDocumentItem(item, loadType, MayAttemptCacheOnlyLoadForFormSubmissionItem, navigationPolicyCheck);
 }
 
 void FrameLoader::retryAfterFailedCacheOnlyMainResourceLoad()
@@ -3593,7 +3596,7 @@ void FrameLoader::retryAfterFailedCacheOnlyMainResourceLoad()
     HistoryItem& item = *history().provisionalItem();
 
     stopAllLoaders(ShouldNotClearProvisionalItem);
-    loadDifferentDocumentItem(item, loadType, MayNotAttemptCacheOnlyLoadForFormSubmissionItem);
+    loadDifferentDocumentItem(item, loadType, MayNotAttemptCacheOnlyLoadForFormSubmissionItem, NavigationPolicyCheck::Require);
 }
 
 ResourceError FrameLoader::cancelledError(const ResourceRequest& request) const
index 8e4b95e..7e5ed5d 100644 (file)
@@ -80,6 +80,8 @@ class SharedBuffer;
 class SubframeLoader;
 class SubstituteData;
 
+enum class NavigationPolicyCheck;
+
 struct WindowFeatures;
 
 WEBCORE_EXPORT bool isBackForwardLoadType(FrameLoadType);
@@ -125,7 +127,7 @@ public:
     WEBCORE_EXPORT void reloadWithOverrideEncoding(const String& overrideEncoding);
 
     void open(CachedFrameBase&);
-    void loadItem(HistoryItem&, FrameLoadType);
+    void loadItem(HistoryItem&, FrameLoadType, NavigationPolicyCheck);
     HistoryItem* requestedHistoryItem() const { return m_requestedHistoryItem.get(); }
 
     void retryAfterFailedCacheOnlyMainResourceLoad();
@@ -317,7 +319,7 @@ private:
     void checkTimerFired();
 
     void loadSameDocumentItem(HistoryItem&);
-    void loadDifferentDocumentItem(HistoryItem&, FrameLoadType, FormSubmissionCacheLoadPolicy);
+    void loadDifferentDocumentItem(HistoryItem&, FrameLoadType, FormSubmissionCacheLoadPolicy, NavigationPolicyCheck);
 
     void loadProvisionalItemFromCachedPage();
 
index 59b6a62..6de1b6f 100644 (file)
@@ -164,4 +164,20 @@ template<> struct EnumTraits<WebCore::PolicyAction> {
     >;
 };
 
+template<> struct EnumTraits<WebCore::FrameLoadType> {
+    using values = EnumValues<
+        WebCore::FrameLoadType,
+        WebCore::FrameLoadType::Standard,
+        WebCore::FrameLoadType::Back,
+        WebCore::FrameLoadType::Forward,
+        WebCore::FrameLoadType::IndexedBackForward,
+        WebCore::FrameLoadType::Reload,
+        WebCore::FrameLoadType::Same,
+        WebCore::FrameLoadType::RedirectWithLockedBackForwardList,
+        WebCore::FrameLoadType::Replace,
+        WebCore::FrameLoadType::ReloadFromOrigin,
+        WebCore::FrameLoadType::ReloadExpiredOnly
+    >;
+};
+
 } // namespace WTF
index b8ee733..ea2567b 100644 (file)
@@ -43,6 +43,7 @@
 #include "HistoryItem.h"
 #include "Logging.h"
 #include "MainFrame.h"
+#include "NavigationPolicyCheck.h"
 #include "Page.h"
 #include "PageCache.h"
 #include "ScrollingCoordinator.h"
@@ -290,7 +291,7 @@ bool HistoryController::shouldStopLoadingForHistoryItem(HistoryItem& targetItem)
 
 // Main funnel for navigating to a previous location (back/forward, non-search snap-back)
 // This includes recursion to handle loading into framesets properly
-void HistoryController::goToItem(HistoryItem& targetItem, FrameLoadType type)
+void HistoryController::goToItem(HistoryItem& targetItem, FrameLoadType type, NavigationPolicyCheck navigationPolicyCheck)
 {
     LOG(History, "HistoryController %p goToItem %p type=%d", this, &targetItem, static_cast<int>(type));
 
@@ -325,14 +326,14 @@ void HistoryController::goToItem(HistoryItem& targetItem, FrameLoadType type)
     recursiveSetProvisionalItem(targetItem, currentItem.get());
 
     // Now that all other frames have provisional items, do the actual navigation.
-    recursiveGoToItem(targetItem, currentItem.get(), type);
+    recursiveGoToItem(targetItem, currentItem.get(), type, navigationPolicyCheck);
 }
 
 void HistoryController::setDefersLoading(bool defer)
 {
     m_defersLoading = defer;
     if (!defer && m_deferredItem) {
-        goToItem(*m_deferredItem, m_deferredFrameLoadType);
+        goToItem(*m_deferredItem, m_deferredFrameLoadType, NavigationPolicyCheck::Require);
         m_deferredItem = nullptr;
     }
 }
@@ -749,10 +750,10 @@ void HistoryController::recursiveSetProvisionalItem(HistoryItem& item, HistoryIt
 
 // We now traverse the frame tree and item tree a second time, loading frames that
 // do have the content the item requests.
-void HistoryController::recursiveGoToItem(HistoryItem& item, HistoryItem* fromItem, FrameLoadType type)
+void HistoryController::recursiveGoToItem(HistoryItem& item, HistoryItem* fromItem, FrameLoadType type, NavigationPolicyCheck navigationPolicyCheck)
 {
     if (!itemsAreClones(item, fromItem)) {
-        m_frame.loader().loadItem(item, type);
+        m_frame.loader().loadItem(item, type, navigationPolicyCheck);
         return;
     }
 
@@ -763,7 +764,7 @@ void HistoryController::recursiveGoToItem(HistoryItem& item, HistoryItem* fromIt
         HistoryItem* fromChildItem = fromItem->childItemWithTarget(childFrameName);
         ASSERT(fromChildItem);
         if (Frame* childFrame = m_frame.tree().child(childFrameName))
-            childFrame->loader().history().recursiveGoToItem(childItem, fromChildItem, type);
+            childFrame->loader().history().recursiveGoToItem(childItem, fromChildItem, type, navigationPolicyCheck);
     }
 }
 
index 3d25e28..4535aae 100644 (file)
@@ -40,6 +40,8 @@ class Frame;
 class HistoryItem;
 class SerializedScriptValue;
 
+enum class NavigationPolicyCheck;
+
 struct StringWithDirection;
 
 class HistoryController {
@@ -92,14 +94,14 @@ public:
 private:
     friend class Page;
     bool shouldStopLoadingForHistoryItem(HistoryItem&) const;
-    void goToItem(HistoryItem&, FrameLoadType);
+    void goToItem(HistoryItem&, FrameLoadType, NavigationPolicyCheck);
 
     void initializeItem(HistoryItem&);
     Ref<HistoryItem> createItem();
     Ref<HistoryItem> createItemTree(Frame& targetFrame, bool clipAtTarget);
 
     void recursiveSetProvisionalItem(HistoryItem&, HistoryItem*);
-    void recursiveGoToItem(HistoryItem&, HistoryItem*, FrameLoadType);
+    void recursiveGoToItem(HistoryItem&, HistoryItem*, FrameLoadType, NavigationPolicyCheck);
     bool isReplaceLoadTypeWithProvisionalItem(FrameLoadType);
     bool isReloadTypeWithProvisionalItem(FrameLoadType);
     void recursiveUpdateForCommit();
diff --git a/Source/WebCore/loader/NavigationPolicyCheck.h b/Source/WebCore/loader/NavigationPolicyCheck.h
new file mode 100644 (file)
index 0000000..22178ef
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <wtf/EnumTraits.h>
+
+namespace WebCore {
+
+enum class NavigationPolicyCheck {
+    Require,
+    Bypass,
+};
+
+} // namespace WebCore
+
+namespace WTF {
+
+template<> struct EnumTraits<WebCore::NavigationPolicyCheck> {
+    using values = EnumValues<
+        WebCore::NavigationPolicyCheck,
+        WebCore::NavigationPolicyCheck::Require,
+        WebCore::NavigationPolicyCheck::Bypass
+    >;
+};
+
+} // namespace WTF
index 3943aa2..9558146 100644 (file)
@@ -447,7 +447,7 @@ void Page::setOpenedByDOM()
     m_openedByDOM = true;
 }
 
-void Page::goToItem(HistoryItem& item, FrameLoadType type)
+void Page::goToItem(HistoryItem& item, FrameLoadType type, NavigationPolicyCheck navigationPolicyCheck)
 {
     // stopAllLoaders may end up running onload handlers, which could cause further history traversals that may lead to the passed in HistoryItem
     // being deref()-ed. Make sure we can still use it with HistoryController::goToItem later.
@@ -456,7 +456,7 @@ void Page::goToItem(HistoryItem& item, FrameLoadType type)
     if (m_mainFrame->loader().history().shouldStopLoadingForHistoryItem(item))
         m_mainFrame->loader().stopAllLoaders();
 
-    m_mainFrame->loader().history().goToItem(item, type);
+    m_mainFrame->loader().history().goToItem(item, type, navigationPolicyCheck);
 }
 
 void Page::setGroupName(const String& name)
index 9fdd4d8..9079d8a 100644 (file)
@@ -145,6 +145,7 @@ enum class EventThrottlingBehavior {
 
 enum class CanWrap : bool;
 enum class DidWrap : bool;
+enum class NavigationPolicyCheck;
 
 class Page : public Supplementable<Page> {
     WTF_MAKE_NONCOPYABLE(Page);
@@ -180,7 +181,7 @@ public:
     bool openedByDOM() const;
     void setOpenedByDOM();
 
-    WEBCORE_EXPORT void goToItem(HistoryItem&, FrameLoadType);
+    WEBCORE_EXPORT void goToItem(HistoryItem&, FrameLoadType, NavigationPolicyCheck);
 
     WEBCORE_EXPORT void setGroupName(const String&);
     WEBCORE_EXPORT const String& groupName() const;
index 46b9d88..bc28809 100644 (file)
@@ -1,3 +1,83 @@
+2018-03-23  Brady Eidson  <beidson@apple.com>
+
+        Go to back/forward list items after a process-swapped navigation.
+        <rdar://problem/38690544> and https://bugs.webkit.org/show_bug.cgi?id=183920
+
+        Reviewed by Andy Estes.
+
+        This takes the initial work of "process swap a normal navigation" and extends it to
+        process swapping for back/forward item navigations.
+
+        * Scripts/webkit/messages.py:
+
+        Make sure state objects are serialized to the UI Process back/forward list items, as otherwise
+        they will be lost in process-swap scenarios:
+        * Shared/SessionState.cpp:
+        (WebKit::PageState::encode const):
+        (WebKit::PageState::decode):
+        * Shared/SessionState.h:
+
+        Make a new variant of APINavigation specifically for back/forward list items.
+        * UIProcess/API/APINavigation.cpp:
+        (API::Navigation::Navigation):
+        (API::Navigation::loggingURL const):
+        * UIProcess/API/APINavigation.h:
+        (API::Navigation::create):
+        (API::Navigation::backForwardListItem):
+        (API::Navigation::backForwardFrameLoadType const):
+
+        * UIProcess/API/C/WKPage.cpp:
+        (WKPageGoToBackForwardListItem):
+
+        * UIProcess/API/Cocoa/WKBrowsingContextController.mm:
+        (-[WKBrowsingContextController goToBackForwardListItem:]):
+
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView goToBackForwardListItem:]):
+
+        * UIProcess/WebNavigationState.cpp:
+        (WebKit::WebNavigationState::createLoadRequestNavigation):
+        (WebKit::WebNavigationState::createBackForwardNavigation):
+        * UIProcess/WebNavigationState.h:
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::reattachToWebProcessForReload):
+        (WebKit::WebPageProxy::reattachToWebProcessWithItem):
+        (WebKit::WebPageProxy::goForward):
+        (WebKit::WebPageProxy::goBack):
+        (WebKit::WebPageProxy::goToBackForwardItem):
+        (WebKit::WebPageProxy::receivedPolicyDecision):
+        (WebKit::WebPageProxy::continueNavigationInNewProcess): Handle back/forward navigations differently than others.
+        (WebKit::WebPageProxy::restoreFromSessionState):
+        * UIProcess/WebPageProxy.h:
+
+        * UIProcess/WebProcessProxy.cpp:
+        (WebKit::WebProcessProxy::addOrUpdateBackForwardItem): Renamed from "addBackForwardItem" for clarity
+        (WebKit::WebProcessProxy::addBackForwardItem): Deleted.
+        * UIProcess/WebProcessProxy.h:
+        * UIProcess/WebProcessProxy.messages.in:
+
+        * UIProcess/ios/ViewGestureControllerIOS.mm:
+        (WebKit::ViewGestureController::endSwipeGesture):
+
+        * UIProcess/mac/ViewGestureControllerMac.mm:
+        (WebKit::ViewGestureController::endSwipeGesture):
+
+        * WebProcess/WebCoreSupport/SessionStateConversion.cpp:
+        (WebKit::toPageState):
+        (WebKit::toHistoryItem):
+
+        * WebProcess/WebPage/WebBackForwardListProxy.cpp:
+        (WebKit::updateBackForwardItem):
+
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::goToBackForwardItem): Combined "goBack" and "goForward" with this method,
+          passing the appropriate FrameLoadType around as needed to remember the specific type.
+        (WebKit::WebPage::goForward): Deleted.
+        (WebKit::WebPage::goBack): Deleted.
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+
 2018-03-23  Megan Gardner  <megan_gardner@apple.com>
 
         Don't use the presence of a textSelectionAssistant as a proxy for if we are in content editable.
index c0b30d3..820780b 100644 (file)
@@ -372,6 +372,7 @@ def headers_for_type(type):
         'WebCore::AutoplayEventFlags': ['<WebCore/AutoplayEvent.h>'],
         'WebCore::ExceptionDetails': ['<WebCore/JSDOMExceptionHandling.h>'],
         'WebCore::FileChooserSettings': ['<WebCore/FileChooser.h>'],
+        'WebCore::FrameLoadType': ['<WebCore/FrameLoaderTypes.h>'],
         'WebCore::GrammarDetail': ['<WebCore/TextCheckerClient.h>'],
         'WebCore::HasInsecureContent': ['<WebCore/FrameLoaderTypes.h>'],
         'WebCore::Highlight': ['<WebCore/InspectorOverlay.h>'],
index b0aae59..911d2e7 100644 (file)
@@ -28,6 +28,8 @@
 
 #include "WebCoreArgumentCoders.h"
 
+using namespace WebCore;
+
 namespace WebKit {
 
 bool isValidEnum(WebCore::ShouldOpenExternalURLsPolicy policy)
@@ -184,8 +186,11 @@ std::optional<FrameState> FrameState::decode(IPC::Decoder& decoder)
 
 void PageState::encode(IPC::Encoder& encoder) const
 {
-    encoder << title;
-    encoder << mainFrameState;
+    encoder << title << mainFrameState << !!sessionStateObject;
+
+    if (sessionStateObject)
+        encoder << sessionStateObject->toWireBytes();
+
     encoder.encodeEnum(shouldOpenExternalURLsPolicy);
 }
 
@@ -198,6 +203,19 @@ bool PageState::decode(IPC::Decoder& decoder, PageState& result)
     if (!mainFrameState)
         return false;
     result.mainFrameState = WTFMove(*mainFrameState);
+
+    bool hasSessionState;
+    if (!decoder.decode(hasSessionState))
+        return false;
+
+    if (hasSessionState) {
+        Vector<uint8_t> wireBytes;
+        if (!decoder.decode(wireBytes))
+            return false;
+
+        result.sessionStateObject = SerializedScriptValue::createFromWireBytes(WTFMove(wireBytes));
+    }
+
     if (!decoder.decodeEnum(result.shouldOpenExternalURLsPolicy) || !isValidEnum(result.shouldOpenExternalURLsPolicy))
         return false;
 
index c354bd7..1482144 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -32,6 +32,7 @@
 #include <WebCore/FloatRect.h>
 #include <WebCore/FrameLoaderTypes.h>
 #include <WebCore/IntRect.h>
+#include <WebCore/SerializedScriptValue.h>
 #include <WebCore/URL.h>
 #include <wtf/Optional.h>
 #include <wtf/Vector.h>
@@ -119,6 +120,7 @@ struct PageState {
     String title;
     FrameState mainFrameState;
     WebCore::ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy { WebCore::ShouldOpenExternalURLsPolicy::ShouldNotAllow };
+    RefPtr<WebCore::SerializedScriptValue> sessionStateObject;
 };
 
 struct BackForwardListItemState {
@@ -131,7 +133,6 @@ struct BackForwardListItemState {
 #if PLATFORM(COCOA)
     RefPtr<ViewSnapshot> snapshot;
 #endif
-
 };
 
 struct BackForwardListState {
index b7f698e..bea333e 100644 (file)
 #include "config.h"
 #include "APINavigation.h"
 
+#include "WebBackForwardListItem.h"
 #include "WebNavigationState.h"
 
+using namespace WebCore;
+using namespace WebKit;
+
 namespace API {
 
-Navigation::Navigation(WebKit::WebNavigationState& state)
+Navigation::Navigation(WebNavigationState& state)
     : m_navigationID(state.generateNavigationID())
 {
 }
 
-Navigation::Navigation(WebKit::WebNavigationState& state, WebCore::ResourceRequest&& request)
+Navigation::Navigation(WebNavigationState& state, WebCore::ResourceRequest&& request)
     : m_navigationID(state.generateNavigationID())
     , m_request(WTFMove(request))
 {
     m_redirectChain.append(m_request.url());
 }
 
+Navigation::Navigation(WebNavigationState& state, WebBackForwardListItem& item, FrameLoadType backForwardFrameLoadType)
+    : m_navigationID(state.generateNavigationID())
+    , m_backForwardListItem(&item)
+    , m_backForwardFrameLoadType(backForwardFrameLoadType)
+{
+}
+
 Navigation::~Navigation()
 {
 }
@@ -52,4 +63,11 @@ void Navigation::appendRedirectionURL(const WebCore::URL& url)
         m_redirectChain.append(url);
 }
 
+#if !LOG_DISABLED
+WTF::String Navigation::loggingURL() const
+{
+    return m_backForwardListItem ? m_backForwardListItem->url() : m_request.url().string();
+}
+#endif
+
 } // namespace WebKit
index 44ff50c..f1f8957 100644 (file)
 #include <WebCore/ResourceRequest.h>
 #include <wtf/Ref.h>
 
+namespace WebCore {
+enum class FrameLoadType;
+};
+
 namespace WebKit {
+class WebBackForwardListItem;
 class WebNavigationState;
 }
 
@@ -43,6 +48,11 @@ public:
         return adoptRef(*new Navigation(state));
     }
 
+    static Ref<Navigation> create(WebKit::WebNavigationState& state, WebKit::WebBackForwardListItem& item, WebCore::FrameLoadType backForwardFrameLoadType)
+    {
+        return adoptRef(*new Navigation(state, item, backForwardFrameLoadType));
+    }
+
     static Ref<Navigation> create(WebKit::WebNavigationState& state, WebCore::ResourceRequest&& request)
     {
         return adoptRef(*new Navigation(state, WTFMove(request)));
@@ -53,6 +63,8 @@ public:
     uint64_t navigationID() const { return m_navigationID; }
 
     const WebCore::ResourceRequest& request() const { return m_request; }
+    WebKit::WebBackForwardListItem* backForwardListItem() { return m_backForwardListItem.get(); }
+    std::optional<WebCore::FrameLoadType> backForwardFrameLoadType() const { return m_backForwardFrameLoadType; }
 
     void appendRedirectionURL(const WebCore::URL&);
     Vector<WebCore::URL> takeRedirectChain() { return WTFMove(m_redirectChain); }
@@ -63,15 +75,23 @@ public:
     void setShouldForceDownload(bool value) { m_shouldForceDownload = value; }
     bool shouldForceDownload() const { return m_shouldForceDownload; }
 
+#if !LOG_DISABLED
+    WTF::String loggingURL() const;
+#endif
+
 private:
     explicit Navigation(WebKit::WebNavigationState&);
     Navigation(WebKit::WebNavigationState&, WebCore::ResourceRequest&&);
+    Navigation(WebKit::WebNavigationState&, WebKit::WebBackForwardListItem&, WebCore::FrameLoadType);
 
     uint64_t m_navigationID;
     WebCore::ResourceRequest m_request;
     Vector<WebCore::URL> m_redirectChain;
     bool m_wasUserInitiated { true };
     bool m_shouldForceDownload { false };
+
+    RefPtr<WebKit::WebBackForwardListItem> m_backForwardListItem;
+    std::optional<WebCore::FrameLoadType> m_backForwardFrameLoadType;
 };
 
 } // namespace API
index 97e9982..6a655fd 100644 (file)
@@ -305,7 +305,7 @@ bool WKPageCanGoBack(WKPageRef pageRef)
 
 void WKPageGoToBackForwardListItem(WKPageRef pageRef, WKBackForwardListItemRef itemRef)
 {
-    toImpl(pageRef)->goToBackForwardItem(toImpl(itemRef));
+    toImpl(pageRef)->goToBackForwardItem(*toImpl(itemRef));
 }
 
 void WKPageTryRestoreScrollPosition(WKPageRef pageRef)
index b7e5e69..81e4e52 100644 (file)
@@ -241,7 +241,7 @@ static HashMap<WebPageProxy*, WKBrowsingContextController *>& browsingContextCon
 
 - (void)goToBackForwardListItem:(WKBackForwardListItem *)item
 {
-    _page->goToBackForwardItem(&item._item);
+    _page->goToBackForwardItem(item._item);
 }
 
 - (WKBackForwardList *)backForwardList
index 8cf6763..5713eee 100644 (file)
@@ -907,7 +907,7 @@ static void validate(WKWebViewConfiguration *configuration)
 
 - (WKNavigation *)goToBackForwardListItem:(WKBackForwardListItem *)item
 {
-    auto navigation = _page->goToBackForwardItem(&item._item);
+    auto navigation = _page->goToBackForwardItem(item._item);
     if (!navigation)
         return nil;
 
index a27f9ec..b9be39c 100644 (file)
@@ -3030,7 +3030,7 @@ void webkit_web_view_go_to_back_forward_list_item(WebKitWebView* webView, WebKit
     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
     g_return_if_fail(WEBKIT_IS_BACK_FORWARD_LIST_ITEM(listItem));
 
-    getPage(webView).goToBackForwardItem(webkitBackForwardListItemGetItem(listItem));
+    getPage(webView).goToBackForwardItem(*webkitBackForwardListItemGetItem(listItem));
 }
 
 /**
index 48f9345..31a707b 100644 (file)
@@ -30,6 +30,8 @@
 #include "WebPageProxy.h"
 #include <WebCore/ResourceRequest.h>
 
+using namespace WebCore;
+
 namespace WebKit {
 
 WebNavigationState::WebNavigationState()
@@ -40,7 +42,7 @@ WebNavigationState::~WebNavigationState()
 {
 }
 
-Ref<API::Navigation> WebNavigationState::createLoadRequestNavigation(WebCore::ResourceRequest&& request)
+Ref<API::Navigation> WebNavigationState::createLoadRequestNavigation(ResourceRequest&& request)
 {
     auto navigation = API::Navigation::create(*this, WTFMove(request));
 
@@ -49,9 +51,9 @@ Ref<API::Navigation> WebNavigationState::createLoadRequestNavigation(WebCore::Re
     return navigation;
 }
 
-Ref<API::Navigation> WebNavigationState::createBackForwardNavigation()
+Ref<API::Navigation> WebNavigationState::createBackForwardNavigation(WebBackForwardListItem& item, FrameLoadType frameLoadType)
 {
-    auto navigation = API::Navigation::create(*this);
+    auto navigation = API::Navigation::create(*this, item, frameLoadType);
 
     m_navigations.set(navigation->navigationID(), navigation.ptr());
 
index 45ab2d2..0e12f3f 100644 (file)
@@ -34,6 +34,8 @@ class Navigation;
 
 namespace WebCore {
 class ResourceRequest;
+
+enum class FrameLoadType;
 }
 
 namespace WebKit {
@@ -46,7 +48,7 @@ public:
     explicit WebNavigationState();
     ~WebNavigationState();
 
-    Ref<API::Navigation> createBackForwardNavigation();
+    Ref<API::Navigation> createBackForwardNavigation(WebBackForwardListItem&, WebCore::FrameLoadType);
     Ref<API::Navigation> createLoadRequestNavigation(WebCore::ResourceRequest&&);
     Ref<API::Navigation> createReloadNavigation();
     Ref<API::Navigation> createLoadDataNavigation();
index 407dfcb..18a10e7 100644 (file)
 #include <WebCore/EventNames.h>
 #include <WebCore/FloatRect.h>
 #include <WebCore/FocusDirection.h>
+#include <WebCore/FrameLoader.h>
 #include <WebCore/JSDOMBinding.h>
 #include <WebCore/JSDOMExceptionHandling.h>
 #include <WebCore/LengthBox.h>
 #include <WebCore/MIMETypeRegistry.h>
 #include <WebCore/MediaStreamRequest.h>
+#include <WebCore/NavigationPolicyCheck.h>
 #include <WebCore/PerformanceLoggingClient.h>
 #include <WebCore/PublicSuffix.h>
 #include <WebCore/RenderEmbeddedObject.h>
@@ -713,13 +715,13 @@ RefPtr<API::Navigation> WebPageProxy::reattachToWebProcessForReload()
     auto navigation = m_navigationState->createReloadNavigation();
 
     // We allow stale content when reloading a WebProcess that's been killed or crashed.
-    m_process->send(Messages::WebPage::GoToBackForwardItem(navigation->navigationID(), m_backForwardList->currentItem()->itemID()), m_pageID);
+    m_process->send(Messages::WebPage::GoToBackForwardItem(navigation->navigationID(), m_backForwardList->currentItem()->itemID(), FrameLoadType::IndexedBackForward, NavigationPolicyCheck::Require), m_pageID);
     m_process->responsivenessTimer().start();
 
     return WTFMove(navigation);
 }
 
-RefPtr<API::Navigation> WebPageProxy::reattachToWebProcessWithItem(WebBackForwardListItem* item)
+RefPtr<API::Navigation> WebPageProxy::reattachToWebProcessWithItem(WebBackForwardListItem& item)
 {
     if (m_isClosed)
         return nullptr;
@@ -727,15 +729,12 @@ RefPtr<API::Navigation> WebPageProxy::reattachToWebProcessWithItem(WebBackForwar
     ASSERT(!isValid());
     reattachToWebProcess();
 
-    if (!item)
-        return nullptr;
+    if (&item != m_backForwardList->currentItem())
+        m_backForwardList->goToItem(item);
 
-    if (item != m_backForwardList->currentItem())
-        m_backForwardList->goToItem(*item);
+    auto navigation = m_navigationState->createBackForwardNavigation(item, FrameLoadType::IndexedBackForward);
 
-    auto navigation = m_navigationState->createBackForwardNavigation();
-
-    m_process->send(Messages::WebPage::GoToBackForwardItem(navigation->navigationID(), item->itemID()), m_pageID);
+    m_process->send(Messages::WebPage::GoToBackForwardItem(navigation->navigationID(), item.itemID(), FrameLoadType::IndexedBackForward, NavigationPolicyCheck::Require), m_pageID);
     m_process->responsivenessTimer().start();
 
     return WTFMove(navigation);
@@ -1184,21 +1183,7 @@ RefPtr<API::Navigation> WebPageProxy::goForward()
     if (!forwardItem)
         return nullptr;
 
-    auto transaction = m_pageLoadState.transaction();
-
-    m_pageLoadState.setPendingAPIRequestURL(transaction, forwardItem->url());
-
-    if (!isValid())
-        return reattachToWebProcessWithItem(forwardItem);
-
-    RefPtr<API::Navigation> navigation;
-    if (!m_backForwardList->currentItem()->itemIsInSameDocument(*forwardItem))
-        navigation = m_navigationState->createBackForwardNavigation();
-
-    m_process->send(Messages::WebPage::GoForward(navigation ? navigation->navigationID() : 0, forwardItem->itemID()), m_pageID);
-    m_process->responsivenessTimer().start();
-
-    return navigation;
+    return goToBackForwardItem(*forwardItem, FrameLoadType::Forward);
 }
 
 RefPtr<API::Navigation> WebPageProxy::goBack()
@@ -1207,37 +1192,30 @@ RefPtr<API::Navigation> WebPageProxy::goBack()
     if (!backItem)
         return nullptr;
 
-    auto transaction = m_pageLoadState.transaction();
-
-    m_pageLoadState.setPendingAPIRequestURL(transaction, backItem->url());
-
-    if (!isValid())
-        return reattachToWebProcessWithItem(backItem);
-
-    RefPtr<API::Navigation> navigation;
-    if (!m_backForwardList->currentItem()->itemIsInSameDocument(*backItem))
-        navigation = m_navigationState->createBackForwardNavigation();
-
-    m_process->send(Messages::WebPage::GoBack(navigation ? navigation->navigationID() : 0, backItem->itemID()), m_pageID);
-    m_process->responsivenessTimer().start();
+    return goToBackForwardItem(*backItem, FrameLoadType::Back);
+}
 
-    return navigation;
+RefPtr<API::Navigation> WebPageProxy::goToBackForwardItem(WebBackForwardListItem& item)
+{
+    return goToBackForwardItem(item, FrameLoadType::IndexedBackForward);
 }
 
-RefPtr<API::Navigation> WebPageProxy::goToBackForwardItem(WebBackForwardListItem* item)
+RefPtr<API::Navigation> WebPageProxy::goToBackForwardItem(WebBackForwardListItem& item, FrameLoadType frameLoadType)
 {
+    LOG(Loading, "WebPageProxy %p goToBackForwardItem to back item URL %s", this, item.url().utf8().data());
+
     if (!isValid())
         return reattachToWebProcessWithItem(item);
 
     auto transaction = m_pageLoadState.transaction();
 
-    m_pageLoadState.setPendingAPIRequestURL(transaction, item->url());
+    m_pageLoadState.setPendingAPIRequestURL(transaction, item.url());
 
     RefPtr<API::Navigation> navigation;
-    if (!m_backForwardList->currentItem()->itemIsInSameDocument(*item))
-        navigation = m_navigationState->createBackForwardNavigation();
+    if (!m_backForwardList->currentItem()->itemIsInSameDocument(item))
+        navigation = m_navigationState->createBackForwardNavigation(item, frameLoadType);
 
-    m_process->send(Messages::WebPage::GoToBackForwardItem(navigation ? navigation->navigationID() : 0, item->itemID()), m_pageID);
+    m_process->send(Messages::WebPage::GoToBackForwardItem(navigation ? navigation->navigationID() : 0, item.itemID(), frameLoadType, NavigationPolicyCheck::Require), m_pageID);
     m_process->responsivenessTimer().start();
 
     return navigation;
@@ -2375,6 +2353,8 @@ void WebPageProxy::receivedPolicyDecision(PolicyAction action, WebFrameProxy& fr
         if (action == PolicyAction::Use && navigation) {
             auto proposedProcess = process().processPool().processForNavigation(*this, navigation->request().url());
             if (proposedProcess.ptr() != &process()) {
+                LOG(Loading, "Switching to new process for navigation %" PRIu64 " to url '%s' (WebBackForwardListItem %p)", navigation->navigationID(), navigation->loggingURL().utf8().data(), navigation->backForwardListItem());
+
                 action = PolicyAction::Suspend;
                 RunLoop::main().dispatch([this, protectedThis = makeRef(*this), navigation = makeRef(*navigation), proposedProcess = WTFMove(proposedProcess)]() mutable {
                     continueNavigationInNewProcess(navigation.get(), WTFMove(proposedProcess));
@@ -2388,10 +2368,22 @@ void WebPageProxy::receivedPolicyDecision(PolicyAction action, WebFrameProxy& fr
 
 void WebPageProxy::continueNavigationInNewProcess(API::Navigation& navigation, Ref<WebProcessProxy>&& process)
 {
-    LOG(Loading, "Continuing navigation %" PRIu64 " to URL %s in a new web process", navigation.navigationID(), navigation.request().url().string().utf8().data());
+    LOG(Loading, "Continuing navigation %" PRIu64 " to URL %s in a new web process", navigation.navigationID(), navigation.loggingURL().utf8().data());
 
     attachToProcessForNavigation(WTFMove(process));
 
+    if (auto* item = navigation.backForwardListItem()) {
+        if (item != m_backForwardList->currentItem())
+            m_backForwardList->goToItem(*item);
+
+        ASSERT(navigation.backForwardFrameLoadType());
+        ASSERT(isBackForwardLoadType(*navigation.backForwardFrameLoadType()));
+
+        m_process->send(Messages::WebPage::GoToBackForwardItem(navigation.navigationID(), item->itemID(), *navigation.backForwardFrameLoadType(), NavigationPolicyCheck::Bypass), m_pageID);
+
+        return;
+    }
+
     // FIXME: Work out timing of responding with the last policy delegate, etc
     loadRequestWithNavigation(navigation, ResourceRequest { navigation.request() }, WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes, nullptr, NavigationPolicyCheck::Bypass);
 }
@@ -2528,9 +2520,8 @@ RefPtr<API::Navigation> WebPageProxy::restoreFromSessionState(SessionState sessi
             return loadRequest(sessionState.provisionalURL);
 
         if (hasBackForwardList) {
-            // FIXME: Do we have to null check the back forward list item here?
             if (WebBackForwardListItem* item = m_backForwardList->currentItem())
-                return goToBackForwardItem(item);
+                return goToBackForwardItem(*item);
         }
     }
 
index dc59498..445ca77 100644 (file)
@@ -164,6 +164,14 @@ class SharedBuffer;
 class TextIndicator;
 class ValidationBubble;
 
+enum SelectionDirection : uint8_t;
+
+enum class AutoplayEvent;
+enum class HasInsecureContent;
+enum class NavigationPolicyCheck;
+enum class NotificationDirection;
+enum class ShouldSample;
+
 struct ApplicationManifest;
 struct DictionaryPopupInfo;
 struct ExceptionDetails;
@@ -175,13 +183,6 @@ struct TextCheckingResult;
 struct ViewportAttributes;
 struct WindowFeatures;
 
-enum SelectionDirection : uint8_t;
-
-enum class AutoplayEvent;
-enum class HasInsecureContent;
-enum class NotificationDirection;
-enum class ShouldSample;
-
 template <typename> class RectEdges;
 using FloatBoxExtent = RectEdges<float>;
 }
@@ -440,7 +441,7 @@ public:
     RefPtr<API::Navigation> goForward();
     RefPtr<API::Navigation> goBack();
 
-    RefPtr<API::Navigation> goToBackForwardItem(WebBackForwardListItem*);
+    RefPtr<API::Navigation> goToBackForwardItem(WebBackForwardListItem&);
     void tryRestoreScrollPosition();
     void didChangeBackForwardList(WebBackForwardListItem* addedItem, Vector<Ref<WebBackForwardListItem>>&& removed);
     void willGoToBackForwardListItem(uint64_t itemID, bool inPageCache, const UserData&);
@@ -1294,6 +1295,8 @@ private:
     WebPageProxy(PageClient&, WebProcessProxy&, uint64_t pageID, Ref<API::PageConfiguration>&&);
     void platformInitialize();
 
+    RefPtr<API::Navigation> goToBackForwardItem(WebBackForwardListItem&, WebCore::FrameLoadType);
+
     void updateActivityState(WebCore::ActivityState::Flags flagsToUpdate = WebCore::ActivityState::AllFlags);
     void updateThrottleState();
     void updateHiddenPageThrottlingAutoIncreases();
@@ -1441,13 +1444,9 @@ private:
     void reattachToWebProcess(Ref<WebProcessProxy>&&);
 
     RefPtr<API::Navigation> reattachToWebProcessForReload();
-    RefPtr<API::Navigation> reattachToWebProcessWithItem(WebBackForwardListItem*);
+    RefPtr<API::Navigation> reattachToWebProcessWithItem(WebBackForwardListItem&);
 
-    enum class NavigationPolicyCheck {
-        Require,
-        Bypass,
-    };
-    void loadRequestWithNavigation(API::Navigation&, WebCore::ResourceRequest&&, WebCore::ShouldOpenExternalURLsPolicy, API::Object* userData, NavigationPolicyCheck);
+    void loadRequestWithNavigation(API::Navigation&, WebCore::ResourceRequest&&, WebCore::ShouldOpenExternalURLsPolicy, API::Object* userData, WebCore::NavigationPolicyCheck);
 
     void requestNotificationPermission(uint64_t notificationID, const String& originString);
     void showNotification(const String& title, const String& body, const String& iconURL, const String& tag, const String& lang, WebCore::NotificationDirection, const String& originString, uint64_t notificationID);
index 6f83e88..dca9899 100644 (file)
@@ -551,7 +551,7 @@ bool WebProcessProxy::fullKeyboardAccessEnabled()
 }
 #endif
 
-void WebProcessProxy::addBackForwardItem(uint64_t itemID, uint64_t pageID, const PageState& pageState)
+void WebProcessProxy::addOrUpdateBackForwardItem(uint64_t itemID, uint64_t pageID, const PageState& pageState)
 {
     MESSAGE_CHECK_URL(pageState.mainFrameState.originalURLString);
     MESSAGE_CHECK_URL(pageState.mainFrameState.urlString);
index 697eb90..3bad2ee 100644 (file)
@@ -220,7 +220,7 @@ private:
     void shutDown();
 
     // IPC message handlers.
-    void addBackForwardItem(uint64_t itemID, uint64_t pageID, const PageState&);
+    void addOrUpdateBackForwardItem(uint64_t itemID, uint64_t pageID, const PageState&);
     void didDestroyFrame(uint64_t);
     void didDestroyUserGestureToken(uint64_t);
 
index 98c712a..ec7cf50 100644 (file)
@@ -21,7 +21,7 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 messages -> WebProcessProxy LegacyReceiver {
-    AddBackForwardItem(uint64_t itemID, uint64_t pageID, struct WebKit::PageState pageState)
+    AddOrUpdateBackForwardItem(uint64_t itemID, uint64_t pageID, struct WebKit::PageState pageState)
     DidDestroyFrame(uint64_t frameID) 
 
     DidDestroyUserGestureToken(uint64_t userGestureTokenID) 
index 4c33d55..7498382 100644 (file)
@@ -294,7 +294,7 @@ void ViewGestureController::endSwipeGesture(WebBackForwardListItem* targetItem,
     if (&m_webPageProxy != m_webPageProxyForBackForwardListForCurrentSwipe)
         m_webPageProxy.navigationGestureDidEnd();
 
-    m_webPageProxyForBackForwardListForCurrentSwipe->goToBackForwardItem(targetItem);
+    m_webPageProxyForBackForwardListForCurrentSwipe->goToBackForwardItem(*targetItem);
 
     if (auto drawingArea = m_webPageProxy.drawingArea()) {
         uint64_t pageID = m_webPageProxy.pageID();
index dffa547..0326c34 100644 (file)
@@ -741,7 +741,7 @@ void ViewGestureController::endSwipeGesture(WebBackForwardListItem* targetItem,
     m_webPageProxy.process().send(Messages::ViewGestureGeometryCollector::SetRenderTreeSizeNotificationThreshold(renderTreeSize * swipeSnapshotRemovalRenderTreeSizeTargetFraction), m_webPageProxy.pageID());
 
     m_webPageProxy.navigationGestureDidEnd(true, *targetItem);
-    m_webPageProxy.goToBackForwardItem(targetItem);
+    m_webPageProxy.goToBackForwardItem(*targetItem);
 
     SnapshotRemovalTracker::Events desiredEvents = SnapshotRemovalTracker::VisuallyNonEmptyLayout
         | SnapshotRemovalTracker::MainFrameLoad
index 1ae2c3c..a5d45a9 100644 (file)
@@ -119,7 +119,7 @@ PageState toPageState(const WebCore::HistoryItem& historyItem)
     pageState.title = historyItem.title();
     pageState.mainFrameState = toFrameState(historyItem);
     pageState.shouldOpenExternalURLsPolicy = historyItem.shouldOpenExternalURLsPolicy();
-
+    pageState.sessionStateObject = historyItem.stateObject();
     return pageState;
 }
 
@@ -193,6 +193,7 @@ Ref<HistoryItem> toHistoryItem(const PageState& pageState)
 {
     Ref<HistoryItem> historyItem = HistoryItem::create(pageState.mainFrameState.urlString, pageState.title);
     historyItem->setShouldOpenExternalURLsPolicy(pageState.shouldOpenExternalURLsPolicy);
+    historyItem->setStateObject(pageState.sessionStateObject.get());
     applyFrameState(historyItem, pageState.mainFrameState);
 
     return historyItem;
index c2e91ea..7f4e127 100644 (file)
@@ -91,7 +91,7 @@ void WebBackForwardListProxy::setHighestItemIDFromUIProcess(uint64_t itemID)
 
 static void updateBackForwardItem(uint64_t itemID, uint64_t pageID, HistoryItem* item)
 {
-    WebProcess::singleton().parentProcessConnection()->send(Messages::WebProcessProxy::AddBackForwardItem(itemID, pageID, toPageState(*item)), 0);
+    WebProcess::singleton().parentProcessConnection()->send(Messages::WebProcessProxy::AddOrUpdateBackForwardItem(itemID, pageID, toPageState(*item)), 0);
 }
 
 void WebBackForwardListProxy::addItemFromUIProcess(uint64_t itemID, Ref<HistoryItem>&& item, uint64_t pageID)
index 81ae45c..8be2d76 100644 (file)
@@ -1380,49 +1380,23 @@ void WebPage::reload(uint64_t navigationID, uint32_t reloadOptions, SandboxExten
     corePage()->userInputBridge().reloadFrame(m_mainFrame->coreFrame(), OptionSet<ReloadOption>::fromRaw(reloadOptions));
 }
 
-void WebPage::goForward(uint64_t navigationID, uint64_t backForwardItemID)
+void WebPage::goToBackForwardItem(uint64_t navigationID, uint64_t backForwardItemID, FrameLoadType backForwardType, NavigationPolicyCheck navigationPolicyCheck)
 {
     SendStopResponsivenessTimer stopper;
 
-    HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
-    ASSERT(item);
-    if (!item)
-        return;
-
-    ASSERT(!m_pendingNavigationID);
-    m_pendingNavigationID = navigationID;
-
-    m_page->goToItem(*item, FrameLoadType::Forward);
-}
-
-void WebPage::goBack(uint64_t navigationID, uint64_t backForwardItemID)
-{
-    SendStopResponsivenessTimer stopper;
+    ASSERT(isBackForwardLoadType(backForwardType));
 
     HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
     ASSERT(item);
     if (!item)
         return;
 
-    ASSERT(!m_pendingNavigationID);
-    m_pendingNavigationID = navigationID;
-
-    m_page->goToItem(*item, FrameLoadType::Back);
-}
-
-void WebPage::goToBackForwardItem(uint64_t navigationID, uint64_t backForwardItemID)
-{
-    SendStopResponsivenessTimer stopper;
-
-    HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
-    ASSERT(item);
-    if (!item)
-        return;
+    LOG(Loading, "In WebProcess, WebPage %" PRIu64 " is navigating to back/forward URL %s", m_pageID, item->url().string().utf8().data());
 
     ASSERT(!m_pendingNavigationID);
     m_pendingNavigationID = navigationID;
 
-    m_page->goToItem(*item, FrameLoadType::IndexedBackForward);
+    m_page->goToItem(*item, backForwardType, navigationPolicyCheck);
 }
 
 void WebPage::tryRestoreScrollPosition()
index 15f92c9..0744a2f 100644 (file)
@@ -149,6 +149,10 @@ class TextCheckingRequest;
 class URL;
 class VisiblePosition;
 
+enum SyntheticClickType : int8_t;
+enum class NavigationPolicyCheck;
+enum class TextIndicatorPresentationTransition : uint8_t;
+
 struct CompositionUnderline;
 struct DictationAlternative;
 struct Highlight;
@@ -157,9 +161,7 @@ struct PromisedBlobInfo;
 struct TextCheckingResult;
 struct ViewportArguments;
 
-enum SyntheticClickType : int8_t;
 
-enum class TextIndicatorPresentationTransition : uint8_t;
 
 #if ENABLE(ATTACHMENT_ELEMENT)
 class HTMLAttachmentElement;
@@ -214,6 +216,9 @@ class WebTouchEvent;
 class WebCredentialsMessenger;
 class RemoteLayerTreeTransaction;
 
+enum FindOptions : uint16_t;
+enum class DragControllerAction;
+
 struct AssistedNodeInformation;
 struct AttributedString;
 struct BackForwardListItemState;
@@ -227,9 +232,6 @@ struct WebPreferencesStore;
 struct WebSelectionData;
 struct WebsitePoliciesData;
 
-enum class DragControllerAction;
-enum FindOptions : uint16_t;
-
 using SnapshotOptions = uint32_t;
 using WKEventModifiers = uint32_t;
 
@@ -1148,9 +1150,7 @@ private:
     void loadAlternateHTMLString(const LoadParameters&);
     void navigateToPDFLinkWithSimulatedClick(const String& url, WebCore::IntPoint documentPoint, WebCore::IntPoint screenPoint);
     void reload(uint64_t navigationID, uint32_t reloadOptions, SandboxExtension::Handle&&);
-    void goForward(uint64_t navigationID, uint64_t);
-    void goBack(uint64_t navigationID, uint64_t);
-    void goToBackForwardItem(uint64_t navigationID, uint64_t);
+    void goToBackForwardItem(uint64_t navigationID, uint64_t, WebCore::FrameLoadType, WebCore::NavigationPolicyCheck);
     void tryRestoreScrollPosition();
     void setInitialFocus(bool forward, bool isKeyboardEventValid, const WebKeyboardEvent&, CallbackID);
     void updateIsInWindow(bool isInitialState = false);
index 71f7c51..5a7aaf4 100644 (file)
@@ -134,9 +134,7 @@ messages -> WebPage LegacyReceiver {
     ScrollBy(uint32_t scrollDirection, uint32_t scrollGranularity)
     CenterSelectionInVisibleArea()
 
-    GoBack(uint64_t navigationID, uint64_t backForwardItemID)
-    GoForward(uint64_t navigationID, uint64_t backForwardItemID)
-    GoToBackForwardItem(uint64_t navigationID, uint64_t backForwardItemID)
+    GoToBackForwardItem(uint64_t navigationID, uint64_t backForwardItemID, enum WebCore::FrameLoadType backForwardType, enum WebCore::NavigationPolicyCheck navigationPolicyCheck)
     TryRestoreScrollPosition()
 
     LoadURLInFrame(WebCore::URL url, uint64_t frameID)
index 8e0e65a..f26ded4 100644 (file)
@@ -1,3 +1,14 @@
+2018-03-23  Brady Eidson  <beidson@apple.com>
+
+        Go to back/forward list items after a process-swapped navigation.
+        <rdar://problem/38690544> and https://bugs.webkit.org/show_bug.cgi?id=183920
+
+        Reviewed by Andy Estes.
+
+        * WebView/WebView.mm:
+        (-[WebView _loadBackForwardListFromOtherView:]):
+        (-[WebView goToBackForwardItem:]):
+
 2018-03-22  Tim Horton  <timothy_horton@apple.com>
 
         Improve readability of WebCore's OTHER_LDFLAGS
index a205c2a..2338792 100644 (file)
 #import <WebCore/MainFrame.h>
 #import <WebCore/MemoryCache.h>
 #import <WebCore/MemoryRelease.h>
+#import <WebCore/NavigationPolicyCheck.h>
 #import <WebCore/NetworkStorageSession.h>
 #import <WebCore/NodeList.h>
 #import <WebCore/Notification.h>
@@ -2566,7 +2567,7 @@ static bool fastDocumentTeardownEnabled()
     }
 
     ASSERT(newItemToGoTo);
-    _private->page->goToItem(*newItemToGoTo, FrameLoadType::IndexedBackForward);
+    _private->page->goToItem(*newItemToGoTo, FrameLoadType::IndexedBackForward, NavigationPolicyCheck::Require);
 }
 
 - (void)_setFormDelegate: (id<WebFormDelegate>)delegate
@@ -6369,7 +6370,7 @@ static NSString * const backingPropertyOldScaleFactorKey = @"NSBackingPropertyOl
         return NO;
 
     ASSERT(item);
-    _private->page->goToItem(*core(item), FrameLoadType::IndexedBackForward);
+    _private->page->goToItem(*core(item), FrameLoadType::IndexedBackForward, NavigationPolicyCheck::Require);
     return YES;
 }
 
index 795bf72..255d606 100644 (file)
@@ -1,3 +1,14 @@
+2018-03-23  Brady Eidson  <beidson@apple.com>
+
+        Go to back/forward list items after a process-swapped navigation.
+        <rdar://problem/38690544> and https://bugs.webkit.org/show_bug.cgi?id=183920
+
+        Reviewed by Andy Estes.
+
+        * WebView.cpp:
+        (WebView::goToBackForwardItem):
+        (WebView::loadBackForwardListFromOtherView):
+
 2018-03-23  Miguel Gomez  <magomez@igalia.com>
 
         [GTK][WPE] Avoid software color conversion inside BitmapTextureGL
index a5ff07c..23702b4 100644 (file)
@@ -3433,7 +3433,7 @@ HRESULT WebView::goToBackForwardItem(_In_opt_ IWebHistoryItem* item, _Out_ BOOL*
     if (FAILED(hr))
         return hr;
 
-    m_page->goToItem(*webHistoryItem->historyItem(), FrameLoadType::IndexedBackForward);
+    m_page->goToItem(*webHistoryItem->historyItem(), FrameLoadType::IndexedBackForward, NavigationPolicyCheck::Require);
     *succeeded = TRUE;
 
     return S_OK;
@@ -5960,7 +5960,7 @@ HRESULT WebView::loadBackForwardListFromOtherView(_In_opt_ IWebView* otherView)
     }
     
     ASSERT(newItemToGoTo);
-    m_page->goToItem(*newItemToGoTo, FrameLoadType::IndexedBackForward);
+    m_page->goToItem(*newItemToGoTo, FrameLoadType::IndexedBackForward, NavigationPolicyCheck::Require);
     return S_OK;
 }
 
index 0ca51c2..08f93a1 100644 (file)
@@ -1,3 +1,21 @@
+2018-03-23  Brady Eidson  <beidson@apple.com>
+
+        Go to back/forward list items after a process-swapped navigation.
+        <rdar://problem/38690544> and https://bugs.webkit.org/show_bug.cgi?id=183920
+
+        Reviewed by Andy Estes.
+
+        Add a new API test that does some process-swapping navigations (including a back navigation)
+        and verifies the state of the engine afterwards.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
+        (-[PSONMessageHandler userContentController:didReceiveScriptMessage:]):
+        (-[PSONScheme initWithBytes:]):
+        (-[PSONScheme webView:startURLSchemeTask:]):
+        (log):
+        (function):
+        (TEST): Deleted.
+
 2018-03-23  Brendan McLoughlin  <brendan@bocoup.com>
 
         Lint web-platform-tests changes with the wpt linter before exporting
index f4b1e07..f222cbe 100644 (file)
 static bool done;
 static int numberOfDecidePolicyCalls;
 
+static RetainPtr<NSMutableArray> receivedMessages = adoptNS([@[] mutableCopy]);
+static bool receivedMessage;
+@interface PSONMessageHandler : NSObject <WKScriptMessageHandler>
+@end
+
+@implementation PSONMessageHandler
+- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
+{
+    [receivedMessages addObject:[message body]];
+    receivedMessage = true;
+}
+@end
+
 @interface PSONNavigationDelegate : NSObject <WKNavigationDelegate>
 @end
 
@@ -71,16 +84,31 @@ static int numberOfDecidePolicyCalls;
 @end
 
 @interface PSONScheme : NSObject <WKURLSchemeHandler> {
+    const char* _bytes;
 }
+- (instancetype)initWithBytes:(const char*)bytes;
 @end
 
 @implementation PSONScheme
 
+- (instancetype)initWithBytes:(const char*)bytes
+{
+    self = [super init];
+    _bytes = bytes;
+    return self;
+}
+
 - (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)task
 {
     RetainPtr<NSURLResponse> response = adoptNS([[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:1 textEncodingName:nil]);
     [task didReceiveResponse:response.get()];
-    [task didReceiveData:[@"Hello" dataUsingEncoding:NSUTF8StringEncoding]];
+
+    if (_bytes) {
+        RetainPtr<NSData> data = adoptNS([[NSData alloc] initWithBytesNoCopy:(void *)_bytes length:strlen(_bytes) freeWhenDone:NO]);
+        [task didReceiveData:data.get()];
+    } else
+        [task didReceiveData:[@"Hello" dataUsingEncoding:NSUTF8StringEncoding]];
+
     [task didFinish];
 }
 
@@ -90,6 +118,28 @@ static int numberOfDecidePolicyCalls;
 
 @end
 
+static const char* testBytes = R"PSONRESOURCE(
+<head>
+<script>
+
+function log(msg)
+{
+    window.webkit.messageHandlers.pson.postMessage(msg);
+}
+
+window.onload = function(evt) {
+    if (window.history.state != "onloadCalled")
+        setTimeout('window.history.replaceState("onloadCalled", "");', 0);
+}
+
+window.onpageshow = function(evt) {
+    log("PageShow called. Persisted: " + evt.persisted + ", and window.history.state is: " + window.history.state);
+}
+
+</script>
+</head>
+)PSONRESOURCE";
+
 TEST(ProcessSwap, Basic)
 {
     auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
@@ -137,4 +187,70 @@ TEST(ProcessSwap, Basic)
     EXPECT_EQ(numberOfDecidePolicyCalls, 3);
 }
 
+TEST(ProcessSwap, Back)
+{
+    auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
+    processPoolConfiguration.get().processSwapsOnNavigation = YES;
+    auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
+
+    auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    [webViewConfiguration setProcessPool:processPool.get()];
+    RetainPtr<PSONScheme> handler1 = adoptNS([[PSONScheme alloc] initWithBytes:testBytes]);
+    RetainPtr<PSONScheme> handler2 = adoptNS([[PSONScheme alloc] init]);
+    [webViewConfiguration setURLSchemeHandler:handler1.get() forURLScheme:@"PSON1"];
+    [webViewConfiguration setURLSchemeHandler:handler2.get() forURLScheme:@"PSON2"];
+
+    RetainPtr<PSONMessageHandler> 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/main1.html"]];
+    [webView loadRequest:request];
+
+    TestWebKitAPI::Util::run(&receivedMessage);
+    receivedMessage = false;
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    auto pid1 = [webView _webProcessIdentifier];
+
+    request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson2://host/main2.html"]];
+    [webView loadRequest:request];
+
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    auto pid2 = [webView _webProcessIdentifier];
+
+    [webView goBack];
+
+    TestWebKitAPI::Util::run(&receivedMessage);
+    receivedMessage = false;
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    auto pid3 = [webView _webProcessIdentifier];
+
+    // 3 loads, 3 decidePolicy calls (e.g. any load that performs a process swap should not have generated an
+    // additional decidePolicy call as a result of the process swap)
+    EXPECT_EQ(numberOfDecidePolicyCalls, 3);
+
+    EXPECT_EQ([receivedMessages count], 2u);
+    EXPECT_TRUE([receivedMessages.get()[0] isEqualToString:@"PageShow called. Persisted: false, and window.history.state is: null"]);
+
+    // 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_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);
+}
+
 #endif // WK_API_ENABLED