<!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>[197787] 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/197787">197787</a></dd>
<dt>Author</dt> <dd>adachan@apple.com</dd>
<dt>Date</dt> <dd>2016-03-08 11:32:58 -0800 (Tue, 08 Mar 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Fix lifetime issues regarding WebVideoFullscreenInterfaceMac
https://bugs.webkit.org/show_bug.cgi?id=155130

Reviewed by Beth Dakin.

Now that both fullscreen and video controls manager rely on WebVideoFullscreenInterface,
we now keep track of a &quot;client count&quot; for each context ID so we'll only remove it
from the context map after all the &quot;clients&quot; are done with it.

Before this change, every time WebVideoFullscreenManager::setUpVideoControlsManager()
is called, the existing interface is cleared and a new one is created even when there's
an existing interface for that. With this change, we reuse the existing interface for
the video element.

* UIProcess/Cocoa/WebVideoFullscreenManagerProxy.h:
* UIProcess/Cocoa/WebVideoFullscreenManagerProxy.mm:
(WebKit::WebVideoFullscreenManagerProxy::invalidate):
Also clear out m_clientCounts.
(WebKit::WebVideoFullscreenManagerProxy::addClientForContext):
If the context ID is not in m_clientCounts yet, add the count of 1 to
that table for that ID. Otherwise, increment the count by 1.
(WebKit::WebVideoFullscreenManagerProxy::removeClientForContext):
Assert that we have added this context id to m_clientCounts before.
Decrement the count. If it reaches 0, remove this context ID from both
m_clientCounts and m_contextMap.
(WebKit::WebVideoFullscreenManagerProxy::setupFullscreenWithID):
We have started a new fullscreen session using this interface. Call
addClientForContext() to update the client count.
(WebKit::WebVideoFullscreenManagerProxy::setUpVideoControlsManagerWithID):
If the current controls manager set up has the same context ID as the one
passed in, we don't have to do anything. Otherwise, if we have set up
the video controls manager with a different ID before, call removeClientForContext()
on the old ID to decrement its client count. Set m_controlsManagerContextId
to the new value and call addClientForContext() with it.
(WebKit::WebVideoFullscreenManagerProxy::didCleanupFullscreen):
Instead of removing the mapping from m_contextMap directly, reset the fullscreen
mode on the interface and call removeClientForContext(), which removes the mapping
only if there's no more client using the interface.
* WebProcess/cocoa/WebVideoFullscreenManager.h:
* WebProcess/cocoa/WebVideoFullscreenManager.mm:
(WebKit::WebVideoFullscreenManager::~WebVideoFullscreenManager):
Clear m_clientCounts.
(WebKit::WebVideoFullscreenManager::removeContext):
Add a helper method for removing the context.
(WebKit::WebVideoFullscreenManager::addClientForContext):
If the context ID is not in m_clientCounts yet, add the count of 1 to
that table for that ID. Otherwise, increment the count by 1.
(WebKit::WebVideoFullscreenManager::removeClientForContext):
Assert that we have added this context id to m_clientCounts before.
Decrement the count. If it reaches 0, remove this context ID from
m_clientCounts and call removeContext() to clean up this context.
(WebKit::WebVideoFullscreenManager::enterVideoFullscreenForVideoElement):
We have started a new fullscreen session using this interface. Call
addClientForContext() to update the client count. Create a layer hosting
context if it's not there.
(WebKit::WebVideoFullscreenManager::setUpVideoControlsManager):
If we have set up a context for this video element before, see if it's
the one we are currently managing video controls for. If it is, return early.
Otherwise, call removeClientForContext() on the previous m_controlsManagerContextId
and update m_controlsManagerContextId to the context ID of this video element.
If there's no context created for this video element yet, set one up.
Send a SetUpVideoControlsManagerWithID message to the proxy object in the UI process
so it'll update its controls manager context ID. Also, conditionalize all of this
under PLATFORM(MAC) to be consistent with WebVideoFullscreenManagerProxy.
(WebKit::WebVideoFullscreenManager::didCleanupFullscreen):
Just reset the fullscreen mode on the interface and call removeClientForContext() which
only cleans up the context if there's no more client using it.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2UIProcessCocoaWebVideoFullscreenManagerProxyh">trunk/Source/WebKit2/UIProcess/Cocoa/WebVideoFullscreenManagerProxy.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessCocoaWebVideoFullscreenManagerProxymm">trunk/Source/WebKit2/UIProcess/Cocoa/WebVideoFullscreenManagerProxy.mm</a></li>
<li><a href="#trunkSourceWebKit2WebProcesscocoaWebVideoFullscreenManagerh">trunk/Source/WebKit2/WebProcess/cocoa/WebVideoFullscreenManager.h</a></li>
<li><a href="#trunkSourceWebKit2WebProcesscocoaWebVideoFullscreenManagermm">trunk/Source/WebKit2/WebProcess/cocoa/WebVideoFullscreenManager.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (197786 => 197787)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2016-03-08 19:02:31 UTC (rev 197786)
+++ trunk/Source/WebKit2/ChangeLog        2016-03-08 19:32:58 UTC (rev 197787)
</span><span class="lines">@@ -1,3 +1,73 @@
</span><ins>+2016-03-04  Ada Chan  &lt;adachan@apple.com&gt;
+
+        Fix lifetime issues regarding WebVideoFullscreenInterfaceMac
+        https://bugs.webkit.org/show_bug.cgi?id=155130
+
+        Reviewed by Beth Dakin.
+
+        Now that both fullscreen and video controls manager rely on WebVideoFullscreenInterface,
+        we now keep track of a &quot;client count&quot; for each context ID so we'll only remove it
+        from the context map after all the &quot;clients&quot; are done with it.
+
+        Before this change, every time WebVideoFullscreenManager::setUpVideoControlsManager()
+        is called, the existing interface is cleared and a new one is created even when there's
+        an existing interface for that. With this change, we reuse the existing interface for
+        the video element.
+
+        * UIProcess/Cocoa/WebVideoFullscreenManagerProxy.h:
+        * UIProcess/Cocoa/WebVideoFullscreenManagerProxy.mm:
+        (WebKit::WebVideoFullscreenManagerProxy::invalidate):
+        Also clear out m_clientCounts.
+        (WebKit::WebVideoFullscreenManagerProxy::addClientForContext):
+        If the context ID is not in m_clientCounts yet, add the count of 1 to
+        that table for that ID. Otherwise, increment the count by 1.
+        (WebKit::WebVideoFullscreenManagerProxy::removeClientForContext):
+        Assert that we have added this context id to m_clientCounts before.
+        Decrement the count. If it reaches 0, remove this context ID from both
+        m_clientCounts and m_contextMap.
+        (WebKit::WebVideoFullscreenManagerProxy::setupFullscreenWithID):
+        We have started a new fullscreen session using this interface. Call
+        addClientForContext() to update the client count.
+        (WebKit::WebVideoFullscreenManagerProxy::setUpVideoControlsManagerWithID):
+        If the current controls manager set up has the same context ID as the one
+        passed in, we don't have to do anything. Otherwise, if we have set up
+        the video controls manager with a different ID before, call removeClientForContext()
+        on the old ID to decrement its client count. Set m_controlsManagerContextId
+        to the new value and call addClientForContext() with it.
+        (WebKit::WebVideoFullscreenManagerProxy::didCleanupFullscreen):
+        Instead of removing the mapping from m_contextMap directly, reset the fullscreen
+        mode on the interface and call removeClientForContext(), which removes the mapping
+        only if there's no more client using the interface.
+        * WebProcess/cocoa/WebVideoFullscreenManager.h:
+        * WebProcess/cocoa/WebVideoFullscreenManager.mm:
+        (WebKit::WebVideoFullscreenManager::~WebVideoFullscreenManager):
+        Clear m_clientCounts.
+        (WebKit::WebVideoFullscreenManager::removeContext):
+        Add a helper method for removing the context.
+        (WebKit::WebVideoFullscreenManager::addClientForContext):
+        If the context ID is not in m_clientCounts yet, add the count of 1 to
+        that table for that ID. Otherwise, increment the count by 1.
+        (WebKit::WebVideoFullscreenManager::removeClientForContext):
+        Assert that we have added this context id to m_clientCounts before.
+        Decrement the count. If it reaches 0, remove this context ID from
+        m_clientCounts and call removeContext() to clean up this context.
+        (WebKit::WebVideoFullscreenManager::enterVideoFullscreenForVideoElement):
+        We have started a new fullscreen session using this interface. Call
+        addClientForContext() to update the client count. Create a layer hosting
+        context if it's not there.
+        (WebKit::WebVideoFullscreenManager::setUpVideoControlsManager):
+        If we have set up a context for this video element before, see if it's
+        the one we are currently managing video controls for. If it is, return early.
+        Otherwise, call removeClientForContext() on the previous m_controlsManagerContextId
+        and update m_controlsManagerContextId to the context ID of this video element.
+        If there's no context created for this video element yet, set one up.
+        Send a SetUpVideoControlsManagerWithID message to the proxy object in the UI process
+        so it'll update its controls manager context ID. Also, conditionalize all of this
+        under PLATFORM(MAC) to be consistent with WebVideoFullscreenManagerProxy.
+        (WebKit::WebVideoFullscreenManager::didCleanupFullscreen):
+        Just reset the fullscreen mode on the interface and call removeClientForContext() which
+        only cleans up the context if there's no more client using it.
+
</ins><span class="cx"> 2016-03-08  Timothy Hatcher  &lt;timothy@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: Add automation protocol methods for navigation
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessCocoaWebVideoFullscreenManagerProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/Cocoa/WebVideoFullscreenManagerProxy.h (197786 => 197787)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/Cocoa/WebVideoFullscreenManagerProxy.h        2016-03-08 19:02:31 UTC (rev 197786)
+++ trunk/Source/WebKit2/UIProcess/Cocoa/WebVideoFullscreenManagerProxy.h        2016-03-08 19:32:58 UTC (rev 197787)
</span><span class="lines">@@ -132,6 +132,8 @@
</span><span class="cx">     ModelInterfaceTuple&amp; ensureModelAndInterface(uint64_t contextId);
</span><span class="cx">     WebVideoFullscreenModelContext&amp; ensureModel(uint64_t contextId);
</span><span class="cx">     PlatformWebVideoFullscreenInterface&amp; ensureInterface(uint64_t contextId);
</span><ins>+    void addClientForContext(uint64_t contextId);
+    void removeClientForContext(uint64_t contextId);
</ins><span class="cx"> 
</span><span class="cx">     // Messages from WebVideoFullscreenManager
</span><span class="cx">     void setupFullscreenWithID(uint64_t contextId, uint32_t videoLayerID, const WebCore::IntRect&amp; initialRect, float hostingScaleFactor, WebCore::HTMLMediaElementEnums::VideoFullscreenMode, bool allowsPictureInPicture);
</span><span class="lines">@@ -182,7 +184,7 @@
</span><span class="cx">     WebPageProxy* m_page;
</span><span class="cx">     HashMap&lt;uint64_t, ModelInterfaceTuple&gt; m_contextMap;
</span><span class="cx">     uint64_t m_controlsManagerContextId { 0 };
</span><del>-
</del><ins>+    HashMap&lt;uint64_t, int&gt; m_clientCounts;
</ins><span class="cx"> };
</span><span class="cx">     
</span><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessCocoaWebVideoFullscreenManagerProxymm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/Cocoa/WebVideoFullscreenManagerProxy.mm (197786 => 197787)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/Cocoa/WebVideoFullscreenManagerProxy.mm        2016-03-08 19:02:31 UTC (rev 197786)
+++ trunk/Source/WebKit2/UIProcess/Cocoa/WebVideoFullscreenManagerProxy.mm        2016-03-08 19:32:58 UTC (rev 197787)
</span><span class="lines">@@ -278,6 +278,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     m_contextMap.clear();
</span><ins>+    m_clientCounts.clear();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebVideoFullscreenManagerProxy::requestHideAndExitFullscreen()
</span><span class="lines">@@ -339,6 +340,30 @@
</span><span class="cx">     return *std::get&lt;1&gt;(ensureModelAndInterface(contextId));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebVideoFullscreenManagerProxy::addClientForContext(uint64_t contextId)
+{
+    auto addResult = m_clientCounts.add(contextId, 1);
+    if (!addResult.isNewEntry)
+        addResult.iterator-&gt;value++;
+}
+
+void WebVideoFullscreenManagerProxy::removeClientForContext(uint64_t contextId)
+{
+    ASSERT(m_clientCounts.contains(contextId));
+
+    int clientCount = m_clientCounts.get(contextId);
+    ASSERT(clientCount &gt; 0);
+    clientCount--;
+
+    if (clientCount &lt;= 0) {
+        m_clientCounts.remove(contextId);
+        m_contextMap.remove(contextId);
+        return;
+    }
+
+    m_clientCounts.set(contextId, clientCount);
+}
+
</ins><span class="cx"> #pragma mark Messages from WebVideoFullscreenManager
</span><span class="cx"> 
</span><span class="cx"> void WebVideoFullscreenManagerProxy::setupFullscreenWithID(uint64_t contextId, uint32_t videoLayerID, const WebCore::IntRect&amp; initialRect, float hostingDeviceScaleFactor, HTMLMediaElementEnums::VideoFullscreenMode videoFullscreenMode, bool allowsPictureInPicture)
</span><span class="lines">@@ -348,6 +373,7 @@
</span><span class="cx">     RefPtr&lt;PlatformWebVideoFullscreenInterface&gt; interface;
</span><span class="cx"> 
</span><span class="cx">     std::tie(model, interface) = ensureModelAndInterface(contextId);
</span><ins>+    addClientForContext(contextId);
</ins><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;WKLayerHostView&gt; view = static_cast&lt;WKLayerHostView*&gt;(model-&gt;layerHostView());
</span><span class="cx">     if (!view) {
</span><span class="lines">@@ -377,16 +403,15 @@
</span><span class="cx"> void WebVideoFullscreenManagerProxy::setUpVideoControlsManagerWithID(uint64_t contextId)
</span><span class="cx"> {
</span><span class="cx"> #if PLATFORM(MAC)
</span><del>-    // If there is an existing controls manager, clean it up.
</del><ins>+    if (m_controlsManagerContextId == contextId)
+        return;
+
</ins><span class="cx">     if (m_controlsManagerContextId)
</span><del>-        m_contextMap.remove(m_controlsManagerContextId);
</del><ins>+        removeClientForContext(m_controlsManagerContextId);
</ins><span class="cx"> 
</span><del>-    RefPtr&lt;WebVideoFullscreenModelContext&gt; model;
-    RefPtr&lt;PlatformWebVideoFullscreenInterface&gt; interface;
-
-    std::tie(model, interface) = ensureModelAndInterface(contextId);
</del><span class="cx">     m_controlsManagerContextId = contextId;
</span><del>-    interface-&gt;ensureControlsManager();
</del><ins>+    ensureInterface(m_controlsManagerContextId).ensureControlsManager();
+    addClientForContext(m_controlsManagerContextId);
</ins><span class="cx"> #else
</span><span class="cx">     UNUSED_PARAM(contextId);
</span><span class="cx"> #endif
</span><span class="lines">@@ -592,14 +617,18 @@
</span><span class="cx"> 
</span><span class="cx"> void WebVideoFullscreenManagerProxy::didCleanupFullscreen(uint64_t contextId)
</span><span class="cx"> {
</span><del>-    auto&amp; model = ensureModel(contextId);
</del><ins>+    RefPtr&lt;WebVideoFullscreenModelContext&gt; model;
+    RefPtr&lt;PlatformWebVideoFullscreenInterface&gt; interface;
</ins><span class="cx"> 
</span><ins>+    std::tie(model, interface) = ensureModelAndInterface(contextId);
+
</ins><span class="cx">     [CATransaction flush];
</span><del>-    [model.layerHostView() removeFromSuperview];
-    model.setLayerHostView(nullptr);
</del><ins>+    [model-&gt;layerHostView() removeFromSuperview];
+    model-&gt;setLayerHostView(nullptr);
</ins><span class="cx">     m_page-&gt;send(Messages::WebVideoFullscreenManager::DidCleanupFullscreen(contextId), m_page-&gt;pageID());
</span><span class="cx"> 
</span><del>-    m_contextMap.remove(contextId);
</del><ins>+    interface-&gt;setMode(HTMLMediaElementEnums::VideoFullscreenModeNone);
+    removeClientForContext(contextId);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebVideoFullscreenManagerProxy::setVideoLayerFrame(uint64_t contextId, WebCore::FloatRect frame)
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcesscocoaWebVideoFullscreenManagerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/cocoa/WebVideoFullscreenManager.h (197786 => 197787)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/cocoa/WebVideoFullscreenManager.h        2016-03-08 19:02:31 UTC (rev 197786)
+++ trunk/Source/WebKit2/WebProcess/cocoa/WebVideoFullscreenManager.h        2016-03-08 19:32:58 UTC (rev 197787)
</span><span class="lines">@@ -129,6 +129,9 @@
</span><span class="cx">     ModelInterfaceTuple&amp; ensureModelAndInterface(uint64_t contextId);
</span><span class="cx">     WebCore::WebVideoFullscreenModelVideoElement&amp; ensureModel(uint64_t contextId);
</span><span class="cx">     WebVideoFullscreenInterfaceContext&amp; ensureInterface(uint64_t contextId);
</span><ins>+    void removeContext(uint64_t contextId);
+    void addClientForContext(uint64_t contextId);
+    void removeClientForContext(uint64_t contextId);
</ins><span class="cx"> 
</span><span class="cx">     // Interface to WebVideoFullscreenInterfaceContext
</span><span class="cx">     void resetMediaState(uint64_t contextId);
</span><span class="lines">@@ -171,6 +174,7 @@
</span><span class="cx">     HashMap&lt;WebCore::HTMLVideoElement*, uint64_t&gt; m_videoElements;
</span><span class="cx">     HashMap&lt;uint64_t, ModelInterfaceTuple&gt; m_contextMap;
</span><span class="cx">     uint64_t m_controlsManagerContextId { 0 };
</span><ins>+    HashMap&lt;uint64_t, int&gt; m_clientCounts;
</ins><span class="cx"> };
</span><span class="cx">     
</span><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcesscocoaWebVideoFullscreenManagermm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/cocoa/WebVideoFullscreenManager.mm (197786 => 197787)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/cocoa/WebVideoFullscreenManager.mm        2016-03-08 19:02:31 UTC (rev 197786)
+++ trunk/Source/WebKit2/WebProcess/cocoa/WebVideoFullscreenManager.mm        2016-03-08 19:32:58 UTC (rev 197787)
</span><span class="lines">@@ -182,6 +182,7 @@
</span><span class="cx"> 
</span><span class="cx">     m_contextMap.clear();
</span><span class="cx">     m_videoElements.clear();
</span><ins>+    m_clientCounts.clear();
</ins><span class="cx"> 
</span><span class="cx">     WebProcess::singleton().removeMessageReceiver(Messages::WebVideoFullscreenManager::messageReceiverName(), m_page-&gt;pageID());
</span><span class="cx"> }
</span><span class="lines">@@ -215,6 +216,44 @@
</span><span class="cx">     return *std::get&lt;1&gt;(ensureModelAndInterface(contextId));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebVideoFullscreenManager::removeContext(uint64_t contextId)
+{
+    RefPtr&lt;WebVideoFullscreenModelVideoElement&gt; model;
+    RefPtr&lt;WebVideoFullscreenInterfaceContext&gt; interface;
+    std::tie(model, interface) = ensureModelAndInterface(contextId);
+
+    RefPtr&lt;HTMLVideoElement&gt; videoElement = model-&gt;videoElement();
+    model-&gt;setVideoElement(nullptr);
+    model-&gt;setWebVideoFullscreenInterface(nullptr);
+    interface-&gt;invalidate();
+    m_videoElements.remove(videoElement.get());
+    m_contextMap.remove(contextId);
+}
+
+void WebVideoFullscreenManager::addClientForContext(uint64_t contextId)
+{
+    auto addResult = m_clientCounts.add(contextId, 1);
+    if (!addResult.isNewEntry)
+        addResult.iterator-&gt;value++;
+}
+
+void WebVideoFullscreenManager::removeClientForContext(uint64_t contextId)
+{
+    ASSERT(m_clientCounts.contains(contextId));
+
+    int clientCount = m_clientCounts.get(contextId);
+    ASSERT(clientCount &gt; 0);
+    clientCount--;
+
+    if (clientCount &lt;= 0) {
+        m_clientCounts.remove(contextId);
+        removeContext(contextId);
+        return;
+    }
+
+    m_clientCounts.set(contextId, clientCount);
+}
+
</ins><span class="cx"> #pragma mark Interface to ChromeClient:
</span><span class="cx"> 
</span><span class="cx"> bool WebVideoFullscreenManager::supportsVideoFullscreen(WebCore::HTMLMediaElementEnums::VideoFullscreenMode mode) const
</span><span class="lines">@@ -243,6 +282,9 @@
</span><span class="cx">     RefPtr&lt;WebVideoFullscreenModelVideoElement&gt; model;
</span><span class="cx">     RefPtr&lt;WebVideoFullscreenInterfaceContext&gt; interface;
</span><span class="cx">     std::tie(model, interface) = ensureModelAndInterface(contextId);
</span><ins>+    addClientForContext(contextId);
+    if (!interface-&gt;layerHostingContext())
+        interface-&gt;setLayerHostingContext(LayerHostingContext::createForExternalHostingProcess());
</ins><span class="cx"> 
</span><span class="cx">     FloatRect clientRect = clientRectForElement(&amp;videoElement);
</span><span class="cx">     FloatRect videoLayerFrame = FloatRect(0, 0, clientRect.width(), clientRect.height());
</span><span class="lines">@@ -281,30 +323,25 @@
</span><span class="cx"> 
</span><span class="cx"> void WebVideoFullscreenManager::setUpVideoControlsManager(WebCore::HTMLVideoElement&amp; videoElement)
</span><span class="cx"> {
</span><del>-    // If there is an existing controls manager, clean it up.
-    if (m_controlsManagerContextId) {
-        RefPtr&lt;WebVideoFullscreenModelVideoElement&gt; model;
-        RefPtr&lt;WebVideoFullscreenInterfaceContext&gt; interface;
-        std::tie(model, interface) = ensureModelAndInterface(m_controlsManagerContextId);
</del><ins>+#if PLATFORM(MAC)
+    if (m_videoElements.contains(&amp;videoElement)) {
+        uint64_t contextId = m_videoElements.get(&amp;videoElement);
+        if (m_controlsManagerContextId == contextId)
+            return;
</ins><span class="cx"> 
</span><del>-        RefPtr&lt;HTMLVideoElement&gt; videoElement = model-&gt;videoElement();
-        model-&gt;setVideoElement(nullptr);
-        model-&gt;setWebVideoFullscreenInterface(nullptr);
-        interface-&gt;invalidate();
-        m_videoElements.remove(videoElement.get());
-        m_contextMap.remove(m_controlsManagerContextId);
</del><ins>+        if (m_controlsManagerContextId)
+            removeClientForContext(m_controlsManagerContextId);
+        m_controlsManagerContextId = contextId;
+    } else {
+        auto addResult = m_videoElements.ensure(&amp;videoElement, [&amp;] { return nextContextId(); });
+        auto contextId = addResult.iterator-&gt;value;
+        m_controlsManagerContextId = contextId;
+        ensureModel(contextId).setVideoElement(&amp;videoElement);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    auto addResult = m_videoElements.ensure(&amp;videoElement, [&amp;] { return nextContextId(); });
-    auto contextId = addResult.iterator-&gt;value;
-    m_controlsManagerContextId = contextId;
-
-    RefPtr&lt;WebVideoFullscreenModelVideoElement&gt; model;
-    RefPtr&lt;WebVideoFullscreenInterfaceContext&gt; interface;
-    std::tie(model, interface) = ensureModelAndInterface(contextId);
-    model-&gt;setVideoElement(&amp;videoElement);
-    
-    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::SetUpVideoControlsManagerWithID(contextId), m_page-&gt;pageID());
</del><ins>+    addClientForContext(m_controlsManagerContextId);
+    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::SetUpVideoControlsManagerWithID(m_controlsManagerContextId), m_page-&gt;pageID());
+#endif
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebVideoFullscreenManager::exitVideoFullscreenToModeWithoutAnimation(WebCore::HTMLVideoElement&amp; videoElement, WebCore::HTMLMediaElementEnums::VideoFullscreenMode targetMode)
</span><span class="lines">@@ -558,11 +595,8 @@
</span><span class="cx">     model-&gt;setVideoFullscreenLayer(nil);
</span><span class="cx">     RefPtr&lt;HTMLVideoElement&gt; videoElement = model-&gt;videoElement();
</span><span class="cx"> 
</span><del>-    model-&gt;setVideoElement(nullptr);
-    model-&gt;setWebVideoFullscreenInterface(nullptr);
-    interface-&gt;invalidate();
-    m_videoElements.remove(videoElement.get());
-    m_contextMap.remove(contextId);
</del><ins>+    interface-&gt;setFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone);
+    removeClientForContext(contextId);
</ins><span class="cx"> 
</span><span class="cx">     if (!videoElement || !targetIsFullscreen)
</span><span class="cx">         return;
</span></span></pre>
</div>
</div>

</body>
</html>