<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[186304] trunk/Source</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/186304">186304</a></dd>
<dt>Author</dt> <dd>cdumez@apple.com</dd>
<dt>Date</dt> <dd>2015-07-05 23:32:02 -0700 (Sun, 05 Jul 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>[WK2] Current page's scroll position is lost when transferring sessionState from one view to another
https://bugs.webkit.org/show_bug.cgi?id=146625
&lt;rdar://problem/21585268&gt;

Reviewed by Gavin Barraclough.

Source/WebCore:

Export HistoryController:saveScrollPositionAndViewStateToItem()
so that it can be called from WebKit2.

* loader/HistoryController.h:

Source/WebKit2:

The current page's scroll position was lost when transferring the
sessionState from one view to another. This is because we only update
the current WebBackForwardListItem after navigating away.
However, when the client swaps WebViews for navigating, we don't detect
this as navigating away and the current WebBackForwardListItem is not
updated with the current page's state (including the scroll position).
This means that the information is not transferred via the sessionState
and the scroll position (among other things) ends up being lost when
navigating back in the new WebView.

Retrieving the session state is a synchronous API and we want to avoid
doing a synchronous IPC between the UIProcess and the WebProcess to
retrieve the current page's state. Therefore, the approach chosen in
this patch is to detect when the user is done scrolling the main frame
(using a HystererisActivity) and then update the scroll position on the
current HistoryItem. This way, the current WebBackForwardListItem
normally has an up-to-date scroll position for the main frame when the
sessionState is queried by the client.

The solution is not perfect as we don't keep the whole page state
up-to-date for the current WebBackForwardListItem, only the main frame
state. However, the proposed solution is cheap, avoid synchronous IPC
and provides a much better user experience in most cases.

* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::WebPage):
(WebKit::WebPage::pageDidScroll):
(WebKit::WebPage::pageStoppedScrolling):
* WebProcess/WebPage/WebPage.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreloaderHistoryControllerh">trunk/Source/WebCore/loader/HistoryController.h</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageWebPagecpp">trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageWebPageh">trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (186303 => 186304)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-07-06 06:26:06 UTC (rev 186303)
+++ trunk/Source/WebCore/ChangeLog        2015-07-06 06:32:02 UTC (rev 186304)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2015-07-05  Chris Dumez  &lt;cdumez@apple.com&gt;
+
+        [WK2] Current page's scroll position is lost when transferring sessionState from one view to another
+        https://bugs.webkit.org/show_bug.cgi?id=146625
+        &lt;rdar://problem/21585268&gt;
+
+        Reviewed by Gavin Barraclough.
+
+        Export HistoryController:saveScrollPositionAndViewStateToItem()
+        so that it can be called from WebKit2.
+
+        * loader/HistoryController.h:
+
</ins><span class="cx"> 2015-07-05  Simon Fraser  &lt;simon.fraser@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         REGRESSION (r180582): background-attachment: local; does not scroll the background image when scrolling the the element's contents
</span></span></pre></div>
<a id="trunkSourceWebCoreloaderHistoryControllerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/HistoryController.h (186303 => 186304)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/HistoryController.h        2015-07-06 06:26:06 UTC (rev 186303)
+++ trunk/Source/WebCore/loader/HistoryController.h        2015-07-06 06:32:02 UTC (rev 186304)
</span><span class="lines">@@ -52,7 +52,7 @@
</span><span class="cx">     explicit HistoryController(Frame&amp;);
</span><span class="cx">     ~HistoryController();
</span><span class="cx"> 
</span><del>-    void saveScrollPositionAndViewStateToItem(HistoryItem*);
</del><ins>+    WEBCORE_EXPORT void saveScrollPositionAndViewStateToItem(HistoryItem*);
</ins><span class="cx">     void clearScrollPositionAndViewState();
</span><span class="cx">     WEBCORE_EXPORT void restoreScrollPositionAndViewState();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (186303 => 186304)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2015-07-06 06:26:06 UTC (rev 186303)
+++ trunk/Source/WebKit2/ChangeLog        2015-07-06 06:32:02 UTC (rev 186304)
</span><span class="lines">@@ -1,3 +1,41 @@
</span><ins>+2015-07-05  Chris Dumez  &lt;cdumez@apple.com&gt;
+
+        [WK2] Current page's scroll position is lost when transferring sessionState from one view to another
+        https://bugs.webkit.org/show_bug.cgi?id=146625
+        &lt;rdar://problem/21585268&gt;
+
+        Reviewed by Gavin Barraclough.
+
+        The current page's scroll position was lost when transferring the
+        sessionState from one view to another. This is because we only update
+        the current WebBackForwardListItem after navigating away.
+        However, when the client swaps WebViews for navigating, we don't detect
+        this as navigating away and the current WebBackForwardListItem is not
+        updated with the current page's state (including the scroll position).
+        This means that the information is not transferred via the sessionState
+        and the scroll position (among other things) ends up being lost when
+        navigating back in the new WebView.
+
+        Retrieving the session state is a synchronous API and we want to avoid
+        doing a synchronous IPC between the UIProcess and the WebProcess to
+        retrieve the current page's state. Therefore, the approach chosen in
+        this patch is to detect when the user is done scrolling the main frame
+        (using a HystererisActivity) and then update the scroll position on the
+        current HistoryItem. This way, the current WebBackForwardListItem
+        normally has an up-to-date scroll position for the main frame when the
+        sessionState is queried by the client.
+
+        The solution is not perfect as we don't keep the whole page state
+        up-to-date for the current WebBackForwardListItem, only the main frame
+        state. However, the proposed solution is cheap, avoid synchronous IPC
+        and provides a much better user experience in most cases.
+
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::WebPage):
+        (WebKit::WebPage::pageDidScroll):
+        (WebKit::WebPage::pageStoppedScrolling):
+        * WebProcess/WebPage/WebPage.h:
+
</ins><span class="cx"> 2015-07-05  Timothy Hatcher  &lt;timothy@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Crash when closing the web inspector
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageWebPagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp (186303 => 186304)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp        2015-07-06 06:26:06 UTC (rev 186303)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp        2015-07-06 06:32:02 UTC (rev 186304)
</span><span class="lines">@@ -221,6 +221,8 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebKit {
</span><span class="cx"> 
</span><ins>+static const double pageScrollHysteresisSeconds = 0.3;
+
</ins><span class="cx"> class SendStopResponsivenessTimer {
</span><span class="cx"> public:
</span><span class="cx">     SendStopResponsivenessTimer(WebPage* page)
</span><span class="lines">@@ -295,6 +297,7 @@
</span><span class="cx"> #if ENABLE(MEDIA_STREAM)
</span><span class="cx">     , m_userMediaPermissionRequestManager(*this)
</span><span class="cx"> #endif
</span><ins>+    , m_pageScrolledHysteresis([this](HysteresisState state) { if (state == HysteresisState::Stopped) pageStoppedScrolling(); }, pageScrollHysteresisSeconds)
</ins><span class="cx">     , m_canRunBeforeUnloadConfirmPanel(parameters.canRunBeforeUnloadConfirmPanel)
</span><span class="cx">     , m_canRunModal(parameters.canRunModal)
</span><span class="cx">     , m_isRunningModal(false)
</span><span class="lines">@@ -1817,9 +1820,18 @@
</span><span class="cx"> #endif
</span><span class="cx">     m_uiClient-&gt;pageDidScroll(this);
</span><span class="cx"> 
</span><ins>+    m_pageScrolledHysteresis.impulse();
+
</ins><span class="cx">     send(Messages::WebPageProxy::PageDidScroll());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebPage::pageStoppedScrolling()
+{
+    // Maintain the current history item's scroll position up-to-date.
+    if (Frame* frame = m_mainFrame-&gt;coreFrame())
+        frame-&gt;loader().history().saveScrollPositionAndViewStateToItem(frame-&gt;loader().history().currentItem());
+}
+
</ins><span class="cx"> #if USE(COORDINATED_GRAPHICS)
</span><span class="cx"> void WebPage::pageDidRequestScroll(const IntPoint&amp; point)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageWebPageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h (186303 => 186304)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h        2015-07-06 06:26:06 UTC (rev 186303)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h        2015-07-06 06:32:02 UTC (rev 186304)
</span><span class="lines">@@ -53,6 +53,7 @@
</span><span class="cx"> #include &lt;WebCore/Editor.h&gt;
</span><span class="cx"> #include &lt;WebCore/FrameLoaderTypes.h&gt;
</span><span class="cx"> #include &lt;WebCore/HitTestResult.h&gt;
</span><ins>+#include &lt;WebCore/HysteresisActivity.h&gt;
</ins><span class="cx"> #include &lt;WebCore/IntRect.h&gt;
</span><span class="cx"> #include &lt;WebCore/IntSizeHash.h&gt;
</span><span class="cx"> #include &lt;WebCore/Page.h&gt;
</span><span class="lines">@@ -1137,6 +1138,8 @@
</span><span class="cx">     void setShouldScaleViewToFitDocument(bool);
</span><span class="cx">     void setUserContentExtensionsEnabled(bool);
</span><span class="cx"> 
</span><ins>+    void pageStoppedScrolling();
+
</ins><span class="cx">     uint64_t m_pageID;
</span><span class="cx"> 
</span><span class="cx">     std::unique_ptr&lt;WebCore::Page&gt; m_page;
</span><span class="lines">@@ -1282,6 +1285,8 @@
</span><span class="cx">     RefPtr&lt;SandboxExtension&gt; m_pendingDropSandboxExtension;
</span><span class="cx">     Vector&lt;RefPtr&lt;SandboxExtension&gt;&gt; m_pendingDropExtensionsForFileUpload;
</span><span class="cx"> 
</span><ins>+    WebCore::HysteresisActivity m_pageScrolledHysteresis;
+
</ins><span class="cx">     bool m_canRunBeforeUnloadConfirmPanel;
</span><span class="cx"> 
</span><span class="cx">     bool m_canRunModal;
</span></span></pre>
</div>
</div>

</body>
</html>