<!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>[201519] 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/201519">201519</a></dd>
<dt>Author</dt> <dd>cdumez@apple.com</dd>
<dt>Date</dt> <dd>2016-05-31 12:35:06 -0700 (Tue, 31 May 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>[iOS] Better deal with WebProcess suspension due to screen locking
https://bugs.webkit.org/show_bug.cgi?id=158229
&lt;rdar://problem/17665473&gt;
&lt;rdar://problem/26554699&gt;

Reviewed by Tim Horton.

When locking the screen while MobileSafari is front-most, we would try keep
trying to mark IOSurfaces as volatile until the 30 seconds timeout was
reached. This patch deals more cleanly with this situation by only trying
to mark IOSurfaces as volatile once if the suspension is due to screen
locking. In such case, it is apparently expected that some IOSurfaces cannot
be marked as volatile so it is enough to try once and let ourselves get
suspended.

This patch also reduces the timeout from 30 seconds to ~3 seconds in the
other suspension cases (e.g. homing out of MobileSafari). If we fail to mark
them as purgeable for 3 seconds for a reason or another, it is no use in
retrying, it is simply not going to happen and there is no reason to delay
process suspension any further.

* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::callVolatilityCompletionHandlers):
(WebKit::WebPage::layerVolatilityTimerFired):
(WebKit::WebPage::markLayersVolatileImmediatelyIfPossible):
(WebKit::WebPage::markLayersVolatile):
* WebProcess/WebPage/WebPage.h:
(WebKit::WebPage::markLayersVolatile):
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::applicationDidEnterBackground):
(WebKit::WebPage::applicationWillEnterForeground):</pre>

<h3>Modified Paths</h3>
<ul>
<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>
<li><a href="#trunkSourceWebKit2WebProcessWebPageiosWebPageIOSmm">trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (201518 => 201519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2016-05-31 19:33:22 UTC (rev 201518)
+++ trunk/Source/WebKit2/ChangeLog        2016-05-31 19:35:06 UTC (rev 201519)
</span><span class="lines">@@ -1,3 +1,37 @@
</span><ins>+2016-05-31  Chris Dumez  &lt;cdumez@apple.com&gt;
+
+        [iOS] Better deal with WebProcess suspension due to screen locking
+        https://bugs.webkit.org/show_bug.cgi?id=158229
+        &lt;rdar://problem/17665473&gt;
+        &lt;rdar://problem/26554699&gt;
+
+        Reviewed by Tim Horton.
+
+        When locking the screen while MobileSafari is front-most, we would try keep
+        trying to mark IOSurfaces as volatile until the 30 seconds timeout was
+        reached. This patch deals more cleanly with this situation by only trying
+        to mark IOSurfaces as volatile once if the suspension is due to screen
+        locking. In such case, it is apparently expected that some IOSurfaces cannot
+        be marked as volatile so it is enough to try once and let ourselves get
+        suspended.
+
+        This patch also reduces the timeout from 30 seconds to ~3 seconds in the
+        other suspension cases (e.g. homing out of MobileSafari). If we fail to mark
+        them as purgeable for 3 seconds for a reason or another, it is no use in
+        retrying, it is simply not going to happen and there is no reason to delay
+        process suspension any further.
+
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::callVolatilityCompletionHandlers):
+        (WebKit::WebPage::layerVolatilityTimerFired):
+        (WebKit::WebPage::markLayersVolatileImmediatelyIfPossible):
+        (WebKit::WebPage::markLayersVolatile):
+        * WebProcess/WebPage/WebPage.h:
+        (WebKit::WebPage::markLayersVolatile):
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::applicationDidEnterBackground):
+        (WebKit::WebPage::applicationWillEnterForeground):
+
</ins><span class="cx"> 2016-05-31  Brady Eidson  &lt;beidson@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Make createCrossThreadTask() functions return on the stack instead of the heap.
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageWebPagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp (201518 => 201519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp        2016-05-31 19:33:22 UTC (rev 201518)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp        2016-05-31 19:35:06 UTC (rev 201519)
</span><span class="lines">@@ -248,7 +248,7 @@
</span><span class="cx"> 
</span><span class="cx"> static const double pageScrollHysteresisSeconds = 0.3;
</span><span class="cx"> static const std::chrono::milliseconds initialLayerVolatilityTimerInterval { 20 };
</span><del>-static const std::chrono::seconds maximumLayerVolatilityTimerInterval { 10 };
</del><ins>+static const std::chrono::seconds maximumLayerVolatilityTimerInterval { 2 };
</ins><span class="cx"> 
</span><span class="cx"> #define WEBPAGE_LOG_ALWAYS(...) LOG_ALWAYS(isAlwaysOnLoggingAllowed(), __VA_ARGS__)
</span><span class="cx"> #define WEBPAGE_LOG_ALWAYS_ERROR(...) LOG_ALWAYS_ERROR(isAlwaysOnLoggingAllowed(), __VA_ARGS__)
</span><span class="lines">@@ -2037,32 +2037,34 @@
</span><span class="cx">     drawingArea-&gt;setLayerTreeStateIsFrozen(frozen);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebPage::callVolatilityCompletionHandlers()
+{
+    auto completionHandlers = WTFMove(m_markLayersAsVolatileCompletionHandlers);
+    for (auto&amp; completionHandler : completionHandlers)
+        completionHandler();
+}
+
</ins><span class="cx"> void WebPage::layerVolatilityTimerFired()
</span><span class="cx"> {
</span><del>-    if (markLayersVolatileImmediatelyIfPossible()) {
</del><ins>+    auto newInterval = 2 * m_layerVolatilityTimer.repeatIntervalMS();
+    bool didSucceed = markLayersVolatileImmediatelyIfPossible();
+    if (didSucceed || newInterval &gt; maximumLayerVolatilityTimerInterval) {
</ins><span class="cx">         m_layerVolatilityTimer.stop();
</span><ins>+        WEBPAGE_LOG_ALWAYS(&quot;%p - WebPage - Attempted to mark surfaces as volatile, success? %d&quot;, this, didSucceed);
+        callVolatilityCompletionHandlers();
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    auto newInterval = std::min(2 * m_layerVolatilityTimer.repeatIntervalMS(), std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(maximumLayerVolatilityTimerInterval));
</del><span class="cx">     WEBPAGE_LOG_ALWAYS_ERROR(&quot;%p - WebPage - Failed to mark all layers as volatile, will retry in %lld ms&quot;, this, static_cast&lt;long long&gt;(newInterval.count()));
</span><span class="cx">     m_layerVolatilityTimer.startRepeating(newInterval);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool WebPage::markLayersVolatileImmediatelyIfPossible()
</span><span class="cx"> {
</span><del>-    bool success = !drawingArea() || drawingArea()-&gt;markLayersVolatileImmediatelyIfPossible();
-    if (success) {
-        WEBPAGE_LOG_ALWAYS(&quot;%p - WebPage - Successfully marked layers as volatile&quot;, this);
-        auto completionHandlers = WTFMove(m_markLayersAsVolatileCompletionHandlers);
-        for (auto&amp; completionHandler : completionHandlers)
-            completionHandler();
-    }
-
-    return success;
</del><ins>+    return !drawingArea() || drawingArea()-&gt;markLayersVolatileImmediatelyIfPossible();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebPage::markLayersVolatile(std::function&lt;void()&gt; completionHandler)
</del><ins>+void WebPage::markLayersVolatile(std::function&lt;void ()&gt; completionHandler)
</ins><span class="cx"> {
</span><span class="cx">     WEBPAGE_LOG_ALWAYS(&quot;%p - WebPage::markLayersVolatile()&quot;, this);
</span><span class="cx"> 
</span><span class="lines">@@ -2072,8 +2074,17 @@
</span><span class="cx">     if (completionHandler)
</span><span class="cx">         m_markLayersAsVolatileCompletionHandlers.append(WTFMove(completionHandler));
</span><span class="cx"> 
</span><del>-    if (markLayersVolatileImmediatelyIfPossible())
</del><ins>+    bool didSucceed = markLayersVolatileImmediatelyIfPossible();
+    if (didSucceed || m_isSuspendedUnderLock) {
+        if (didSucceed)
+            WEBPAGE_LOG_ALWAYS(&quot;%p - WebPage - Successfully marked layers as volatile&quot;, this);
+        else {
+            // If we get suspended when locking the screen, it is expected that some IOSurfaces cannot be marked as purgeable so we do not keep retrying.
+            WEBPAGE_LOG_ALWAYS(&quot;%p - WebPage - Did what we could to mark IOSurfaces as purgeable after locking the screen&quot;, this);
+        }
+        callVolatilityCompletionHandlers();
</ins><span class="cx">         return;
</span><ins>+    }
</ins><span class="cx"> 
</span><span class="cx">     WEBPAGE_LOG_ALWAYS(&quot;%p - Failed to mark all layers as volatile, will retry in %lld ms&quot;, this, initialLayerVolatilityTimerInterval.count());
</span><span class="cx">     m_layerVolatilityTimer.startRepeating(initialLayerVolatilityTimerInterval);
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageWebPageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h (201518 => 201519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h        2016-05-31 19:33:22 UTC (rev 201518)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h        2016-05-31 19:35:06 UTC (rev 201519)
</span><span class="lines">@@ -582,7 +582,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     void setLayerTreeStateIsFrozen(bool);
</span><del>-    void markLayersVolatile(std::function&lt;void()&gt; completionHandler = {});
</del><ins>+    void markLayersVolatile(std::function&lt;void ()&gt; completionHandler = { });
</ins><span class="cx">     void cancelMarkLayersVolatile();
</span><span class="cx"> 
</span><span class="cx">     NotificationPermissionRequestManager* notificationPermissionRequestManager();
</span><span class="lines">@@ -992,6 +992,7 @@
</span><span class="cx"> 
</span><span class="cx">     bool markLayersVolatileImmediatelyIfPossible();
</span><span class="cx">     void layerVolatilityTimerFired();
</span><ins>+    void callVolatilityCompletionHandlers();
</ins><span class="cx"> 
</span><span class="cx">     String sourceForFrame(WebFrame*);
</span><span class="cx"> 
</span><span class="lines">@@ -1426,7 +1427,8 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     WebCore::Timer m_layerVolatilityTimer;
</span><del>-    Vector&lt;std::function&lt;void()&gt;&gt; m_markLayersAsVolatileCompletionHandlers;
</del><ins>+    Vector&lt;std::function&lt;void ()&gt;&gt; m_markLayersAsVolatileCompletionHandlers;
+    bool m_isSuspendedUnderLock { false };
</ins><span class="cx"> 
</span><span class="cx">     HashSet&lt;String, ASCIICaseInsensitiveHash&gt; m_mimeTypesWithCustomContentProviders;
</span><span class="cx">     WebCore::Color m_backgroundColor;
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageiosWebPageIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm (201518 => 201519)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm        2016-05-31 19:33:22 UTC (rev 201518)
+++ trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm        2016-05-31 19:35:06 UTC (rev 201519)
</span><span class="lines">@@ -2973,12 +2973,14 @@
</span><span class="cx"> {
</span><span class="cx">     [[NSNotificationCenter defaultCenter] postNotificationName:WebUIApplicationDidEnterBackgroundNotification object:nil userInfo:@{@&quot;isSuspendedUnderLock&quot;: [NSNumber numberWithBool:isSuspendedUnderLock]}];
</span><span class="cx"> 
</span><ins>+    m_isSuspendedUnderLock = isSuspendedUnderLock;
</ins><span class="cx">     setLayerTreeStateIsFrozen(true);
</span><span class="cx">     markLayersVolatile();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebPage::applicationWillEnterForeground(bool isSuspendedUnderLock)
</span><span class="cx"> {
</span><ins>+    m_isSuspendedUnderLock = false;
</ins><span class="cx">     cancelMarkLayersVolatile();
</span><span class="cx">     setLayerTreeStateIsFrozen(false);
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>