<!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>[212619] 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/212619">212619</a></dd>
<dt>Author</dt> <dd>cdumez@apple.com</dd>
<dt>Date</dt> <dd>2017-02-19 18:38:43 -0800 (Sun, 19 Feb 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>[WK2] Support termination of unresponsive WebContent processes that are in the background
https://bugs.webkit.org/show_bug.cgi?id=168479
&lt;rdar://problem/30558745&gt;

Reviewed by Antti Koivisto.

Support termination of unresponsive WebContent processes that are in the background.
This protects us against cases where a background tab is unresponsive and has high CPU
usage, thus draining the battery without the user knowing about it (e.g.
&lt;rdar://problem/29808005&gt;).

The feature works as follows:
- If a WebProcessProxy has pages but none of them are visible, then it will check
  regularly if its associated WebContent process is still responsive.
- Every time we find that the WebContent process is responsive, we exponentially
  back off the timer to avoid waking up the process too often. The timer initially
  uses a 20 seconds interval and can back off up to 8 hours.
- If the WebContent process is unresponsive, then we terminate it. No notification
  is shown to the user and the termination is not immediately observable since the
  tab is not visible and its title remains. The tab is not immediately reloaded
  so as to avoid getting back into a bad state in the background (and have a
  yo-yo effect).
- If the user switches to a tab that was previously killed for being unresponsive
  while in the background, we will then reload the tab in a fresh WebContent
  process. The crash banner will only be shown if the tab has ever been visible.
  If it wasn't ever visible (e.g. session restore case), then it will look as if
  the tab loads for the first time when the user switches to it.

The functionality is disabled by default and can be enabled by the client via the new
WKContextSetUnresponsiveBackgroundProcessesTerminationEnabled() private API.

* CMakeLists.txt:
* UIProcess/API/APIProcessPoolConfiguration.cpp:
(API::ProcessPoolConfiguration::copy):
* UIProcess/API/APIProcessPoolConfiguration.h:
* UIProcess/API/C/WKContext.cpp:
(WKContextSetUnresponsiveBackgroundProcessesTerminationEnabled):
* UIProcess/API/C/WKContextPrivate.h:
* UIProcess/UnresponsiveWebProcessTerminator.cpp: Added.
(WebKit::UnresponsiveWebProcessTerminator::UnresponsiveWebProcessTerminator):
(WebKit::UnresponsiveWebProcessTerminator::updateState):
(WebKit::pagesCopy):
(WebKit::UnresponsiveWebProcessTerminator::timerFired):
* UIProcess/UnresponsiveWebProcessTerminator.h: Added.
(WebKit::UnresponsiveWebProcessTerminator::shouldBeActive):
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::reattachToWebProcess):
(WebKit::WebPageProxy::reloadAfterBeingKilledInBackground):
(WebKit::WebPageProxy::dispatchActivityStateChange):
(WebKit::WebPageProxy::terminateProcess):
(WebKit::WebPageProxy::resetStateAfterProcessExited):
* UIProcess/WebPageProxy.h:
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::WebProcessProxy):
(WebKit::m_backgroundResponsivenessTimer):
(WebKit::WebProcessProxy::createWebPage):
(WebKit::WebProcessProxy::addExistingWebPage):
(WebKit::WebProcessProxy::removeWebPage):
(WebKit::WebProcessProxy::updateBackgroundResponsivenessTimer):
* UIProcess/WebProcessProxy.h:
(WebKit::WebProcessProxy::visiblePageCount):
* WebKit2.xcodeproj/project.pbxproj:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2CMakeListstxt">trunk/Source/WebKit2/CMakeLists.txt</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIAPIProcessPoolConfigurationcpp">trunk/Source/WebKit2/UIProcess/API/APIProcessPoolConfiguration.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIAPIProcessPoolConfigurationh">trunk/Source/WebKit2/UIProcess/API/APIProcessPoolConfiguration.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICWKContextcpp">trunk/Source/WebKit2/UIProcess/API/C/WKContext.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICWKContextPrivateh">trunk/Source/WebKit2/UIProcess/API/C/WKContextPrivate.h</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>
<li><a href="#trunkSourceWebKit2UIProcessWebProcessProxyh">trunk/Source/WebKit2/UIProcess/WebProcessProxy.h</a></li>
<li><a href="#trunkSourceWebKit2WebKit2xcodeprojprojectpbxproj">trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2UIProcessUnresponsiveWebProcessTerminatorcpp">trunk/Source/WebKit2/UIProcess/UnresponsiveWebProcessTerminator.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessUnresponsiveWebProcessTerminatorh">trunk/Source/WebKit2/UIProcess/UnresponsiveWebProcessTerminator.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2CMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/CMakeLists.txt (212618 => 212619)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/CMakeLists.txt        2017-02-20 01:46:04 UTC (rev 212618)
+++ trunk/Source/WebKit2/CMakeLists.txt        2017-02-20 02:38:43 UTC (rev 212619)
</span><span class="lines">@@ -285,6 +285,7 @@
</span><span class="cx">     UIProcess/ResponsivenessTimer.cpp
</span><span class="cx">     UIProcess/StatisticsRequest.cpp
</span><span class="cx">     UIProcess/TextCheckerCompletion.cpp
</span><ins>+    UIProcess/UnresponsiveWebProcessTerminator.cpp
</ins><span class="cx">     UIProcess/UserMediaPermissionCheckProxy.cpp
</span><span class="cx">     UIProcess/UserMediaPermissionRequestManagerProxy.cpp
</span><span class="cx">     UIProcess/UserMediaPermissionRequestProxy.cpp
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (212618 => 212619)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2017-02-20 01:46:04 UTC (rev 212618)
+++ trunk/Source/WebKit2/ChangeLog        2017-02-20 02:38:43 UTC (rev 212619)
</span><span class="lines">@@ -1,3 +1,68 @@
</span><ins>+2017-02-19  Chris Dumez  &lt;cdumez@apple.com&gt;
+
+        [WK2] Support termination of unresponsive WebContent processes that are in the background
+        https://bugs.webkit.org/show_bug.cgi?id=168479
+        &lt;rdar://problem/30558745&gt;
+
+        Reviewed by Antti Koivisto.
+
+        Support termination of unresponsive WebContent processes that are in the background.
+        This protects us against cases where a background tab is unresponsive and has high CPU
+        usage, thus draining the battery without the user knowing about it (e.g.
+        &lt;rdar://problem/29808005&gt;).
+
+        The feature works as follows:
+        - If a WebProcessProxy has pages but none of them are visible, then it will check
+          regularly if its associated WebContent process is still responsive.
+        - Every time we find that the WebContent process is responsive, we exponentially
+          back off the timer to avoid waking up the process too often. The timer initially
+          uses a 20 seconds interval and can back off up to 8 hours.
+        - If the WebContent process is unresponsive, then we terminate it. No notification
+          is shown to the user and the termination is not immediately observable since the
+          tab is not visible and its title remains. The tab is not immediately reloaded
+          so as to avoid getting back into a bad state in the background (and have a
+          yo-yo effect).
+        - If the user switches to a tab that was previously killed for being unresponsive
+          while in the background, we will then reload the tab in a fresh WebContent
+          process. The crash banner will only be shown if the tab has ever been visible.
+          If it wasn't ever visible (e.g. session restore case), then it will look as if
+          the tab loads for the first time when the user switches to it.
+
+        The functionality is disabled by default and can be enabled by the client via the new
+        WKContextSetUnresponsiveBackgroundProcessesTerminationEnabled() private API.
+
+        * CMakeLists.txt:
+        * UIProcess/API/APIProcessPoolConfiguration.cpp:
+        (API::ProcessPoolConfiguration::copy):
+        * UIProcess/API/APIProcessPoolConfiguration.h:
+        * UIProcess/API/C/WKContext.cpp:
+        (WKContextSetUnresponsiveBackgroundProcessesTerminationEnabled):
+        * UIProcess/API/C/WKContextPrivate.h:
+        * UIProcess/UnresponsiveWebProcessTerminator.cpp: Added.
+        (WebKit::UnresponsiveWebProcessTerminator::UnresponsiveWebProcessTerminator):
+        (WebKit::UnresponsiveWebProcessTerminator::updateState):
+        (WebKit::pagesCopy):
+        (WebKit::UnresponsiveWebProcessTerminator::timerFired):
+        * UIProcess/UnresponsiveWebProcessTerminator.h: Added.
+        (WebKit::UnresponsiveWebProcessTerminator::shouldBeActive):
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::reattachToWebProcess):
+        (WebKit::WebPageProxy::reloadAfterBeingKilledInBackground):
+        (WebKit::WebPageProxy::dispatchActivityStateChange):
+        (WebKit::WebPageProxy::terminateProcess):
+        (WebKit::WebPageProxy::resetStateAfterProcessExited):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebProcessProxy.cpp:
+        (WebKit::WebProcessProxy::WebProcessProxy):
+        (WebKit::m_backgroundResponsivenessTimer):
+        (WebKit::WebProcessProxy::createWebPage):
+        (WebKit::WebProcessProxy::addExistingWebPage):
+        (WebKit::WebProcessProxy::removeWebPage):
+        (WebKit::WebProcessProxy::updateBackgroundResponsivenessTimer):
+        * UIProcess/WebProcessProxy.h:
+        (WebKit::WebProcessProxy::visiblePageCount):
+        * WebKit2.xcodeproj/project.pbxproj:
+
</ins><span class="cx"> 2017-02-18  Michael Catanzaro  &lt;mcatanzaro@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Remove COORDINATED_GRAPHICS_MULTIPROCESS
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIAPIProcessPoolConfigurationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/APIProcessPoolConfiguration.cpp (212618 => 212619)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/APIProcessPoolConfiguration.cpp        2017-02-20 01:46:04 UTC (rev 212618)
+++ trunk/Source/WebKit2/UIProcess/API/APIProcessPoolConfiguration.cpp        2017-02-20 02:38:43 UTC (rev 212619)
</span><span class="lines">@@ -96,6 +96,7 @@
</span><span class="cx">     copy-&gt;m_maximumProcessCount = this-&gt;m_maximumProcessCount;
</span><span class="cx">     copy-&gt;m_cacheModel = this-&gt;m_cacheModel;
</span><span class="cx">     copy-&gt;m_diskCacheSpeculativeValidationEnabled = this-&gt;m_diskCacheSpeculativeValidationEnabled;
</span><ins>+    copy-&gt;m_unresponsiveBackgroundProcessesTerminationEnabled = this-&gt;m_unresponsiveBackgroundProcessesTerminationEnabled;
</ins><span class="cx">     copy-&gt;m_diskCacheSizeOverride = this-&gt;m_diskCacheSizeOverride;
</span><span class="cx">     copy-&gt;m_applicationCacheDirectory = this-&gt;m_applicationCacheDirectory;
</span><span class="cx">     copy-&gt;m_applicationCacheFlatFileSubdirectoryName = this-&gt;m_applicationCacheFlatFileSubdirectoryName;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIAPIProcessPoolConfigurationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/APIProcessPoolConfiguration.h (212618 => 212619)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/APIProcessPoolConfiguration.h        2017-02-20 01:46:04 UTC (rev 212618)
+++ trunk/Source/WebKit2/UIProcess/API/APIProcessPoolConfiguration.h        2017-02-20 02:38:43 UTC (rev 212619)
</span><span class="lines">@@ -55,6 +55,9 @@
</span><span class="cx">     bool diskCacheSpeculativeValidationEnabled() const { return m_diskCacheSpeculativeValidationEnabled; }
</span><span class="cx">     void setDiskCacheSpeculativeValidationEnabled(bool enabled) { m_diskCacheSpeculativeValidationEnabled = enabled; }
</span><span class="cx"> 
</span><ins>+    bool unresponsiveBackgroundProcessesTerminationEnabled() const { return m_unresponsiveBackgroundProcessesTerminationEnabled; }
+    void setUnresponsiveBackgroundProcessesTerminationEnabled(bool enabled) { m_unresponsiveBackgroundProcessesTerminationEnabled = enabled; }
+
</ins><span class="cx">     WebKit::CacheModel cacheModel() const { return m_cacheModel; }
</span><span class="cx">     void setCacheModel(WebKit::CacheModel cacheModel) { m_cacheModel = cacheModel; }
</span><span class="cx"> 
</span><span class="lines">@@ -121,6 +124,7 @@
</span><span class="cx"> 
</span><span class="cx">     unsigned m_maximumProcessCount { 0 };
</span><span class="cx">     bool m_diskCacheSpeculativeValidationEnabled { false };
</span><ins>+    bool m_unresponsiveBackgroundProcessesTerminationEnabled { false };
</ins><span class="cx">     WebKit::CacheModel m_cacheModel { WebKit::CacheModelPrimaryWebBrowser };
</span><span class="cx">     int64_t m_diskCacheSizeOverride { -1 };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICWKContextcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/C/WKContext.cpp (212618 => 212619)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/C/WKContext.cpp        2017-02-20 01:46:04 UTC (rev 212618)
+++ trunk/Source/WebKit2/UIProcess/API/C/WKContext.cpp        2017-02-20 02:38:43 UTC (rev 212619)
</span><span class="lines">@@ -397,6 +397,11 @@
</span><span class="cx">     toImpl(contextRef)-&gt;configuration().setDiskCacheSpeculativeValidationEnabled(value);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WKContextSetUnresponsiveBackgroundProcessesTerminationEnabled(WKContextRef contextRef, bool value)
+{
+    toImpl(contextRef)-&gt;configuration().setUnresponsiveBackgroundProcessesTerminationEnabled(value);
+}
+
</ins><span class="cx"> WKCookieManagerRef WKContextGetCookieManager(WKContextRef contextRef)
</span><span class="cx"> {
</span><span class="cx">     return toAPI(toImpl(contextRef)-&gt;supplement&lt;WebCookieManagerProxy&gt;());
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICWKContextPrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/C/WKContextPrivate.h (212618 => 212619)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/C/WKContextPrivate.h        2017-02-20 01:46:04 UTC (rev 212618)
+++ trunk/Source/WebKit2/UIProcess/API/C/WKContextPrivate.h        2017-02-20 02:38:43 UTC (rev 212619)
</span><span class="lines">@@ -62,6 +62,8 @@
</span><span class="cx"> 
</span><span class="cx"> WK_EXPORT void WKContextSetDiskCacheSpeculativeValidationEnabled(WKContextRef context, bool value);
</span><span class="cx"> 
</span><ins>+WK_EXPORT void WKContextSetUnresponsiveBackgroundProcessesTerminationEnabled(WKContextRef context, bool value);
+
</ins><span class="cx"> WK_EXPORT void WKContextSetIconDatabasePath(WKContextRef context, WKStringRef iconDatabasePath);
</span><span class="cx"> 
</span><span class="cx"> WK_EXPORT void WKContextAllowSpecificHTTPSCertificateForHost(WKContextRef context, WKCertificateInfoRef certificate, WKStringRef host);
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessUnresponsiveWebProcessTerminatorcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit2/UIProcess/UnresponsiveWebProcessTerminator.cpp (0 => 212619)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/UnresponsiveWebProcessTerminator.cpp                                (rev 0)
+++ trunk/Source/WebKit2/UIProcess/UnresponsiveWebProcessTerminator.cpp        2017-02-20 02:38:43 UTC (rev 212619)
</span><span class="lines">@@ -0,0 +1,82 @@
</span><ins>+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;UnresponsiveWebProcessTerminator.h&quot;
+
+#include &quot;Logging.h&quot;
+
+namespace WebKit {
+
+static const std::chrono::seconds initialInterval { 20s };
+static const std::chrono::seconds maximumInterval { 8h };
+
+UnresponsiveWebProcessTerminator::UnresponsiveWebProcessTerminator(WebProcessProxy&amp; webProcessProxy)
+    : m_webProcessProxy(webProcessProxy)
+    , m_interval(initialInterval)
+    , m_timer(RunLoop::main(), this, &amp;UnresponsiveWebProcessTerminator::timerFired)
+{
+}
+
+void UnresponsiveWebProcessTerminator::updateState()
+{
+    if (!shouldBeActive()) {
+        if (m_timer.isActive()) {
+            m_interval = initialInterval;
+            m_timer.stop();
+        }
+        return;
+    }
+
+    if (!m_timer.isActive())
+        m_timer.startOneShot(m_interval);
+}
+
+static Vector&lt;RefPtr&lt;WebPageProxy&gt;&gt; pagesCopy(WTF::IteratorRange&lt;WebProcessProxy::WebPageProxyMap::const_iterator::Values&gt; pages)
+{
+    Vector&lt;RefPtr&lt;WebPageProxy&gt;&gt; vector;
+    for (auto&amp; page : pages)
+        vector.append(page);
+    return vector;
+}
+
+void UnresponsiveWebProcessTerminator::timerFired()
+{
+    ASSERT(shouldBeActive());
+    m_webProcessProxy.isResponsive([this](bool processIsResponsive) {
+        if (processIsResponsive) {
+            // Exponential backoff to avoid waking up the process too often.
+            m_interval = std::min(m_interval * 2, maximumInterval);
+            m_timer.startOneShot(m_interval);
+            return;
+        }
+
+        RELEASE_LOG_ERROR(PerformanceLogging, &quot;Killing a background WebProcess because it is not responsive&quot;);
+        for (auto&amp; page : pagesCopy(m_webProcessProxy.pages()))
+            page-&gt;terminateProcess(WebPageProxy::TerminationReason::UnresponsiveWhileInBackground);
+    });
+}
+
+} // namespace WebKit
</ins></span></pre></div>
<a id="trunkSourceWebKit2UIProcessUnresponsiveWebProcessTerminatorh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit2/UIProcess/UnresponsiveWebProcessTerminator.h (0 => 212619)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/UnresponsiveWebProcessTerminator.h                                (rev 0)
+++ trunk/Source/WebKit2/UIProcess/UnresponsiveWebProcessTerminator.h        2017-02-20 02:38:43 UTC (rev 212619)
</span><span class="lines">@@ -0,0 +1,47 @@
</span><ins>+/*
+ * Copyright (C) 2017 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 &quot;WebProcessProxy.h&quot;
+#include &lt;wtf/RunLoop.h&gt;
+
+namespace WebKit {
+
+class UnresponsiveWebProcessTerminator {
+public:
+    explicit UnresponsiveWebProcessTerminator(WebProcessProxy&amp;);
+    void updateState();
+
+private:
+    void timerFired();
+    bool shouldBeActive() const { return !m_webProcessProxy.visiblePageCount() &amp;&amp; m_webProcessProxy.pageCount(); }
+
+    WebProcessProxy&amp; m_webProcessProxy;
+    std::chrono::seconds m_interval;
+    RunLoop::Timer&lt;UnresponsiveWebProcessTerminator&gt; m_timer;
+};
+
+}
</ins></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp (212618 => 212619)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2017-02-20 01:46:04 UTC (rev 212618)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2017-02-20 02:38:43 UTC (rev 212619)
</span><span class="lines">@@ -712,6 +712,7 @@
</span><span class="cx">     ASSERT(m_process-&gt;state() == WebProcessProxy::State::Terminated);
</span><span class="cx"> 
</span><span class="cx">     m_isValid = true;
</span><ins>+    m_wasKilledForBeingUnresponsiveWhileInBackground = false;
</ins><span class="cx">     m_process-&gt;removeWebPage(m_pageID);
</span><span class="cx">     m_process-&gt;removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
</span><span class="cx"> 
</span><span class="lines">@@ -1513,6 +1514,19 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebPageProxy::reloadAfterBeingKilledInBackground()
+{
+    ASSERT(!isValid());
+
+    RELEASE_LOG_IF_ALLOWED(&quot;%p - Reloading tab that was killed in the background&quot;, this);
+
+    // Only report as a crash if the page was ever visible, otherwise silently reload.
+    if (m_hasEverBeenVisible)
+        processDidCrash();
+    else
+        reattachToWebProcessForReload();
+}
+
</ins><span class="cx"> void WebPageProxy::dispatchActivityStateChange()
</span><span class="cx"> {
</span><span class="cx"> #if PLATFORM(COCOA)
</span><span class="lines">@@ -1519,8 +1533,11 @@
</span><span class="cx">     m_activityStateChangeDispatcher-&gt;invalidate();
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    if (!isValid())
</del><ins>+    if (!isValid()) {
+        if (m_potentiallyChangedActivityStateFlags &amp; ActivityState::IsVisible &amp;&amp; m_wasKilledForBeingUnresponsiveWhileInBackground)
+            reloadAfterBeingKilledInBackground();
</ins><span class="cx">         return;
</span><ins>+    }
</ins><span class="cx"> 
</span><span class="cx">     // If the visibility state may have changed, then so may the visually idle &amp; occluded agnostic state.
</span><span class="cx">     if (m_potentiallyChangedActivityStateFlags &amp; ActivityState::IsVisible)
</span><span class="lines">@@ -1552,12 +1569,6 @@
</span><span class="cx">     // This must happen after the SetActivityState message is sent, to ensure the page visibility event can fire.
</span><span class="cx">     updateThrottleState();
</span><span class="cx"> 
</span><del>-    // If we've started the responsiveness timer as part of telling the web process to update the backing store
-    // state, it might not send back a reply (since it won't paint anything if the web page is hidden) so we
-    // stop the unresponsiveness timer here.
-    if ((changed &amp; ActivityState::IsVisible) &amp;&amp; !isViewVisible())
-        m_process-&gt;responsivenessTimer().stop();
-
</del><span class="cx"> #if ENABLE(POINTER_LOCK)
</span><span class="cx">     if (((changed &amp; ActivityState::IsVisible) &amp;&amp; !isViewVisible()) || ((changed &amp; ActivityState::WindowIsActive) &amp;&amp; !m_pageClient.isViewWindowActive())
</span><span class="cx">         || ((changed &amp; ActivityState::IsFocused) &amp;&amp; !(m_activityState &amp; ActivityState::IsFocused)))
</span><span class="lines">@@ -1564,6 +1575,20 @@
</span><span class="cx">         requestPointerUnlock();
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    if (changed &amp; ActivityState::IsVisible) {
+        if (isViewVisible()) {
+            m_hasEverBeenVisible = true;
+            m_visiblePageToken = m_process-&gt;visiblePageToken();
+        } else {
+            m_visiblePageToken = nullptr;
+
+            // If we've started the responsiveness timer as part of telling the web process to update the backing store
+            // state, it might not send back a reply (since it won't paint anything if the web page is hidden) so we
+            // stop the unresponsiveness timer here.
+            m_process-&gt;responsivenessTimer().stop();
+        }
+    }
+
</ins><span class="cx">     if (changed &amp; ActivityState::IsInWindow) {
</span><span class="cx">         if (isInWindow())
</span><span class="cx">             viewDidEnterWindow();
</span><span class="lines">@@ -2369,7 +2394,7 @@
</span><span class="cx">     m_process-&gt;send(Messages::WebPage::SetCustomTextEncodingName(encodingName), m_pageID);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebPageProxy::terminateProcess()
</del><ins>+void WebPageProxy::terminateProcess(TerminationReason terminationReason)
</ins><span class="cx"> {
</span><span class="cx">     // NOTE: This uses a check of m_isValid rather than calling isValid() since
</span><span class="cx">     // we want this to run even for pages being closed or that already closed.
</span><span class="lines">@@ -2378,6 +2403,7 @@
</span><span class="cx"> 
</span><span class="cx">     m_process-&gt;requestTermination();
</span><span class="cx">     resetStateAfterProcessExited();
</span><ins>+    m_wasKilledForBeingUnresponsiveWhileInBackground = terminationReason == TerminationReason::UnresponsiveWhileInBackground;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> SessionState WebPageProxy::sessionState(const std::function&lt;bool (WebBackForwardListItem&amp;)&gt;&amp; filter) const
</span><span class="lines">@@ -5448,6 +5474,7 @@
</span><span class="cx">     m_activityToken = nullptr;
</span><span class="cx"> #endif
</span><span class="cx">     m_pageIsUserObservableCount = nullptr;
</span><ins>+    m_visiblePageToken = nullptr;
</ins><span class="cx"> 
</span><span class="cx">     m_isValid = false;
</span><span class="cx">     m_isPageSuspended = false;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.h (212618 => 212619)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.h        2017-02-20 01:46:04 UTC (rev 212618)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.h        2017-02-20 02:38:43 UTC (rev 212619)
</span><span class="lines">@@ -233,6 +233,10 @@
</span><span class="cx"> typedef GenericCallback&lt;const String&amp;&gt; StringCallback;
</span><span class="cx"> typedef GenericCallback&lt;API::SerializedScriptValue*, bool, const WebCore::ExceptionDetails&amp;&gt; ScriptValueCallback;
</span><span class="cx"> 
</span><ins>+enum VisibleWebPageCounterType { };
+using VisibleWebPageCounter = RefCounter&lt;VisibleWebPageCounterType&gt;;
+using VisibleWebPageToken = VisibleWebPageCounter::Token;
+
</ins><span class="cx"> #if PLATFORM(GTK)
</span><span class="cx"> typedef GenericCallback&lt;API::Error*&gt; PrintFinishedCallback;
</span><span class="cx"> #endif
</span><span class="lines">@@ -671,7 +675,8 @@
</span><span class="cx"> 
</span><span class="cx">     double estimatedProgress() const;
</span><span class="cx"> 
</span><del>-    void terminateProcess();
</del><ins>+    enum class TerminationReason { UnresponsiveWhileInBackground, Other };
+    void terminateProcess(TerminationReason = TerminationReason::Other);
</ins><span class="cx"> 
</span><span class="cx">     SessionState sessionState(const std::function&lt;bool (WebBackForwardListItem&amp;)&gt;&amp; = nullptr) const;
</span><span class="cx">     RefPtr&lt;API::Navigation&gt; restoreFromSessionState(SessionState, bool navigate);
</span><span class="lines">@@ -1570,6 +1575,7 @@
</span><span class="cx">     void dispatchActivityStateChange();
</span><span class="cx">     void viewDidLeaveWindow();
</span><span class="cx">     void viewDidEnterWindow();
</span><ins>+    void reloadAfterBeingKilledInBackground();
</ins><span class="cx"> 
</span><span class="cx"> #if PLATFORM(MAC)
</span><span class="cx">     void didPerformImmediateActionHitTest(const WebHitTestResultData&amp;, bool contentPreventsDefault, const UserData&amp;);
</span><span class="lines">@@ -1925,6 +1931,7 @@
</span><span class="cx">     UserObservablePageCounter::Token m_pageIsUserObservableCount;
</span><span class="cx">     ProcessSuppressionDisabledToken m_preventProcessSuppressionCount;
</span><span class="cx">     HiddenPageThrottlingAutoIncreasesCounter::Token m_hiddenPageDOMTimerThrottlingAutoIncreasesCount;
</span><ins>+    VisibleWebPageToken m_visiblePageToken;
</ins><span class="cx">         
</span><span class="cx">     WebCore::ScrollPinningBehavior m_scrollPinningBehavior;
</span><span class="cx">     std::optional&lt;WebCore::ScrollbarOverlayStyle&gt; m_scrollbarOverlayStyle;
</span><span class="lines">@@ -1943,6 +1950,7 @@
</span><span class="cx">     bool m_hasHadSelectionChangesFromUserInteraction { false };
</span><span class="cx">     bool m_needsHiddenContentEditableQuirk { false };
</span><span class="cx">     bool m_needsPlainTextQuirk { false };
</span><ins>+    bool m_hasEverBeenVisible { false };
</ins><span class="cx"> 
</span><span class="cx"> #if ENABLE(MEDIA_SESSION)
</span><span class="cx">     bool m_hasMediaSessionWithActiveMediaElements { false };
</span><span class="lines">@@ -1968,6 +1976,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     bool m_isUsingHighPerformanceWebGL { false };
</span><ins>+    bool m_wasKilledForBeingUnresponsiveWhileInBackground { false };
</ins><span class="cx">         
</span><span class="cx">     WeakPtrFactory&lt;WebPageProxy&gt; m_weakPtrFactory;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebProcessProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebProcessProxy.cpp (212618 => 212619)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebProcessProxy.cpp        2017-02-20 01:46:04 UTC (rev 212618)
+++ trunk/Source/WebKit2/UIProcess/WebProcessProxy.cpp        2017-02-20 02:38:43 UTC (rev 212619)
</span><span class="lines">@@ -36,6 +36,7 @@
</span><span class="cx"> #include &quot;PluginProcessManager.h&quot;
</span><span class="cx"> #include &quot;TextChecker.h&quot;
</span><span class="cx"> #include &quot;TextCheckerState.h&quot;
</span><ins>+#include &quot;UnresponsiveWebProcessTerminator.h&quot;
</ins><span class="cx"> #include &quot;UserData.h&quot;
</span><span class="cx"> #include &quot;WebBackForwardListItem.h&quot;
</span><span class="cx"> #include &quot;WebIconDatabase.h&quot;
</span><span class="lines">@@ -101,6 +102,8 @@
</span><span class="cx">     , m_numberOfTimesSuddenTerminationWasDisabled(0)
</span><span class="cx">     , m_throttler(*this)
</span><span class="cx">     , m_isResponsive(NoOrMaybe::Maybe)
</span><ins>+    , m_visiblePageCounter([this](RefCounterEvent) { updateBackgroundResponsivenessTimer(); })
+    , m_backgroundResponsivenessTimer(processPool.configuration().unresponsiveBackgroundProcessesTerminationEnabled() ? std::make_unique&lt;UnresponsiveWebProcessTerminator&gt;(*this) : nullptr)
</ins><span class="cx"> {
</span><span class="cx">     WebPasteboardProxy::singleton().addWebProcessProxy(*this);
</span><span class="cx"> 
</span><span class="lines">@@ -255,6 +258,8 @@
</span><span class="cx">     m_pageMap.set(pageID, webPage.ptr());
</span><span class="cx">     globalPageMap().set(pageID, webPage.ptr());
</span><span class="cx"> 
</span><ins>+    updateBackgroundResponsivenessTimer();
+
</ins><span class="cx">     return webPage;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -265,6 +270,8 @@
</span><span class="cx"> 
</span><span class="cx">     m_pageMap.set(pageID, webPage);
</span><span class="cx">     globalPageMap().set(pageID, webPage);
</span><ins>+
+    updateBackgroundResponsivenessTimer();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebProcessProxy::removeWebPage(uint64_t pageID)
</span><span class="lines">@@ -271,6 +278,8 @@
</span><span class="cx"> {
</span><span class="cx">     m_pageMap.remove(pageID);
</span><span class="cx">     globalPageMap().remove(pageID);
</span><ins>+
+    updateBackgroundResponsivenessTimer();
</ins><span class="cx">     
</span><span class="cx">     Vector&lt;uint64_t&gt; itemIDsToRemove;
</span><span class="cx">     for (auto&amp; idAndItem : m_backForwardListItemMap) {
</span><span class="lines">@@ -708,6 +717,11 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+auto WebProcessProxy::visiblePageToken() const -&gt; VisibleWebPageToken
+{
+    return m_visiblePageCounter.count();
+}
+
</ins><span class="cx"> RefPtr&lt;API::UserInitiatedAction&gt; WebProcessProxy::userInitiatedActivity(uint64_t identifier)
</span><span class="cx"> {
</span><span class="cx">     if (!UserInitiatedActionMap::isValidKey(identifier) || !identifier)
</span><span class="lines">@@ -1073,6 +1087,12 @@
</span><span class="cx">         callback(isWebProcessResponsive);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebProcessProxy::updateBackgroundResponsivenessTimer()
+{
+    if (m_backgroundResponsivenessTimer)
+        m_backgroundResponsivenessTimer-&gt;updateState();
+}
+
</ins><span class="cx"> #if !PLATFORM(COCOA)
</span><span class="cx"> const HashSet&lt;String&gt;&amp; WebProcessProxy::platformPathsWithAssumedReadAccess()
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebProcessProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebProcessProxy.h (212618 => 212619)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebProcessProxy.h        2017-02-20 01:46:04 UTC (rev 212618)
+++ trunk/Source/WebKit2/UIProcess/WebProcessProxy.h        2017-02-20 02:38:43 UTC (rev 212619)
</span><span class="lines">@@ -55,6 +55,7 @@
</span><span class="cx"> namespace WebKit {
</span><span class="cx"> 
</span><span class="cx"> class NetworkProcessProxy;
</span><ins>+class UnresponsiveWebProcessTerminator;
</ins><span class="cx"> class WebBackForwardListItem;
</span><span class="cx"> class WebPageGroup;
</span><span class="cx"> class WebProcessPool;
</span><span class="lines">@@ -83,6 +84,7 @@
</span><span class="cx"> 
</span><span class="cx">     WTF::IteratorRange&lt;WebPageProxyMap::const_iterator::Values&gt; pages() const { return m_pageMap.values(); }
</span><span class="cx">     unsigned pageCount() const { return m_pageMap.size(); }
</span><ins>+    unsigned visiblePageCount() const { return m_visiblePageCounter.value(); }
</ins><span class="cx"> 
</span><span class="cx">     void addVisitedLinkStore(VisitedLinkStore&amp;);
</span><span class="cx">     void addWebUserContentControllerProxy(WebUserContentControllerProxy&amp;);
</span><span class="lines">@@ -100,6 +102,8 @@
</span><span class="cx">     void disconnectFramesFromPage(WebPageProxy*); // Including main frame.
</span><span class="cx">     size_t frameCountInPage(WebPageProxy*) const; // Including main frame.
</span><span class="cx"> 
</span><ins>+    VisibleWebPageToken visiblePageToken() const;
+
</ins><span class="cx">     void updateTextCheckerState();
</span><span class="cx"> 
</span><span class="cx">     void registerNewWebBackForwardListItem(WebBackForwardListItem*);
</span><span class="lines">@@ -189,6 +193,8 @@
</span><span class="cx"> 
</span><span class="cx">     static const HashSet&lt;String&gt;&amp; platformPathsWithAssumedReadAccess();
</span><span class="cx"> 
</span><ins>+    void updateBackgroundResponsivenessTimer();
+
</ins><span class="cx">     // IPC::Connection::Client
</span><span class="cx">     friend class WebConnectionToWebProcess;
</span><span class="cx">     void didReceiveMessage(IPC::Connection&amp;, IPC::Decoder&amp;) override;
</span><span class="lines">@@ -247,6 +253,9 @@
</span><span class="cx"> 
</span><span class="cx">     enum class NoOrMaybe { No, Maybe } m_isResponsive;
</span><span class="cx">     Vector&lt;std::function&lt;void(bool webProcessIsResponsive)&gt;&gt; m_isResponsiveCallbacks;
</span><ins>+
+    VisibleWebPageCounter m_visiblePageCounter;
+    std::unique_ptr&lt;UnresponsiveWebProcessTerminator&gt; m_backgroundResponsivenessTimer;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2WebKit2xcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj (212618 => 212619)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj        2017-02-20 01:46:04 UTC (rev 212618)
+++ trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj        2017-02-20 02:38:43 UTC (rev 212619)
</span><span class="lines">@@ -899,6 +899,8 @@
</span><span class="cx">                 41FAF5F81E3C1021001AE678 /* LibWebRTCResolver.h in Headers */ = {isa = PBXBuildFile; fileRef = 41FAF5F61E3C0B47001AE678 /* LibWebRTCResolver.h */; };
</span><span class="cx">                 41FAF5F91E3C1025001AE678 /* LibWebRTCResolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41FAF5F71E3C0B47001AE678 /* LibWebRTCResolver.cpp */; };
</span><span class="cx">                 4450AEC01DC3FAE5009943F2 /* SharedMemoryCocoa.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4450AEBF1DC3FAE5009943F2 /* SharedMemoryCocoa.cpp */; };
</span><ins>+                46A2B6081E5676A600C3DEDA /* UnresponsiveWebProcessTerminator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46A2B6061E5675A200C3DEDA /* UnresponsiveWebProcessTerminator.cpp */; };
+                46A2B6091E5676A600C3DEDA /* UnresponsiveWebProcessTerminator.h in Headers */ = {isa = PBXBuildFile; fileRef = 46A2B6071E5675A200C3DEDA /* UnresponsiveWebProcessTerminator.h */; };
</ins><span class="cx">                 4A3CC18A19B063E700D14AEF /* UserMediaPermissionRequestManagerProxy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A410F3919AF7B04002EBAB5 /* UserMediaPermissionRequestManagerProxy.cpp */; };
</span><span class="cx">                 4A3CC18B19B0640F00D14AEF /* UserMediaPermissionRequestManagerProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A410F3A19AF7B04002EBAB5 /* UserMediaPermissionRequestManagerProxy.h */; };
</span><span class="cx">                 4A3CC18C19B0641500D14AEF /* UserMediaPermissionRequestProxy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A410F3B19AF7B04002EBAB5 /* UserMediaPermissionRequestProxy.cpp */; };
</span><span class="lines">@@ -3050,6 +3052,8 @@
</span><span class="cx">                 41FAF5F61E3C0B47001AE678 /* LibWebRTCResolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LibWebRTCResolver.h; path = Network/webrtc/LibWebRTCResolver.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 41FAF5F71E3C0B47001AE678 /* LibWebRTCResolver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibWebRTCResolver.cpp; path = Network/webrtc/LibWebRTCResolver.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 4450AEBF1DC3FAE5009943F2 /* SharedMemoryCocoa.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SharedMemoryCocoa.cpp; path = cocoa/SharedMemoryCocoa.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                46A2B6061E5675A200C3DEDA /* UnresponsiveWebProcessTerminator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UnresponsiveWebProcessTerminator.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                46A2B6071E5675A200C3DEDA /* UnresponsiveWebProcessTerminator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnresponsiveWebProcessTerminator.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 4A410F3519AF7AC3002EBAB5 /* WKUserMediaPermissionRequest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WKUserMediaPermissionRequest.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 4A410F3619AF7AC3002EBAB5 /* WKUserMediaPermissionRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKUserMediaPermissionRequest.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 4A410F3919AF7B04002EBAB5 /* UserMediaPermissionRequestManagerProxy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UserMediaPermissionRequestManagerProxy.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -6457,6 +6461,8 @@
</span><span class="cx">                                 1AA417C912C00CCA002BE67B /* TextChecker.h */,
</span><span class="cx">                                 1BB417C912C00CCA002BE67B /* TextCheckerCompletion.cpp */,
</span><span class="cx">                                 1CC417C912C00CCA002BE67B /* TextCheckerCompletion.h */,
</span><ins>+                                46A2B6061E5675A200C3DEDA /* UnresponsiveWebProcessTerminator.cpp */,
+                                46A2B6071E5675A200C3DEDA /* UnresponsiveWebProcessTerminator.h */,
</ins><span class="cx">                                 07297F9C1C17BBEA003F0735 /* UserMediaPermissionCheckProxy.cpp */,
</span><span class="cx">                                 07297F9D1C17BBEA003F0735 /* UserMediaPermissionCheckProxy.h */,
</span><span class="cx">                                 4A410F3919AF7B04002EBAB5 /* UserMediaPermissionRequestManagerProxy.cpp */,
</span><span class="lines">@@ -7964,6 +7970,7 @@
</span><span class="cx">                                 4F601432155C5AA2001FBDE0 /* BlockingResponseMap.h in Headers */,
</span><span class="cx">                                 1A5705111BE410E600874AF1 /* BlockSPI.h in Headers */,
</span><span class="cx">                                 BC3065FA1259344E00E71278 /* CacheModel.h in Headers */,
</span><ins>+                                46A2B6091E5676A600C3DEDA /* UnresponsiveWebProcessTerminator.h in Headers */,
</ins><span class="cx">                                 1AA2E51D12E4C05E00BC4966 /* CGUtilities.h in Headers */,
</span><span class="cx">                                 1A2D956F12848564001EB962 /* ChildProcess.h in Headers */,
</span><span class="cx">                                 51FAEC3A1B0657630009C4E7 /* ChildProcessMessages.h in Headers */,
</span><span class="lines">@@ -9645,6 +9652,7 @@
</span><span class="cx">                                 532159531DBAE7180054AA3C /* NetworkSession.cpp in Sources */,
</span><span class="cx">                                 5C20CB9D1BB0DCFA00895BB1 /* NetworkSessionCocoa.mm in Sources */,
</span><span class="cx">                                 31A2EC551489982E00810D71 /* NotificationPermissionRequest.cpp in Sources */,
</span><ins>+                                46A2B6081E5676A600C3DEDA /* UnresponsiveWebProcessTerminator.cpp in Sources */,
</ins><span class="cx">                                 3131261E148FF82C00BA2A39 /* NotificationPermissionRequestManager.cpp in Sources */,
</span><span class="cx">                                 31A2EC501489980500810D71 /* NotificationPermissionRequestManagerProxy.cpp in Sources */,
</span><span class="cx">                                 1A2D848C127F6A49001EB962 /* NPIdentifierData.cpp in Sources */,
</span></span></pre>
</div>
</div>

</body>
</html>