<!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>[277573] trunk</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/277573">277573</a></dd>
<dt>Author</dt> <dd>jer.noble@apple.com</dd>
<dt>Date</dt> <dd>2021-05-16 13:32:30 -0700 (Sun, 16 May 2021)</dd>
</dl>

<h3>Log Message</h3>
<pre>MediaSessionCoordinator survives page reload/navigation
https://bugs.webkit.org/show_bug.cgi?id=225822

Reviewed by Eric Carlson.

Source/WebCore:

Because the MediaSessionCoordinator is created and owned by Page, it will survive
a reload (as Page is not re-created), and the same MediaSessionCoordinator object
will be added to MediaSession when the new Navigator is created.

Rather than have Page own the coordinator itself, it can instead own the
MediaSessionCoordinatorPrivate used to create the coordinator. When the MediaSession
is created, it will query the Page to ask for a MediaSessionCoordinatorPrivate to
use to create the coordinator, guaranteeing a new object is created.

The session itself should be left when the document is put into Back/Forward
Cache, or closed when the document is stopped entirely.

A few drive-by fixes:

The direction of coordinatorStateChanged() is now reversed; it flows down from the
UIProcess to update the state of the MediaSessionCoordinator. This allows the coordinator
to react when it's private implementation changes state.

Add a new upward notification when the trackIdentifier in MediaMetadata changes.

* Modules/mediasession/MediaSession.cpp:
(WebCore::MediaSession::MediaSession):
(WebCore::MediaSession::suspend):
(WebCore::MediaSession::stop):
(WebCore::MediaSession::createCoordinator):
(WebCore::MediaSession::setCoordinator): Deleted.
* Modules/mediasession/MediaSession.h:
* Modules/mediasession/MediaSessionCoordinator.cpp:
(WebCore::MediaSessionCoordinator::join):
(WebCore::MediaSessionCoordinator::leave):
(WebCore::MediaSessionCoordinator::close):
(WebCore::MediaSessionCoordinator::metadataChanged):
(WebCore::MediaSessionCoordinator::positionStateChanged):
(WebCore::MediaSessionCoordinator::playbackStateChanged):
(WebCore::MediaSessionCoordinator::readyStateChanged):
(WebCore::MediaSessionCoordinator::seekSessionToTime):
(WebCore::MediaSessionCoordinator::pauseSession):
(WebCore::MediaSessionCoordinator::coordinatorStateChanged):
* Modules/mediasession/MediaSessionCoordinator.h:
* Modules/mediasession/MediaSessionCoordinatorPrivate.h:
(WebCore::MediaSessionCoordinatorClient::coordinatorStateChanged):
* page/Page.cpp:
(WebCore::Page::setMediaSessionCoordinator):
(WebCore::Page::invalidateMediaSessionCoordinator):
* page/Page.h:
(WebCore::Page::mediaSessionCoordinator):
* testing/Internals.cpp:
(WebCore::Internals::registerMockMediaSessionCoordinator):
* testing/Internals.h:
* testing/MockMediaSessionCoordinator.cpp:
(WebCore::MockMediaSessionCoordinator::trackIdentifierChanged):
(WebCore::MockMediaSessionCoordinator::coordinatorStateChanged): Deleted.
* testing/MockMediaSessionCoordinator.h:

Source/WebKit:

Update the classes affected by virtual function changes in MediaSessionCoordinator. Update
the creation mechanism inside WebPage/Proxy.

* UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h:
* UIProcess/API/Cocoa/WKWebViewTesting.mm:
(-[WKWebView _createMediaSessionCoordinatorForTesting:completionHandler:]):
* UIProcess/Media/MediaSessionCoordinatorProxyPrivate.h:
* UIProcess/Media/RemoteMediaSessionCoordinatorProxy.cpp:
(WebKit::RemoteMediaSessionCoordinatorProxy::trackIdentifierChanged):
(WebKit::RemoteMediaSessionCoordinatorProxy::coordinatorStateChanged):
* UIProcess/Media/RemoteMediaSessionCoordinatorProxy.h:
* UIProcess/Media/RemoteMediaSessionCoordinatorProxy.messages.in:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::createMediaSessionCoordinator):
* WebProcess/MediaSession/RemoteMediaSessionCoordinator.cpp:
(WebKit::RemoteMediaSessionCoordinator::trackIdentifierChanged):
(WebKit::RemoteMediaSessionCoordinator::coordinatorStateChanged):
* WebProcess/MediaSession/RemoteMediaSessionCoordinator.h:
* WebProcess/MediaSession/RemoteMediaSessionCoordinator.messages.in:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::createMediaSessionCoordinator):
(WebKit::WebPage::invalidateMediaSessionCoordinator):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:

Tools:

* TestWebKitAPI/Tests/WebKit/MediaSessionCoordinatorTest.mm:
(-[_WKMockMediaSessionCoordinator trackIdentifierChanged:]):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModulesmediasessionMediaPositionStateh">trunk/Source/WebCore/Modules/mediasession/MediaPositionState.h</a></li>
<li><a href="#trunkSourceWebCoreModulesmediasessionMediaSessioncpp">trunk/Source/WebCore/Modules/mediasession/MediaSession.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediasessionMediaSessionh">trunk/Source/WebCore/Modules/mediasession/MediaSession.h</a></li>
<li><a href="#trunkSourceWebCoreModulesmediasessionMediaSessionCoordinatorcpp">trunk/Source/WebCore/Modules/mediasession/MediaSessionCoordinator.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediasessionMediaSessionCoordinatorh">trunk/Source/WebCore/Modules/mediasession/MediaSessionCoordinator.h</a></li>
<li><a href="#trunkSourceWebCoreModulesmediasessionMediaSessionCoordinatorPrivateh">trunk/Source/WebCore/Modules/mediasession/MediaSessionCoordinatorPrivate.h</a></li>
<li><a href="#trunkSourceWebCorepagePagecpp">trunk/Source/WebCore/page/Page.cpp</a></li>
<li><a href="#trunkSourceWebCorepagePageh">trunk/Source/WebCore/page/Page.h</a></li>
<li><a href="#trunkSourceWebCoretestingInternalscpp">trunk/Source/WebCore/testing/Internals.cpp</a></li>
<li><a href="#trunkSourceWebCoretestingInternalsh">trunk/Source/WebCore/testing/Internals.h</a></li>
<li><a href="#trunkSourceWebCoretestingMockMediaSessionCoordinatorcpp">trunk/Source/WebCore/testing/MockMediaSessionCoordinator.cpp</a></li>
<li><a href="#trunkSourceWebCoretestingMockMediaSessionCoordinatorh">trunk/Source/WebCore/testing/MockMediaSessionCoordinator.h</a></li>
<li><a href="#trunkSourceWebKitChangeLog">trunk/Source/WebKit/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitUIProcessAPICocoaWKWebViewPrivateForTestingh">trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessAPICocoaWKWebViewTestingmm">trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewTesting.mm</a></li>
<li><a href="#trunkSourceWebKitUIProcessMediaMediaSessionCoordinatorProxyPrivateh">trunk/Source/WebKit/UIProcess/Media/MediaSessionCoordinatorProxyPrivate.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessMediaRemoteMediaSessionCoordinatorProxycpp">trunk/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.cpp</a></li>
<li><a href="#trunkSourceWebKitUIProcessMediaRemoteMediaSessionCoordinatorProxyh">trunk/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessMediaRemoteMediaSessionCoordinatorProxymessagesin">trunk/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.messages.in</a></li>
<li><a href="#trunkSourceWebKitUIProcessWebPageProxycpp">trunk/Source/WebKit/UIProcess/WebPageProxy.cpp</a></li>
<li><a href="#trunkSourceWebKitWebProcessMediaSessionRemoteMediaSessionCoordinatorcpp">trunk/Source/WebKit/WebProcess/MediaSession/RemoteMediaSessionCoordinator.cpp</a></li>
<li><a href="#trunkSourceWebKitWebProcessMediaSessionRemoteMediaSessionCoordinatorh">trunk/Source/WebKit/WebProcess/MediaSession/RemoteMediaSessionCoordinator.h</a></li>
<li><a href="#trunkSourceWebKitWebProcessMediaSessionRemoteMediaSessionCoordinatormessagesin">trunk/Source/WebKit/WebProcess/MediaSession/RemoteMediaSessionCoordinator.messages.in</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebPageWebPagecpp">trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebPageWebPageh">trunk/Source/WebKit/WebProcess/WebPage/WebPage.h</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebPageWebPagemessagesin">trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKitMediaSessionCoordinatorTestmm">trunk/Tools/TestWebKitAPI/Tests/WebKit/MediaSessionCoordinatorTest.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog   2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebCore/ChangeLog      2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -1,3 +1,64 @@
</span><ins>+2021-05-14  Jer Noble  <jer.noble@apple.com>
+
+        MediaSessionCoordinator survives page reload/navigation
+        https://bugs.webkit.org/show_bug.cgi?id=225822
+
+        Reviewed by Eric Carlson.
+
+        Because the MediaSessionCoordinator is created and owned by Page, it will survive
+        a reload (as Page is not re-created), and the same MediaSessionCoordinator object
+        will be added to MediaSession when the new Navigator is created.
+
+        Rather than have Page own the coordinator itself, it can instead own the
+        MediaSessionCoordinatorPrivate used to create the coordinator. When the MediaSession
+        is created, it will query the Page to ask for a MediaSessionCoordinatorPrivate to
+        use to create the coordinator, guaranteeing a new object is created.
+
+        The session itself should be left when the document is put into Back/Forward
+        Cache, or closed when the document is stopped entirely.
+
+        A few drive-by fixes:
+
+        The direction of coordinatorStateChanged() is now reversed; it flows down from the
+        UIProcess to update the state of the MediaSessionCoordinator. This allows the coordinator
+        to react when it's private implementation changes state.
+
+        Add a new upward notification when the trackIdentifier in MediaMetadata changes.
+
+        * Modules/mediasession/MediaSession.cpp:
+        (WebCore::MediaSession::MediaSession):
+        (WebCore::MediaSession::suspend):
+        (WebCore::MediaSession::stop):
+        (WebCore::MediaSession::createCoordinator):
+        (WebCore::MediaSession::setCoordinator): Deleted.
+        * Modules/mediasession/MediaSession.h:
+        * Modules/mediasession/MediaSessionCoordinator.cpp:
+        (WebCore::MediaSessionCoordinator::join):
+        (WebCore::MediaSessionCoordinator::leave):
+        (WebCore::MediaSessionCoordinator::close):
+        (WebCore::MediaSessionCoordinator::metadataChanged):
+        (WebCore::MediaSessionCoordinator::positionStateChanged):
+        (WebCore::MediaSessionCoordinator::playbackStateChanged):
+        (WebCore::MediaSessionCoordinator::readyStateChanged):
+        (WebCore::MediaSessionCoordinator::seekSessionToTime):
+        (WebCore::MediaSessionCoordinator::pauseSession):
+        (WebCore::MediaSessionCoordinator::coordinatorStateChanged):
+        * Modules/mediasession/MediaSessionCoordinator.h:
+        * Modules/mediasession/MediaSessionCoordinatorPrivate.h:
+        (WebCore::MediaSessionCoordinatorClient::coordinatorStateChanged):
+        * page/Page.cpp:
+        (WebCore::Page::setMediaSessionCoordinator):
+        (WebCore::Page::invalidateMediaSessionCoordinator):
+        * page/Page.h:
+        (WebCore::Page::mediaSessionCoordinator):
+        * testing/Internals.cpp:
+        (WebCore::Internals::registerMockMediaSessionCoordinator):
+        * testing/Internals.h:
+        * testing/MockMediaSessionCoordinator.cpp:
+        (WebCore::MockMediaSessionCoordinator::trackIdentifierChanged):
+        (WebCore::MockMediaSessionCoordinator::coordinatorStateChanged): Deleted.
+        * testing/MockMediaSessionCoordinator.h:
+
</ins><span class="cx"> 2021-05-16  Chris Dumez  <cdumez@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Modernize / Optimize SQLiteStatement creation and preparation
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasessionMediaPositionStateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediasession/MediaPositionState.h (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasession/MediaPositionState.h   2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebCore/Modules/mediasession/MediaPositionState.h      2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -38,6 +38,8 @@
</span><span class="cx"> 
</span><span class="cx">     template<class Encoder> void encode(Encoder&) const;
</span><span class="cx">     template<class Decoder> static Optional<MediaPositionState> decode(Decoder&);
</span><ins>+
+    bool operator==(const MediaPositionState& other) const { return duration == other.duration && playbackRate == other.playbackRate && position == other.position; }
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> template<class Encoder> inline void MediaPositionState::encode(Encoder& encoder) const
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasessionMediaSessioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediasession/MediaSession.cpp (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasession/MediaSession.cpp       2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebCore/Modules/mediasession/MediaSession.cpp  2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -38,6 +38,7 @@
</span><span class="cx"> #include "MediaMetadata.h"
</span><span class="cx"> #include "MediaSessionCoordinator.h"
</span><span class="cx"> #include "Navigator.h"
</span><ins>+#include "Page.h"
</ins><span class="cx"> #include "PlatformMediaSessionManager.h"
</span><span class="cx"> #include <wtf/JSONValues.h>
</span><span class="cx"> 
</span><span class="lines">@@ -136,6 +137,15 @@
</span><span class="cx"> {
</span><span class="cx">     m_logger = makeRefPtr(Document::sharedLogger());
</span><span class="cx">     m_logIdentifier = nextLogIdentifier();
</span><ins>+
+#if ENABLE(MEDIA_SESSION_COORDINATOR)
+    auto* frame = navigator.frame();
+    if (auto* page = frame ? frame->page() : nullptr) {
+        if (auto coordinatorPrivate = page->mediaSessionCoordinator())
+            createCoordinator(*coordinatorPrivate);
+    }
+#endif
+
</ins><span class="cx">     suspendIfNeeded();
</span><span class="cx"> 
</span><span class="cx">     ALWAYS_LOG(LOGIDENTIFIER);
</span><span class="lines">@@ -148,6 +158,24 @@
</span><span class="cx">     return m_asyncEventQueue->hasPendingActivity();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MediaSession::suspend(ReasonForSuspension reason)
+{
+#if ENABLE(MEDIA_SESSION_COORDINATOR)
+    if (m_coordinator && reason == ReasonForSuspension::BackForwardCache)
+        m_coordinator->leave();
+#else
+    UNUSED_PARAM(reason);
+#endif
+}
+
+void MediaSession::stop()
+{
+#if ENABLE(MEDIA_SESSION_COORDINATOR)
+    if (m_coordinator)
+        m_coordinator->close();
+#endif
+}
+
</ins><span class="cx"> void MediaSession::setMetadata(RefPtr<MediaMetadata>&& metadata)
</span><span class="cx"> {
</span><span class="cx">     ALWAYS_LOG(LOGIDENTIFIER);
</span><span class="lines">@@ -171,17 +199,14 @@
</span><span class="cx">     notifyReadyStateObservers();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MediaSession::setCoordinator(MediaSessionCoordinator* coordinator)
</del><ins>+void MediaSession::createCoordinator(Ref<MediaSessionCoordinatorPrivate>&& coordinatorPrivate)
</ins><span class="cx"> {
</span><del>-    if (m_coordinator == coordinator)
-        return;
-
</del><span class="cx">     ALWAYS_LOG(LOGIDENTIFIER);
</span><span class="cx"> 
</span><span class="cx">     if (m_coordinator)
</span><span class="cx">         m_coordinator->setMediaSession(nullptr);
</span><span class="cx"> 
</span><del>-    m_coordinator = coordinator;
</del><ins>+    m_coordinator = MediaSessionCoordinator::create(WTFMove(coordinatorPrivate));
</ins><span class="cx"> 
</span><span class="cx">     if (m_coordinator)
</span><span class="cx">         m_coordinator->setMediaSession(this);
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasessionMediaSessionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediasession/MediaSession.h (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasession/MediaSession.h 2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebCore/Modules/mediasession/MediaSession.h    2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -48,6 +48,7 @@
</span><span class="cx"> class HTMLMediaElement;
</span><span class="cx"> class MediaMetadata;
</span><span class="cx"> class MediaSessionCoordinator;
</span><ins>+class MediaSessionCoordinatorPrivate;
</ins><span class="cx"> class Navigator;
</span><span class="cx"> 
</span><span class="cx"> class MediaSession : public RefCounted<MediaSession>, public ActiveDOMObject, public EventTargetWithInlineData {
</span><span class="lines">@@ -77,7 +78,7 @@
</span><span class="cx">     void setReadyState(MediaSessionReadyState);
</span><span class="cx"> 
</span><span class="cx">     MediaSessionCoordinator* coordinator() const { return m_coordinator.get(); }
</span><del>-    WEBCORE_EXPORT void setCoordinator(MediaSessionCoordinator*);
</del><ins>+    WEBCORE_EXPORT void createCoordinator(Ref<MediaSessionCoordinatorPrivate>&&);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(MEDIA_SESSION_PLAYLIST)
</span><span class="lines">@@ -131,6 +132,8 @@
</span><span class="cx">     // ActiveDOMObject
</span><span class="cx">     const char* activeDOMObjectName() const final { return "MediaSession"; }
</span><span class="cx">     bool virtualHasPendingActivity() const final;
</span><ins>+    void suspend(ReasonForSuspension) final;
+    void stop() final;
</ins><span class="cx"> 
</span><span class="cx">     RefPtr<HTMLMediaElement> activeMediaElement() const;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasessionMediaSessionCoordinatorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediasession/MediaSessionCoordinator.cpp (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasession/MediaSessionCoordinator.cpp    2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebCore/Modules/mediasession/MediaSessionCoordinator.cpp       2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -89,7 +89,6 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         protectedThis->m_state = MediaSessionCoordinatorState::Joined;
</span><del>-        protectedThis->m_privateCoordinator->coordinatorStateChanged(MediaSessionCoordinatorState::Joined);
</del><span class="cx">         promise.resolve();
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="lines">@@ -100,13 +99,22 @@
</span><span class="cx">     if (m_state != MediaSessionCoordinatorState::Joined)
</span><span class="cx">         return Exception { InvalidStateError, makeString("Unable to leave when state is ", convertEnumerationToString(m_state)) };
</span><span class="cx"> 
</span><del>-    m_state = MediaSessionCoordinatorState::Closed;
-    m_privateCoordinator->leave();
-    m_privateCoordinator->coordinatorStateChanged(MediaSessionCoordinatorState::Closed);
</del><ins>+    close();
</ins><span class="cx"> 
</span><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MediaSessionCoordinator::close()
+{
+    ALWAYS_LOG(LOGIDENTIFIER);
+    m_state = MediaSessionCoordinatorState::Closed;
+    if (!m_privateCoordinator)
+        return;
+
+    m_privateCoordinator->leave();
+    m_privateCoordinator = nullptr;
+}
+
</ins><span class="cx"> void MediaSessionCoordinator::seekTo(double time, DOMPromiseDeferred<void>&& promise)
</span><span class="cx"> {
</span><span class="cx">     auto identifier = LOGIDENTIFIER;
</span><span class="lines">@@ -248,6 +256,18 @@
</span><span class="cx">         m_session->addObserver(*this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MediaSessionCoordinator::metadataChanged(const RefPtr<MediaMetadata>& metadata)
+{
+#if ENABLE(MEDIA_SESSION_PLAYLIST)
+    if (!m_privateCoordinator)
+        return;
+
+    auto identifier = metadata ? metadata->trackIdentifier() : emptyString();
+    ALWAYS_LOG(LOGIDENTIFIER, m_state, ", trackIdentifier:", identifier);
+    m_privateCoordinator->trackIdentifierChanged(identifier);
+#endif
+}
+
</ins><span class="cx"> void MediaSessionCoordinator::positionStateChanged(const Optional<MediaPositionState>& positionState)
</span><span class="cx"> {
</span><span class="cx">     if (positionState)
</span><span class="lines">@@ -258,6 +278,9 @@
</span><span class="cx">     if (m_state != MediaSessionCoordinatorState::Joined)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    if (!m_privateCoordinator)
+        return;
+
</ins><span class="cx">     if (!positionState) {
</span><span class="cx">         m_privateCoordinator->positionStateChanged({ });
</span><span class="cx">         return;
</span><span class="lines">@@ -273,6 +296,9 @@
</span><span class="cx">     if (m_state != MediaSessionCoordinatorState::Joined)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    if (!m_privateCoordinator)
+        return;
+
</ins><span class="cx">     m_privateCoordinator->playbackStateChanged(playbackState);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -283,6 +309,9 @@
</span><span class="cx">     if (m_state != MediaSessionCoordinatorState::Joined)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    if (!m_privateCoordinator)
+        return;
+
</ins><span class="cx">     m_privateCoordinator->readyStateChanged(readyState);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -295,6 +324,16 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    bool isPaused = m_session->playbackState() == MediaSessionPlaybackState::Paused;
+
+    if (isPaused && currentPositionApproximatelyEqualTo(time)) {
+        completionHandler(true);
+        return;
+    }
+
+    if (!isPaused)
+        m_session->callActionHandler({ .action = MediaSessionAction::Pause });
+
</ins><span class="cx">     m_session->callActionHandler({ .action = MediaSessionAction::Seekto, .seekTime = time });
</span><span class="cx">     completionHandler(true);
</span><span class="cx"> }
</span><span class="lines">@@ -325,7 +364,7 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    m_session->callActionHandler({ .action = MediaSessionAction::Play });
</del><ins>+    m_session->callActionHandler({ .action = MediaSessionAction::Pause });
</ins><span class="cx">     completionHandler(true);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -342,6 +381,14 @@
</span><span class="cx">     completionHandler(true);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MediaSessionCoordinator::coordinatorStateChanged(MediaSessionCoordinatorState state)
+{
+    if (m_state == state)
+        return;
+    m_state = state;
+    ALWAYS_LOG(LOGIDENTIFIER, m_state);
+}
+
</ins><span class="cx"> bool MediaSessionCoordinator::currentPositionApproximatelyEqualTo(double time) const
</span><span class="cx"> {
</span><span class="cx">     if (!m_session)
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasessionMediaSessionCoordinatorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediasession/MediaSessionCoordinator.h (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasession/MediaSessionCoordinator.h      2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebCore/Modules/mediasession/MediaSessionCoordinator.h 2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -48,6 +48,7 @@
</span><span class="cx"> 
</span><span class="cx">     void join(DOMPromiseDeferred<void>&&);
</span><span class="cx">     ExceptionOr<void> leave();
</span><ins>+    void close();
</ins><span class="cx"> 
</span><span class="cx">     String identifier() const { return m_privateCoordinator->identifier(); }
</span><span class="cx">     MediaSessionCoordinatorState state() const { return m_state; }
</span><span class="lines">@@ -66,6 +67,7 @@
</span><span class="cx">     explicit MediaSessionCoordinator(Ref<MediaSessionCoordinatorPrivate>&&);
</span><span class="cx"> 
</span><span class="cx">     // MediaSession::Observer
</span><ins>+    void metadataChanged(const RefPtr<MediaMetadata>&) final;
</ins><span class="cx">     void positionStateChanged(const Optional<MediaPositionState>&) final;
</span><span class="cx">     void playbackStateChanged(MediaSessionPlaybackState) final;
</span><span class="cx">     void readyStateChanged(MediaSessionReadyState) final;
</span><span class="lines">@@ -75,6 +77,7 @@
</span><span class="cx">     void playSession(Optional<double> atTime, Optional<double> hostTime, CompletionHandler<void(bool)>&&) final;
</span><span class="cx">     void pauseSession(CompletionHandler<void(bool)>&&) final;
</span><span class="cx">     void setSessionTrack(const String&, CompletionHandler<void(bool)>&&) final;
</span><ins>+    void coordinatorStateChanged(WebCore::MediaSessionCoordinatorState) final;
</ins><span class="cx"> 
</span><span class="cx">     bool currentPositionApproximatelyEqualTo(double) const;
</span><span class="cx"> 
</span><span class="lines">@@ -85,7 +88,7 @@
</span><span class="cx"> 
</span><span class="cx">     WeakPtr<MediaSession> m_session;
</span><span class="cx">     MediaSessionCoordinatorState m_state { MediaSessionCoordinatorState::Waiting };
</span><del>-    Ref<MediaSessionCoordinatorPrivate> m_privateCoordinator;
</del><ins>+    RefPtr<MediaSessionCoordinatorPrivate> m_privateCoordinator;
</ins><span class="cx">     Ref<const Logger> m_logger;
</span><span class="cx">     const void* m_logIdentifier;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediasessionMediaSessionCoordinatorPrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediasession/MediaSessionCoordinatorPrivate.h (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediasession/MediaSessionCoordinatorPrivate.h       2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebCore/Modules/mediasession/MediaSessionCoordinatorPrivate.h  2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -49,6 +49,7 @@
</span><span class="cx">     virtual void playSession(Optional<double> atTime, Optional<double> hostTime, CompletionHandler<void(bool)>&&) = 0;
</span><span class="cx">     virtual void pauseSession(CompletionHandler<void(bool)>&&) = 0;
</span><span class="cx">     virtual void setSessionTrack(const String&, CompletionHandler<void(bool)>&&) = 0;
</span><ins>+    virtual void coordinatorStateChanged(WebCore::MediaSessionCoordinatorState) { };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> class MediaSessionCoordinatorPrivate : public RefCounted<MediaSessionCoordinatorPrivate> {
</span><span class="lines">@@ -68,7 +69,7 @@
</span><span class="cx">     virtual void positionStateChanged(const Optional<MediaPositionState>&) = 0;
</span><span class="cx">     virtual void readyStateChanged(MediaSessionReadyState) = 0;
</span><span class="cx">     virtual void playbackStateChanged(MediaSessionPlaybackState) = 0;
</span><del>-    virtual void coordinatorStateChanged(MediaSessionCoordinatorState) = 0;
</del><ins>+    virtual void trackIdentifierChanged(const String&) = 0;
</ins><span class="cx"> 
</span><span class="cx">     void setLogger(const WTF::Logger&, const void*);
</span><span class="cx">     virtual void setClient(WeakPtr<MediaSessionCoordinatorClient> client) { m_client = client;}
</span></span></pre></div>
<a id="trunkSourceWebCorepagePagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/Page.cpp (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/Page.cpp       2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebCore/page/Page.cpp  2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -174,6 +174,11 @@
</span><span class="cx"> #include "DisplayView.h"
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if ENABLE(MEDIA_SESSION_COORDINATOR)
+#include "MediaSessionCoordinator.h"
+#include "NavigatorMediaSession.h"
+#endif
+
</ins><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> static HashSet<Page*>& allPages()
</span><span class="lines">@@ -3407,6 +3412,35 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if ENABLE(MEDIA_SESSION_COORDINATOR)
+void Page::setMediaSessionCoordinator(Ref<MediaSessionCoordinatorPrivate>&& mediaSessionCoordinator)
+{
+    m_mediaSessionCoordinator = WTFMove(mediaSessionCoordinator);
+
+    auto* window = mainFrame().window();
+    if (auto* navigator = window ? window->optionalNavigator() : nullptr)
+        NavigatorMediaSession::mediaSession(*navigator).createCoordinator(*m_mediaSessionCoordinator);
+}
+
+void Page::invalidateMediaSessionCoordinator()
+{
+    m_mediaSessionCoordinator = nullptr;
+    auto* window = mainFrame().window();
+    if (!window)
+        return;
+
+    auto* navigator = window->optionalNavigator();
+    if (!navigator)
+        return;
+
+    auto* coordinator = NavigatorMediaSession::mediaSession(*navigator).coordinator();
+    if (!coordinator)
+        return;
+
+    coordinator->close();
+}
+#endif
+
</ins><span class="cx"> void Page::configureLoggingChannel(const String& channelName, WTFLogChannelState state, WTFLogLevel level)
</span><span class="cx"> {
</span><span class="cx"> #if !RELEASE_LOG_DISABLED
</span></span></pre></div>
<a id="trunkSourceWebCorepagePageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/Page.h (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/Page.h 2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebCore/page/Page.h    2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -116,6 +116,7 @@
</span><span class="cx"> class MediaCanStartListener;
</span><span class="cx"> class MediaPlaybackTarget;
</span><span class="cx"> class MediaRecorderProvider;
</span><ins>+class MediaSessionCoordinatorPrivate;
</ins><span class="cx"> class PageConfiguration;
</span><span class="cx"> class PageConsoleClient;
</span><span class="cx"> class PageDebuggable;
</span><span class="lines">@@ -523,6 +524,12 @@
</span><span class="cx">     const Optional<ApplicationManifest>& applicationManifest() const { return m_applicationManifest; }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if ENABLE(MEDIA_SESSION_COORDINATOR)
+    MediaSessionCoordinatorPrivate* mediaSessionCoordinator() { return m_mediaSessionCoordinator.get(); }
+    WEBCORE_EXPORT void setMediaSessionCoordinator(Ref<MediaSessionCoordinatorPrivate>&&);
+    WEBCORE_EXPORT void invalidateMediaSessionCoordinator();
+#endif
+
</ins><span class="cx">     // Notifications when the Page starts and stops being presented via a native window.
</span><span class="cx">     WEBCORE_EXPORT void setActivityState(OptionSet<ActivityState::Flag>);
</span><span class="cx">     OptionSet<ActivityState::Flag> activityState() const { return m_activityState; }
</span><span class="lines">@@ -1143,6 +1150,10 @@
</span><span class="cx">     RefPtr<DeviceOrientationUpdateProvider> m_deviceOrientationUpdateProvider;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if ENABLE(MEDIA_SESSION_COORDINATOR)
+    RefPtr<MediaSessionCoordinatorPrivate> m_mediaSessionCoordinator;
+#endif
+
</ins><span class="cx">     Vector<UserContentURLPattern> m_corsDisablingPatterns;
</span><span class="cx">     Vector<UserStyleSheet> m_userStyleSheetsPendingInjection;
</span><span class="cx">     Optional<HashSet<String>> m_allowedNetworkHosts;
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.cpp (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.cpp       2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebCore/testing/Internals.cpp  2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -6219,7 +6219,7 @@
</span><span class="cx"> #if ENABLE(MEDIA_SESSION_COORDINATOR)
</span><span class="cx"> ExceptionOr<void> Internals::registerMockMediaSessionCoordinator(ScriptExecutionContext& context, RefPtr<StringCallback>&& listener)
</span><span class="cx"> {
</span><del>-    if (m_mediaSessionCoordinator)
</del><ins>+    if (m_mockMediaSessionCoordinator)
</ins><span class="cx">         return { };
</span><span class="cx"> 
</span><span class="cx">     auto* document = contextDocument();
</span><span class="lines">@@ -6232,8 +6232,7 @@
</span><span class="cx">     auto& session = NavigatorMediaSession::mediaSession(document->domWindow()->navigator());
</span><span class="cx">     auto mock = MockMediaSessionCoordinator::create(context, WTFMove(listener));
</span><span class="cx">     m_mockMediaSessionCoordinator = mock.ptr();
</span><del>-    m_mediaSessionCoordinator = MediaSessionCoordinator::create(mock.get());
-    session.setCoordinator(m_mediaSessionCoordinator.get());
</del><ins>+    session.createCoordinator(WTFMove(mock));
</ins><span class="cx"> 
</span><span class="cx">     return { };
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.h (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.h 2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebCore/testing/Internals.h    2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -1192,7 +1192,6 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(MEDIA_SESSION_COORDINATOR)
</span><del>-    RefPtr<MediaSessionCoordinator> m_mediaSessionCoordinator;
</del><span class="cx">     RefPtr<MockMediaSessionCoordinator> m_mockMediaSessionCoordinator;
</span><span class="cx"> #endif
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCoretestingMockMediaSessionCoordinatorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/MockMediaSessionCoordinator.cpp (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/MockMediaSessionCoordinator.cpp     2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebCore/testing/MockMediaSessionCoordinator.cpp        2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -120,10 +120,10 @@
</span><span class="cx">     m_stateChangeListener->scheduleCallback(m_context.get(), "playbackStateChanged");
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MockMediaSessionCoordinator::coordinatorStateChanged(MediaSessionCoordinatorState state)
</del><ins>+void MockMediaSessionCoordinator::trackIdentifierChanged(const String& identifier)
</ins><span class="cx"> {
</span><del>-    ALWAYS_LOG_IF_POSSIBLE(LOGIDENTIFIER, state);
-    m_stateChangeListener->scheduleCallback(m_context.get(), "coordinatorStateChanged");
</del><ins>+    ALWAYS_LOG_IF_POSSIBLE(LOGIDENTIFIER, identifier);
+    m_stateChangeListener->scheduleCallback(m_context.get(), "trackIdentifierChanged");
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> WTFLogChannel& MockMediaSessionCoordinator::logChannel() const
</span></span></pre></div>
<a id="trunkSourceWebCoretestingMockMediaSessionCoordinatorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/MockMediaSessionCoordinator.h (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/MockMediaSessionCoordinator.h       2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebCore/testing/MockMediaSessionCoordinator.h  2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -60,7 +60,7 @@
</span><span class="cx">     void positionStateChanged(const Optional<MediaPositionState>&) final;
</span><span class="cx">     void readyStateChanged(MediaSessionReadyState) final;
</span><span class="cx">     void playbackStateChanged(MediaSessionPlaybackState) final;
</span><del>-    void coordinatorStateChanged(MediaSessionCoordinatorState) final;
</del><ins>+    void trackIdentifierChanged(const String&) final;
</ins><span class="cx"> 
</span><span class="cx">     const char* logClassName() const { return "MockMediaSessionCoordinator"; }
</span><span class="cx">     WTFLogChannel& logChannel() const;
</span></span></pre></div>
<a id="trunkSourceWebKitChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/ChangeLog (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/ChangeLog    2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebKit/ChangeLog       2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -1,3 +1,35 @@
</span><ins>+2021-05-14  Jer Noble  <jer.noble@apple.com>
+
+        MediaSessionCoordinator survives page reload/navigation
+        https://bugs.webkit.org/show_bug.cgi?id=225822
+
+        Reviewed by Eric Carlson.
+
+        Update the classes affected by virtual function changes in MediaSessionCoordinator. Update
+        the creation mechanism inside WebPage/Proxy.
+
+        * UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h:
+        * UIProcess/API/Cocoa/WKWebViewTesting.mm:
+        (-[WKWebView _createMediaSessionCoordinatorForTesting:completionHandler:]):
+        * UIProcess/Media/MediaSessionCoordinatorProxyPrivate.h:
+        * UIProcess/Media/RemoteMediaSessionCoordinatorProxy.cpp:
+        (WebKit::RemoteMediaSessionCoordinatorProxy::trackIdentifierChanged):
+        (WebKit::RemoteMediaSessionCoordinatorProxy::coordinatorStateChanged):
+        * UIProcess/Media/RemoteMediaSessionCoordinatorProxy.h:
+        * UIProcess/Media/RemoteMediaSessionCoordinatorProxy.messages.in:
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::createMediaSessionCoordinator):
+        * WebProcess/MediaSession/RemoteMediaSessionCoordinator.cpp:
+        (WebKit::RemoteMediaSessionCoordinator::trackIdentifierChanged):
+        (WebKit::RemoteMediaSessionCoordinator::coordinatorStateChanged):
+        * WebProcess/MediaSession/RemoteMediaSessionCoordinator.h:
+        * WebProcess/MediaSession/RemoteMediaSessionCoordinator.messages.in:
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::createMediaSessionCoordinator):
+        (WebKit::WebPage::invalidateMediaSessionCoordinator):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+
</ins><span class="cx"> 2021-05-16  Chris Dumez  <cdumez@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Modernize / Optimize SQLiteStatement creation and preparation
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessAPICocoaWKWebViewPrivateForTestingh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h     2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h        2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -155,7 +155,7 @@
</span><span class="cx"> - (void)positionStateChanged:(struct _WKMediaPositionState * _Nullable)state;
</span><span class="cx"> - (void)readyStateChanged:(_WKMediaSessionReadyState)state;
</span><span class="cx"> - (void)playbackStateChanged:(_WKMediaSessionPlaybackState)state;
</span><del>-- (void)coordinatorStateChanged:(_WKMediaSessionCoordinatorState)state;
</del><ins>+- (void)trackIdentifierChanged:(NSString *)trackIdentifier;
</ins><span class="cx"> @end
</span><span class="cx"> 
</span><span class="cx"> NS_ASSUME_NONNULL_END
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessAPICocoaWKWebViewTestingmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewTesting.mm (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewTesting.mm      2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewTesting.mm 2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -557,13 +557,9 @@
</span><span class="cx">             [m_clientCoordinator playbackStateChanged:static_cast<_WKMediaSessionPlaybackState>(state)];
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        void coordinatorStateChanged(WebCore::MediaSessionCoordinatorState state) final
</del><ins>+        void trackIdentifierChanged(const String& identifier) final
</ins><span class="cx">         {
</span><del>-            static_assert(static_cast<size_t>(WebCore::MediaSessionCoordinatorState::Waiting) == static_cast<size_t>(WKMediaSessionCoordinatorStateWaiting), "WKMediaSessionCoordinatorStateWaiting does not match WebKit value");
-            static_assert(static_cast<size_t>(WebCore::MediaSessionCoordinatorState::Joined) == static_cast<size_t>(WKMediaSessionCoordinatorStateJoined), "WKMediaSessionCoordinatorStateJoined does not match WebKit value");
-            static_assert(static_cast<size_t>(WebCore::MediaSessionCoordinatorState::Closed) == static_cast<size_t>(WKMediaSessionCoordinatorStateClosed), "WKMediaSessionCoordinatorStateClosed does not match WebKit value");
-
-            [m_clientCoordinator coordinatorStateChanged:static_cast<_WKMediaSessionCoordinatorState>(state)];
</del><ins>+            [m_clientCoordinator trackIdentifierChanged:identifier];
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">     private:
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessMediaMediaSessionCoordinatorProxyPrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/Media/MediaSessionCoordinatorProxyPrivate.h (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/Media/MediaSessionCoordinatorProxyPrivate.h        2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebKit/UIProcess/Media/MediaSessionCoordinatorProxyPrivate.h   2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -58,7 +58,7 @@
</span><span class="cx">     virtual void positionStateChanged(const Optional<WebCore::MediaPositionState>&) = 0;
</span><span class="cx">     virtual void readyStateChanged(WebCore::MediaSessionReadyState) = 0;
</span><span class="cx">     virtual void playbackStateChanged(WebCore::MediaSessionPlaybackState) = 0;
</span><del>-    virtual void coordinatorStateChanged(WebCore::MediaSessionCoordinatorState) = 0;
</del><ins>+    virtual void trackIdentifierChanged(const String&) = 0;
</ins><span class="cx"> 
</span><span class="cx">     virtual void setClient(WeakPtr<WebCore::MediaSessionCoordinatorClient> client) { m_client = client; }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessMediaRemoteMediaSessionCoordinatorProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.cpp (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.cpp       2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.cpp  2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -148,10 +148,10 @@
</span><span class="cx">     m_privateCoordinator->readyStateChanged(state);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void RemoteMediaSessionCoordinatorProxy::coordinatorStateChanged(WebCore::MediaSessionCoordinatorState state)
</del><ins>+void RemoteMediaSessionCoordinatorProxy::trackIdentifierChanged(const String& identifier)
</ins><span class="cx"> {
</span><span class="cx">     ALWAYS_LOG(LOGIDENTIFIER);
</span><del>-    m_privateCoordinator->coordinatorStateChanged(state);
</del><ins>+    m_privateCoordinator->trackIdentifierChanged(identifier);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RemoteMediaSessionCoordinatorProxy::seekSessionToTime(double time, CompletionHandler<void(bool)>&& callback)
</span><span class="lines">@@ -174,6 +174,11 @@
</span><span class="cx">     m_webPageProxy.sendWithAsyncReply(Messages::RemoteMediaSessionCoordinator::SetSessionTrack { trackId }, callback);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void RemoteMediaSessionCoordinatorProxy::coordinatorStateChanged(WebCore::MediaSessionCoordinatorState state)
+{
+    m_webPageProxy.send(Messages::RemoteMediaSessionCoordinator::CoordinatorStateChanged { state });
+}
+
</ins><span class="cx"> #if !RELEASE_LOG_DISABLED
</span><span class="cx"> WTFLogChannel& RemoteMediaSessionCoordinatorProxy::logChannel() const
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessMediaRemoteMediaSessionCoordinatorProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.h (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.h 2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.h    2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -73,7 +73,7 @@
</span><span class="cx">     void positionStateChanged(const Optional<WebCore::MediaPositionState>&);
</span><span class="cx">     void readyStateChanged(WebCore::MediaSessionReadyState);
</span><span class="cx">     void playbackStateChanged(WebCore::MediaSessionPlaybackState);
</span><del>-    void coordinatorStateChanged(WebCore::MediaSessionCoordinatorState);
</del><ins>+    void trackIdentifierChanged(const String&);
</ins><span class="cx"> 
</span><span class="cx">     // MediaSessionCoordinatorClient
</span><span class="cx">     void seekSessionToTime(double, CompletionHandler<void(bool)>&&) final;
</span><span class="lines">@@ -80,6 +80,7 @@
</span><span class="cx">     void playSession(Optional<double> atTime, Optional<double> hostTime, CompletionHandler<void(bool)>&&) final;
</span><span class="cx">     void pauseSession(CompletionHandler<void(bool)>&&) final;
</span><span class="cx">     void setSessionTrack(const String&, CompletionHandler<void(bool)>&&) final;
</span><ins>+    void coordinatorStateChanged(WebCore::MediaSessionCoordinatorState) final;
</ins><span class="cx"> 
</span><span class="cx"> #if !RELEASE_LOG_DISABLED
</span><span class="cx">     const WTF::Logger& logger() const { return m_logger; }
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessMediaRemoteMediaSessionCoordinatorProxymessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.messages.in (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.messages.in       2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.messages.in  2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -44,7 +44,7 @@
</span><span class="cx"> 
</span><span class="cx">     PlaybackStateChanged(enum:uint8_t WebCore::MediaSessionPlaybackState state);
</span><span class="cx"> 
</span><del>-    CoordinatorStateChanged(enum:uint8_t WebCore::MediaSessionCoordinatorState state);
</del><ins>+    TrackIdentifierChanged(String trackIdentifier) final
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessWebPageProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp   2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp      2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -10625,8 +10625,6 @@
</span><span class="cx"> #if ENABLE(MEDIA_SESSION_COORDINATOR)
</span><span class="cx"> void WebPageProxy::createMediaSessionCoordinator(Ref<MediaSessionCoordinatorProxyPrivate>&& privateCoordinator, CompletionHandler<void(bool)>&& completionHandler)
</span><span class="cx"> {
</span><del>-    ASSERT(!m_mediaSessionCoordinatorProxy);
-
</del><span class="cx">     sendWithAsyncReply(Messages::WebPage::CreateMediaSessionCoordinator(privateCoordinator->identifier()), [weakThis = makeWeakPtr(*this), privateCoordinator = WTFMove(privateCoordinator), completionHandler = WTFMove(completionHandler)](bool success) mutable {
</span><span class="cx"> 
</span><span class="cx">         if (!weakThis || !success) {
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessMediaSessionRemoteMediaSessionCoordinatorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/MediaSession/RemoteMediaSessionCoordinator.cpp (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/MediaSession/RemoteMediaSessionCoordinator.cpp    2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebKit/WebProcess/MediaSession/RemoteMediaSessionCoordinator.cpp       2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -175,10 +175,10 @@
</span><span class="cx">     m_page.send(Messages::RemoteMediaSessionCoordinatorProxy::PlaybackStateChanged { state });
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void RemoteMediaSessionCoordinator::coordinatorStateChanged(WebCore::MediaSessionCoordinatorState state)
</del><ins>+void RemoteMediaSessionCoordinator::trackIdentifierChanged(const String& identifier)
</ins><span class="cx"> {
</span><del>-    ALWAYS_LOG_IF_POSSIBLE(LOGIDENTIFIER, state);
-    m_page.send(Messages::RemoteMediaSessionCoordinatorProxy::CoordinatorStateChanged { state });
</del><ins>+    ALWAYS_LOG_IF_POSSIBLE(LOGIDENTIFIER, identifier);
+    m_page.send(Messages::RemoteMediaSessionCoordinatorProxy::TrackIdentifierChanged { identifier });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RemoteMediaSessionCoordinator::seekSessionToTime(double time, CompletionHandler<void(bool)>&& completionHandler)
</span><span class="lines">@@ -217,6 +217,13 @@
</span><span class="cx">         completionHandler(false);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void RemoteMediaSessionCoordinator::coordinatorStateChanged(WebCore::MediaSessionCoordinatorState state)
+{
+    ALWAYS_LOG_IF_POSSIBLE(LOGIDENTIFIER, state);
+    if (auto coordinatorClient = client())
+        coordinatorClient->coordinatorStateChanged(state);
+}
+
</ins><span class="cx"> WTFLogChannel& RemoteMediaSessionCoordinator::logChannel() const
</span><span class="cx"> {
</span><span class="cx">     return LogMedia;
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessMediaSessionRemoteMediaSessionCoordinatorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/MediaSession/RemoteMediaSessionCoordinator.h (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/MediaSession/RemoteMediaSessionCoordinator.h      2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebKit/WebProcess/MediaSession/RemoteMediaSessionCoordinator.h 2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -58,6 +58,7 @@
</span><span class="cx">     void playSession(Optional<double>, Optional<double>, CompletionHandler<void(bool)>&&);
</span><span class="cx">     void pauseSession(CompletionHandler<void(bool)>&&);
</span><span class="cx">     void setSessionTrack(const String&, CompletionHandler<void(bool)>&&);
</span><ins>+    void coordinatorStateChanged(WebCore::MediaSessionCoordinatorState);
</ins><span class="cx"> 
</span><span class="cx">     // MediaSessionCoordinatorPrivate overrides.
</span><span class="cx">     String identifier() const final { return m_identifier; }
</span><span class="lines">@@ -71,7 +72,7 @@
</span><span class="cx">     void positionStateChanged(const Optional<WebCore::MediaPositionState>&) final;
</span><span class="cx">     void readyStateChanged(WebCore::MediaSessionReadyState) final;
</span><span class="cx">     void playbackStateChanged(WebCore::MediaSessionPlaybackState) final;
</span><del>-    void coordinatorStateChanged(WebCore::MediaSessionCoordinatorState) final;
</del><ins>+    void trackIdentifierChanged(const String&) final;
</ins><span class="cx"> 
</span><span class="cx">     const char* logClassName() const { return "RemoteMediaSessionCoordinator"; }
</span><span class="cx">     WTFLogChannel& logChannel() const;
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessMediaSessionRemoteMediaSessionCoordinatormessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/MediaSession/RemoteMediaSessionCoordinator.messages.in (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/MediaSession/RemoteMediaSessionCoordinator.messages.in    2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebKit/WebProcess/MediaSession/RemoteMediaSessionCoordinator.messages.in       2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -34,6 +34,8 @@
</span><span class="cx">     PauseSession() -> (bool result) Async
</span><span class="cx"> 
</span><span class="cx">     SetSessionTrack(String trackIdentifier) -> (bool result) Async
</span><ins>+
+    CoordinatorStateChanged(enum:uint8_t WebCore::MediaSessionCoordinatorState state);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebPageWebPagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp       2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp  2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -7581,14 +7581,14 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    auto& session = NavigatorMediaSession::mediaSession(document->domWindow()->navigator());
-    auto coordinator = RemoteMediaSessionCoordinator::create(*this, identifier);
-    m_remoteMediaSessionCoordinator = coordinator.ptr();
-    m_mediaSessionCoordinator = MediaSessionCoordinator::create(coordinator.get());
-    session.setCoordinator(m_mediaSessionCoordinator.get());
-
</del><ins>+    m_page->setMediaSessionCoordinator(RemoteMediaSessionCoordinator::create(*this, identifier));
</ins><span class="cx">     completionHandler(true);
</span><span class="cx"> }
</span><ins>+
+void WebPage::invalidateMediaSessionCoordinator()
+{
+    m_page->invalidateMediaSessionCoordinator();
+}
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if !PLATFORM(COCOA)
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebPageWebPageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h 2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h    2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -1440,6 +1440,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(MEDIA_SESSION_COORDINATOR)
</span><span class="cx">     void createMediaSessionCoordinator(const String&, CompletionHandler<void(bool)>&&);
</span><ins>+    void invalidateMediaSessionCoordinator();
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     void setLastNavigationWasAppBound(bool wasAppBound) { m_lastNavigationWasAppBound = wasAppBound; }
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebPageWebPagemessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in       2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in  2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -639,6 +639,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(MEDIA_SESSION_COORDINATOR)
</span><span class="cx">     CreateMediaSessionCoordinator(String identifier) -> (bool success) Async
</span><ins>+    InvalidateMediaSessionCoordinator()
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(IMAGE_EXTRACTION)
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog    2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Tools/ChangeLog       2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2021-05-15  Jer Noble  <jer.noble@apple.com>
+
+        MediaSessionCoordinator survives page reload/navigation
+        https://bugs.webkit.org/show_bug.cgi?id=225822
+
+        Reviewed by Eric Carlson.
+
+        * TestWebKitAPI/Tests/WebKit/MediaSessionCoordinatorTest.mm:
+        (-[_WKMockMediaSessionCoordinator trackIdentifierChanged:]):
+
</ins><span class="cx"> 2021-05-16  Chris Dumez  <cdumez@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Modernize / Optimize SQLiteStatement creation and preparation
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKitMediaSessionCoordinatorTestmm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit/MediaSessionCoordinatorTest.mm (277572 => 277573)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKit/MediaSessionCoordinatorTest.mm    2021-05-16 17:46:33 UTC (rev 277572)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit/MediaSessionCoordinatorTest.mm       2021-05-16 20:32:30 UTC (rev 277573)
</span><span class="lines">@@ -141,6 +141,11 @@
</span><span class="cx">     _lastStateChange = @"coordinatorStateChanged";
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (void)trackIdentifierChanged:(NSString *)trackIdentifier
+{
+    _lastStateChange = @"trackIdentifierChanged";
+}
+
</ins><span class="cx"> - (void)seekSessionToTime:(double)time
</span><span class="cx"> {
</span><span class="cx">     [self.delegate seekSessionToTime:time withCompletion:^(BOOL result) {
</span></span></pre>
</div>
</div>

</body>
</html>