[WK2] We should allow stale content when restoring a killed / crashed WebProcess
https://bugs.webkit.org/show_bug.cgi?id=142893
<rdar://problem/19633737>
<rdar://problem/19869257>

Reviewed by Antti Koivisto.

Source/WebCore:

Always use ReturnCacheDataElseLoad cache policy for history navigations.
Previously, we would use the default protocol cache policy for history
navigations if m_stateMachine.committedFirstRealDocumentLoad() returned
false so that we do not display stale content when restoring the session
state of Safari statup (rdar://problem/8131355). This is now handled
before reaching this method by no longer using "IndexedBackForward"
FrameLoadType when restoring session tabs, and using "Standard" load
type instead.

* loader/FrameLoader.cpp:
(WebCore::FrameLoader::loadDifferentDocumentItem):

Source/WebKit2:

Allow stale content when restoring a killed / crashed WebProcess
(similarly to a history navigation). This is actually what was intended
as we call WebPage::goToBackForwardItem() in this case, which uses
IndexedBackForward load type. However, this value was then ignored in
FrameLoader::loadDifferentDocumentItem().

This patch gets rid of the special casing in
FrameLoader::loadDifferentDocumentItem() and makes it clear at call
sites when calling goToBackForwardItem() if we should allow stale
content or not. If goToBackForwardItem() is called with the
allowStaleContent flag off, we'll keep using the IndexedBackForward
frame load type. However, if the flag is on, we'll use the Standard
frame load type and do a fresh load.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::reattachToWebProcessForReload):
Set allowStaleContent flag to true as we want to allow stale content
when reloading a WebProcess after it crashed or was killed (behavior
change).

(WebKit::WebPageProxy::reattachToWebProcessWithItem):
Add allowStaleContent parameter so that call sites can decide which
policy to use.

(WebKit::WebPageProxy::goForward):
(WebKit::WebPageProxy::goBack):
Set allowStaleContent flag to true as this is our policy for history
navigations.

(WebKit::WebPageProxy::goToBackForwardItem):
Add allowStaleContent parameter so that the call site can let us know
what to do. This is useful as this is called not only for indexed
back / forward navigations (allowing stale content) but also for
restoring session state (forbidding state content:
<rdar://problem/8131355>).

(WebKit::WebPageProxy::restoreFromSessionState):
Call goToBackForwardItem() with allowStaleContent flag set to false
as users expect fresh contents in this case. This method is called
when:
- Tabs are restored on Safari / MobileSafari startup
- Tabs are restored via "History > Reopen All windows from last session"

* UIProcess/WebPageProxy.h:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::goToBackForwardItem):
Add allowStaleContent parameter and use "Standard" frame load type
instead of "IndexedBackForward" if it is false. This is needed as
"IndexedBackForward" frame load type allows using stale content.

* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
Add allowStaleContent flag to GoToBackForwardItem message.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@181782 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 7655966..7570e1d 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,24 @@
+2015-03-19  Chris Dumez  <cdumez@apple.com>
+
+        [WK2] We should allow stale content when restoring a killed / crashed WebProcess
+        https://bugs.webkit.org/show_bug.cgi?id=142893
+        <rdar://problem/19633737>
+        <rdar://problem/19869257>
+
+        Reviewed by Antti Koivisto.
+
+        Always use ReturnCacheDataElseLoad cache policy for history navigations.
+        Previously, we would use the default protocol cache policy for history
+        navigations if m_stateMachine.committedFirstRealDocumentLoad() returned
+        false so that we do not display stale content when restoring the session
+        state of Safari statup (rdar://problem/8131355). This is now handled
+        before reaching this method by no longer using "IndexedBackForward"
+        FrameLoadType when restoring session tabs, and using "Standard" load
+        type instead.
+
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::loadDifferentDocumentItem):
+
 2015-03-19  Andy Estes  <aestes@apple.com>
 
         [Content Filtering] Move ContentFilter to from platform/ to loader/
diff --git a/Source/WebCore/loader/FrameLoader.cpp b/Source/WebCore/loader/FrameLoader.cpp
index ae927da..8c34459 100644
--- a/Source/WebCore/loader/FrameLoader.cpp
+++ b/Source/WebCore/loader/FrameLoader.cpp
@@ -3216,10 +3216,7 @@
         case FrameLoadType::Back:
         case FrameLoadType::Forward:
         case FrameLoadType::IndexedBackForward:
-            // If the first load within a frame is a navigation within a back/forward list that was attached 
-            // without any of the items being loaded then we should use the default caching policy (<rdar://problem/8131355>).
-            if (m_stateMachine.committedFirstRealDocumentLoad())
-                request.setCachePolicy(ReturnCacheDataElseLoad);
+            request.setCachePolicy(ReturnCacheDataElseLoad);
             break;
         case FrameLoadType::Standard:
         case FrameLoadType::RedirectWithLockedBackForwardList:
diff --git a/Source/WebKit2/ChangeLog b/Source/WebKit2/ChangeLog
index e7f1b6b..8121bed 100644
--- a/Source/WebKit2/ChangeLog
+++ b/Source/WebKit2/ChangeLog
@@ -1,3 +1,66 @@
+2015-03-19  Chris Dumez  <cdumez@apple.com>
+
+        [WK2] We should allow stale content when restoring a killed / crashed WebProcess
+        https://bugs.webkit.org/show_bug.cgi?id=142893
+        <rdar://problem/19633737>
+        <rdar://problem/19869257>
+
+        Reviewed by Antti Koivisto.
+
+        Allow stale content when restoring a killed / crashed WebProcess
+        (similarly to a history navigation). This is actually what was intended
+        as we call WebPage::goToBackForwardItem() in this case, which uses
+        IndexedBackForward load type. However, this value was then ignored in
+        FrameLoader::loadDifferentDocumentItem().
+
+        This patch gets rid of the special casing in
+        FrameLoader::loadDifferentDocumentItem() and makes it clear at call
+        sites when calling goToBackForwardItem() if we should allow stale
+        content or not. If goToBackForwardItem() is called with the
+        allowStaleContent flag off, we'll keep using the IndexedBackForward
+        frame load type. However, if the flag is on, we'll use the Standard
+        frame load type and do a fresh load.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::reattachToWebProcessForReload):
+        Set allowStaleContent flag to true as we want to allow stale content
+        when reloading a WebProcess after it crashed or was killed (behavior
+        change).
+
+        (WebKit::WebPageProxy::reattachToWebProcessWithItem):
+        Add allowStaleContent parameter so that call sites can decide which
+        policy to use.
+
+        (WebKit::WebPageProxy::goForward):
+        (WebKit::WebPageProxy::goBack):
+        Set allowStaleContent flag to true as this is our policy for history
+        navigations.
+
+        (WebKit::WebPageProxy::goToBackForwardItem):
+        Add allowStaleContent parameter so that the call site can let us know
+        what to do. This is useful as this is called not only for indexed
+        back / forward navigations (allowing stale content) but also for
+        restoring session state (forbidding state content:
+        <rdar://problem/8131355>).
+
+        (WebKit::WebPageProxy::restoreFromSessionState):
+        Call goToBackForwardItem() with allowStaleContent flag set to false
+        as users expect fresh contents in this case. This method is called
+        when:
+        - Tabs are restored on Safari / MobileSafari startup
+        - Tabs are restored via "History > Reopen All windows from last session"
+
+        * UIProcess/WebPageProxy.h:
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::goToBackForwardItem):
+        Add allowStaleContent parameter and use "Standard" frame load type
+        instead of "IndexedBackForward" if it is false. This is needed as
+        "IndexedBackForward" frame load type allows using stale content.
+
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+        Add allowStaleContent flag to GoToBackForwardItem message.
+
 2015-03-19  Eric Carlson  <eric.carlson@apple.com>
 
         [Mac] Move MediaPlaybackTargetPicker
diff --git a/Source/WebKit2/UIProcess/WebPageProxy.cpp b/Source/WebKit2/UIProcess/WebPageProxy.cpp
index 3b2efee..2946b02 100644
--- a/Source/WebKit2/UIProcess/WebPageProxy.cpp
+++ b/Source/WebKit2/UIProcess/WebPageProxy.cpp
@@ -655,13 +655,14 @@
 
     auto navigation = m_navigationState->createReloadNavigation();
 
-    m_process->send(Messages::WebPage::GoToBackForwardItem(navigation->navigationID(), m_backForwardList->currentItem()->itemID()), m_pageID);
+    // 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(), true /* allowStale */), m_pageID);
     m_process->responsivenessTimer()->start();
 
     return WTF::move(navigation);
 }
 
-RefPtr<API::Navigation> WebPageProxy::reattachToWebProcessWithItem(WebBackForwardListItem* item)
+RefPtr<API::Navigation> WebPageProxy::reattachToWebProcessWithItem(WebBackForwardListItem* item, AllowStaleContent allowStaleContent)
 {
     if (m_isClosed)
         return nullptr;
@@ -677,7 +678,7 @@
 
     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(), allowStaleContent == AllowStaleContent::Yes), m_pageID);
     m_process->responsivenessTimer()->start();
 
     return WTF::move(navigation);
@@ -1025,7 +1026,7 @@
     m_pageLoadState.setPendingAPIRequestURL(transaction, forwardItem->url());
 
     if (!isValid())
-        return reattachToWebProcessWithItem(forwardItem);
+        return reattachToWebProcessWithItem(forwardItem, AllowStaleContent::Yes);
 
     RefPtr<API::Navigation> navigation;
     if (!m_backForwardList->currentItem()->itemIsInSameDocument(*forwardItem))
@@ -1048,7 +1049,7 @@
     m_pageLoadState.setPendingAPIRequestURL(transaction, backItem->url());
 
     if (!isValid())
-        return reattachToWebProcessWithItem(backItem);
+        return reattachToWebProcessWithItem(backItem, AllowStaleContent::Yes);
 
     RefPtr<API::Navigation> navigation;
     if (!m_backForwardList->currentItem()->itemIsInSameDocument(*backItem))
@@ -1060,10 +1061,10 @@
     return navigation;
 }
 
-RefPtr<API::Navigation> WebPageProxy::goToBackForwardItem(WebBackForwardListItem* item)
+RefPtr<API::Navigation> WebPageProxy::goToBackForwardItem(WebBackForwardListItem* item, AllowStaleContent allowStaleContent)
 {
     if (!isValid())
-        return reattachToWebProcessWithItem(item);
+        return reattachToWebProcessWithItem(item, allowStaleContent);
 
     auto transaction = m_pageLoadState.transaction();
 
@@ -1073,7 +1074,7 @@
     if (!m_backForwardList->currentItem()->itemIsInSameDocument(*item))
         navigation = m_navigationState->createBackForwardNavigation();
 
-    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(), allowStaleContent == AllowStaleContent::Yes), m_pageID);
     m_process->responsivenessTimer()->start();
 
     return navigation;
@@ -2094,8 +2095,10 @@
 
         if (hasBackForwardList) {
             // FIXME: Do we have to null check the back forward list item here?
-            if (WebBackForwardListItem* item = m_backForwardList->currentItem())
-                return goToBackForwardItem(item);
+            if (WebBackForwardListItem* item = m_backForwardList->currentItem()) {
+                // We forbid stale content when restoring the session state and do a fresh load (rdar://problem/8131355).
+                return goToBackForwardItem(item, AllowStaleContent::No);
+            }
         }
     }
 
diff --git a/Source/WebKit2/UIProcess/WebPageProxy.h b/Source/WebKit2/UIProcess/WebPageProxy.h
index fd01e18..b7a9589 100644
--- a/Source/WebKit2/UIProcess/WebPageProxy.h
+++ b/Source/WebKit2/UIProcess/WebPageProxy.h
@@ -358,7 +358,8 @@
     RefPtr<API::Navigation> goForward();
     RefPtr<API::Navigation> goBack();
 
-    RefPtr<API::Navigation> goToBackForwardItem(WebBackForwardListItem*);
+    enum class AllowStaleContent { No, Yes };
+    RefPtr<API::Navigation> goToBackForwardItem(WebBackForwardListItem*, AllowStaleContent = AllowStaleContent::Yes);
     void tryRestoreScrollPosition();
     void didChangeBackForwardList(WebBackForwardListItem* addedItem, Vector<RefPtr<WebBackForwardListItem>> removed);
     void willGoToBackForwardListItem(uint64_t itemID, const UserData&);
@@ -1162,7 +1163,7 @@
 
     void reattachToWebProcess();
     RefPtr<API::Navigation> reattachToWebProcessForReload();
-    RefPtr<API::Navigation> reattachToWebProcessWithItem(WebBackForwardListItem*);
+    RefPtr<API::Navigation> reattachToWebProcessWithItem(WebBackForwardListItem*, AllowStaleContent);
 
     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, const String& dir, const String& originString, uint64_t notificationID);
diff --git a/Source/WebKit2/WebProcess/WebPage/WebPage.cpp b/Source/WebKit2/WebProcess/WebPage/WebPage.cpp
index 10873db..b8bbebb 100644
--- a/Source/WebKit2/WebProcess/WebPage/WebPage.cpp
+++ b/Source/WebKit2/WebProcess/WebPage/WebPage.cpp
@@ -1161,7 +1161,7 @@
     m_page->goToItem(*item, FrameLoadType::Back);
 }
 
-void WebPage::goToBackForwardItem(uint64_t navigationID, uint64_t backForwardItemID)
+void WebPage::goToBackForwardItem(uint64_t navigationID, uint64_t backForwardItemID, bool allowStaleContent)
 {
     SendStopResponsivenessTimer stopper(this);
 
@@ -1174,7 +1174,7 @@
     if (!item->isInPageCache())
         m_pendingNavigationID = navigationID;
 
-    m_page->goToItem(*item, FrameLoadType::IndexedBackForward);
+    m_page->goToItem(*item, allowStaleContent ? FrameLoadType::IndexedBackForward : FrameLoadType::Standard);
 }
 
 void WebPage::tryRestoreScrollPosition()
diff --git a/Source/WebKit2/WebProcess/WebPage/WebPage.h b/Source/WebKit2/WebProcess/WebPage/WebPage.h
index e64e6c1..df48431 100644
--- a/Source/WebKit2/WebProcess/WebPage/WebPage.h
+++ b/Source/WebKit2/WebProcess/WebPage/WebPage.h
@@ -926,7 +926,7 @@
     void reload(uint64_t navigationID, bool reloadFromOrigin, const 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, bool allowStaleContent);
     void tryRestoreScrollPosition();
     void setInitialFocus(bool forward, bool isKeyboardEventValid, const WebKeyboardEvent&);
     void setWindowResizerSize(const WebCore::IntSize&);
diff --git a/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in b/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in
index 7bf99fc..b3a53b4 100644
--- a/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in
+++ b/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in
@@ -119,7 +119,7 @@
 
     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, bool allowStaleContent)
     TryRestoreScrollPosition()
 
     LoadURLInFrame(String url, uint64_t frameID)