<!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>[182914] trunk/Source</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/182914">182914</a></dd>
<dt>Author</dt> <dd>jer.noble@apple.com</dd>
<dt>Date</dt> <dd>2015-04-16 15:42:58 -0700 (Thu, 16 Apr 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>[iOS] When simultaneously exiting-and-entering fullscreen, WebVideoFullscreenManager/Proxy becomes confused about what video element it represents.
https://bugs.webkit.org/show_bug.cgi?id=143680

Reviewed by Simon Fraser.

Source/WebCore:

Add getters for the video's fullscreen layer, and be more tolerant about the order in which setVideoElement() and
setWebVideoFullscreenInterface are called.

* html/HTMLMediaElement.h:
(WebCore::HTMLMediaElement::videoFullscreenLayer): Added simple getter.
* platform/ios/WebVideoFullscreenInterfaceAVKit.h:
* platform/ios/WebVideoFullscreenModelVideoElement.h:
(WebCore::WebVideoFullscreenModelVideoElement::videoElement): Added simple getter.
(WebCore::WebVideoFullscreenModelVideoElement::setWebVideoFullscreenInterface): Deleted. Moved to .mm file.
* platform/ios/WebVideoFullscreenModelVideoElement.mm:
(WebVideoFullscreenModelVideoElement::WebVideoFullscreenModelVideoElement): Initialize ivars in the .h file.
(WebVideoFullscreenModelVideoElement::setWebVideoFullscreenInterface): Call those methods skipped in setVideoElement()
    if m_videoFullscreenInterface had not yet been set.
(WebVideoFullscreenModelVideoElement::setVideoElement): Null-check m_videoFullscreenInterface.

Source/WebKit2:

The original assumption of WebVideoFullscreenManager and -Proxy was that the two classes would represent a
single video element and its full screen state. With multiple animations in and out of fullscreen combined with
multiple fullscreen modes, this assumption no longer holds true.

Rather than having a WebVideoFullscreenManager which /isa/ WebVideoFullscreenModelVideoElement, the manager now
/hasa/ WebVideoFullscreenModelVideoElement (or has many such models). Ditto for WebVideoFullscreenManager and
WebVideoFullscreenInterfaceAVKit. The WebVideoFullscreenInterfaceAVKit still needs a WebVideoFullscreenModel to
communicate with, so a new wrapper class is used for that purpose, WebVideoFullscreenModelContext. Ditto for
WebVideoFullscreenModelVideoElement and the new class WebVideoFullscreenInterfaceContext. These context classes
are paired and share a contextId, allowing the manager and its proxy to route messages between the UIProcess's
WebVideoFullscreenInterfaceAVKit to-and-from the WebProcess's WebVideoFullscreenModelVideoElement.

Both the WebVideoFullscreenModelContext and the WebVideoFullscreenInterfaceContext take a back-pointer to their
manager or manager proxy, and each method on the context simply calls the matching method on the manager and
passes its contextId as a parameter.

Both the WebVideoFullscreenManager and the WebVideoFullscreenManagerProxy pass that contextId in each of their
cross-process messages.

On the other side, the manager and proxy also have a map between contextIds and their matching
WebVideoFullscreenModelVideoElement (in the case of WebVideoFullscreenManager) or
WebVideoFullscreenInterfaceAVKit (in the case of WebVideoFullscreenManagerProxy).

While this change is large by LoC, it is almost entirely boilerplate.  The new and interesting pieces are these:

* UIProcess/ios/WebVideoFullscreenManagerProxy.mm:
(WebKit::WebVideoFullscreenManagerProxy::WebVideoFullscreenManagerProxy): No longer a WebVideoFullscreenInterfaceAVKit.
(WebKit::WebVideoFullscreenManagerProxy::invalidate): Walk through the models and interfaces, invalidating each.
(WebKit::WebVideoFullscreenManagerProxy::createModelAndInterface): Added. Return a new model and interface tuple.
(WebKit::WebVideoFullscreenManagerProxy::ensureModelAndInterface): Added. Lazily create, and add to the m_contextMap
    a new model and interface object.
(WebKit::WebVideoFullscreenManagerProxy::ensureModel): Return the model half of ensureModelAndInterface().
(WebKit::WebVideoFullscreenManagerProxy::ensureInterface): Return the interface half of ensureModelAndInterface().
(WebKit::WebVideoFullscreenManagerProxy::enterFullscreen): Walk through the outstanding interface objects, and if
    any have a fullscreen mode which matches the about-to-be-fullscreen interface, request that that other interface
    exit fullscreen.
* WebProcess/ios/WebVideoFullscreenManager.mm:
(WebKit::nextContextId): Static, incrementing counter used as a contextId source.
(WebKit::WebVideoFullscreenManager::WebVideoFullscreenManager): No longer a WebVideoFullscreenModelVideoElement.
(WebKit::WebVideoFullscreenManager::~WebVideoFullscreenManager): Walk through the models and interfaces, invalidating each.
(WebKit::WebVideoFullscreenManager::ensureModelAndInterface): Added. Return a new model and interface tuple.
(WebKit::WebVideoFullscreenManager::ensureModelAndInterface):  Added. Lazily create, and add to the m_contextMap
    a new model and interface object.
(WebKit::WebVideoFullscreenManager::ensureModel): Return the model half of ensureModelAndInterface().
(WebKit::WebVideoFullscreenManager::ensureInterface): Return the interface half of ensureModelAndInterface().

New classes and methods which just forward on to their owning objects:

* UIProcess/ios/WebVideoFullscreenManagerProxy.h:
(WebKit::WebVideoFullscreenModelContext::create):
(WebKit::WebVideoFullscreenModelContext::~WebVideoFullscreenModelContext):
(WebKit::WebVideoFullscreenModelContext::invalidate):
(WebKit::WebVideoFullscreenModelContext::layerHost):
(WebKit::WebVideoFullscreenModelContext::setLayerHost):
(WebKit::WebVideoFullscreenModelContext::setInitialVideoLayerFrame):
(WebKit::WebVideoFullscreenModelContext::WebVideoFullscreenModelContext):
* UIProcess/ios/WebVideoFullscreenManagerProxy.mm:
(WebKit::WebVideoFullscreenModelContext::play):
(WebKit::WebVideoFullscreenModelContext::pause):
(WebKit::WebVideoFullscreenModelContext::togglePlayState):
(WebKit::WebVideoFullscreenModelContext::beginScrubbing):
(WebKit::WebVideoFullscreenModelContext::endScrubbing):
(WebKit::WebVideoFullscreenModelContext::seekToTime):
(WebKit::WebVideoFullscreenModelContext::fastSeek):
(WebKit::WebVideoFullscreenModelContext::beginScanningForward):
(WebKit::WebVideoFullscreenModelContext::beginScanningBackward):
(WebKit::WebVideoFullscreenModelContext::endScanning):
(WebKit::WebVideoFullscreenModelContext::requestExitFullscreen):
(WebKit::WebVideoFullscreenModelContext::setVideoLayerFrame):
(WebKit::WebVideoFullscreenModelContext::videoLayerFrame):
(WebKit::WebVideoFullscreenModelContext::setVideoLayerGravity):
(WebKit::WebVideoFullscreenModelContext::videoLayerGravity):
(WebKit::WebVideoFullscreenModelContext::selectAudioMediaOption):
(WebKit::WebVideoFullscreenModelContext::selectLegibleMediaOption):
(WebKit::WebVideoFullscreenModelContext::fullscreenModeChanged):
(WebKit::WebVideoFullscreenModelContext::didSetupFullscreen):
(WebKit::WebVideoFullscreenModelContext::didEnterFullscreen):
(WebKit::WebVideoFullscreenModelContext::didExitFullscreen):
(WebKit::WebVideoFullscreenModelContext::didCleanupFullscreen):
(WebKit::WebVideoFullscreenModelContext::fullscreenMayReturnToInline):
* WebProcess/ios/WebVideoFullscreenManager.h:
(WebKit::WebVideoFullscreenInterfaceContext::create):
(WebKit::WebVideoFullscreenInterfaceContext::invalidate):
(WebKit::WebVideoFullscreenInterfaceContext::layerHostingContext):
(WebKit::WebVideoFullscreenInterfaceContext::isAnimating):
(WebKit::WebVideoFullscreenInterfaceContext::setIsAnimating):
(WebKit::WebVideoFullscreenInterfaceContext::targetIsFullscreen):
(WebKit::WebVideoFullscreenInterfaceContext::setTargetIsFullscreen):
(WebKit::WebVideoFullscreenInterfaceContext::fullscreenMode):
(WebKit::WebVideoFullscreenInterfaceContext::setFullscreenMode):
(WebKit::WebVideoFullscreenInterfaceContext::isFullscreen):
(WebKit::WebVideoFullscreenInterfaceContext::setIsFullscreen):
* WebProcess/ios/WebVideoFullscreenManager.mm:
(WebKit::WebVideoFullscreenInterfaceContext::WebVideoFullscreenInterfaceContext):
(WebKit::WebVideoFullscreenInterfaceContext::~WebVideoFullscreenInterfaceContext):
(WebKit::WebVideoFullscreenInterfaceContext::setLayerHostingContext):
(WebKit::WebVideoFullscreenInterfaceContext::resetMediaState):
(WebKit::WebVideoFullscreenInterfaceContext::setDuration):
(WebKit::WebVideoFullscreenInterfaceContext::setCurrentTime):
(WebKit::WebVideoFullscreenInterfaceContext::setBufferedTime):
(WebKit::WebVideoFullscreenInterfaceContext::setRate):
(WebKit::WebVideoFullscreenInterfaceContext::setVideoDimensions):
(WebKit::WebVideoFullscreenInterfaceContext::setSeekableRanges):
(WebKit::WebVideoFullscreenInterfaceContext::setCanPlayFastReverse):
(WebKit::WebVideoFullscreenInterfaceContext::setAudioMediaSelectionOptions):
(WebKit::WebVideoFullscreenInterfaceContext::setLegibleMediaSelectionOptions):
(WebKit::WebVideoFullscreenInterfaceContext::setExternalPlayback):

Cross-process methods which now take a contextId parameter:

* UIProcess/ios/WebVideoFullscreenManagerProxy.messages.in:
* UIProcess/ios/WebVideoFullscreenManagerProxy.mm:
(WebKit::WebVideoFullscreenManagerProxy::setupFullscreenWithID):
(WebKit::WebVideoFullscreenManagerProxy::resetMediaState):
(WebKit::WebVideoFullscreenManagerProxy::setCurrentTime):
(WebKit::WebVideoFullscreenManagerProxy::setBufferedTime):
(WebKit::WebVideoFullscreenManagerProxy::setVideoDimensions):
(WebKit::WebVideoFullscreenManagerProxy::setSeekableRangesVector):
(WebKit::WebVideoFullscreenManagerProxy::setCanPlayFastReverse):
(WebKit::WebVideoFullscreenManagerProxy::setAudioMediaSelectionOptions):
(WebKit::WebVideoFullscreenManagerProxy::setLegibleMediaSelectionOptions):
(WebKit::WebVideoFullscreenManagerProxy::setExternalPlaybackProperties):
(WebKit::WebVideoFullscreenManagerProxy::setDuration):
(WebKit::WebVideoFullscreenManagerProxy::setRate):
(WebKit::WebVideoFullscreenManagerProxy::exitFullscreen):
(WebKit::WebVideoFullscreenManagerProxy::cleanupFullscreen):
(WebKit::WebVideoFullscreenManagerProxy::preparedToReturnToInline):
(WebKit::WebVideoFullscreenManagerProxy::play):
(WebKit::WebVideoFullscreenManagerProxy::pause):
(WebKit::WebVideoFullscreenManagerProxy::togglePlayState):
(WebKit::WebVideoFullscreenManagerProxy::beginScrubbing):
(WebKit::WebVideoFullscreenManagerProxy::endScrubbing):
(WebKit::WebVideoFullscreenManagerProxy::seekToTime):
(WebKit::WebVideoFullscreenManagerProxy::fastSeek):
(WebKit::WebVideoFullscreenManagerProxy::beginScanningForward):
(WebKit::WebVideoFullscreenManagerProxy::beginScanningBackward):
(WebKit::WebVideoFullscreenManagerProxy::endScanning):
(WebKit::WebVideoFullscreenManagerProxy::requestExitFullscreen):
(WebKit::WebVideoFullscreenManagerProxy::didSetupFullscreen):
(WebKit::WebVideoFullscreenManagerProxy::didExitFullscreen):
(WebKit::WebVideoFullscreenManagerProxy::didEnterFullscreen):
(WebKit::WebVideoFullscreenManagerProxy::didCleanupFullscreen):
(WebKit::WebVideoFullscreenManagerProxy::setVideoLayerFrame):
(WebKit::WebVideoFullscreenManagerProxy::setVideoLayerGravity):
(WebKit::WebVideoFullscreenManagerProxy::selectAudioMediaOption):
(WebKit::WebVideoFullscreenManagerProxy::selectLegibleMediaOption):
(WebKit::WebVideoFullscreenManagerProxy::fullscreenModeChanged):
(WebKit::WebVideoFullscreenManagerProxy::fullscreenMayReturnToInline):
(WebKit::WebVideoFullscreenManagerProxy::videoLayerFrame): Deleted.
(WebKit::WebVideoFullscreenManagerProxy::videoLayerGravity): Deleted.
* WebProcess/ios/WebVideoFullscreenManager.messages.in:
* WebProcess/ios/WebVideoFullscreenManager.mm:
(WebKit::WebVideoFullscreenManager::enterVideoFullscreenForVideoElement):
(WebKit::WebVideoFullscreenManager::exitVideoFullscreenForVideoElement):
(WebKit::WebVideoFullscreenManager::resetMediaState):
(WebKit::WebVideoFullscreenManager::setDuration):
(WebKit::WebVideoFullscreenManager::setCurrentTime):
(WebKit::WebVideoFullscreenManager::setBufferedTime):
(WebKit::WebVideoFullscreenManager::setRate):
(WebKit::WebVideoFullscreenManager::setVideoDimensions):
(WebKit::WebVideoFullscreenManager::setSeekableRanges):
(WebKit::WebVideoFullscreenManager::setCanPlayFastReverse):
(WebKit::WebVideoFullscreenManager::setAudioMediaSelectionOptions):
(WebKit::WebVideoFullscreenManager::setLegibleMediaSelectionOptions):
(WebKit::WebVideoFullscreenManager::setExternalPlayback):
(WebKit::WebVideoFullscreenManager::play):
(WebKit::WebVideoFullscreenManager::pause):
(WebKit::WebVideoFullscreenManager::togglePlayState):
(WebKit::WebVideoFullscreenManager::beginScrubbing):
(WebKit::WebVideoFullscreenManager::endScrubbing):
(WebKit::WebVideoFullscreenManager::seekToTime):
(WebKit::WebVideoFullscreenManager::fastSeek):
(WebKit::WebVideoFullscreenManager::beginScanningForward):
(WebKit::WebVideoFullscreenManager::beginScanningBackward):
(WebKit::WebVideoFullscreenManager::endScanning):
(WebKit::WebVideoFullscreenManager::requestExitFullscreen):
(WebKit::WebVideoFullscreenManager::selectAudioMediaOption):
(WebKit::WebVideoFullscreenManager::selectLegibleMediaOption):
(WebKit::WebVideoFullscreenManager::fullscreenModeChanged):
(WebKit::WebVideoFullscreenManager::didSetupFullscreen):
(WebKit::WebVideoFullscreenManager::didEnterFullscreen):
(WebKit::WebVideoFullscreenManager::didExitFullscreen):
(WebKit::WebVideoFullscreenManager::didCleanupFullscreen):
(WebKit::WebVideoFullscreenManager::setVideoLayerGravityEnum):
(WebKit::WebVideoFullscreenManager::fullscreenMayReturnToInline):
(WebKit::WebVideoFullscreenManager::setVideoLayerFrameFenced):
(WebKit::WebVideoFullscreenManager::exitVideoFullscreen): Deleted.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLMediaElementh">trunk/Source/WebCore/html/HTMLMediaElement.h</a></li>
<li><a href="#trunkSourceWebCoreplatformiosWebVideoFullscreenControllerAVKitmm">trunk/Source/WebCore/platform/ios/WebVideoFullscreenControllerAVKit.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformiosWebVideoFullscreenInterfaceAVKith">trunk/Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.h</a></li>
<li><a href="#trunkSourceWebCoreplatformiosWebVideoFullscreenInterfaceAVKitmm">trunk/Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformiosWebVideoFullscreenModelVideoElementh">trunk/Source/WebCore/platform/ios/WebVideoFullscreenModelVideoElement.h</a></li>
<li><a href="#trunkSourceWebCoreplatformiosWebVideoFullscreenModelVideoElementmm">trunk/Source/WebCore/platform/ios/WebVideoFullscreenModelVideoElement.mm</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoaWKWebViewmm">trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosWebVideoFullscreenManagerProxyh">trunk/Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosWebVideoFullscreenManagerProxymessagesin">trunk/Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.messages.in</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosWebVideoFullscreenManagerProxymm">trunk/Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.mm</a></li>
<li><a href="#trunkSourceWebKit2WebProcessiosWebVideoFullscreenManagerh">trunk/Source/WebKit2/WebProcess/ios/WebVideoFullscreenManager.h</a></li>
<li><a href="#trunkSourceWebKit2WebProcessiosWebVideoFullscreenManagermessagesin">trunk/Source/WebKit2/WebProcess/ios/WebVideoFullscreenManager.messages.in</a></li>
<li><a href="#trunkSourceWebKit2WebProcessiosWebVideoFullscreenManagermm">trunk/Source/WebKit2/WebProcess/ios/WebVideoFullscreenManager.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (182913 => 182914)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-04-16 22:29:10 UTC (rev 182913)
+++ trunk/Source/WebCore/ChangeLog        2015-04-16 22:42:58 UTC (rev 182914)
</span><span class="lines">@@ -1,3 +1,25 @@
</span><ins>+2015-04-13  Jer Noble  &lt;jer.noble@apple.com&gt;
+
+        [iOS] When simultaneously exiting-and-entering fullscreen, WebVideoFullscreenManager/Proxy becomes confused about what video element it represents.
+        https://bugs.webkit.org/show_bug.cgi?id=143680
+
+        Reviewed by Simon Fraser.
+
+        Add getters for the video's fullscreen layer, and be more tolerant about the order in which setVideoElement() and 
+        setWebVideoFullscreenInterface are called.
+
+        * html/HTMLMediaElement.h:
+        (WebCore::HTMLMediaElement::videoFullscreenLayer): Added simple getter.
+        * platform/ios/WebVideoFullscreenInterfaceAVKit.h:
+        * platform/ios/WebVideoFullscreenModelVideoElement.h:
+        (WebCore::WebVideoFullscreenModelVideoElement::videoElement): Added simple getter.
+        (WebCore::WebVideoFullscreenModelVideoElement::setWebVideoFullscreenInterface): Deleted. Moved to .mm file.
+        * platform/ios/WebVideoFullscreenModelVideoElement.mm:
+        (WebVideoFullscreenModelVideoElement::WebVideoFullscreenModelVideoElement): Initialize ivars in the .h file.
+        (WebVideoFullscreenModelVideoElement::setWebVideoFullscreenInterface): Call those methods skipped in setVideoElement()
+            if m_videoFullscreenInterface had not yet been set.
+        (WebVideoFullscreenModelVideoElement::setVideoElement): Null-check m_videoFullscreenInterface.
+
</ins><span class="cx"> 2015-04-16  Beth Dakin  &lt;bdakin@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Force mouse events should go through normal mouse event handling code paths
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLMediaElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (182913 => 182914)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLMediaElement.h        2015-04-16 22:29:10 UTC (rev 182913)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h        2015-04-16 22:42:58 UTC (rev 182914)
</span><span class="lines">@@ -128,6 +128,7 @@
</span><span class="cx">     PlatformLayer* platformLayer() const;
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">     void setVideoFullscreenLayer(PlatformLayer*);
</span><ins>+    PlatformLayer* videoFullscreenLayer() const { return m_videoFullscreenLayer.get(); }
</ins><span class="cx">     void setVideoFullscreenFrame(FloatRect);
</span><span class="cx">     void setVideoFullscreenGravity(MediaPlayer::VideoGravity);
</span><span class="cx">     MediaPlayer::VideoGravity videoFullscreenGravity() const { return m_videoFullscreenGravity; }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformiosWebVideoFullscreenControllerAVKitmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/ios/WebVideoFullscreenControllerAVKit.mm (182913 => 182914)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/ios/WebVideoFullscreenControllerAVKit.mm        2015-04-16 22:29:10 UTC (rev 182913)
+++ trunk/Source/WebCore/platform/ios/WebVideoFullscreenControllerAVKit.mm        2015-04-16 22:42:58 UTC (rev 182914)
</span><span class="lines">@@ -125,9 +125,9 @@
</span><span class="cx"> {
</span><span class="cx">     [self retain]; // Balanced by -release in didExitFullscreen:
</span><span class="cx">     
</span><del>-    _interface = adoptRef(new WebVideoFullscreenInterfaceAVKit);
</del><ins>+    _interface = WebVideoFullscreenInterfaceAVKit::create();
</ins><span class="cx">     _interface-&gt;setWebVideoFullscreenChangeObserver(&amp;_changeObserver);
</span><del>-    _model = adoptRef(new WebVideoFullscreenModelVideoElement);
</del><ins>+    _model = WebVideoFullscreenModelVideoElement::create();
</ins><span class="cx">     _model-&gt;setWebVideoFullscreenInterface(_interface.get());
</span><span class="cx">     _interface-&gt;setWebVideoFullscreenModel(_model.get());
</span><span class="cx">     _model-&gt;setVideoElement(_videoElement.get());
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformiosWebVideoFullscreenInterfaceAVKith"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.h (182913 => 182914)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.h        2015-04-16 22:29:10 UTC (rev 182913)
+++ trunk/Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.h        2015-04-16 22:42:58 UTC (rev 182914)
</span><span class="lines">@@ -68,7 +68,10 @@
</span><span class="cx">     , public ThreadSafeRefCounted&lt;WebVideoFullscreenInterfaceAVKit&gt; {
</span><span class="cx"> 
</span><span class="cx"> public:
</span><del>-    WEBCORE_EXPORT WebVideoFullscreenInterfaceAVKit();
</del><ins>+    static Ref&lt;WebVideoFullscreenInterfaceAVKit&gt; create()
+    {
+        return adoptRef(*new WebVideoFullscreenInterfaceAVKit());
+    }
</ins><span class="cx">     virtual ~WebVideoFullscreenInterfaceAVKit() { }
</span><span class="cx">     WEBCORE_EXPORT void setWebVideoFullscreenModel(WebVideoFullscreenModel*);
</span><span class="cx">     WEBCORE_EXPORT void setWebVideoFullscreenChangeObserver(WebVideoFullscreenChangeObserver*);
</span><span class="lines">@@ -95,7 +98,7 @@
</span><span class="cx"> 
</span><span class="cx">     HTMLMediaElement::VideoFullscreenMode mode() const { return m_mode; }
</span><span class="cx">     void setIsOptimized(bool);
</span><del>-    WEBCORE_EXPORT bool mayAutomaticallyShowVideoOptimized();
</del><ins>+    WEBCORE_EXPORT bool mayAutomaticallyShowVideoOptimized() const;
</ins><span class="cx">     void fullscreenMayReturnToInline(std::function&lt;void(bool)&gt; callback);
</span><span class="cx"> 
</span><span class="cx">     void willStartOptimizedFullscreen();
</span><span class="lines">@@ -106,7 +109,13 @@
</span><span class="cx">     void didCancelOptimizedFullscreen();
</span><span class="cx">     void prepareForOptimizedFullscreenStopWithCompletionHandler(void (^)(BOOL));
</span><span class="cx"> 
</span><ins>+    void setMode(HTMLMediaElement::VideoFullscreenMode);
+    void clearMode(HTMLMediaElement::VideoFullscreenMode);
+    bool hasMode(HTMLMediaElement::VideoFullscreenMode mode) const { return m_mode &amp; mode; }
+    bool isMode(HTMLMediaElement::VideoFullscreenMode mode) const { return m_mode == mode; }
+
</ins><span class="cx"> protected:
</span><ins>+    WEBCORE_EXPORT WebVideoFullscreenInterfaceAVKit();
</ins><span class="cx">     void beginSession();
</span><span class="cx">     void setupFullscreenInternal(PlatformLayer&amp;, const IntRect&amp; initialRect, UIView *, HTMLMediaElement::VideoFullscreenMode, bool allowOptimizedFullscreen);
</span><span class="cx">     void enterFullscreenOptimized();
</span><span class="lines">@@ -114,11 +123,6 @@
</span><span class="cx">     void exitFullscreenInternal(const IntRect&amp; finalRect);
</span><span class="cx">     void cleanupFullscreenInternal();
</span><span class="cx"> 
</span><del>-    void setMode(HTMLMediaElement::VideoFullscreenMode);
-    void clearMode(HTMLMediaElement::VideoFullscreenMode);
-    bool hasMode(HTMLMediaElement::VideoFullscreenMode mode) const { return m_mode &amp; mode; }
-    bool isMode(HTMLMediaElement::VideoFullscreenMode mode) const { return m_mode == mode; }
-
</del><span class="cx">     RetainPtr&lt;WebAVPlayerController&gt; m_playerController;
</span><span class="cx">     RetainPtr&lt;AVPlayerViewController&gt; m_playerViewController;
</span><span class="cx">     RetainPtr&lt;CALayer&gt; m_videoLayer;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformiosWebVideoFullscreenInterfaceAVKitmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.mm (182913 => 182914)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.mm        2015-04-16 22:29:10 UTC (rev 182913)
+++ trunk/Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.mm        2015-04-16 22:42:58 UTC (rev 182914)
</span><span class="lines">@@ -1175,7 +1175,7 @@
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool WebVideoFullscreenInterfaceAVKit::mayAutomaticallyShowVideoOptimized()
</del><ins>+bool WebVideoFullscreenInterfaceAVKit::mayAutomaticallyShowVideoOptimized() const
</ins><span class="cx"> {
</span><span class="cx">     return [m_playerController isPlaying] &amp;&amp; m_mode == HTMLMediaElement::VideoFullscreenModeStandard &amp;&amp; wkIsOptimizedFullscreenSupported();
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformiosWebVideoFullscreenModelVideoElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/ios/WebVideoFullscreenModelVideoElement.h (182913 => 182914)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/ios/WebVideoFullscreenModelVideoElement.h        2015-04-16 22:29:10 UTC (rev 182913)
+++ trunk/Source/WebCore/platform/ios/WebVideoFullscreenModelVideoElement.h        2015-04-16 22:42:58 UTC (rev 182914)
</span><span class="lines">@@ -45,10 +45,13 @@
</span><span class="cx"> 
</span><span class="cx"> class WebVideoFullscreenModelVideoElement : public WebVideoFullscreenModel, public EventListener {
</span><span class="cx"> public:
</span><del>-    WEBCORE_EXPORT WebVideoFullscreenModelVideoElement();
</del><ins>+    static RefPtr&lt;WebVideoFullscreenModelVideoElement&gt; create() {
+        return adoptRef(*new WebVideoFullscreenModelVideoElement());
+    }
</ins><span class="cx">     WEBCORE_EXPORT virtual ~WebVideoFullscreenModelVideoElement();
</span><del>-    void setWebVideoFullscreenInterface(WebVideoFullscreenInterface* interface) {m_videoFullscreenInterface = interface;}
</del><ins>+    WEBCORE_EXPORT void setWebVideoFullscreenInterface(WebVideoFullscreenInterface*);
</ins><span class="cx">     WEBCORE_EXPORT void setVideoElement(HTMLVideoElement*);
</span><ins>+    WEBCORE_EXPORT HTMLVideoElement* videoElement() const { return m_videoElement.get(); }
</ins><span class="cx">     WEBCORE_EXPORT void setVideoFullscreenLayer(PlatformLayer*);
</span><span class="cx">     
</span><span class="cx">     WEBCORE_EXPORT virtual void handleEvent(WebCore::ScriptExecutionContext*, WebCore::Event*) override;
</span><span class="lines">@@ -75,14 +78,17 @@
</span><span class="cx">     WEBCORE_EXPORT virtual void selectLegibleMediaOption(uint64_t index) override;
</span><span class="cx">     WEBCORE_EXPORT virtual void fullscreenModeChanged(HTMLMediaElement::VideoFullscreenMode) override;
</span><span class="cx"> 
</span><ins>+protected:
+    WEBCORE_EXPORT WebVideoFullscreenModelVideoElement();
+
</ins><span class="cx"> private:
</span><span class="cx">     static const Vector&lt;WTF::AtomicString&gt;&amp; observedEventNames();
</span><span class="cx">     const WTF::AtomicString&amp; eventNameAll();
</span><span class="cx">     
</span><span class="cx">     RefPtr&lt;HTMLVideoElement&gt; m_videoElement;
</span><span class="cx">     RetainPtr&lt;PlatformLayer&gt; m_videoFullscreenLayer;
</span><del>-    bool m_isListening;
-    WebVideoFullscreenInterface* m_videoFullscreenInterface;
</del><ins>+    bool m_isListening { false };
+    WebVideoFullscreenInterface* m_videoFullscreenInterface { nullptr };
</ins><span class="cx">     FloatRect m_videoFrame;
</span><span class="cx">     Vector&lt;RefPtr&lt;TextTrack&gt;&gt; m_legibleTracksForMenu;
</span><span class="cx">     Vector&lt;RefPtr&lt;AudioTrack&gt;&gt; m_audioTracksForMenu;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformiosWebVideoFullscreenModelVideoElementmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/ios/WebVideoFullscreenModelVideoElement.mm (182913 => 182914)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/ios/WebVideoFullscreenModelVideoElement.mm        2015-04-16 22:29:10 UTC (rev 182913)
+++ trunk/Source/WebCore/platform/ios/WebVideoFullscreenModelVideoElement.mm        2015-04-16 22:42:58 UTC (rev 182914)
</span><span class="lines">@@ -53,8 +53,6 @@
</span><span class="cx"> 
</span><span class="cx"> WebVideoFullscreenModelVideoElement::WebVideoFullscreenModelVideoElement()
</span><span class="cx">     : EventListener(EventListener::CPPEventListenerType)
</span><del>-    , m_isListening(false)
-    , m_videoFullscreenInterface(nullptr)
</del><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -62,6 +60,20 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebVideoFullscreenModelVideoElement::setWebVideoFullscreenInterface(WebVideoFullscreenInterface* interface)
+{
+    if (interface == m_videoFullscreenInterface)
+        return;
+
+    m_videoFullscreenInterface = interface;
+
+    if (m_videoFullscreenInterface) {
+        m_videoFullscreenInterface-&gt;resetMediaState();
+        if (m_videoElement)
+            m_videoFullscreenInterface-&gt;setVideoDimensions(true, m_videoElement-&gt;videoWidth(), m_videoElement-&gt;videoHeight());
+    }
+}
+
</ins><span class="cx"> void WebVideoFullscreenModelVideoElement::setVideoElement(HTMLVideoElement* videoElement)
</span><span class="cx"> {
</span><span class="cx">     if (m_videoElement == videoElement)
</span><span class="lines">@@ -69,7 +81,13 @@
</span><span class="cx"> 
</span><span class="cx">     if (m_videoFullscreenInterface)
</span><span class="cx">         m_videoFullscreenInterface-&gt;resetMediaState();
</span><del>-    
</del><ins>+
+    if (m_videoElement &amp;&amp; m_videoElement-&gt;fullscreenMode())
+        m_videoElement-&gt;fullscreenModeChanged(HTMLMediaElement::VideoFullscreenModeNone);
+
+    if (m_videoElement &amp;&amp; m_videoElement-&gt;videoFullscreenLayer())
+        m_videoElement-&gt;setVideoFullscreenLayer(nullptr);
+
</ins><span class="cx">     if (m_videoElement &amp;&amp; m_isListening) {
</span><span class="cx">         for (auto eventName : observedEventNames())
</span><span class="cx">             m_videoElement-&gt;removeEventListener(eventName, this, false);
</span><span class="lines">@@ -87,7 +105,8 @@
</span><span class="cx"> 
</span><span class="cx">     updateForEventName(eventNameAll());
</span><span class="cx"> 
</span><del>-    m_videoFullscreenInterface-&gt;setVideoDimensions(true, videoElement-&gt;videoWidth(), videoElement-&gt;videoHeight());
</del><ins>+    if (m_videoFullscreenInterface)
+        m_videoFullscreenInterface-&gt;setVideoDimensions(true, videoElement-&gt;videoWidth(), videoElement-&gt;videoHeight());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebVideoFullscreenModelVideoElement::handleEvent(WebCore::ScriptExecutionContext*, WebCore::Event* event)
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (182913 => 182914)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2015-04-16 22:29:10 UTC (rev 182913)
+++ trunk/Source/WebKit2/ChangeLog        2015-04-16 22:42:58 UTC (rev 182914)
</span><span class="lines">@@ -1,3 +1,198 @@
</span><ins>+2015-04-13  Jer Noble  &lt;jer.noble@apple.com&gt;
+
+        [iOS] When simultaneously exiting-and-entering fullscreen, WebVideoFullscreenManager/Proxy becomes confused about what video element it represents.
+        https://bugs.webkit.org/show_bug.cgi?id=143680
+
+        Reviewed by Simon Fraser.
+
+        The original assumption of WebVideoFullscreenManager and -Proxy was that the two classes would represent a
+        single video element and its full screen state. With multiple animations in and out of fullscreen combined with
+        multiple fullscreen modes, this assumption no longer holds true.
+
+        Rather than having a WebVideoFullscreenManager which /isa/ WebVideoFullscreenModelVideoElement, the manager now
+        /hasa/ WebVideoFullscreenModelVideoElement (or has many such models). Ditto for WebVideoFullscreenManager and
+        WebVideoFullscreenInterfaceAVKit. The WebVideoFullscreenInterfaceAVKit still needs a WebVideoFullscreenModel to
+        communicate with, so a new wrapper class is used for that purpose, WebVideoFullscreenModelContext. Ditto for
+        WebVideoFullscreenModelVideoElement and the new class WebVideoFullscreenInterfaceContext. These context classes
+        are paired and share a contextId, allowing the manager and its proxy to route messages between the UIProcess's
+        WebVideoFullscreenInterfaceAVKit to-and-from the WebProcess's WebVideoFullscreenModelVideoElement.
+
+        Both the WebVideoFullscreenModelContext and the WebVideoFullscreenInterfaceContext take a back-pointer to their
+        manager or manager proxy, and each method on the context simply calls the matching method on the manager and
+        passes its contextId as a parameter.
+
+        Both the WebVideoFullscreenManager and the WebVideoFullscreenManagerProxy pass that contextId in each of their
+        cross-process messages.
+
+        On the other side, the manager and proxy also have a map between contextIds and their matching
+        WebVideoFullscreenModelVideoElement (in the case of WebVideoFullscreenManager) or
+        WebVideoFullscreenInterfaceAVKit (in the case of WebVideoFullscreenManagerProxy).
+
+        While this change is large by LoC, it is almost entirely boilerplate.  The new and interesting pieces are these:
+
+        * UIProcess/ios/WebVideoFullscreenManagerProxy.mm:
+        (WebKit::WebVideoFullscreenManagerProxy::WebVideoFullscreenManagerProxy): No longer a WebVideoFullscreenInterfaceAVKit.
+        (WebKit::WebVideoFullscreenManagerProxy::invalidate): Walk through the models and interfaces, invalidating each.
+        (WebKit::WebVideoFullscreenManagerProxy::createModelAndInterface): Added. Return a new model and interface tuple.
+        (WebKit::WebVideoFullscreenManagerProxy::ensureModelAndInterface): Added. Lazily create, and add to the m_contextMap
+            a new model and interface object.
+        (WebKit::WebVideoFullscreenManagerProxy::ensureModel): Return the model half of ensureModelAndInterface().
+        (WebKit::WebVideoFullscreenManagerProxy::ensureInterface): Return the interface half of ensureModelAndInterface().
+        (WebKit::WebVideoFullscreenManagerProxy::enterFullscreen): Walk through the outstanding interface objects, and if 
+            any have a fullscreen mode which matches the about-to-be-fullscreen interface, request that that other interface
+            exit fullscreen.
+        * WebProcess/ios/WebVideoFullscreenManager.mm:
+        (WebKit::nextContextId): Static, incrementing counter used as a contextId source.
+        (WebKit::WebVideoFullscreenManager::WebVideoFullscreenManager): No longer a WebVideoFullscreenModelVideoElement.
+        (WebKit::WebVideoFullscreenManager::~WebVideoFullscreenManager): Walk through the models and interfaces, invalidating each.
+        (WebKit::WebVideoFullscreenManager::ensureModelAndInterface): Added. Return a new model and interface tuple.
+        (WebKit::WebVideoFullscreenManager::ensureModelAndInterface):  Added. Lazily create, and add to the m_contextMap
+            a new model and interface object.
+        (WebKit::WebVideoFullscreenManager::ensureModel): Return the model half of ensureModelAndInterface().
+        (WebKit::WebVideoFullscreenManager::ensureInterface): Return the interface half of ensureModelAndInterface().
+
+        New classes and methods which just forward on to their owning objects:
+
+        * UIProcess/ios/WebVideoFullscreenManagerProxy.h:
+        (WebKit::WebVideoFullscreenModelContext::create):
+        (WebKit::WebVideoFullscreenModelContext::~WebVideoFullscreenModelContext):
+        (WebKit::WebVideoFullscreenModelContext::invalidate):
+        (WebKit::WebVideoFullscreenModelContext::layerHost):
+        (WebKit::WebVideoFullscreenModelContext::setLayerHost):
+        (WebKit::WebVideoFullscreenModelContext::setInitialVideoLayerFrame):
+        (WebKit::WebVideoFullscreenModelContext::WebVideoFullscreenModelContext):
+        * UIProcess/ios/WebVideoFullscreenManagerProxy.mm:
+        (WebKit::WebVideoFullscreenModelContext::play):
+        (WebKit::WebVideoFullscreenModelContext::pause):
+        (WebKit::WebVideoFullscreenModelContext::togglePlayState):
+        (WebKit::WebVideoFullscreenModelContext::beginScrubbing):
+        (WebKit::WebVideoFullscreenModelContext::endScrubbing):
+        (WebKit::WebVideoFullscreenModelContext::seekToTime):
+        (WebKit::WebVideoFullscreenModelContext::fastSeek):
+        (WebKit::WebVideoFullscreenModelContext::beginScanningForward):
+        (WebKit::WebVideoFullscreenModelContext::beginScanningBackward):
+        (WebKit::WebVideoFullscreenModelContext::endScanning):
+        (WebKit::WebVideoFullscreenModelContext::requestExitFullscreen):
+        (WebKit::WebVideoFullscreenModelContext::setVideoLayerFrame):
+        (WebKit::WebVideoFullscreenModelContext::videoLayerFrame):
+        (WebKit::WebVideoFullscreenModelContext::setVideoLayerGravity):
+        (WebKit::WebVideoFullscreenModelContext::videoLayerGravity):
+        (WebKit::WebVideoFullscreenModelContext::selectAudioMediaOption):
+        (WebKit::WebVideoFullscreenModelContext::selectLegibleMediaOption):
+        (WebKit::WebVideoFullscreenModelContext::fullscreenModeChanged):
+        (WebKit::WebVideoFullscreenModelContext::didSetupFullscreen):
+        (WebKit::WebVideoFullscreenModelContext::didEnterFullscreen):
+        (WebKit::WebVideoFullscreenModelContext::didExitFullscreen):
+        (WebKit::WebVideoFullscreenModelContext::didCleanupFullscreen):
+        (WebKit::WebVideoFullscreenModelContext::fullscreenMayReturnToInline):
+        * WebProcess/ios/WebVideoFullscreenManager.h:
+        (WebKit::WebVideoFullscreenInterfaceContext::create):
+        (WebKit::WebVideoFullscreenInterfaceContext::invalidate):
+        (WebKit::WebVideoFullscreenInterfaceContext::layerHostingContext):
+        (WebKit::WebVideoFullscreenInterfaceContext::isAnimating):
+        (WebKit::WebVideoFullscreenInterfaceContext::setIsAnimating):
+        (WebKit::WebVideoFullscreenInterfaceContext::targetIsFullscreen):
+        (WebKit::WebVideoFullscreenInterfaceContext::setTargetIsFullscreen):
+        (WebKit::WebVideoFullscreenInterfaceContext::fullscreenMode):
+        (WebKit::WebVideoFullscreenInterfaceContext::setFullscreenMode):
+        (WebKit::WebVideoFullscreenInterfaceContext::isFullscreen):
+        (WebKit::WebVideoFullscreenInterfaceContext::setIsFullscreen):
+        * WebProcess/ios/WebVideoFullscreenManager.mm:
+        (WebKit::WebVideoFullscreenInterfaceContext::WebVideoFullscreenInterfaceContext):
+        (WebKit::WebVideoFullscreenInterfaceContext::~WebVideoFullscreenInterfaceContext):
+        (WebKit::WebVideoFullscreenInterfaceContext::setLayerHostingContext):
+        (WebKit::WebVideoFullscreenInterfaceContext::resetMediaState):
+        (WebKit::WebVideoFullscreenInterfaceContext::setDuration):
+        (WebKit::WebVideoFullscreenInterfaceContext::setCurrentTime):
+        (WebKit::WebVideoFullscreenInterfaceContext::setBufferedTime):
+        (WebKit::WebVideoFullscreenInterfaceContext::setRate):
+        (WebKit::WebVideoFullscreenInterfaceContext::setVideoDimensions):
+        (WebKit::WebVideoFullscreenInterfaceContext::setSeekableRanges):
+        (WebKit::WebVideoFullscreenInterfaceContext::setCanPlayFastReverse):
+        (WebKit::WebVideoFullscreenInterfaceContext::setAudioMediaSelectionOptions):
+        (WebKit::WebVideoFullscreenInterfaceContext::setLegibleMediaSelectionOptions):
+        (WebKit::WebVideoFullscreenInterfaceContext::setExternalPlayback):
+
+        Cross-process methods which now take a contextId parameter:
+
+        * UIProcess/ios/WebVideoFullscreenManagerProxy.messages.in:
+        * UIProcess/ios/WebVideoFullscreenManagerProxy.mm:
+        (WebKit::WebVideoFullscreenManagerProxy::setupFullscreenWithID):
+        (WebKit::WebVideoFullscreenManagerProxy::resetMediaState):
+        (WebKit::WebVideoFullscreenManagerProxy::setCurrentTime):
+        (WebKit::WebVideoFullscreenManagerProxy::setBufferedTime):
+        (WebKit::WebVideoFullscreenManagerProxy::setVideoDimensions):
+        (WebKit::WebVideoFullscreenManagerProxy::setSeekableRangesVector):
+        (WebKit::WebVideoFullscreenManagerProxy::setCanPlayFastReverse):
+        (WebKit::WebVideoFullscreenManagerProxy::setAudioMediaSelectionOptions):
+        (WebKit::WebVideoFullscreenManagerProxy::setLegibleMediaSelectionOptions):
+        (WebKit::WebVideoFullscreenManagerProxy::setExternalPlaybackProperties):
+        (WebKit::WebVideoFullscreenManagerProxy::setDuration):
+        (WebKit::WebVideoFullscreenManagerProxy::setRate):
+        (WebKit::WebVideoFullscreenManagerProxy::exitFullscreen):
+        (WebKit::WebVideoFullscreenManagerProxy::cleanupFullscreen):
+        (WebKit::WebVideoFullscreenManagerProxy::preparedToReturnToInline):
+        (WebKit::WebVideoFullscreenManagerProxy::play):
+        (WebKit::WebVideoFullscreenManagerProxy::pause):
+        (WebKit::WebVideoFullscreenManagerProxy::togglePlayState):
+        (WebKit::WebVideoFullscreenManagerProxy::beginScrubbing):
+        (WebKit::WebVideoFullscreenManagerProxy::endScrubbing):
+        (WebKit::WebVideoFullscreenManagerProxy::seekToTime):
+        (WebKit::WebVideoFullscreenManagerProxy::fastSeek):
+        (WebKit::WebVideoFullscreenManagerProxy::beginScanningForward):
+        (WebKit::WebVideoFullscreenManagerProxy::beginScanningBackward):
+        (WebKit::WebVideoFullscreenManagerProxy::endScanning):
+        (WebKit::WebVideoFullscreenManagerProxy::requestExitFullscreen):
+        (WebKit::WebVideoFullscreenManagerProxy::didSetupFullscreen):
+        (WebKit::WebVideoFullscreenManagerProxy::didExitFullscreen):
+        (WebKit::WebVideoFullscreenManagerProxy::didEnterFullscreen):
+        (WebKit::WebVideoFullscreenManagerProxy::didCleanupFullscreen):
+        (WebKit::WebVideoFullscreenManagerProxy::setVideoLayerFrame):
+        (WebKit::WebVideoFullscreenManagerProxy::setVideoLayerGravity):
+        (WebKit::WebVideoFullscreenManagerProxy::selectAudioMediaOption):
+        (WebKit::WebVideoFullscreenManagerProxy::selectLegibleMediaOption):
+        (WebKit::WebVideoFullscreenManagerProxy::fullscreenModeChanged):
+        (WebKit::WebVideoFullscreenManagerProxy::fullscreenMayReturnToInline):
+        (WebKit::WebVideoFullscreenManagerProxy::videoLayerFrame): Deleted.
+        (WebKit::WebVideoFullscreenManagerProxy::videoLayerGravity): Deleted.
+        * WebProcess/ios/WebVideoFullscreenManager.messages.in:
+        * WebProcess/ios/WebVideoFullscreenManager.mm:
+        (WebKit::WebVideoFullscreenManager::enterVideoFullscreenForVideoElement):
+        (WebKit::WebVideoFullscreenManager::exitVideoFullscreenForVideoElement):
+        (WebKit::WebVideoFullscreenManager::resetMediaState):
+        (WebKit::WebVideoFullscreenManager::setDuration):
+        (WebKit::WebVideoFullscreenManager::setCurrentTime):
+        (WebKit::WebVideoFullscreenManager::setBufferedTime):
+        (WebKit::WebVideoFullscreenManager::setRate):
+        (WebKit::WebVideoFullscreenManager::setVideoDimensions):
+        (WebKit::WebVideoFullscreenManager::setSeekableRanges):
+        (WebKit::WebVideoFullscreenManager::setCanPlayFastReverse):
+        (WebKit::WebVideoFullscreenManager::setAudioMediaSelectionOptions):
+        (WebKit::WebVideoFullscreenManager::setLegibleMediaSelectionOptions):
+        (WebKit::WebVideoFullscreenManager::setExternalPlayback):
+        (WebKit::WebVideoFullscreenManager::play):
+        (WebKit::WebVideoFullscreenManager::pause):
+        (WebKit::WebVideoFullscreenManager::togglePlayState):
+        (WebKit::WebVideoFullscreenManager::beginScrubbing):
+        (WebKit::WebVideoFullscreenManager::endScrubbing):
+        (WebKit::WebVideoFullscreenManager::seekToTime):
+        (WebKit::WebVideoFullscreenManager::fastSeek):
+        (WebKit::WebVideoFullscreenManager::beginScanningForward):
+        (WebKit::WebVideoFullscreenManager::beginScanningBackward):
+        (WebKit::WebVideoFullscreenManager::endScanning):
+        (WebKit::WebVideoFullscreenManager::requestExitFullscreen):
+        (WebKit::WebVideoFullscreenManager::selectAudioMediaOption):
+        (WebKit::WebVideoFullscreenManager::selectLegibleMediaOption):
+        (WebKit::WebVideoFullscreenManager::fullscreenModeChanged):
+        (WebKit::WebVideoFullscreenManager::didSetupFullscreen):
+        (WebKit::WebVideoFullscreenManager::didEnterFullscreen):
+        (WebKit::WebVideoFullscreenManager::didExitFullscreen):
+        (WebKit::WebVideoFullscreenManager::didCleanupFullscreen):
+        (WebKit::WebVideoFullscreenManager::setVideoLayerGravityEnum):
+        (WebKit::WebVideoFullscreenManager::fullscreenMayReturnToInline):
+        (WebKit::WebVideoFullscreenManager::setVideoLayerFrameFenced):
+        (WebKit::WebVideoFullscreenManager::exitVideoFullscreen): Deleted.
+
</ins><span class="cx"> 2015-04-16  Beth Dakin  &lt;bdakin@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Force mouse events should go through normal mouse event handling code paths
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoaWKWebViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm (182913 => 182914)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm        2015-04-16 22:29:10 UTC (rev 182913)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm        2015-04-16 22:42:58 UTC (rev 182914)
</span><span class="lines">@@ -242,7 +242,7 @@
</span><span class="cx">     if (!_page || !_page-&gt;videoFullscreenManager())
</span><span class="cx">         return false;
</span><span class="cx">     
</span><del>-    return _page-&gt;videoFullscreenManager()-&gt;mode() &amp; WebCore::HTMLMediaElement::VideoFullscreenModeOptimized;
</del><ins>+    return _page-&gt;videoFullscreenManager()-&gt;hasMode(WebCore::HTMLMediaElement::VideoFullscreenModeOptimized);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (BOOL)_mayAutomaticallyShowVideoOptimized
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosWebVideoFullscreenManagerProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.h (182913 => 182914)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.h        2015-04-16 22:29:10 UTC (rev 182913)
+++ trunk/Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.h        2015-04-16 22:42:58 UTC (rev 182914)
</span><span class="lines">@@ -41,34 +41,31 @@
</span><span class="cx"> namespace WebKit {
</span><span class="cx"> 
</span><span class="cx"> class WebPageProxy;
</span><ins>+class WebVideoFullscreenManagerProxy;
</ins><span class="cx"> 
</span><del>-class WebVideoFullscreenManagerProxy : public WebCore::WebVideoFullscreenInterfaceAVKit, public WebCore::WebVideoFullscreenChangeObserver, public WebCore::WebVideoFullscreenModel, private IPC::MessageReceiver {
</del><ins>+class WebVideoFullscreenModelContext final: public RefCounted&lt;WebVideoFullscreenModelContext&gt;, public WebCore::WebVideoFullscreenModel, public WebCore::WebVideoFullscreenChangeObserver  {
</ins><span class="cx"> public:
</span><del>-    static PassRefPtr&lt;WebVideoFullscreenManagerProxy&gt; create(WebPageProxy&amp;);
-    virtual ~WebVideoFullscreenManagerProxy();
</del><ins>+    static Ref&lt;WebVideoFullscreenModelContext&gt; create(WebVideoFullscreenManagerProxy&amp; manager, uint64_t contextId)
+    {
+        return adoptRef(*new WebVideoFullscreenModelContext(manager, contextId));
+    }
+    virtual ~WebVideoFullscreenModelContext() { }
</ins><span class="cx"> 
</span><del>-    virtual void invalidate() override;
-    virtual void requestExitFullscreen() override;
</del><ins>+    void invalidate() { m_manager = nullptr; }
</ins><span class="cx"> 
</span><ins>+    PlatformLayer* layerHost() const { return m_layerHost.get(); }
+    void setLayerHost(RetainPtr&lt;PlatformLayer&gt;&amp;&amp; layerHost) { m_layerHost = WTF::move(layerHost); }
+
+    void setInitialVideoLayerFrame(WebCore::FloatRect frame) { m_videoLayerFrame = frame; }
+
</ins><span class="cx"> private:
</span><del>-    explicit WebVideoFullscreenManagerProxy(WebPageProxy&amp;);
-    virtual void didReceiveMessage(IPC::Connection&amp;, IPC::MessageDecoder&amp;) override;
</del><ins>+    WebVideoFullscreenModelContext(WebVideoFullscreenManagerProxy&amp; manager, uint64_t contextId)
+        : m_manager(&amp;manager)
+        , m_contextId(contextId)
+    {
+    }
</ins><span class="cx"> 
</span><del>-    // Translate to FullscreenInterface
-    void setupFullscreenWithID(uint32_t, const WebCore::IntRect&amp; initialRect, float hostingDeviceScaleFactor, WebCore::HTMLMediaElement::VideoFullscreenMode, bool allowOptimizedFullscreen);
-    void setSeekableRangesVector(const Vector&lt;std::pair&lt;double, double&gt;&gt;&amp;);
-    void setExternalPlaybackProperties(bool enabled, uint32_t targetType, String localizedDeviceName);
-    void fullscreenModeChanged(WebCore::HTMLMediaElement::VideoFullscreenMode) override;
-    void preparedToReturnToInline(bool visible, const WebCore::IntRect&amp; inlineRect) override;
-
-    // Fullscreen Observer
-    virtual void didSetupFullscreen() override;
-    virtual void didEnterFullscreen() override;
-    virtual void didExitFullscreen() override;
-    virtual void didCleanupFullscreen() override;
-    virtual void fullscreenMayReturnToInline() override;
-    
-    // FullscreenModel
</del><ins>+    // WebVideoFullscreenModel
</ins><span class="cx">     virtual void play() override;
</span><span class="cx">     virtual void pause() override;
</span><span class="cx">     virtual void togglePlayState() override;
</span><span class="lines">@@ -79,18 +76,97 @@
</span><span class="cx">     virtual void beginScanningForward() override;
</span><span class="cx">     virtual void beginScanningBackward() override;
</span><span class="cx">     virtual void endScanning() override;
</span><ins>+    virtual void requestExitFullscreen() override;
</ins><span class="cx">     virtual void setVideoLayerFrame(WebCore::FloatRect) override;
</span><span class="cx">     virtual WebCore::FloatRect videoLayerFrame() const override;
</span><del>-    virtual void setVideoLayerGravity(WebCore::WebVideoFullscreenModel::VideoGravity) override;
</del><ins>+    virtual void setVideoLayerGravity(VideoGravity) override;
</ins><span class="cx">     virtual VideoGravity videoLayerGravity() const override;
</span><span class="cx">     virtual void selectAudioMediaOption(uint64_t) override;
</span><span class="cx">     virtual void selectLegibleMediaOption(uint64_t) override;
</span><ins>+    virtual void fullscreenModeChanged(WebCore::HTMLMediaElement::VideoFullscreenMode) override;
</ins><span class="cx"> 
</span><del>-    WebPageProxy* m_page;
</del><ins>+    // WebVideoFullscreenChangeObserver
+    virtual void didSetupFullscreen() override;
+    virtual void didEnterFullscreen() override;
+    virtual void didExitFullscreen() override;
+    virtual void didCleanupFullscreen() override;
+    virtual void fullscreenMayReturnToInline() override;
+
+    WebVideoFullscreenManagerProxy* m_manager;
+    uint64_t m_contextId;
</ins><span class="cx">     RetainPtr&lt;PlatformLayer&gt; m_layerHost;
</span><span class="cx">     WebCore::FloatRect m_videoLayerFrame;
</span><span class="cx">     VideoGravity m_videoLayerGravity { VideoGravityResize };
</span><span class="cx"> };
</span><ins>+
+class WebVideoFullscreenManagerProxy : public RefCounted&lt;WebVideoFullscreenManagerProxy&gt;, private IPC::MessageReceiver {
+public:
+    static PassRefPtr&lt;WebVideoFullscreenManagerProxy&gt; create(WebPageProxy&amp;);
+    virtual ~WebVideoFullscreenManagerProxy();
+
+    void invalidate();
+
+    void requestHideAndExitFullscreen();
+    bool hasMode(WebCore::HTMLMediaElement::VideoFullscreenMode) const;
+    bool mayAutomaticallyShowVideoOptimized() const;
+
+private:
+    friend class WebVideoFullscreenModelContext;
+
+    explicit WebVideoFullscreenManagerProxy(WebPageProxy&amp;);
+    virtual void didReceiveMessage(IPC::Connection&amp;, IPC::MessageDecoder&amp;) override;
+
+    typedef std::tuple&lt;RefPtr&lt;WebVideoFullscreenModelContext&gt;, RefPtr&lt;WebCore::WebVideoFullscreenInterfaceAVKit&gt;&gt; ModelInterfaceTuple;
+    ModelInterfaceTuple createModelAndInterface(uint64_t contextId);
+    ModelInterfaceTuple&amp; ensureModelAndInterface(uint64_t contextId);
+    WebVideoFullscreenModelContext&amp; ensureModel(uint64_t contextId);
+    WebCore::WebVideoFullscreenInterfaceAVKit&amp; ensureInterface(uint64_t contextId);
+
+    // Messages from WebVideoFullscreenManager
+    void setupFullscreenWithID(uint64_t contextId, uint32_t videoLayerID, const WebCore::IntRect&amp; initialRect, float hostingScaleFactor, WebCore::HTMLMediaElement::VideoFullscreenMode, bool allowOptimizedFullscreen);
+    void resetMediaState(uint64_t contextId);
+    void setCurrentTime(uint64_t contextId, double currentTime, double hostTime);
+    void setBufferedTime(uint64_t contextId, double bufferedTime);
+    void setVideoDimensions(uint64_t contextId, bool hasVideo, unsigned width, unsigned height);
+    void setSeekableRangesVector(uint64_t contextId, Vector&lt;std::pair&lt;double, double&gt;&gt; ranges);
+    void setCanPlayFastReverse(uint64_t contextId, bool value);
+    void setAudioMediaSelectionOptions(uint64_t contextId, Vector&lt;String&gt; options, uint64_t selectedIndex);
+    void setLegibleMediaSelectionOptions(uint64_t contextId, Vector&lt;String&gt; options, uint64_t selectedIndex);
+    void setExternalPlaybackProperties(uint64_t contextId, bool enabled, uint32_t targetType, String localizedDeviceName);
+    void setDuration(uint64_t contextId, double duration);
+    void setRate(uint64_t contextId, bool isPlaying, double rate);
+    void enterFullscreen(uint64_t contextId);
+    void exitFullscreen(uint64_t contextId, WebCore::IntRect finalRect);
+    void cleanupFullscreen(uint64_t contextId);
+    void preparedToReturnToInline(uint64_t contextId, bool visible, WebCore::IntRect inlineRect);
+
+    // Messages to WebVideoFullscreenManager
+    void play(uint64_t contextId);
+    void pause(uint64_t contextId);
+    void togglePlayState(uint64_t contextId);
+    void beginScrubbing(uint64_t contextId);
+    void endScrubbing(uint64_t contextId);
+    void seekToTime(uint64_t contextId, double time);
+    void fastSeek(uint64_t contextId, double time);
+    void beginScanningForward(uint64_t contextId);
+    void beginScanningBackward(uint64_t contextId);
+    void endScanning(uint64_t contextId);
+    void requestExitFullscreen(uint64_t contextId);
+    void didSetupFullscreen(uint64_t contextId);
+    void didExitFullscreen(uint64_t contextId);
+    void didEnterFullscreen(uint64_t contextId);
+    void didCleanupFullscreen(uint64_t contextId);
+    void setVideoLayerFrame(uint64_t contextId, WebCore::FloatRect);
+    void setVideoLayerGravity(uint64_t contextId, WebCore::WebVideoFullscreenModel::VideoGravity);
+    void selectAudioMediaOption(uint64_t contextId, uint64_t index);
+    void selectLegibleMediaOption(uint64_t contextId, uint64_t index);
+    void fullscreenModeChanged(uint64_t contextId, WebCore::HTMLMediaElement::VideoFullscreenMode);
+    void fullscreenMayReturnToInline(uint64_t contextId);
+
+    WebPageProxy* m_page;
+    HashMap&lt;uint64_t, ModelInterfaceTuple&gt; m_contextMap;
+
+};
</ins><span class="cx">     
</span><span class="cx"> } // namespace WebKit
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosWebVideoFullscreenManagerProxymessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.messages.in (182913 => 182914)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.messages.in        2015-04-16 22:29:10 UTC (rev 182913)
+++ trunk/Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.messages.in        2015-04-16 22:42:58 UTC (rev 182914)
</span><span class="lines">@@ -22,21 +22,21 @@
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx"> messages -&gt; WebVideoFullscreenManagerProxy {
</span><del>-    ResetMediaState()
-    SetCurrentTime(double currentTime, double hostTime)
-    SetBufferedTime(double bufferedTime)
-    SetVideoDimensions(bool hasVideo, unsigned width, unsigned height)
-    SetSeekableRangesVector(Vector&lt;std::pair&lt;double, double&gt;&gt; ranges);
-    SetCanPlayFastReverse(bool value);
-    SetAudioMediaSelectionOptions(Vector&lt;String&gt; options, uint64_t selectedIndex);
-    SetLegibleMediaSelectionOptions(Vector&lt;String&gt; options, uint64_t selectedIndex);
-    SetExternalPlaybackProperties(bool enabled, uint32_t targetType, String localizedDeviceName);
-    SetDuration(double duration)
-    SetRate(bool isPlaying, double rate)
-    SetupFullscreenWithID(uint32_t videoLayerID, WebCore::IntRect initialRect, float hostingScaleFactor, WebCore::HTMLMediaElement::VideoFullscreenMode videoFullscreenMode, bool allowOptimizedFullscreen)
-    EnterFullscreen()
-    ExitFullscreen(WebCore::IntRect finalRect)
-    CleanupFullscreen()
-    PreparedToReturnToInline(bool visible, WebCore::IntRect inlineRect)
</del><ins>+    ResetMediaState(uint64_t contextId)
+    SetCurrentTime(uint64_t contextId, double currentTime, double hostTime)
+    SetBufferedTime(uint64_t contextId, double bufferedTime)
+    SetVideoDimensions(uint64_t contextId, bool hasVideo, unsigned width, unsigned height)
+    SetSeekableRangesVector(uint64_t contextId, Vector&lt;std::pair&lt;double, double&gt;&gt; ranges)
+    SetCanPlayFastReverse(uint64_t contextId, bool value)
+    SetAudioMediaSelectionOptions(uint64_t contextId, Vector&lt;String&gt; options, uint64_t selectedIndex)
+    SetLegibleMediaSelectionOptions(uint64_t contextId, Vector&lt;String&gt; options, uint64_t selectedIndex)
+    SetExternalPlaybackProperties(uint64_t contextId, bool enabled, uint32_t targetType, String localizedDeviceName)
+    SetDuration(uint64_t contextId, double duration)
+    SetRate(uint64_t contextId, bool isPlaying, double rate)
+    SetupFullscreenWithID(uint64_t contextId, uint32_t videoLayerID, WebCore::IntRect initialRect, float hostingScaleFactor, WebCore::HTMLMediaElement::VideoFullscreenMode videoFullscreenMode, bool allowOptimizedFullscreen)
+    EnterFullscreen(uint64_t contextId)
+    ExitFullscreen(uint64_t contextId, WebCore::IntRect finalRect)
+    CleanupFullscreen(uint64_t contextId)
+    PreparedToReturnToInline(uint64_t contextId, bool visible, WebCore::IntRect inlineRect)
</ins><span class="cx"> }
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosWebVideoFullscreenManagerProxymm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.mm (182913 => 182914)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.mm        2015-04-16 22:29:10 UTC (rev 182913)
+++ trunk/Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.mm        2015-04-16 22:42:58 UTC (rev 182914)
</span><span class="lines">@@ -53,8 +53,168 @@
</span><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebVideoFullscreenManagerProxy::invalidate()
+{
+}
+
+bool WebVideoFullscreenManagerProxy::hasMode(HTMLMediaElement::VideoFullscreenMode) const
+{
+    return false;
+}
+
+bool WebVideoFullscreenManagerProxy::mayAutomaticallyShowVideoOptimized() const
+{
+    return false;
+}
+
+void WebVideoFullscreenManagerProxy::requestHideAndExitFullscreen()
+{
+
+}
</ins><span class="cx"> #else
</span><span class="cx"> 
</span><ins>+#pragma mark - WebVideoFullscreenModelContext
+
+void WebVideoFullscreenModelContext::play()
+{
+    if (m_manager)
+        m_manager-&gt;play(m_contextId);
+}
+
+void WebVideoFullscreenModelContext::pause()
+{
+    if (m_manager)
+        m_manager-&gt;pause(m_contextId);
+}
+
+void WebVideoFullscreenModelContext::togglePlayState()
+{
+    if (m_manager)
+        m_manager-&gt;togglePlayState(m_contextId);
+}
+
+void WebVideoFullscreenModelContext::beginScrubbing()
+{
+    if (m_manager)
+        m_manager-&gt;beginScrubbing(m_contextId);
+}
+
+void WebVideoFullscreenModelContext::endScrubbing()
+{
+    if (m_manager)
+        m_manager-&gt;endScrubbing(m_contextId);
+}
+
+void WebVideoFullscreenModelContext::seekToTime(double time)
+{
+    if (m_manager)
+        m_manager-&gt;seekToTime(m_contextId, time);
+}
+
+void WebVideoFullscreenModelContext::fastSeek(double time)
+{
+    if (m_manager)
+        m_manager-&gt;fastSeek(m_contextId, time);
+}
+
+void WebVideoFullscreenModelContext::beginScanningForward()
+{
+    if (m_manager)
+        m_manager-&gt;beginScanningForward(m_contextId);
+}
+
+void WebVideoFullscreenModelContext::beginScanningBackward()
+{
+    if (m_manager)
+        m_manager-&gt;beginScanningBackward(m_contextId);
+}
+
+void WebVideoFullscreenModelContext::endScanning()
+{
+    if (m_manager)
+        m_manager-&gt;endScanning(m_contextId);
+}
+
+void WebVideoFullscreenModelContext::requestExitFullscreen()
+{
+    if (m_manager)
+        m_manager-&gt;requestExitFullscreen(m_contextId);
+}
+
+void WebVideoFullscreenModelContext::setVideoLayerFrame(WebCore::FloatRect frame)
+{
+    m_videoLayerFrame = frame;
+    if (m_manager)
+        m_manager-&gt;setVideoLayerFrame(m_contextId, frame);
+}
+
+WebCore::FloatRect WebVideoFullscreenModelContext::videoLayerFrame() const
+{
+    return m_videoLayerFrame;
+}
+
+void WebVideoFullscreenModelContext::setVideoLayerGravity(WebCore::WebVideoFullscreenModel::VideoGravity gravity)
+{
+    m_videoLayerGravity = gravity;
+    if (m_manager)
+        m_manager-&gt;setVideoLayerGravity(m_contextId, gravity);
+}
+
+WebCore::WebVideoFullscreenModel::VideoGravity WebVideoFullscreenModelContext::videoLayerGravity() const
+{
+    return m_videoLayerGravity;
+}
+
+void WebVideoFullscreenModelContext::selectAudioMediaOption(uint64_t optionId)
+{
+    if (m_manager)
+        m_manager-&gt;selectAudioMediaOption(m_contextId, optionId);
+}
+
+void WebVideoFullscreenModelContext::selectLegibleMediaOption(uint64_t optionId)
+{
+    if (m_manager)
+        m_manager-&gt;selectLegibleMediaOption(m_contextId, optionId);
+}
+
+void WebVideoFullscreenModelContext::fullscreenModeChanged(WebCore::HTMLMediaElement::VideoFullscreenMode mode)
+{
+    if (m_manager)
+        m_manager-&gt;fullscreenModeChanged(m_contextId, mode);
+}
+
+void WebVideoFullscreenModelContext::didSetupFullscreen()
+{
+    if (m_manager)
+        m_manager-&gt;didSetupFullscreen(m_contextId);
+}
+
+void WebVideoFullscreenModelContext::didEnterFullscreen()
+{
+    if (m_manager)
+        m_manager-&gt;didEnterFullscreen(m_contextId);
+}
+
+void WebVideoFullscreenModelContext::didExitFullscreen()
+{
+    if (m_manager)
+        m_manager-&gt;didExitFullscreen(m_contextId);
+}
+
+void WebVideoFullscreenModelContext::didCleanupFullscreen()
+{
+    if (m_manager)
+        m_manager-&gt;didCleanupFullscreen(m_contextId);
+}
+
+void WebVideoFullscreenModelContext::fullscreenMayReturnToInline()
+{
+    if (m_manager)
+        m_manager-&gt;fullscreenMayReturnToInline(m_contextId);
+}
+
+#pragma mark - WebVideoFullscreenManagerProxy
+
</ins><span class="cx"> PassRefPtr&lt;WebVideoFullscreenManagerProxy&gt; WebVideoFullscreenManagerProxy::create(WebPageProxy&amp; page)
</span><span class="cx"> {
</span><span class="cx">     return adoptRef(new WebVideoFullscreenManagerProxy(page));
</span><span class="lines">@@ -64,8 +224,6 @@
</span><span class="cx">     : m_page(&amp;page)
</span><span class="cx"> {
</span><span class="cx">     m_page-&gt;process().addMessageReceiver(Messages::WebVideoFullscreenManagerProxy::messageReceiverName(), m_page-&gt;pageID(), *this);
</span><del>-    setWebVideoFullscreenModel(this);
-    setWebVideoFullscreenChangeObserver(this);
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> WebVideoFullscreenManagerProxy::~WebVideoFullscreenManagerProxy()
</span><span class="lines">@@ -77,38 +235,119 @@
</span><span class="cx"> 
</span><span class="cx"> void WebVideoFullscreenManagerProxy::invalidate()
</span><span class="cx"> {
</span><del>-    WebVideoFullscreenInterfaceAVKit::invalidate();
-
</del><span class="cx">     m_page-&gt;process().removeMessageReceiver(Messages::WebVideoFullscreenManagerProxy::messageReceiverName(), m_page-&gt;pageID());
</span><span class="cx">     m_page = nullptr;
</span><span class="cx"> 
</span><del>-    [m_layerHost removeFromSuperlayer];
-    m_layerHost.clear();
</del><ins>+    for (auto&amp; tuple : m_contextMap.values()) {
+        RefPtr&lt;WebVideoFullscreenModelContext&gt; model;
+        RefPtr&lt;WebCore::WebVideoFullscreenInterfaceAVKit&gt; interface;
+        std::tie(model, interface) = tuple;
+
+        interface-&gt;invalidate();
+        [model-&gt;layerHost() removeFromSuperlayer];
+        model-&gt;setLayerHost(nullptr);
+    }
+
+    m_contextMap.clear();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVideoFullscreenManagerProxy::setupFullscreenWithID(uint32_t videoLayerID, const WebCore::IntRect&amp; initialRect, float hostingDeviceScaleFactor, HTMLMediaElement::VideoFullscreenMode videoFullscreenMode, bool allowOptimizedFullscreen)
</del><ins>+void WebVideoFullscreenManagerProxy::requestHideAndExitFullscreen()
</ins><span class="cx"> {
</span><ins>+    for (auto&amp; tuple : m_contextMap.values())
+        std::get&lt;1&gt;(tuple)-&gt;requestHideAndExitFullscreen();
+}
+
+bool WebVideoFullscreenManagerProxy::hasMode(HTMLMediaElement::VideoFullscreenMode mode) const
+{
+    for (auto&amp; tuple : m_contextMap.values()) {
+        if (std::get&lt;1&gt;(tuple)-&gt;hasMode(mode))
+            return true;
+    }
+    return false;
+}
+
+bool WebVideoFullscreenManagerProxy::mayAutomaticallyShowVideoOptimized() const
+{
+    for (auto&amp; tuple : m_contextMap.values()) {
+        if (std::get&lt;1&gt;(tuple)-&gt;mayAutomaticallyShowVideoOptimized())
+            return true;
+    }
+    return false;
+}
+
+WebVideoFullscreenManagerProxy::ModelInterfaceTuple WebVideoFullscreenManagerProxy::createModelAndInterface(uint64_t contextId)
+{
+    Ref&lt;WebVideoFullscreenModelContext&gt; model = WebVideoFullscreenModelContext::create(*this, contextId);
+    Ref&lt;WebCore::WebVideoFullscreenInterfaceAVKit&gt; interface = WebVideoFullscreenInterfaceAVKit::create();
+
+    interface-&gt;setWebVideoFullscreenModel(&amp;model.get());
+    interface-&gt;setWebVideoFullscreenChangeObserver(&amp;model.get());
+
+    return std::make_tuple(WTF::move(model), WTF::move(interface));
+}
+
+WebVideoFullscreenManagerProxy::ModelInterfaceTuple&amp; WebVideoFullscreenManagerProxy::ensureModelAndInterface(uint64_t contextId)
+{
+    auto addResult = m_contextMap.add(contextId, ModelInterfaceTuple());
+    if (addResult.isNewEntry)
+        addResult.iterator-&gt;value = createModelAndInterface(contextId);
+    return addResult.iterator-&gt;value;
+}
+
+WebVideoFullscreenModelContext&amp; WebVideoFullscreenManagerProxy::ensureModel(uint64_t contextId)
+{
+    return *std::get&lt;0&gt;(ensureModelAndInterface(contextId));
+}
+
+WebCore::WebVideoFullscreenInterfaceAVKit&amp; WebVideoFullscreenManagerProxy::ensureInterface(uint64_t contextId)
+{
+    return *std::get&lt;1&gt;(ensureModelAndInterface(contextId));
+}
+
+#pragma mark Messages from WebVideoFullscreenManager
+
+void WebVideoFullscreenManagerProxy::setupFullscreenWithID(uint64_t contextId, uint32_t videoLayerID, const WebCore::IntRect&amp; initialRect, float hostingDeviceScaleFactor, HTMLMediaElement::VideoFullscreenMode videoFullscreenMode, bool allowOptimizedFullscreen)
+{
</ins><span class="cx">     ASSERT(videoLayerID);
</span><del>-    m_layerHost = WKMakeRenderLayer(videoLayerID);
</del><ins>+    RefPtr&lt;WebVideoFullscreenModelContext&gt; model;
+    RefPtr&lt;WebCore::WebVideoFullscreenInterfaceAVKit&gt; interface;
+
+    std::tie(model, interface) = ensureModelAndInterface(contextId);
+
+    model-&gt;setInitialVideoLayerFrame(initialRect);
+    model-&gt;setLayerHost(WKMakeRenderLayer(videoLayerID));
</ins><span class="cx">     if (hostingDeviceScaleFactor != 1) {
</span><span class="cx">         // Invert the scale transform added in the WebProcess to fix &lt;rdar://problem/18316542&gt;.
</span><span class="cx">         float inverseScale = 1 / hostingDeviceScaleFactor;
</span><del>-        [m_layerHost setTransform:CATransform3DMakeScale(inverseScale, inverseScale, 1)];
</del><ins>+        [model-&gt;layerHost() setTransform:CATransform3DMakeScale(inverseScale, inverseScale, 1)];
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    m_videoLayerFrame = initialRect;
-
</del><span class="cx">     UIView *parentView = downcast&lt;RemoteLayerTreeDrawingAreaProxy&gt;(*m_page-&gt;drawingArea()).remoteLayerTreeHost().rootLayer();
</span><del>-    setupFullscreen(*m_layerHost.get(), initialRect, parentView, videoFullscreenMode, allowOptimizedFullscreen);
</del><ins>+    interface-&gt;setupFullscreen(*model-&gt;layerHost(), initialRect, parentView, videoFullscreenMode, allowOptimizedFullscreen);
</ins><span class="cx"> }
</span><del>-    
-void WebVideoFullscreenManagerProxy::fullscreenModeChanged(HTMLMediaElement::VideoFullscreenMode mode)
</del><ins>+
+void WebVideoFullscreenManagerProxy::resetMediaState(uint64_t contextId)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManager::fullscreenModeChanged(mode), m_page-&gt;pageID());
</del><ins>+    ensureInterface(contextId).resetMediaState();
</ins><span class="cx"> }
</span><del>-    
-void WebVideoFullscreenManagerProxy::setSeekableRangesVector(const Vector&lt;std::pair&lt;double, double&gt;&gt;&amp; ranges)
</del><ins>+
+void WebVideoFullscreenManagerProxy::setCurrentTime(uint64_t contextId, double currentTime, double hostTime)
</ins><span class="cx"> {
</span><ins>+    ensureInterface(contextId).setCurrentTime(currentTime, hostTime);
+}
+
+void WebVideoFullscreenManagerProxy::setBufferedTime(uint64_t contextId, double bufferedTime)
+{
+    ensureInterface(contextId).setBufferedTime(bufferedTime);
+}
+
+void WebVideoFullscreenManagerProxy::setVideoDimensions(uint64_t contextId, bool hasVideo, unsigned width, unsigned height)
+{
+    ensureInterface(contextId).setVideoDimensions(hasVideo, width, height);
+}
+
+void WebVideoFullscreenManagerProxy::setSeekableRangesVector(uint64_t contextId, Vector&lt;std::pair&lt;double, double&gt;&gt; ranges)
+{
</ins><span class="cx">     RefPtr&lt;TimeRanges&gt; timeRanges = TimeRanges::create();
</span><span class="cx">     for (const auto&amp; range : ranges)
</span><span class="cx">     {
</span><span class="lines">@@ -118,118 +357,164 @@
</span><span class="cx">         timeRanges-&gt;add(range.first, range.second);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    setSeekableRanges(*timeRanges);
</del><ins>+    ensureInterface(contextId).setSeekableRanges(*timeRanges);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVideoFullscreenManagerProxy::setExternalPlaybackProperties(bool enabled, uint32_t targetType, String localizedDeviceName)
</del><ins>+void WebVideoFullscreenManagerProxy::setCanPlayFastReverse(uint64_t contextId, bool value)
</ins><span class="cx"> {
</span><ins>+    ensureInterface(contextId).setCanPlayFastReverse(value);
+}
+
+void WebVideoFullscreenManagerProxy::setAudioMediaSelectionOptions(uint64_t contextId, Vector&lt;String&gt; options, uint64_t selectedIndex)
+{
+    ensureInterface(contextId).setAudioMediaSelectionOptions(options, selectedIndex);
+}
+
+void WebVideoFullscreenManagerProxy::setLegibleMediaSelectionOptions(uint64_t contextId, Vector&lt;String&gt; options, uint64_t selectedIndex)
+{
+    ensureInterface(contextId).setLegibleMediaSelectionOptions(options, selectedIndex);
+}
+
+void WebVideoFullscreenManagerProxy::setExternalPlaybackProperties(uint64_t contextId, bool enabled, uint32_t targetType, String localizedDeviceName)
+{
</ins><span class="cx">     WebVideoFullscreenInterface::ExternalPlaybackTargetType type = static_cast&lt;WebVideoFullscreenInterface::ExternalPlaybackTargetType&gt;(targetType);
</span><del>-    
</del><span class="cx">     ASSERT(type == WebVideoFullscreenInterface::TargetTypeAirPlay || type == WebVideoFullscreenInterface::TargetTypeTVOut || type == WebVideoFullscreenInterface::TargetTypeNone);
</span><span class="cx">     
</span><del>-    setExternalPlayback(enabled, type, localizedDeviceName);
</del><ins>+    ensureInterface(contextId).setExternalPlayback(enabled, type, localizedDeviceName);
</ins><span class="cx"> }
</span><del>-    
-void WebVideoFullscreenManagerProxy::fullscreenMayReturnToInline()
</del><ins>+
+void WebVideoFullscreenManagerProxy::setDuration(uint64_t contextId, double duration)
</ins><span class="cx"> {
</span><del>-    bool isViewVisible = m_page-&gt;isViewVisible();
-    m_page-&gt;send(Messages::WebVideoFullscreenManager::FullscreenMayReturnToInline(isViewVisible), m_page-&gt;pageID());
</del><ins>+    ensureInterface(contextId).setDuration(duration);
</ins><span class="cx"> }
</span><del>-    
-void WebVideoFullscreenManagerProxy::preparedToReturnToInline(bool visible, const WebCore::IntRect&amp; inlineRect)
</del><ins>+
+void WebVideoFullscreenManagerProxy::setRate(uint64_t contextId, bool isPlaying, double rate)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;fullscreenMayReturnToInline();
-    WebVideoFullscreenInterfaceAVKit::preparedToReturnToInline(visible, inlineRect);
</del><ins>+    ensureInterface(contextId).setRate(isPlaying, rate);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVideoFullscreenManagerProxy::requestExitFullscreen()
</del><ins>+void WebVideoFullscreenManagerProxy::enterFullscreen(uint64_t contextId)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManager::RequestExitFullscreen(), m_page-&gt;pageID());
</del><ins>+    auto&amp; interface = ensureInterface(contextId);
+    interface.enterFullscreen();
+
+    // Only one context can be in a given full screen mode at a time:
+    for (auto&amp; contextPair : m_contextMap) {
+        auto&amp; otherContextId = contextPair.key;
+        if (contextId == otherContextId)
+            continue;
+
+        auto&amp; otherInterface = std::get&lt;1&gt;(contextPair.value);
+        if (otherInterface-&gt;hasMode(interface.mode()))
+            otherInterface-&gt;requestHideAndExitFullscreen();
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVideoFullscreenManagerProxy::didExitFullscreen()
</del><ins>+void WebVideoFullscreenManagerProxy::exitFullscreen(uint64_t contextId, WebCore::IntRect finalRect)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManager::DidExitFullscreen(), m_page-&gt;pageID());
-    m_page-&gt;didExitFullscreen();
</del><ins>+    ensureInterface(contextId).exitFullscreen(finalRect);
</ins><span class="cx"> }
</span><del>-    
-void WebVideoFullscreenManagerProxy::didCleanupFullscreen()
</del><ins>+
+void WebVideoFullscreenManagerProxy::cleanupFullscreen(uint64_t contextId)
</ins><span class="cx"> {
</span><del>-    [CATransaction flush];
-    [m_layerHost removeFromSuperlayer];
-    m_layerHost.clear();
-    m_page-&gt;send(Messages::WebVideoFullscreenManager::DidCleanupFullscreen(), m_page-&gt;pageID());
</del><ins>+    ensureInterface(contextId).cleanupFullscreen();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVideoFullscreenManagerProxy::didSetupFullscreen()
</del><ins>+void WebVideoFullscreenManagerProxy::preparedToReturnToInline(uint64_t contextId, bool visible, WebCore::IntRect inlineRect)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManager::DidSetupFullscreen(), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;fullscreenMayReturnToInline();
+
+    ensureInterface(contextId).preparedToReturnToInline(visible, inlineRect);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVideoFullscreenManagerProxy::didEnterFullscreen()
</del><ins>+#pragma mark Messages to WebVideoFullscreenManager
+
+void WebVideoFullscreenManagerProxy::play(uint64_t contextId)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManager::DidEnterFullscreen(), m_page-&gt;pageID());
-    m_page-&gt;didEnterFullscreen();
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManager::Play(contextId), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVideoFullscreenManagerProxy::play()
</del><ins>+void WebVideoFullscreenManagerProxy::pause(uint64_t contextId)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManager::Play(), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManager::Pause(contextId), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><del>-    
-void WebVideoFullscreenManagerProxy::pause()
</del><ins>+
+void WebVideoFullscreenManagerProxy::togglePlayState(uint64_t contextId)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManager::Pause(), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManager::TogglePlayState(contextId), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><del>-    
-void WebVideoFullscreenManagerProxy::togglePlayState()
</del><ins>+
+void WebVideoFullscreenManagerProxy::beginScrubbing(uint64_t contextId)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManager::TogglePlayState(), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManager::BeginScrubbing(contextId), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><del>-    
-void WebVideoFullscreenManagerProxy::beginScrubbing()
</del><ins>+
+void WebVideoFullscreenManagerProxy::endScrubbing(uint64_t contextId)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManager::BeginScrubbing(), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManager::EndScrubbing(contextId), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVideoFullscreenManagerProxy::endScrubbing()
</del><ins>+void WebVideoFullscreenManagerProxy::seekToTime(uint64_t contextId, double time)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManager::EndScrubbing(), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManager::SeekToTime(contextId, time), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVideoFullscreenManagerProxy::seekToTime(double time)
</del><ins>+void WebVideoFullscreenManagerProxy::fastSeek(uint64_t contextId, double time)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManager::SeekToTime(time), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManager::FastSeek(contextId, time), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVideoFullscreenManagerProxy::fastSeek(double time)
</del><ins>+void WebVideoFullscreenManagerProxy::beginScanningForward(uint64_t contextId)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManager::FastSeek(time), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManager::BeginScanningForward(contextId), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVideoFullscreenManagerProxy::beginScanningForward()
</del><ins>+void WebVideoFullscreenManagerProxy::beginScanningBackward(uint64_t contextId)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManager::BeginScanningForward(), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManager::BeginScanningBackward(contextId), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVideoFullscreenManagerProxy::beginScanningBackward()
</del><ins>+void WebVideoFullscreenManagerProxy::endScanning(uint64_t contextId)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManager::BeginScanningBackward(), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManager::EndScanning(contextId), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVideoFullscreenManagerProxy::endScanning()
</del><ins>+void WebVideoFullscreenManagerProxy::requestExitFullscreen(uint64_t contextId)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManager::EndScanning(), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManager::RequestExitFullscreen(contextId), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-FloatRect WebVideoFullscreenManagerProxy::videoLayerFrame() const
</del><ins>+void WebVideoFullscreenManagerProxy::didSetupFullscreen(uint64_t contextId)
</ins><span class="cx"> {
</span><del>-    return m_videoLayerFrame;
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManager::DidSetupFullscreen(contextId), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVideoFullscreenManagerProxy::setVideoLayerFrame(WebCore::FloatRect frame)
</del><ins>+void WebVideoFullscreenManagerProxy::didExitFullscreen(uint64_t contextId)
</ins><span class="cx"> {
</span><del>-    m_videoLayerFrame = frame;
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManager::DidExitFullscreen(contextId), m_page-&gt;pageID());
+    m_page-&gt;didExitFullscreen();
+}
+
+void WebVideoFullscreenManagerProxy::didEnterFullscreen(uint64_t contextId)
+{
+    m_page-&gt;send(Messages::WebVideoFullscreenManager::DidEnterFullscreen(contextId), m_page-&gt;pageID());
+    m_page-&gt;didEnterFullscreen();
+}
+
+void WebVideoFullscreenManagerProxy::didCleanupFullscreen(uint64_t contextId)
+{
+    auto&amp; model = ensureModel(contextId);
+
+    [CATransaction flush];
+    [model.layerHost() removeFromSuperlayer];
+    model.setLayerHost(nullptr);
+    m_page-&gt;send(Messages::WebVideoFullscreenManager::DidCleanupFullscreen(contextId), m_page-&gt;pageID());
+
+    m_contextMap.remove(contextId);
+}
+
+void WebVideoFullscreenManagerProxy::setVideoLayerFrame(uint64_t contextId, WebCore::FloatRect frame)
+{
</ins><span class="cx">     @autoreleasepool {
</span><span class="cx"> #if __IPHONE_OS_VERSION_MIN_REQUIRED &gt; 90000
</span><span class="cx">         BKSAnimationFenceHandle* synchronizationFence = [UIWindow _synchronizedDrawingFence];
</span><span class="lines">@@ -238,30 +523,36 @@
</span><span class="cx">         mach_port_name_t fencePort = [UIWindow _synchronizeDrawingAcrossProcesses];
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-        m_page-&gt;send(Messages::WebVideoFullscreenManager::SetVideoLayerFrameFenced(frame, IPC::Attachment(fencePort, MACH_MSG_TYPE_MOVE_SEND)), m_page-&gt;pageID());
</del><ins>+        m_page-&gt;send(Messages::WebVideoFullscreenManager::SetVideoLayerFrameFenced(contextId, frame, IPC::Attachment(fencePort, MACH_MSG_TYPE_MOVE_SEND)), m_page-&gt;pageID());
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-WebCore::WebVideoFullscreenModel::VideoGravity WebVideoFullscreenManagerProxy::videoLayerGravity() const
</del><ins>+void WebVideoFullscreenManagerProxy::setVideoLayerGravity(uint64_t contextId, WebCore::WebVideoFullscreenModel::VideoGravity gravity)
</ins><span class="cx"> {
</span><del>-    return m_videoLayerGravity;
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManager::SetVideoLayerGravityEnum(contextId, (unsigned)gravity), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVideoFullscreenManagerProxy::setVideoLayerGravity(WebCore::WebVideoFullscreenModel::VideoGravity gravity)
</del><ins>+void WebVideoFullscreenManagerProxy::selectAudioMediaOption(uint64_t contextId, uint64_t index)
</ins><span class="cx"> {
</span><del>-    m_videoLayerGravity = gravity;
-    m_page-&gt;send(Messages::WebVideoFullscreenManager::SetVideoLayerGravityEnum((unsigned)gravity), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManager::SelectAudioMediaOption(contextId, index), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><del>-    
-void WebVideoFullscreenManagerProxy::selectAudioMediaOption(uint64_t index)
</del><ins>+
+void WebVideoFullscreenManagerProxy::selectLegibleMediaOption(uint64_t contextId, uint64_t index)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManager::SelectAudioMediaOption(index), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManager::SelectLegibleMediaOption(contextId, index), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><del>-    
-void WebVideoFullscreenManagerProxy::selectLegibleMediaOption(uint64_t index)
</del><ins>+
+void WebVideoFullscreenManagerProxy::fullscreenModeChanged(uint64_t contextId, WebCore::HTMLMediaElement::VideoFullscreenMode mode)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManager::SelectLegibleMediaOption(index), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManager::FullscreenModeChanged(contextId, mode), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><ins>+
+void WebVideoFullscreenManagerProxy::fullscreenMayReturnToInline(uint64_t contextId)
+{
+    bool isViewVisible = m_page-&gt;isViewVisible();
+    m_page-&gt;send(Messages::WebVideoFullscreenManager::FullscreenMayReturnToInline(contextId, isViewVisible), m_page-&gt;pageID());
+}
+
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessiosWebVideoFullscreenManagerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/ios/WebVideoFullscreenManager.h (182913 => 182914)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/ios/WebVideoFullscreenManager.h        2015-04-16 22:29:10 UTC (rev 182913)
+++ trunk/Source/WebKit2/WebProcess/ios/WebVideoFullscreenManager.h        2015-04-16 22:42:58 UTC (rev 182914)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> #include &lt;WebCore/PlatformCALayer.h&gt;
</span><span class="cx"> #include &lt;WebCore/WebVideoFullscreenInterface.h&gt;
</span><span class="cx"> #include &lt;WebCore/WebVideoFullscreenModelVideoElement.h&gt;
</span><ins>+#include &lt;wtf/HashMap.h&gt;
</ins><span class="cx"> #include &lt;wtf/RefCounted.h&gt;
</span><span class="cx"> #include &lt;wtf/RefPtr.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -51,53 +52,120 @@
</span><span class="cx"> 
</span><span class="cx"> class LayerHostingContext;
</span><span class="cx"> class WebPage;
</span><ins>+class WebVideoFullscreenManager;
</ins><span class="cx"> 
</span><del>-class WebVideoFullscreenManager : public WebCore::WebVideoFullscreenModelVideoElement, public WebCore::WebVideoFullscreenInterface, private IPC::MessageReceiver {
</del><ins>+class WebVideoFullscreenInterfaceContext : public RefCounted&lt;WebVideoFullscreenInterfaceContext&gt;, public WebCore::WebVideoFullscreenInterface {
</ins><span class="cx"> public:
</span><ins>+    static Ref&lt;WebVideoFullscreenInterfaceContext&gt; create(WebVideoFullscreenManager&amp; manager, uint64_t contextId)
+    {
+        return adoptRef(*new WebVideoFullscreenInterfaceContext(manager, contextId));
+    }
+    virtual ~WebVideoFullscreenInterfaceContext();
+
+    void invalidate() { m_manager = nullptr; }
+
+    LayerHostingContext* layerHostingContext() { return m_layerHostingContext.get(); }
+    void setLayerHostingContext(std::unique_ptr&lt;LayerHostingContext&gt;&amp;&amp;);
+
+    bool isAnimating() const { return m_isAnimating; }
+    void setIsAnimating(bool flag) { m_isAnimating = flag; }
+
+    bool targetIsFullscreen() const { return m_targetIsFullscreen; }
+    void setTargetIsFullscreen(bool flag) { m_targetIsFullscreen = flag; }
+
+    WebCore::HTMLMediaElement::VideoFullscreenMode fullscreenMode() const { return m_fullscreenMode; }
+    void setFullscreenMode(WebCore::HTMLMediaElement::VideoFullscreenMode mode) { m_fullscreenMode = mode; }
+
+    bool isFullscreen() const { return m_isFullscreen; }
+    void setIsFullscreen(bool flag) { m_isFullscreen = flag; }
+
+private:
+    // WebVideoFullscreenInterface
+    virtual void resetMediaState() override;
+    virtual void setDuration(double) override;
+    virtual void setCurrentTime(double currentTime, double anchorTime) override;
+    virtual void setBufferedTime(double) override;
+    virtual void setRate(bool isPlaying, float playbackRate) override;
+    virtual void setVideoDimensions(bool hasVideo, float width, float height) override;
+    virtual void setSeekableRanges(const WebCore::TimeRanges&amp;) override;
+    virtual void setCanPlayFastReverse(bool value) override;
+    virtual void setAudioMediaSelectionOptions(const Vector&lt;WTF::String&gt;&amp; options, uint64_t selectedIndex) override;
+    virtual void setLegibleMediaSelectionOptions(const Vector&lt;WTF::String&gt;&amp; options, uint64_t selectedIndex) override;
+    virtual void setExternalPlayback(bool enabled, ExternalPlaybackTargetType, WTF::String localizedDeviceName) override;
+
+    WebVideoFullscreenInterfaceContext(WebVideoFullscreenManager&amp;, uint64_t contextId);
+
+    WebVideoFullscreenManager* m_manager;
+    uint64_t m_contextId;
+    std::unique_ptr&lt;LayerHostingContext&gt; m_layerHostingContext;
+    bool m_isAnimating { false };
+    bool m_targetIsFullscreen { false };
+    WebCore::HTMLMediaElement::VideoFullscreenMode m_fullscreenMode { WebCore::HTMLMediaElement::VideoFullscreenModeNone };
+    bool m_isFullscreen { false };
+};
+
+class WebVideoFullscreenManager : public RefCounted&lt;WebVideoFullscreenManager&gt;, private IPC::MessageReceiver {
+public:
</ins><span class="cx">     static PassRefPtr&lt;WebVideoFullscreenManager&gt; create(PassRefPtr&lt;WebPage&gt;);
</span><span class="cx">     virtual ~WebVideoFullscreenManager();
</span><span class="cx">     
</span><span class="cx">     void didReceiveMessage(IPC::Connection&amp;, IPC::MessageDecoder&amp;) override;
</span><del>-    
</del><ins>+
+    // Interface to ChromeClient
</ins><span class="cx">     bool supportsVideoFullscreen() const;
</span><span class="cx">     void enterVideoFullscreenForVideoElement(WebCore::HTMLVideoElement&amp;, WebCore::HTMLMediaElement::VideoFullscreenMode);
</span><span class="cx">     void exitVideoFullscreenForVideoElement(WebCore::HTMLVideoElement&amp;);
</span><span class="cx">     
</span><span class="cx"> protected:
</span><ins>+    friend class WebVideoFullscreenInterfaceContext;
+
</ins><span class="cx">     explicit WebVideoFullscreenManager(PassRefPtr&lt;WebPage&gt;);
</span><del>-    virtual bool operator==(const EventListener&amp; rhs) override { return static_cast&lt;WebCore::EventListener*&gt;(this) == &amp;rhs; }
-    
-    // FullscreenInterface
-    virtual void resetMediaState() override;
-    virtual void setDuration(double) override;
-    virtual void setCurrentTime(double currentTime, double anchorTime) override;
-    virtual void setBufferedTime(double bufferedTime) override;
-    virtual void setRate(bool isPlaying, float playbackRate) override;
-    virtual void setVideoDimensions(bool hasVideo, float width, float height) override;
-    virtual void setSeekableRanges(const WebCore::TimeRanges&amp;) override;
-    virtual void setCanPlayFastReverse(bool value) override;
</del><span class="cx"> 
</span><del>-    virtual void setAudioMediaSelectionOptions(const Vector&lt;String&gt;&amp; options, uint64_t selectedIndex) override;
-    virtual void setLegibleMediaSelectionOptions(const Vector&lt;String&gt;&amp; options, uint64_t selectedIndex) override;
-    virtual void setExternalPlayback(bool enabled, WebVideoFullscreenInterface::ExternalPlaybackTargetType, String localizedDeviceName) override;
</del><ins>+    typedef std::tuple&lt;RefPtr&lt;WebCore::WebVideoFullscreenModelVideoElement&gt;, RefPtr&lt;WebVideoFullscreenInterfaceContext&gt;&gt; ModelInterfaceTuple;
+    ModelInterfaceTuple createModelAndInterface(uint64_t contextId);
+    ModelInterfaceTuple&amp; ensureModelAndInterface(uint64_t contextId);
+    WebCore::WebVideoFullscreenModelVideoElement&amp; ensureModel(uint64_t contextId);
+    WebVideoFullscreenInterfaceContext&amp; ensureInterface(uint64_t contextId);
</ins><span class="cx"> 
</span><del>-    // additional incoming
-    virtual void didSetupFullscreen();
-    virtual void didEnterFullscreen();
-    virtual void didExitFullscreen();
-    virtual void didCleanupFullscreen();
-    virtual void setVideoLayerGravityEnum(unsigned);
-    virtual void fullscreenMayReturnToInline(bool isPageVisible);
-    void setVideoLayerFrameFenced(WebCore::FloatRect bounds, IPC::Attachment fencePort);
</del><ins>+    // Interface to WebVideoFullscreenInterfaceContext
+    void resetMediaState(uint64_t contextId);
+    void setDuration(uint64_t contextId, double);
+    void setCurrentTime(uint64_t contextId, double currentTime, double anchorTime);
+    void setBufferedTime(uint64_t contextId, double bufferedTime);
+    void setRate(uint64_t contextId, bool isPlaying, float playbackRate);
+    void setVideoDimensions(uint64_t contextId, bool hasVideo, float width, float height);
+    void setSeekableRanges(uint64_t contextId, const WebCore::TimeRanges&amp;);
+    void setCanPlayFastReverse(uint64_t contextId, bool value);
+    void setAudioMediaSelectionOptions(uint64_t contextId, const Vector&lt;String&gt;&amp; options, uint64_t selectedIndex);
+    void setLegibleMediaSelectionOptions(uint64_t contextId, const Vector&lt;String&gt;&amp; options, uint64_t selectedIndex);
+    void setExternalPlayback(uint64_t contextId, bool enabled, WebCore::WebVideoFullscreenInterface::ExternalPlaybackTargetType, String localizedDeviceName);
+
+    // Messages from WebVideoFullscreenManagerProxy
+    void play(uint64_t contextId);
+    void pause(uint64_t contextId);
+    void togglePlayState(uint64_t contextId);
+    void beginScrubbing(uint64_t contextId);
+    void endScrubbing(uint64_t contextId);
+    void seekToTime(uint64_t contextId, double time);
+    void fastSeek(uint64_t contextId, double time);
+    void beginScanningForward(uint64_t contextId);
+    void beginScanningBackward(uint64_t contextId);
+    void endScanning(uint64_t contextId);
+    void requestExitFullscreen(uint64_t contextId);
+    void didSetupFullscreen(uint64_t contextId);
+    void didExitFullscreen(uint64_t contextId);
+    void didEnterFullscreen(uint64_t contextId);
+    void didCleanupFullscreen(uint64_t contextId);
+    void setVideoLayerFrameFenced(uint64_t contextId, WebCore::FloatRect bounds, IPC::Attachment fencePort);
+    void setVideoLayerGravityEnum(uint64_t contextId, unsigned gravity);
+    void selectAudioMediaOption(uint64_t contextId, uint64_t index);
+    void selectLegibleMediaOption(uint64_t contextId, uint64_t index);
+    void fullscreenModeChanged(uint64_t contextId, WebCore::HTMLMediaElement::VideoFullscreenMode);
+    void fullscreenMayReturnToInline(uint64_t contextId, bool isPageVisible);
</ins><span class="cx">     
</span><span class="cx">     WebPage* m_page;
</span><del>-    RefPtr&lt;WebCore::HTMLVideoElement&gt; m_videoElement;
-    std::unique_ptr&lt;LayerHostingContext&gt; m_layerHostingContext;
-    
-    bool m_isAnimating;
-    bool m_targetIsFullscreen;
-    WebCore::HTMLMediaElement::VideoFullscreenMode m_fullscreenMode;
-    bool m_isFullscreen;
</del><ins>+    HashMap&lt;WebCore::HTMLVideoElement*, uint64_t&gt; m_videoElements;
+    HashMap&lt;uint64_t, ModelInterfaceTuple&gt; m_contextMap;
</ins><span class="cx"> };
</span><span class="cx">     
</span><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessiosWebVideoFullscreenManagermessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/ios/WebVideoFullscreenManager.messages.in (182913 => 182914)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/ios/WebVideoFullscreenManager.messages.in        2015-04-16 22:29:10 UTC (rev 182913)
+++ trunk/Source/WebKit2/WebProcess/ios/WebVideoFullscreenManager.messages.in        2015-04-16 22:42:58 UTC (rev 182914)
</span><span class="lines">@@ -22,26 +22,26 @@
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx"> messages -&gt; WebVideoFullscreenManager {
</span><del>-    Play()
-    Pause()
-    TogglePlayState()
-    BeginScrubbing()
-    EndScrubbing()
-    SeekToTime(double time)
-    FastSeek(double time)
-    BeginScanningForward()
-    BeginScanningBackward()
-    EndScanning()
-    RequestExitFullscreen()
-    DidSetupFullscreen()
-    DidExitFullscreen()
-    DidEnterFullscreen()
-    DidCleanupFullscreen()
-    SetVideoLayerFrameFenced(WebCore::FloatRect bounds, IPC::Attachment fencePort)
-    SetVideoLayerGravityEnum(unsigned gravity)
-    SelectAudioMediaOption(uint64_t index)
-    SelectLegibleMediaOption(uint64_t index)
-    fullscreenModeChanged(WebCore::HTMLMediaElement::VideoFullscreenMode videoFullscreenMode)
-    FullscreenMayReturnToInline(bool isPageVisible)
</del><ins>+    Play(uint64_t contextId)
+    Pause(uint64_t contextId)
+    TogglePlayState(uint64_t contextId)
+    BeginScrubbing(uint64_t contextId)
+    EndScrubbing(uint64_t contextId)
+    SeekToTime(uint64_t contextId, double time)
+    FastSeek(uint64_t contextId, double time)
+    BeginScanningForward(uint64_t contextId)
+    BeginScanningBackward(uint64_t contextId)
+    EndScanning(uint64_t contextId)
+    RequestExitFullscreen(uint64_t contextId)
+    DidSetupFullscreen(uint64_t contextId)
+    DidExitFullscreen(uint64_t contextId)
+    DidEnterFullscreen(uint64_t contextId)
+    DidCleanupFullscreen(uint64_t contextId)
+    SetVideoLayerFrameFenced(uint64_t contextId, WebCore::FloatRect bounds, IPC::Attachment fencePort)
+    SetVideoLayerGravityEnum(uint64_t contextId, unsigned gravity)
+    SelectAudioMediaOption(uint64_t contextId, uint64_t index)
+    SelectLegibleMediaOption(uint64_t contextId, uint64_t index)
+    FullscreenModeChanged(uint64_t contextId, WebCore::HTMLMediaElement::VideoFullscreenMode videoFullscreenMode)
+    FullscreenMayReturnToInline(uint64_t contextId, bool isPageVisible)
</ins><span class="cx"> }
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessiosWebVideoFullscreenManagermm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/ios/WebVideoFullscreenManager.mm (182913 => 182914)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/ios/WebVideoFullscreenManager.mm        2015-04-16 22:29:10 UTC (rev 182913)
+++ trunk/Source/WebKit2/WebProcess/ios/WebVideoFullscreenManager.mm        2015-04-16 22:42:58 UTC (rev 182914)
</span><span class="lines">@@ -60,6 +60,97 @@
</span><span class="cx">     return element-&gt;clientRect();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static uint64_t nextContextId()
+{
+    static uint64_t contextId = 0;
+    return ++contextId;
+}
+
+#pragma mark - WebVideoFullscreenInterfaceContext
+
+WebVideoFullscreenInterfaceContext::WebVideoFullscreenInterfaceContext(WebVideoFullscreenManager&amp; manager, uint64_t contextId)
+    : m_manager(&amp;manager)
+    , m_contextId(contextId)
+{
+}
+
+WebVideoFullscreenInterfaceContext::~WebVideoFullscreenInterfaceContext()
+{
+}
+
+void WebVideoFullscreenInterfaceContext::setLayerHostingContext(std::unique_ptr&lt;LayerHostingContext&gt;&amp;&amp; context)
+{
+    m_layerHostingContext = WTF::move(context);
+}
+
+void WebVideoFullscreenInterfaceContext::resetMediaState()
+{
+    if (m_manager)
+        m_manager-&gt;resetMediaState(m_contextId);
+}
+
+void WebVideoFullscreenInterfaceContext::setDuration(double duration)
+{
+    if (m_manager)
+        m_manager-&gt;setDuration(m_contextId, duration);
+}
+
+void WebVideoFullscreenInterfaceContext::setCurrentTime(double currentTime, double anchorTime)
+{
+    if (m_manager)
+        m_manager-&gt;setCurrentTime(m_contextId, currentTime, anchorTime);
+}
+
+void WebVideoFullscreenInterfaceContext::setBufferedTime(double bufferedTime)
+{
+    if (m_manager)
+        m_manager-&gt;setBufferedTime(m_contextId, bufferedTime);
+}
+
+void WebVideoFullscreenInterfaceContext::setRate(bool isPlaying, float playbackRate)
+{
+    if (m_manager)
+        m_manager-&gt;setRate(m_contextId, isPlaying, playbackRate);
+}
+
+void WebVideoFullscreenInterfaceContext::setVideoDimensions(bool hasVideo, float width, float height)
+{
+    if (m_manager)
+        m_manager-&gt;setVideoDimensions(m_contextId, hasVideo, width, height);
+}
+
+void WebVideoFullscreenInterfaceContext::setSeekableRanges(const WebCore::TimeRanges&amp; ranges)
+{
+    if (m_manager)
+        m_manager-&gt;setSeekableRanges(m_contextId, ranges);
+}
+
+void WebVideoFullscreenInterfaceContext::setCanPlayFastReverse(bool value)
+{
+    if (m_manager)
+        m_manager-&gt;setCanPlayFastReverse(m_contextId, value);
+}
+
+void WebVideoFullscreenInterfaceContext::setAudioMediaSelectionOptions(const Vector&lt;WTF::String&gt;&amp; options, uint64_t selectedIndex)
+{
+    if (m_manager)
+        m_manager-&gt;setAudioMediaSelectionOptions(m_contextId, options, selectedIndex);
+}
+
+void WebVideoFullscreenInterfaceContext::setLegibleMediaSelectionOptions(const Vector&lt;WTF::String&gt;&amp; options, uint64_t selectedIndex)
+{
+    if (m_manager)
+        m_manager-&gt;setLegibleMediaSelectionOptions(m_contextId, options, selectedIndex);
+}
+
+void WebVideoFullscreenInterfaceContext::setExternalPlayback(bool enabled, ExternalPlaybackTargetType type, WTF::String localizedDeviceName)
+{
+    if (m_manager)
+        m_manager-&gt;setExternalPlayback(m_contextId, enabled, type, localizedDeviceName);
+}
+
+#pragma mark - WebVideoFullscreenManager
+
</ins><span class="cx"> PassRefPtr&lt;WebVideoFullscreenManager&gt; WebVideoFullscreenManager::create(PassRefPtr&lt;WebPage&gt; page)
</span><span class="cx"> {
</span><span class="cx">     return adoptRef(new WebVideoFullscreenManager(page));
</span><span class="lines">@@ -67,20 +158,60 @@
</span><span class="cx"> 
</span><span class="cx"> WebVideoFullscreenManager::WebVideoFullscreenManager(PassRefPtr&lt;WebPage&gt; page)
</span><span class="cx">     : m_page(page.get())
</span><del>-    , m_isAnimating(false)
-    , m_targetIsFullscreen(false)
-    , m_fullscreenMode(HTMLMediaElement::VideoFullscreenModeNone)
-    , m_isFullscreen(false)
</del><span class="cx"> {
</span><del>-    setWebVideoFullscreenInterface(this);
</del><span class="cx">     WebProcess::singleton().addMessageReceiver(Messages::WebVideoFullscreenManager::messageReceiverName(), page-&gt;pageID(), *this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> WebVideoFullscreenManager::~WebVideoFullscreenManager()
</span><span class="cx"> {
</span><ins>+    for (auto&amp; tuple : m_contextMap.values()) {
+        RefPtr&lt;WebVideoFullscreenModelVideoElement&gt; model;
+        RefPtr&lt;WebVideoFullscreenInterfaceContext&gt; interface;
+        std::tie(model, interface) = tuple;
+
+        model-&gt;setWebVideoFullscreenInterface(nullptr);
+        model-&gt;setVideoElement(nullptr);
+
+        interface-&gt;invalidate();
+    }
+
+    m_contextMap.clear();
+    m_videoElements.clear();
+
</ins><span class="cx">     WebProcess::singleton().removeMessageReceiver(Messages::WebVideoFullscreenManager::messageReceiverName(), m_page-&gt;pageID());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+WebVideoFullscreenManager::ModelInterfaceTuple WebVideoFullscreenManager::createModelAndInterface(uint64_t contextId)
+{
+    RefPtr&lt;WebVideoFullscreenModelVideoElement&gt; model = WebVideoFullscreenModelVideoElement::create();
+    RefPtr&lt;WebVideoFullscreenInterfaceContext&gt; interface = WebVideoFullscreenInterfaceContext::create(*this, contextId);
+
+    interface-&gt;setLayerHostingContext(LayerHostingContext::createForExternalHostingProcess());
+    model-&gt;setWebVideoFullscreenInterface(interface.get());
+
+    return std::make_tuple(WTF::move(model), WTF::move(interface));
+}
+
+WebVideoFullscreenManager::ModelInterfaceTuple&amp; WebVideoFullscreenManager::ensureModelAndInterface(uint64_t contextId)
+{
+    auto addResult = m_contextMap.add(contextId, ModelInterfaceTuple());
+    if (addResult.isNewEntry)
+        addResult.iterator-&gt;value = createModelAndInterface(contextId);
+    return addResult.iterator-&gt;value;
+}
+
+WebCore::WebVideoFullscreenModelVideoElement&amp; WebVideoFullscreenManager::ensureModel(uint64_t contextId)
+{
+    return *std::get&lt;0&gt;(ensureModelAndInterface(contextId));
+}
+
+WebVideoFullscreenInterfaceContext&amp; WebVideoFullscreenManager::ensureInterface(uint64_t contextId)
+{
+    return *std::get&lt;1&gt;(ensureModelAndInterface(contextId));
+}
+
+#pragma mark Interface to ChromeClient:
+
</ins><span class="cx"> bool WebVideoFullscreenManager::supportsVideoFullscreen() const
</span><span class="cx"> {
</span><span class="cx">     return Settings::avKitEnabled();
</span><span class="lines">@@ -90,66 +221,79 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(mode != HTMLMediaElement::VideoFullscreenModeNone);
</span><span class="cx"> 
</span><del>-    m_videoElement = &amp;videoElement;
</del><ins>+    uint64_t contextId;
</ins><span class="cx"> 
</span><del>-    m_targetIsFullscreen = true;
-    m_fullscreenMode = mode;
</del><ins>+    auto addResult = m_videoElements.add(&amp;videoElement, 0);
+    if (addResult.isNewEntry)
+        addResult.iterator-&gt;value = nextContextId();
+    contextId = addResult.iterator-&gt;value;
</ins><span class="cx"> 
</span><del>-    if (m_isAnimating)
</del><ins>+    RefPtr&lt;WebVideoFullscreenModelVideoElement&gt; model;
+    RefPtr&lt;WebVideoFullscreenInterfaceContext&gt; interface;
+    std::tie(model, interface) = ensureModelAndInterface(contextId);
+
+    interface-&gt;setTargetIsFullscreen(true);
+    interface-&gt;setFullscreenMode(mode);
+    model-&gt;setVideoElement(&amp;videoElement);
+
+    if (interface-&gt;isAnimating())
</ins><span class="cx">         return;
</span><ins>+    interface-&gt;setIsAnimating(true);
</ins><span class="cx"> 
</span><del>-    m_isAnimating = true;
-    setVideoElement(&amp;videoElement);
-
-    m_layerHostingContext = LayerHostingContext::createForExternalHostingProcess();
-    bool allowOptimizedFullscreen = m_videoElement-&gt;mediaSession().allowsAlternateFullscreen(*m_videoElement.get());
</del><ins>+    bool allowOptimizedFullscreen = videoElement.mediaSession().allowsAlternateFullscreen(videoElement);
</ins><span class="cx">     
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::SetupFullscreenWithID(m_layerHostingContext-&gt;contextID(), clientRectForElement(&amp;videoElement), m_page-&gt;deviceScaleFactor(), m_fullscreenMode, allowOptimizedFullscreen), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::SetupFullscreenWithID(contextId, interface-&gt;layerHostingContext()-&gt;contextID(), clientRectForElement(&amp;videoElement), m_page-&gt;deviceScaleFactor(), interface-&gt;fullscreenMode(), allowOptimizedFullscreen), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVideoFullscreenManager::exitVideoFullscreenForVideoElement(WebCore::HTMLVideoElement&amp;)
</del><ins>+void WebVideoFullscreenManager::exitVideoFullscreenForVideoElement(WebCore::HTMLVideoElement&amp; videoElement)
</ins><span class="cx"> {
</span><del>-    RefPtr&lt;HTMLVideoElement&gt; videoElement = m_videoElement.release();
-    m_targetIsFullscreen = false;
</del><ins>+    ASSERT(m_videoElements.contains(&amp;videoElement));
</ins><span class="cx"> 
</span><del>-    if (m_isAnimating)
</del><ins>+    uint64_t contextId = m_videoElements.get(&amp;videoElement);
+    auto&amp; interface = ensureInterface(contextId);
+
+    interface.setTargetIsFullscreen(false);
+
+    if (interface.isAnimating())
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    m_isAnimating = true;
-    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::ExitFullscreen(clientRectForElement(videoElement.get())), m_page-&gt;pageID());
</del><ins>+    interface.setIsAnimating(true);
+    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::ExitFullscreen(contextId, clientRectForElement(&amp;videoElement)), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVideoFullscreenManager::resetMediaState()
</del><ins>+#pragma mark Interface to WebVideoFullscreenInterfaceContext:
+
+void WebVideoFullscreenManager::resetMediaState(uint64_t contextId)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::ResetMediaState(), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::ResetMediaState(contextId), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><span class="cx">     
</span><del>-void WebVideoFullscreenManager::setDuration(double duration)
</del><ins>+void WebVideoFullscreenManager::setDuration(uint64_t contextId, double duration)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::SetDuration(duration), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::SetDuration(contextId, duration), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVideoFullscreenManager::setCurrentTime(double currentTime, double anchorTime)
</del><ins>+void WebVideoFullscreenManager::setCurrentTime(uint64_t contextId, double currentTime, double anchorTime)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::SetCurrentTime(currentTime, anchorTime), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::SetCurrentTime(contextId, currentTime, anchorTime), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVideoFullscreenManager::setBufferedTime(double bufferedTime)
</del><ins>+void WebVideoFullscreenManager::setBufferedTime(uint64_t contextId, double bufferedTime)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::SetBufferedTime(bufferedTime), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::SetBufferedTime(contextId, bufferedTime), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVideoFullscreenManager::setRate(bool isPlaying, float playbackRate)
</del><ins>+void WebVideoFullscreenManager::setRate(uint64_t contextId, bool isPlaying, float playbackRate)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::SetRate(isPlaying, playbackRate), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::SetRate(contextId, isPlaying, playbackRate), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVideoFullscreenManager::setVideoDimensions(bool hasVideo, float width, float height)
</del><ins>+void WebVideoFullscreenManager::setVideoDimensions(uint64_t contextId, bool hasVideo, float width, float height)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::SetVideoDimensions(hasVideo, width, height), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::SetVideoDimensions(contextId, hasVideo, width, height), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><span class="cx">     
</span><del>-void WebVideoFullscreenManager::setSeekableRanges(const WebCore::TimeRanges&amp; timeRanges)
</del><ins>+void WebVideoFullscreenManager::setSeekableRanges(uint64_t contextId, const WebCore::TimeRanges&amp; timeRanges)
</ins><span class="cx"> {
</span><span class="cx">     Vector&lt;std::pair&lt;double, double&gt;&gt; rangesVector;
</span><span class="cx">     
</span><span class="lines">@@ -160,31 +304,105 @@
</span><span class="cx">         rangesVector.append(std::pair&lt;double,double&gt;(start, end));
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::SetSeekableRangesVector(WTF::move(rangesVector)), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::SetSeekableRangesVector(contextId, WTF::move(rangesVector)), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVideoFullscreenManager::setCanPlayFastReverse(bool value)
</del><ins>+void WebVideoFullscreenManager::setCanPlayFastReverse(uint64_t contextId, bool value)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::SetCanPlayFastReverse(value), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::SetCanPlayFastReverse(contextId, value), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVideoFullscreenManager::setAudioMediaSelectionOptions(const Vector&lt;String&gt;&amp; options, uint64_t selectedIndex)
</del><ins>+void WebVideoFullscreenManager::setAudioMediaSelectionOptions(uint64_t contextId, const Vector&lt;String&gt;&amp; options, uint64_t selectedIndex)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::SetAudioMediaSelectionOptions(options, selectedIndex), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::SetAudioMediaSelectionOptions(contextId, options, selectedIndex), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVideoFullscreenManager::setLegibleMediaSelectionOptions(const Vector&lt;String&gt;&amp; options, uint64_t selectedIndex)
</del><ins>+void WebVideoFullscreenManager::setLegibleMediaSelectionOptions(uint64_t contextId, const Vector&lt;String&gt;&amp; options, uint64_t selectedIndex)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::SetLegibleMediaSelectionOptions(options, selectedIndex), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::SetLegibleMediaSelectionOptions(contextId, options, selectedIndex), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVideoFullscreenManager::setExternalPlayback(bool enabled, WebVideoFullscreenInterface::ExternalPlaybackTargetType targetType, String localizedDeviceName)
</del><ins>+void WebVideoFullscreenManager::setExternalPlayback(uint64_t contextId, bool enabled, WebVideoFullscreenInterface::ExternalPlaybackTargetType targetType, String localizedDeviceName)
</ins><span class="cx"> {
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::SetExternalPlaybackProperties(enabled, static_cast&lt;uint32_t&gt;(targetType), localizedDeviceName), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::SetExternalPlaybackProperties(contextId, enabled, static_cast&lt;uint32_t&gt;(targetType), localizedDeviceName), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><del>-    
-void WebVideoFullscreenManager::didSetupFullscreen()
</del><ins>+
+#pragma mark Messages from WebVideoFullscreenManagerProxy:
+
+void WebVideoFullscreenManager::play(uint64_t contextId)
</ins><span class="cx"> {
</span><ins>+    ensureModel(contextId).play();
+}
+
+void WebVideoFullscreenManager::pause(uint64_t contextId)
+{
+    ensureModel(contextId).pause();
+}
+
+void WebVideoFullscreenManager::togglePlayState(uint64_t contextId)
+{
+    ensureModel(contextId).togglePlayState();
+}
+
+void WebVideoFullscreenManager::beginScrubbing(uint64_t contextId)
+{
+    ensureModel(contextId).beginScrubbing();
+}
+
+void WebVideoFullscreenManager::endScrubbing(uint64_t contextId)
+{
+    ensureModel(contextId).endScrubbing();
+}
+
+void WebVideoFullscreenManager::seekToTime(uint64_t contextId, double time)
+{
+    ensureModel(contextId).seekToTime(time);
+}
+
+void WebVideoFullscreenManager::fastSeek(uint64_t contextId, double time)
+{
+    ensureModel(contextId).fastSeek(time);
+}
+
+void WebVideoFullscreenManager::beginScanningForward(uint64_t contextId)
+{
+    ensureModel(contextId).beginScanningForward();
+}
+
+void WebVideoFullscreenManager::beginScanningBackward(uint64_t contextId)
+{
+    ensureModel(contextId).beginScanningBackward();
+}
+
+void WebVideoFullscreenManager::endScanning(uint64_t contextId)
+{
+    ensureModel(contextId).endScanning();
+}
+
+void WebVideoFullscreenManager::requestExitFullscreen(uint64_t contextId)
+{
+    ensureModel(contextId).requestExitFullscreen();
+}
+
+void WebVideoFullscreenManager::selectAudioMediaOption(uint64_t contextId, uint64_t index)
+{
+    ensureModel(contextId).selectAudioMediaOption(index);
+}
+
+void WebVideoFullscreenManager::selectLegibleMediaOption(uint64_t contextId, uint64_t index)
+{
+    ensureModel(contextId).selectLegibleMediaOption(index);
+}
+
+void WebVideoFullscreenManager::fullscreenModeChanged(uint64_t contextId, WebCore::HTMLMediaElement::VideoFullscreenMode videoFullscreenMode)
+{
+    ensureModel(contextId).fullscreenModeChanged(videoFullscreenMode);
+}
+
+#pragma mark Messages from WebVideoFullscreenManager:
+
+void WebVideoFullscreenManager::didSetupFullscreen(uint64_t contextId)
+{
</ins><span class="cx">     PlatformLayer* videoLayer = [CALayer layer];
</span><span class="cx"> #ifndef NDEBUG
</span><span class="cx">     [videoLayer setName:@&quot;Web video fullscreen manager layer&quot;];
</span><span class="lines">@@ -200,83 +418,118 @@
</span><span class="cx">     // This scale factor is inverted in the hosting process.
</span><span class="cx">     float hostingScaleFactor = m_page-&gt;deviceScaleFactor();
</span><span class="cx">     [videoLayer setTransform:CATransform3DMakeScale(hostingScaleFactor, hostingScaleFactor, 1)];
</span><del>-    m_layerHostingContext-&gt;setRootLayer(videoLayer);
</del><span class="cx"> 
</span><del>-    setVideoFullscreenLayer(videoLayer);
</del><ins>+    RefPtr&lt;WebVideoFullscreenModelVideoElement&gt; model;
+    RefPtr&lt;WebVideoFullscreenInterfaceContext&gt; interface;
+    std::tie(model, interface) = ensureModelAndInterface(contextId);
+
+    interface-&gt;layerHostingContext()-&gt;setRootLayer(videoLayer);
+    model-&gt;setVideoFullscreenLayer(videoLayer);
+
</ins><span class="cx">     [CATransaction commit];
</span><span class="cx"> 
</span><del>-    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::EnterFullscreen(), m_page-&gt;pageID());
</del><ins>+    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::EnterFullscreen(contextId), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><span class="cx">     
</span><del>-void WebVideoFullscreenManager::didEnterFullscreen()
</del><ins>+void WebVideoFullscreenManager::didEnterFullscreen(uint64_t contextId)
</ins><span class="cx"> {
</span><del>-    m_isAnimating = false;
-    m_isFullscreen = false;
</del><ins>+    RefPtr&lt;WebVideoFullscreenModelVideoElement&gt; model;
+    RefPtr&lt;WebVideoFullscreenInterfaceContext&gt; interface;
+    std::tie(model, interface) = ensureModelAndInterface(contextId);
</ins><span class="cx"> 
</span><del>-    if (m_targetIsFullscreen)
</del><ins>+    interface-&gt;setIsAnimating(false);
+    interface-&gt;setIsFullscreen(false);
+
+    if (interface-&gt;targetIsFullscreen())
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    RefPtr&lt;HTMLVideoElement&gt; videoElement = model-&gt;videoElement();
+    if (!videoElement)
+        return;
+
</ins><span class="cx">     // exit fullscreen now if it was previously requested during an animation.
</span><del>-    __block RefPtr&lt;WebVideoFullscreenModelVideoElement&gt; protect(this);
-    WebThreadRun(^ {
-        exitVideoFullscreenForVideoElement(*m_videoElement);
-        protect.clear();
</del><ins>+    RefPtr&lt;WebVideoFullscreenManager&gt; strongThis(this);
+    WebThreadRun([strongThis, videoElement] {
+        strongThis-&gt;exitVideoFullscreenForVideoElement(*videoElement);
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVideoFullscreenManager::didExitFullscreen()
</del><ins>+void WebVideoFullscreenManager::didExitFullscreen(uint64_t contextId)
</ins><span class="cx"> {
</span><del>-    setVideoFullscreenLayer(nil);
-    __block RefPtr&lt;WebVideoFullscreenModelVideoElement&gt; protect(this);
</del><ins>+    RefPtr&lt;WebVideoFullscreenModelVideoElement&gt; model;
+    RefPtr&lt;WebVideoFullscreenInterfaceContext&gt; interface;
+    std::tie(model, interface) = ensureModelAndInterface(contextId);
</ins><span class="cx"> 
</span><del>-    dispatch_async(dispatch_get_main_queue(), ^{
-        if (m_layerHostingContext) {
-            m_layerHostingContext-&gt;setRootLayer(nullptr);
-            m_layerHostingContext = nullptr;
</del><ins>+    model-&gt;setVideoFullscreenLayer(nil);
+
+    RefPtr&lt;WebVideoFullscreenManager&gt; strongThis(this);
+    dispatch_async(dispatch_get_main_queue(), [strongThis, contextId, interface] {
+        if (interface-&gt;layerHostingContext()) {
+            interface-&gt;layerHostingContext()-&gt;setRootLayer(nullptr);
+            interface-&gt;setLayerHostingContext(nullptr);
</ins><span class="cx">         }
</span><del>-        if (m_page)
-            m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::CleanupFullscreen(), m_page-&gt;pageID());
-        protect.clear();
</del><ins>+        if (strongThis-&gt;m_page)
+            strongThis-&gt;m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::CleanupFullscreen(contextId), strongThis-&gt;m_page-&gt;pageID());
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx">     
</span><del>-void WebVideoFullscreenManager::didCleanupFullscreen()
</del><ins>+void WebVideoFullscreenManager::didCleanupFullscreen(uint64_t contextId)
</ins><span class="cx"> {
</span><del>-    m_isAnimating = false;
-    m_isFullscreen = false;
-    
-    setVideoElement(nullptr);
</del><ins>+    RefPtr&lt;WebVideoFullscreenModelVideoElement&gt; model;
+    RefPtr&lt;WebVideoFullscreenInterfaceContext&gt; interface;
+    std::tie(model, interface) = ensureModelAndInterface(contextId);
</ins><span class="cx"> 
</span><del>-    if (!m_targetIsFullscreen)
</del><ins>+    interface-&gt;setIsAnimating(false);
+    interface-&gt;setIsFullscreen(false);
+    HTMLMediaElement::VideoFullscreenMode mode = interface-&gt;fullscreenMode();
+
+    model-&gt;setVideoFullscreenLayer(nil);
+    RefPtr&lt;HTMLVideoElement&gt; videoElement = model-&gt;videoElement();
+
+    if (!interface-&gt;targetIsFullscreen()) {
+        model-&gt;setVideoElement(nullptr);
+        model-&gt;setWebVideoFullscreenInterface(nullptr);
+        interface-&gt;invalidate();
+        m_videoElements.remove(videoElement.get());
+        m_contextMap.remove(contextId);
</ins><span class="cx">         return;
</span><ins>+    }
</ins><span class="cx"> 
</span><del>-    // enter fullscreen now if it was previously requested during an animation.
-    __block RefPtr&lt;WebVideoFullscreenModelVideoElement&gt; protect(this);
-    WebThreadRun(^ {
-        enterVideoFullscreenForVideoElement(*m_videoElement, m_fullscreenMode);
-        protect.clear();
</del><ins>+    if (!videoElement)
+        return;
+
+    // exit fullscreen now if it was previously requested during an animation.
+    RefPtr&lt;WebVideoFullscreenManager&gt; strongThis(this);
+    WebThreadRun([strongThis, videoElement, mode] {
+        strongThis-&gt;enterVideoFullscreenForVideoElement(*videoElement, mode);
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx">     
</span><del>-void WebVideoFullscreenManager::setVideoLayerGravityEnum(unsigned gravity)
</del><ins>+void WebVideoFullscreenManager::setVideoLayerGravityEnum(uint64_t contextId, unsigned gravity)
</ins><span class="cx"> {
</span><del>-    setVideoLayerGravity((WebVideoFullscreenModel::VideoGravity)gravity);
</del><ins>+    ensureModel(contextId).setVideoLayerGravity((WebVideoFullscreenModel::VideoGravity)gravity);
</ins><span class="cx"> }
</span><span class="cx">     
</span><del>-void WebVideoFullscreenManager::fullscreenMayReturnToInline(bool isPageVisible)
</del><ins>+void WebVideoFullscreenManager::fullscreenMayReturnToInline(uint64_t contextId, bool isPageVisible)
</ins><span class="cx"> {
</span><ins>+    auto&amp; model = ensureModel(contextId);
+
</ins><span class="cx">     if (!isPageVisible)
</span><del>-        m_videoElement-&gt;scrollIntoViewIfNotVisible(false);
-    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::PreparedToReturnToInline(true, clientRectForElement(m_videoElement.get())), m_page-&gt;pageID());
</del><ins>+        model.videoElement()-&gt;scrollIntoViewIfNotVisible(false);
+    m_page-&gt;send(Messages::WebVideoFullscreenManagerProxy::PreparedToReturnToInline(contextId, true, clientRectForElement(model.videoElement())), m_page-&gt;pageID());
</ins><span class="cx"> }
</span><span class="cx">     
</span><del>-void WebVideoFullscreenManager::setVideoLayerFrameFenced(WebCore::FloatRect bounds, IPC::Attachment fencePort)
</del><ins>+void WebVideoFullscreenManager::setVideoLayerFrameFenced(uint64_t contextId, WebCore::FloatRect bounds, IPC::Attachment fencePort)
</ins><span class="cx"> {
</span><ins>+    RefPtr&lt;WebVideoFullscreenModelVideoElement&gt; model;
+    RefPtr&lt;WebVideoFullscreenInterfaceContext&gt; interface;
+    std::tie(model, interface) = ensureModelAndInterface(contextId);
+
</ins><span class="cx">     [CATransaction begin];
</span><span class="cx">     [CATransaction setAnimationDuration:0];
</span><del>-    if (m_layerHostingContext)
-        m_layerHostingContext-&gt;setFencePort(fencePort.port());
-    setVideoLayerFrame(bounds);
</del><ins>+    if (interface-&gt;layerHostingContext())
+        interface-&gt;layerHostingContext()-&gt;setFencePort(fencePort.port());
+    model-&gt;setVideoLayerFrame(bounds);
</ins><span class="cx">     mach_port_deallocate(mach_task_self(), fencePort.port());
</span><span class="cx">     [CATransaction commit];
</span><span class="cx"> }
</span></span></pre>
</div>
</div>

</body>
</html>