<!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>[166441] 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/166441">166441</a></dd>
<dt>Author</dt> <dd>slewis@apple.com</dd>
<dt>Date</dt> <dd>2014-03-28 18:15:44 -0700 (Fri, 28 Mar 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Have the plugin process track visibility of it’s plugin and sleep when none
are visible.
Part of &lt;rdar://problem/16061257&gt; PluginProcess should AppNap when no plugins on active tab.
https://bugs.webkit.org/show_bug.cgi?id=130694

Reviewed by Anders Carlsson.

Currently AppSleep is enabled on the PluginProcess based on web page visibility.
Add visibility tracking to plugins and move the decision to AppSleep into the the
PluginProcess

* PluginProcess/PluginProcess.cpp:
(WebKit::PluginProcess::PluginProcess): Add a new activity for visible plugins
(WebKit::PluginProcess::pluginsForWebProcessDidBecomeVisible): take an activity
     assertion if any web processes have a visible plugin.
(WebKit::PluginProcess::pluginsForWebProcessDidBecomeHidden):
* PluginProcess/PluginProcess.h:
* PluginProcess/WebProcessConnection.cpp:
(WebKit::WebProcessConnection::removePluginControllerProxy): remove plugin from
    visible plugins when destroying it
(WebKit::WebProcessConnection::pluginDidBecomeVisible):
(WebKit::WebProcessConnection::pluginDidBecomeHidden): track which plugins are
    visible for each web process
* PluginProcess/WebProcessConnection.h:
* PluginProcess/mac/PluginControllerProxyMac.mm:
(WebKit::PluginControllerProxy::windowVisibilityChanged): notify WebProcessConnection
    when visibility changed.
* UIProcess/WebContext.h:
* UIProcess/mac/WebContextMac.mm:  instead of tracking plugin app sleep state on the web pref.
    and visibility state, just use the web pref.
(WebKit::WebContext::updateProcessSuppressionState):
(WebKit::WebContext::processSuppressionPreferenceIsEnabledForAllContexts):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2PluginProcessPluginProcesscpp">trunk/Source/WebKit2/PluginProcess/PluginProcess.cpp</a></li>
<li><a href="#trunkSourceWebKit2PluginProcessPluginProcessh">trunk/Source/WebKit2/PluginProcess/PluginProcess.h</a></li>
<li><a href="#trunkSourceWebKit2PluginProcessWebProcessConnectioncpp">trunk/Source/WebKit2/PluginProcess/WebProcessConnection.cpp</a></li>
<li><a href="#trunkSourceWebKit2PluginProcessWebProcessConnectionh">trunk/Source/WebKit2/PluginProcess/WebProcessConnection.h</a></li>
<li><a href="#trunkSourceWebKit2PluginProcessmacPluginControllerProxyMacmm">trunk/Source/WebKit2/PluginProcess/mac/PluginControllerProxyMac.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebContexth">trunk/Source/WebKit2/UIProcess/WebContext.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessmacWebContextMacmm">trunk/Source/WebKit2/UIProcess/mac/WebContextMac.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (166440 => 166441)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2014-03-29 00:37:10 UTC (rev 166440)
+++ trunk/Source/WebKit2/ChangeLog        2014-03-29 01:15:44 UTC (rev 166441)
</span><span class="lines">@@ -1,3 +1,38 @@
</span><ins>+2014-03-28  Stephanie Lewis  &lt;slewis@apple.com&gt;
+
+        Have the plugin process track visibility of it’s plugin and sleep when none
+        are visible.
+        Part of &lt;rdar://problem/16061257&gt; PluginProcess should AppNap when no plugins on active tab.
+        https://bugs.webkit.org/show_bug.cgi?id=130694
+
+        Reviewed by Anders Carlsson.
+
+        Currently AppSleep is enabled on the PluginProcess based on web page visibility.
+        Add visibility tracking to plugins and move the decision to AppSleep into the the
+        PluginProcess
+
+        * PluginProcess/PluginProcess.cpp:
+        (WebKit::PluginProcess::PluginProcess): Add a new activity for visible plugins
+        (WebKit::PluginProcess::pluginsForWebProcessDidBecomeVisible): take an activity
+             assertion if any web processes have a visible plugin.
+        (WebKit::PluginProcess::pluginsForWebProcessDidBecomeHidden): 
+        * PluginProcess/PluginProcess.h:
+        * PluginProcess/WebProcessConnection.cpp: 
+        (WebKit::WebProcessConnection::removePluginControllerProxy): remove plugin from 
+            visible plugins when destroying it
+        (WebKit::WebProcessConnection::pluginDidBecomeVisible):
+        (WebKit::WebProcessConnection::pluginDidBecomeHidden): track which plugins are
+            visible for each web process
+        * PluginProcess/WebProcessConnection.h:
+        * PluginProcess/mac/PluginControllerProxyMac.mm:
+        (WebKit::PluginControllerProxy::windowVisibilityChanged): notify WebProcessConnection
+            when visibility changed.
+        * UIProcess/WebContext.h:
+        * UIProcess/mac/WebContextMac.mm:  instead of tracking plugin app sleep state on the web pref.
+            and visibility state, just use the web pref.
+        (WebKit::WebContext::updateProcessSuppressionState):
+        (WebKit::WebContext::processSuppressionPreferenceIsEnabledForAllContexts):
+
</ins><span class="cx"> 2014-03-28  Brian Burg  &lt;bburg@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Replay: add page-level setting to bypass the MemoryCache
</span></span></pre></div>
<a id="trunkSourceWebKit2PluginProcessPluginProcesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/PluginProcess/PluginProcess.cpp (166440 => 166441)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/PluginProcess/PluginProcess.cpp        2014-03-29 00:37:10 UTC (rev 166440)
+++ trunk/Source/WebKit2/PluginProcess/PluginProcess.cpp        2014-03-29 01:15:44 UTC (rev 166441)
</span><span class="lines">@@ -61,6 +61,7 @@
</span><span class="cx">     , m_compositingRenderServerPort(MACH_PORT_NULL)
</span><span class="cx"> #endif
</span><span class="cx">     , m_connectionActivity(&quot;PluginProcess connection activity.&quot;)
</span><ins>+    , m_visiblePluginsActivity(&quot;Visible plugins from PluginProcess activity.&quot;)
</ins><span class="cx"> {
</span><span class="cx">     NetscapePlugin::setSetExceptionFunction(WebProcessConnection::setGlobalException);
</span><span class="cx"> }
</span><span class="lines">@@ -236,6 +237,16 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+void PluginProcess::pluginsForWebProcessDidBecomeVisible()
+{
+    m_visiblePluginsActivity.increment();
+}
+
+void PluginProcess::pluginsForWebProcessDidBecomeHidden()
+{
+    m_visiblePluginsActivity.decrement();
+}
+
</ins><span class="cx"> } // namespace WebKit
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(NETSCAPE_PLUGIN_API)
</span></span></pre></div>
<a id="trunkSourceWebKit2PluginProcessPluginProcessh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/PluginProcess/PluginProcess.h (166440 => 166441)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/PluginProcess/PluginProcess.h        2014-03-29 00:37:10 UTC (rev 166440)
+++ trunk/Source/WebKit2/PluginProcess/PluginProcess.h        2014-03-29 01:15:44 UTC (rev 166441)
</span><span class="lines">@@ -66,6 +66,9 @@
</span><span class="cx"> 
</span><span class="cx">     CountedUserActivity&amp; connectionActivity() { return m_connectionActivity; }
</span><span class="cx"> 
</span><ins>+    void pluginsForWebProcessDidBecomeHidden();
+    void pluginsForWebProcessDidBecomeVisible();
+
</ins><span class="cx"> private:
</span><span class="cx">     PluginProcess();
</span><span class="cx">     ~PluginProcess();
</span><span class="lines">@@ -121,6 +124,7 @@
</span><span class="cx"> 
</span><span class="cx">     static void lowMemoryHandler(bool critical);
</span><span class="cx">     CountedUserActivity m_connectionActivity;
</span><ins>+    CountedUserActivity m_visiblePluginsActivity;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2PluginProcessWebProcessConnectioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/PluginProcess/WebProcessConnection.cpp (166440 => 166441)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/PluginProcess/WebProcessConnection.cpp        2014-03-29 00:37:10 UTC (rev 166440)
+++ trunk/Source/WebKit2/PluginProcess/WebProcessConnection.cpp        2014-03-29 01:15:44 UTC (rev 166441)
</span><span class="lines">@@ -91,6 +91,8 @@
</span><span class="cx">         ASSERT(pluginControllerUniquePtr.get() == pluginController);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    pluginDidBecomeHidden(pluginController-&gt;pluginInstanceID());
+
</ins><span class="cx">     // Invalidate all objects related to this plug-in.
</span><span class="cx">     if (plugin)
</span><span class="cx">         m_npRemoteObjectMap-&gt;pluginDestroyed(plugin);
</span><span class="lines">@@ -323,7 +325,29 @@
</span><span class="cx"> 
</span><span class="cx">     m_connection-&gt;sendSync(Messages::PluginProxy::DidCreatePlugin(wantsWheelEvents, remoteLayerClientID), Messages::PluginProxy::DidCreatePlugin::Reply(), creationParameters.pluginInstanceID);
</span><span class="cx"> }
</span><ins>+    
+void WebProcessConnection::pluginDidBecomeVisible(unsigned pluginInstanceID)
+{
+    bool oldState = m_visiblePluginInstanceIDs.isEmpty();
+    
+    m_visiblePluginInstanceIDs.add(pluginInstanceID);
</ins><span class="cx"> 
</span><ins>+    ASSERT(m_visiblePluginInstanceIDs.size() &lt;= m_pluginControllers.size());
+    
+    if (oldState != m_visiblePluginInstanceIDs.isEmpty())
+        PluginProcess::shared().pluginsForWebProcessDidBecomeVisible();
+}
+
+void WebProcessConnection::pluginDidBecomeHidden(unsigned pluginInstanceID)
+{
+    bool oldState = m_visiblePluginInstanceIDs.isEmpty();
+    
+    m_visiblePluginInstanceIDs.remove(pluginInstanceID);
+    
+    if (oldState != m_visiblePluginInstanceIDs.isEmpty())
+        PluginProcess::shared().pluginsForWebProcessDidBecomeHidden();
+}
+    
</ins><span class="cx"> } // namespace WebKit
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(NETSCAPE_PLUGIN_API)
</span></span></pre></div>
<a id="trunkSourceWebKit2PluginProcessWebProcessConnectionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/PluginProcess/WebProcessConnection.h (166440 => 166441)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/PluginProcess/WebProcessConnection.h        2014-03-29 00:37:10 UTC (rev 166440)
+++ trunk/Source/WebKit2/PluginProcess/WebProcessConnection.h        2014-03-29 01:15:44 UTC (rev 166441)
</span><span class="lines">@@ -53,6 +53,9 @@
</span><span class="cx">     void removePluginControllerProxy(PluginControllerProxy*, Plugin*);
</span><span class="cx"> 
</span><span class="cx">     static void setGlobalException(const String&amp;);
</span><ins>+    
+    void pluginDidBecomeVisible(unsigned pluginInstanceID);
+    void pluginDidBecomeHidden(unsigned pluginInstanceID);
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     WebProcessConnection(IPC::Connection::Identifier);
</span><span class="lines">@@ -81,6 +84,7 @@
</span><span class="cx">     HashMap&lt;uint64_t, std::unique_ptr&lt;PluginControllerProxy&gt;&gt; m_pluginControllers;
</span><span class="cx">     RefPtr&lt;NPRemoteObjectMap&gt; m_npRemoteObjectMap;
</span><span class="cx">     HashSet&lt;uint64_t&gt; m_asynchronousInstanceIDsToIgnore;
</span><ins>+    HashSet&lt;uint64_t&gt; m_visiblePluginInstanceIDs;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2PluginProcessmacPluginControllerProxyMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/PluginProcess/mac/PluginControllerProxyMac.mm (166440 => 166441)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/PluginProcess/mac/PluginControllerProxyMac.mm        2014-03-29 00:37:10 UTC (rev 166440)
+++ trunk/Source/WebKit2/PluginProcess/mac/PluginControllerProxyMac.mm        2014-03-29 01:15:44 UTC (rev 166441)
</span><span class="lines">@@ -107,6 +107,10 @@
</span><span class="cx"> void PluginControllerProxy::windowVisibilityChanged(bool isVisible)
</span><span class="cx"> {
</span><span class="cx">     m_plugin-&gt;windowVisibilityChanged(isVisible);
</span><ins>+    if (isVisible)
+        m_connection-&gt;pluginDidBecomeVisible(m_pluginInstanceID);
+    else
+        m_connection-&gt;pluginDidBecomeHidden(m_pluginInstanceID);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void PluginControllerProxy::sendComplexTextInput(const String&amp; textInput)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebContexth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebContext.h (166440 => 166441)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebContext.h        2014-03-29 00:37:10 UTC (rev 166440)
+++ trunk/Source/WebKit2/UIProcess/WebContext.h        2014-03-29 01:15:44 UTC (rev 166441)
</span><span class="lines">@@ -300,6 +300,7 @@
</span><span class="cx"> #if PLATFORM(COCOA)
</span><span class="cx">     bool processSuppressionEnabled() const;
</span><span class="cx">     static bool processSuppressionIsEnabledForAllContexts();
</span><ins>+    static bool processSuppressionPreferenceIsEnabledForAllContexts();
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     void windowServerConnectionStateChanged();
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessmacWebContextMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/mac/WebContextMac.mm (166440 => 166441)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/mac/WebContextMac.mm        2014-03-29 00:37:10 UTC (rev 166440)
+++ trunk/Source/WebKit2/UIProcess/mac/WebContextMac.mm        2014-03-29 01:15:44 UTC (rev 166441)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> #import &quot;WKBrowsingContextControllerInternal.h&quot;
</span><span class="cx"> #import &quot;WKBrowsingContextControllerInternal.h&quot;
</span><span class="cx"> #import &quot;WebKitSystemInterface.h&quot;
</span><ins>+#import &quot;WebPageGroup.h&quot;
</ins><span class="cx"> #import &quot;WebProcessCreationParameters.h&quot;
</span><span class="cx"> #import &quot;WebProcessMessages.h&quot;
</span><span class="cx"> #import &quot;WindowServerConnection.h&quot;
</span><span class="lines">@@ -116,7 +117,7 @@
</span><span class="cx">         m_networkProcess-&gt;setProcessSuppressionEnabled(processSuppressionEnabled());
</span><span class="cx"> #endif
</span><span class="cx"> #if ENABLE(NETSCAPE_PLUGIN_API)
</span><del>-    PluginProcessManager::shared().setProcessSuppressionEnabled(processSuppressionIsEnabledForAllContexts());
</del><ins>+    PluginProcessManager::shared().setProcessSuppressionEnabled(processSuppressionPreferenceIsEnabledForAllContexts());
</ins><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -430,6 +431,15 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool WebContext::processSuppressionPreferenceIsEnabledForAllContexts()
+{
+    for (const auto* context : WebContext::allContexts()) {
+        if (!context-&gt;m_defaultPageGroup-&gt;preferences().store().getBoolValueForKey(WebPreferencesKey::pageVisibilityBasedProcessSuppressionEnabledKey()))
+            return false;
+    }
+    return true;
+}
+    
</ins><span class="cx"> void WebContext::registerNotificationObservers()
</span><span class="cx"> {
</span><span class="cx"> #if !PLATFORM(IOS)
</span></span></pre>
</div>
</div>

</body>
</html>