<!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>[186200] trunk/Source/WebKit2</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/186200">186200</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2015-07-01 16:17:58 -0700 (Wed, 01 Jul 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Web page doesn't update its loading state when web process becomes suspended if there are pending network requests (XHR).
https://bugs.webkit.org/show_bug.cgi?id=146439

When web page is loading, we hold a background activity token in NavigationState and we release the token when the page done
loading. A web page can start loading subresources (like XHR) after the page is loaded, and WebPageProxy will update its
_networkRequestsInProgress state which will notify the client there is network actvity on-going. Since we don't hold
the background activity token after page is loaded, the WebContent process could become suspended without notifying the client
and the client will lose track of the loading state.

The first thought was to hold another background activity when _networkRequestsInProgress flag is set in NavigationState.
However, this could result in side-effect that a WebContent process can stay active for too long if there is a long lasting
XHR resquest.

This patch fix this by notifying the client that network activity is stopped when WebContent process is going to be suspended.
We also cache the networkRequestsInProgress state for suspended process, so that when it becomes foreground, we can tell
the client the correct state of network activity.

Patch by Yongjun Zhang &lt;yongjun_zhang@apple.com&gt; on 2015-07-01
Reviewed by Dan Bernstein.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::WebPageProxy): Initialize m_hasNetworkRequestsOnSuspended.
(WebKit::WebPageProxy::processWillBecomeSuspended): If there is pending requests on suspend, cache the network activity state
    and notify the client.
(WebKit::WebPageProxy::processWillBecomeForground): Restore the network activity state when the process becomes foreground.
(WebKit::WebPageProxy::resetState):
* UIProcess/WebPageProxy.h: Add a data member m_hasNetworkRequestsOnSuspended to cache the network activity state on process
    suspend.
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::didSetAssertionState):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebPageProxycpp">trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebPageProxyh">trunk/Source/WebKit2/UIProcess/WebPageProxy.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebProcessProxycpp">trunk/Source/WebKit2/UIProcess/WebProcessProxy.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (186199 => 186200)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2015-07-01 23:09:48 UTC (rev 186199)
+++ trunk/Source/WebKit2/ChangeLog        2015-07-01 23:17:58 UTC (rev 186200)
</span><span class="lines">@@ -1,3 +1,35 @@
</span><ins>+2015-07-01  Yongjun Zhang  &lt;yongjun_zhang@apple.com&gt;
+
+        Web page doesn't update its loading state when web process becomes suspended if there are pending network requests (XHR).
+        https://bugs.webkit.org/show_bug.cgi?id=146439
+
+        When web page is loading, we hold a background activity token in NavigationState and we release the token when the page done
+        loading. A web page can start loading subresources (like XHR) after the page is loaded, and WebPageProxy will update its
+        _networkRequestsInProgress state which will notify the client there is network actvity on-going. Since we don't hold
+        the background activity token after page is loaded, the WebContent process could become suspended without notifying the client
+        and the client will lose track of the loading state.
+
+        The first thought was to hold another background activity when _networkRequestsInProgress flag is set in NavigationState.
+        However, this could result in side-effect that a WebContent process can stay active for too long if there is a long lasting
+        XHR resquest.
+        
+        This patch fix this by notifying the client that network activity is stopped when WebContent process is going to be suspended.
+        We also cache the networkRequestsInProgress state for suspended process, so that when it becomes foreground, we can tell
+        the client the correct state of network activity.
+
+        Reviewed by Dan Bernstein.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::WebPageProxy): Initialize m_hasNetworkRequestsOnSuspended.
+        (WebKit::WebPageProxy::processWillBecomeSuspended): If there is pending requests on suspend, cache the network activity state
+            and notify the client.
+        (WebKit::WebPageProxy::processWillBecomeForground): Restore the network activity state when the process becomes foreground. 
+        (WebKit::WebPageProxy::resetState):
+        * UIProcess/WebPageProxy.h: Add a data member m_hasNetworkRequestsOnSuspended to cache the network activity state on process
+            suspend.
+        * UIProcess/WebProcessProxy.cpp:
+        (WebKit::WebProcessProxy::didSetAssertionState):
+
</ins><span class="cx"> 2015-07-01  Dean Jackson  &lt;dino@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Disable the experimental WebGL2 implementation
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp (186199 => 186200)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2015-07-01 23:09:48 UTC (rev 186199)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2015-07-01 23:17:58 UTC (rev 186200)
</span><span class="lines">@@ -303,6 +303,7 @@
</span><span class="cx">     , m_dynamicViewportSizeUpdateWaitingForLayerTreeCommit(false)
</span><span class="cx">     , m_dynamicViewportSizeUpdateLayerTreeTransactionID(0)
</span><span class="cx">     , m_layerTreeTransactionIdAtLastTouchStart(0)
</span><ins>+    , m_hasNetworkRequestsOnSuspended(false)
</ins><span class="cx"> #endif
</span><span class="cx">     , m_geolocationPermissionRequestManager(*this)
</span><span class="cx">     , m_notificationPermissionRequestManager(*this)
</span><span class="lines">@@ -4834,6 +4835,27 @@
</span><span class="cx">         m_loaderClient-&gt;processDidCrash(*this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if PLATFORM(IOS)
+void WebPageProxy::processWillBecomeSuspended()
+{
+    ASSERT(m_isValid);
+
+    m_hasNetworkRequestsOnSuspended = m_pageLoadState.networkRequestsInProgress();
+    if (m_hasNetworkRequestsOnSuspended)
+        setNetworkRequestsInProgress(false);
+}
+
+void WebPageProxy::processWillBecomeForeground()
+{
+    ASSERT(m_isValid);
+
+    if (m_hasNetworkRequestsOnSuspended) {
+        setNetworkRequestsInProgress(true);
+        m_hasNetworkRequestsOnSuspended = false;
+    }
+}
+#endif
+
</ins><span class="cx"> void WebPageProxy::resetState(ResetStateReason resetStateReason)
</span><span class="cx"> {
</span><span class="cx">     m_mainFrame = nullptr;
</span><span class="lines">@@ -4903,6 +4925,7 @@
</span><span class="cx">     m_dynamicViewportSizeUpdateWaitingForLayerTreeCommit = false;
</span><span class="cx">     m_dynamicViewportSizeUpdateLayerTreeTransactionID = 0;
</span><span class="cx">     m_layerTreeTransactionIdAtLastTouchStart = 0;
</span><ins>+    m_hasNetworkRequestsOnSuspended = false;
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(WIRELESS_PLAYBACK_TARGET) &amp;&amp; !PLATFORM(IOS)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.h (186199 => 186200)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.h        2015-07-01 23:09:48 UTC (rev 186199)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.h        2015-07-01 23:17:58 UTC (rev 186200)
</span><span class="lines">@@ -816,6 +816,10 @@
</span><span class="cx">     void interactionOccurredWhileProcessUnresponsive();
</span><span class="cx">     void processDidBecomeResponsive();
</span><span class="cx">     void processDidCrash();
</span><ins>+#if PLATFORM(IOS)
+    void processWillBecomeSuspended();
+    void processWillBecomeForeground();
+#endif
</ins><span class="cx"> 
</span><span class="cx">     virtual void enterAcceleratedCompositingMode(const LayerTreeContext&amp;);
</span><span class="cx">     virtual void exitAcceleratedCompositingMode();
</span><span class="lines">@@ -1532,6 +1536,7 @@
</span><span class="cx">     uint64_t m_dynamicViewportSizeUpdateLayerTreeTransactionID;
</span><span class="cx">     uint64_t m_layerTreeTransactionIdAtLastTouchStart;
</span><span class="cx">     uint64_t m_currentDynamicViewportSizeUpdateID { 0 };
</span><ins>+    bool m_hasNetworkRequestsOnSuspended;
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(VIBRATION)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebProcessProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebProcessProxy.cpp (186199 => 186200)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebProcessProxy.cpp        2015-07-01 23:09:48 UTC (rev 186199)
+++ trunk/Source/WebKit2/UIProcess/WebProcessProxy.cpp        2015-07-01 23:17:58 UTC (rev 186200)
</span><span class="lines">@@ -921,6 +921,8 @@
</span><span class="cx">     case AssertionState::Suspended:
</span><span class="cx">         m_foregroundTokenForNetworkProcess = nullptr;
</span><span class="cx">         m_backgroundTokenForNetworkProcess = nullptr;
</span><ins>+        for (auto&amp; page : m_pageMap.values())
+            page-&gt;processWillBecomeSuspended();
</ins><span class="cx">         break;
</span><span class="cx"> 
</span><span class="cx">     case AssertionState::Background:
</span><span class="lines">@@ -933,6 +935,8 @@
</span><span class="cx">         if (processPool().usesNetworkProcess())
</span><span class="cx">             m_foregroundTokenForNetworkProcess = processPool().ensureNetworkProcess().throttler().foregroundActivityToken();
</span><span class="cx">         m_backgroundTokenForNetworkProcess = nullptr;
</span><ins>+        for (auto&amp; page : m_pageMap.values())
+            page-&gt;processWillBecomeForeground();
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> #else
</span></span></pre>
</div>
</div>

</body>
</html>