<!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>[237364] trunk/Source/WebCore</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/237364">237364</a></dd>
<dt>Author</dt> <dd>tsavell@apple.com</dd>
<dt>Date</dt> <dd>2018-10-23 13:02:52 -0700 (Tue, 23 Oct 2018)</dd>
</dl>

<h3>Log Message</h3>
<pre>Unreviewed, rolling out <a href="http://trac.webkit.org/projects/webkit/changeset/237350">r237350</a>.

Caused several Crashes cross multiple tests and platforms.

Reverted changeset:

"Use WeakPtr and GenericTaskQueue within ObjC classes used by
MediaPlayerPrivateAVFoundationObjC"
https://bugs.webkit.org/show_bug.cgi?id=190790
https://trac.webkit.org/changeset/237350</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformGenericTaskQueuecpp">trunk/Source/WebCore/platform/GenericTaskQueue.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformGenericTaskQueueh">trunk/Source/WebCore/platform/GenericTaskQueue.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateAVFoundationObjCh">trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateAVFoundationObjCmm">trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (237363 => 237364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog   2018-10-23 19:44:46 UTC (rev 237363)
+++ trunk/Source/WebCore/ChangeLog      2018-10-23 20:02:52 UTC (rev 237364)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2018-10-23  Truitt Savell  <tsavell@apple.com>
+
+        Unreviewed, rolling out r237350.
+
+        Caused several Crashes cross multiple tests and platforms.
+
+        Reverted changeset:
+
+        "Use WeakPtr and GenericTaskQueue within ObjC classes used by
+        MediaPlayerPrivateAVFoundationObjC"
+        https://bugs.webkit.org/show_bug.cgi?id=190790
+        https://trac.webkit.org/changeset/237350
+
</ins><span class="cx"> 2018-10-23  Ryan Haddad  <ryanhaddad@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, rolling out r237280.
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformGenericTaskQueuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/GenericTaskQueue.cpp (237363 => 237364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/GenericTaskQueue.cpp       2018-10-23 19:44:46 UTC (rev 237363)
+++ trunk/Source/WebCore/platform/GenericTaskQueue.cpp  2018-10-23 20:02:52 UTC (rev 237364)
</span><span class="lines">@@ -26,7 +26,6 @@
</span><span class="cx"> #include "config.h"
</span><span class="cx"> #include "GenericTaskQueue.h"
</span><span class="cx"> 
</span><del>-#include <wtf/Lock.h>
</del><span class="cx"> #include <wtf/MainThread.h>
</span><span class="cx"> #include <wtf/NeverDestroyed.h>
</span><span class="cx"> 
</span><span class="lines">@@ -38,20 +37,10 @@
</span><span class="cx"> 
</span><span class="cx"> void TaskDispatcher<Timer>::postTask(Function<void()>&& function)
</span><span class="cx"> {
</span><del>-    {
-        auto locker = holdLock(sharedLock());
-        m_pendingTasks.append(WTFMove(function));
-        pendingDispatchers().append(makeWeakPtr(*this));
-    }
-
-    auto startTimer = [] {
-        if (!sharedTimer().isActive())
-            sharedTimer().startOneShot(0_s);
-    };
-    if (isMainThread())
-        startTimer();
-    else
-        callOnMainThread(WTFMove(startTimer));
</del><ins>+    m_pendingTasks.append(WTFMove(function));
+    pendingDispatchers().append(makeWeakPtr(*this));
+    if (!sharedTimer().isActive())
+        sharedTimer().startOneShot(0_s);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Timer& TaskDispatcher<Timer>::sharedTimer()
</span><span class="lines">@@ -61,12 +50,6 @@
</span><span class="cx">     return timer.get();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Lock& TaskDispatcher<Timer>::sharedLock()
-{
-    static NeverDestroyed<Lock> lock;
-    return lock;
-}
-
</del><span class="cx"> void TaskDispatcher<Timer>::sharedTimerFired()
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!sharedTimer().isActive());
</span><span class="lines">@@ -74,11 +57,7 @@
</span><span class="cx"> 
</span><span class="cx">     // Copy the pending events first because we don't want to process synchronously the new events
</span><span class="cx">     // queued by the JS events handlers that are executed in the loop below.
</span><del>-    Deque<WeakPtr<TaskDispatcher<Timer>>> queuedDispatchers;
-    {
-        auto locker = holdLock(sharedLock());
-        queuedDispatchers = WTFMove(pendingDispatchers());
-    }
</del><ins>+    Deque<WeakPtr<TaskDispatcher<Timer>>> queuedDispatchers = WTFMove(pendingDispatchers());
</ins><span class="cx">     while (!queuedDispatchers.isEmpty()) {
</span><span class="cx">         WeakPtr<TaskDispatcher<Timer>> dispatcher = queuedDispatchers.takeFirst();
</span><span class="cx">         if (!dispatcher)
</span><span class="lines">@@ -87,27 +66,17 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-
</del><span class="cx"> Deque<WeakPtr<TaskDispatcher<Timer>>>& TaskDispatcher<Timer>::pendingDispatchers()
</span><span class="cx"> {
</span><del>-    static LazyNeverDestroyed<Deque<WeakPtr<TaskDispatcher<Timer>>>> dispatchers;
-
-    static std::once_flag onceFlag;
-    std::call_once(onceFlag, [] {
-        dispatchers.construct();
-    });
-
</del><ins>+    ASSERT(isMainThread());
+    static NeverDestroyed<Deque<WeakPtr<TaskDispatcher<Timer>>>> dispatchers;
</ins><span class="cx">     return dispatchers.get();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void TaskDispatcher<Timer>::dispatchOneTask()
</span><span class="cx"> {
</span><del>-    WTF::Function<void()> task;
-    {
-        auto locker = holdLock(sharedLock());
-        ASSERT(!m_pendingTasks.isEmpty());
-        task = m_pendingTasks.takeFirst();
-    }
</del><ins>+    ASSERT(!m_pendingTasks.isEmpty());
+    auto task = m_pendingTasks.takeFirst();
</ins><span class="cx">     task();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformGenericTaskQueueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/GenericTaskQueue.h (237363 => 237364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/GenericTaskQueue.h 2018-10-23 19:44:46 UTC (rev 237363)
+++ trunk/Source/WebCore/platform/GenericTaskQueue.h    2018-10-23 20:02:52 UTC (rev 237364)
</span><span class="lines">@@ -30,10 +30,6 @@
</span><span class="cx"> #include <wtf/Function.h>
</span><span class="cx"> #include <wtf/WeakPtr.h>
</span><span class="cx"> 
</span><del>-namespace WTF {
-class Lock;
-};
-
</del><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> template <typename T>
</span><span class="lines">@@ -62,7 +58,6 @@
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     static Timer& sharedTimer();
</span><del>-    static WTF::Lock& sharedLock();
</del><span class="cx">     static void sharedTimerFired();
</span><span class="cx">     static Deque<WeakPtr<TaskDispatcher<Timer>>>& pendingDispatchers();
</span><span class="cx"> 
</span><span class="lines">@@ -71,8 +66,8 @@
</span><span class="cx">     Deque<WTF::Function<void()>> m_pendingTasks;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-template <typename T, typename C = unsigned>
-class GenericTaskQueue : public CanMakeWeakPtr<GenericTaskQueue<T, C>> {
</del><ins>+template <typename T>
+class GenericTaskQueue : public CanMakeWeakPtr<GenericTaskQueue<T>> {
</ins><span class="cx"> public:
</span><span class="cx">     GenericTaskQueue()
</span><span class="cx">         : m_dispatcher()
</span><span class="lines">@@ -124,7 +119,7 @@
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     TaskDispatcher<T> m_dispatcher;
</span><del>-    C m_pendingTasks { 0 };
</del><ins>+    unsigned m_pendingTasks { 0 };
</ins><span class="cx">     bool m_isClosed { false };
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateAVFoundationObjCh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h (237363 => 237364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h    2018-10-23 19:44:46 UTC (rev 237363)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h       2018-10-23 20:02:52 UTC (rev 237364)
</span><span class="lines">@@ -330,7 +330,6 @@
</span><span class="cx"> 
</span><span class="cx">     AVPlayer *objCAVFoundationAVPlayer() const final { return m_avPlayer.get(); }
</span><span class="cx"> 
</span><del>-    WeakPtrFactory<MediaPlayerPrivateAVFoundationObjC> m_weakPtrFactory;
</del><span class="cx">     RetainPtr<AVURLAsset> m_avAsset;
</span><span class="cx">     RetainPtr<AVPlayer> m_avPlayer;
</span><span class="cx">     RetainPtr<AVPlayerItem> m_avPlayerItem;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateAVFoundationObjCmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm (237363 => 237364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm   2018-10-23 19:44:46 UTC (rev 237363)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm      2018-10-23 20:02:52 UTC (rev 237364)
</span><span class="lines">@@ -336,11 +336,10 @@
</span><span class="cx"> @interface WebCoreAVFMovieObserver : NSObject
</span><span class="cx"> #endif
</span><span class="cx"> {
</span><del>-    WeakPtr<MediaPlayerPrivateAVFoundationObjC> m_player;
-    GenericTaskQueue<Timer, std::atomic<unsigned>> m_taskQueue;
</del><ins>+    MediaPlayerPrivateAVFoundationObjC* m_callback;
</ins><span class="cx">     int m_delayCallbacks;
</span><span class="cx"> }
</span><del>--(id)initWithPlayer:(WeakPtr<MediaPlayerPrivateAVFoundationObjC>&&)callback;
</del><ins>+-(id)initWithCallback:(MediaPlayerPrivateAVFoundationObjC*)callback;
</ins><span class="cx"> -(void)disconnect;
</span><span class="cx"> -(void)metadataLoaded;
</span><span class="cx"> -(void)didEnd:(NSNotification *)notification;
</span><span class="lines">@@ -353,19 +352,20 @@
</span><span class="cx"> 
</span><span class="cx"> #if HAVE(AVFOUNDATION_LOADER_DELEGATE)
</span><span class="cx"> @interface WebCoreAVFLoaderDelegate : NSObject<AVAssetResourceLoaderDelegate> {
</span><del>-    WeakPtr<MediaPlayerPrivateAVFoundationObjC> m_player;
-    GenericTaskQueue<Timer, std::atomic<unsigned>> m_taskQueue;
</del><ins>+    MediaPlayerPrivateAVFoundationObjC* m_callback;
</ins><span class="cx"> }
</span><del>-- (id)initWithPlayer:(WeakPtr<MediaPlayerPrivateAVFoundationObjC>&&)player;
</del><ins>+- (id)initWithCallback:(MediaPlayerPrivateAVFoundationObjC*)callback;
</ins><span class="cx"> - (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest;
</span><ins>+- (void)setCallback:(MediaPlayerPrivateAVFoundationObjC*)callback;
</ins><span class="cx"> @end
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if HAVE(AVFOUNDATION_VIDEO_OUTPUT)
</span><span class="cx"> @interface WebCoreAVFPullDelegate : NSObject<AVPlayerItemOutputPullDelegate> {
</span><del>-    WeakPtr<MediaPlayerPrivateAVFoundationObjC> m_player;
</del><ins>+    MediaPlayerPrivateAVFoundationObjC *m_callback;
</ins><span class="cx"> }
</span><del>-- (id)initWithPlayer:(WeakPtr<MediaPlayerPrivateAVFoundationObjC>&&)player;
</del><ins>+- (id)initWithCallback:(MediaPlayerPrivateAVFoundationObjC *)callback;
+- (void)setCallback:(MediaPlayerPrivateAVFoundationObjC*)callback;
</ins><span class="cx"> - (void)outputMediaDataWillChange:(AVPlayerItemOutput *)sender;
</span><span class="cx"> - (void)outputSequenceWasFlushed:(AVPlayerItemOutput *)output;
</span><span class="cx"> @end
</span><span class="lines">@@ -501,14 +501,14 @@
</span><span class="cx">     : MediaPlayerPrivateAVFoundation(player)
</span><span class="cx">     , m_videoFullscreenLayerManager(std::make_unique<VideoFullscreenLayerManagerObjC>())
</span><span class="cx">     , m_videoFullscreenGravity(MediaPlayer::VideoGravityResizeAspect)
</span><del>-    , m_objcObserver(adoptNS([[WebCoreAVFMovieObserver alloc] initWithPlayer:m_weakPtrFactory.createWeakPtr(*this)]))
</del><ins>+    , m_objcObserver(adoptNS([[WebCoreAVFMovieObserver alloc] initWithCallback:this]))
</ins><span class="cx">     , m_videoFrameHasDrawn(false)
</span><span class="cx">     , m_haveCheckedPlayability(false)
</span><span class="cx"> #if HAVE(AVFOUNDATION_VIDEO_OUTPUT)
</span><del>-    , m_videoOutputDelegate(adoptNS([[WebCoreAVFPullDelegate alloc] initWithPlayer:m_weakPtrFactory.createWeakPtr(*this)]))
</del><ins>+    , m_videoOutputDelegate(adoptNS([[WebCoreAVFPullDelegate alloc] initWithCallback:this]))
</ins><span class="cx"> #endif
</span><span class="cx"> #if HAVE(AVFOUNDATION_LOADER_DELEGATE)
</span><del>-    , m_loaderDelegate(adoptNS([[WebCoreAVFLoaderDelegate alloc] initWithPlayer:m_weakPtrFactory.createWeakPtr(*this)]))
</del><ins>+    , m_loaderDelegate(adoptNS([[WebCoreAVFLoaderDelegate alloc] initWithCallback:this]))
</ins><span class="cx"> #endif
</span><span class="cx">     , m_currentTextTrack(0)
</span><span class="cx">     , m_cachedRate(0)
</span><span class="lines">@@ -530,9 +530,8 @@
</span><span class="cx"> 
</span><span class="cx"> MediaPlayerPrivateAVFoundationObjC::~MediaPlayerPrivateAVFoundationObjC()
</span><span class="cx"> {
</span><del>-    m_weakPtrFactory.revokeAll();
-
</del><span class="cx"> #if HAVE(AVFOUNDATION_LOADER_DELEGATE)
</span><ins>+    [m_loaderDelegate.get() setCallback:0];
</ins><span class="cx">     [[m_avAsset.get() resourceLoader] setDelegate:nil queue:0];
</span><span class="cx"> 
</span><span class="cx">     for (auto& pair : m_resourceLoaderMap)
</span><span class="lines">@@ -539,6 +538,7 @@
</span><span class="cx">         pair.value->invalidate();
</span><span class="cx"> #endif
</span><span class="cx"> #if HAVE(AVFOUNDATION_VIDEO_OUTPUT)
</span><ins>+    [m_videoOutputDelegate setCallback:0];
</ins><span class="cx">     [m_videoOutput setDelegate:nil queue:0];
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -3349,134 +3349,147 @@
</span><span class="cx"> 
</span><span class="cx"> @implementation WebCoreAVFMovieObserver
</span><span class="cx"> 
</span><del>-- (id)initWithPlayer:(WeakPtr<MediaPlayerPrivateAVFoundationObjC>&&)player
</del><ins>+- (id)initWithCallback:(MediaPlayerPrivateAVFoundationObjC*)callback
</ins><span class="cx"> {
</span><span class="cx">     self = [super init];
</span><span class="cx">     if (!self)
</span><span class="cx">         return nil;
</span><del>-    m_player = WTFMove(player);
</del><ins>+    m_callback = callback;
</ins><span class="cx">     return self;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)disconnect
</span><span class="cx"> {
</span><del>-    m_player = nullptr;
</del><ins>+    [NSObject cancelPreviousPerformRequestsWithTarget:self];
+    m_callback = nil;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)metadataLoaded
</span><span class="cx"> {
</span><del>-    m_taskQueue.enqueueTask([player = m_player] {
-        if (player)
-            player->metadataLoaded();
-    });
</del><ins>+    if (!m_callback)
+        return;
+    m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::AssetMetadataLoaded);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)didEnd:(NSNotification *)unusedNotification
</span><span class="cx"> {
</span><span class="cx">     UNUSED_PARAM(unusedNotification);
</span><del>-    m_taskQueue.enqueueTask([player = m_player] {
-        if (player)
-            player->didEnd();
-    });
</del><ins>+    if (!m_callback)
+        return;
+    m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemDidPlayToEndTime);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)observeValueForKeyPath:keyPath ofObject:(id)object change:(NSDictionary *)change context:(MediaPlayerAVFoundationObservationContext)context
</span><span class="cx"> {
</span><del>-    m_taskQueue.enqueueTask([player = m_player, keyPath = retainPtr(keyPath), change = retainPtr(change), object = retainPtr(object), context] {
-        if (!player)
-            return;
-        id newValue = [change valueForKey:NSKeyValueChangeNewKey];
-        bool willChange = [[change valueForKey:NSKeyValueChangeNotificationIsPriorKey] boolValue];
-        bool shouldLogValue = !willChange;
</del><ins>+    UNUSED_PARAM(object);
+    id newValue = [change valueForKey:NSKeyValueChangeNewKey];
</ins><span class="cx"> 
</span><del>-        if (context == MediaPlayerAVFoundationObservationContextAVPlayerLayer) {
-            if ([keyPath isEqualToString:@"readyForDisplay"])
-                player->firstFrameAvailableDidChange([newValue boolValue]);
-        }
</del><ins>+    if (!m_callback)
+        return;
</ins><span class="cx"> 
</span><del>-        if (context == MediaPlayerAVFoundationObservationContextPlayerItemTrack) {
-            if ([keyPath isEqualToString:@"enabled"])
-                player->trackEnabledDidChange([newValue boolValue]);
-        }
</del><ins>+    bool willChange = [[change valueForKey:NSKeyValueChangeNotificationIsPriorKey] boolValue];
+    bool shouldLogValue = !willChange;
+    WTF::Function<void ()> function;
</ins><span class="cx"> 
</span><del>-        if (context == MediaPlayerAVFoundationObservationContextPlayerItem && willChange) {
-            if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"])
-                player->playbackLikelyToKeepUpWillChange();
-            else if ([keyPath isEqualToString:@"playbackBufferEmpty"])
-                player->playbackBufferEmptyWillChange();
-            else if ([keyPath isEqualToString:@"playbackBufferFull"])
-                player->playbackBufferFullWillChange();
-        }
</del><ins>+    if (context == MediaPlayerAVFoundationObservationContextAVPlayerLayer) {
+        if ([keyPath isEqualToString:@"readyForDisplay"])
+            function = std::bind(&MediaPlayerPrivateAVFoundationObjC::firstFrameAvailableDidChange, m_callback, [newValue boolValue]);
+    }
</ins><span class="cx"> 
</span><del>-        if (context == MediaPlayerAVFoundationObservationContextPlayerItem && !willChange) {
-            // A value changed for an AVPlayerItem
-            if ([keyPath isEqualToString:@"status"])
-                player->playerItemStatusDidChange([newValue intValue]);
-            else if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"])
-                player->playbackLikelyToKeepUpDidChange([newValue boolValue]);
-            else if ([keyPath isEqualToString:@"playbackBufferEmpty"])
-                player->playbackBufferEmptyDidChange([newValue boolValue]);
-            else if ([keyPath isEqualToString:@"playbackBufferFull"])
-                player->playbackBufferFullDidChange([newValue boolValue]);
-            else if ([keyPath isEqualToString:@"asset"]) {
-                player->setAsset(RetainPtr<id>(newValue));
-                shouldLogValue = false;
-            } else if ([keyPath isEqualToString:@"loadedTimeRanges"])
-                player->loadedTimeRangesDidChange(RetainPtr<NSArray>(newValue));
-            else if ([keyPath isEqualToString:@"seekableTimeRanges"])
-                player->seekableTimeRangesDidChange(RetainPtr<NSArray>(newValue));
-            else if ([keyPath isEqualToString:@"tracks"]) {
-                player->tracksDidChange(RetainPtr<NSArray>(newValue));
-                shouldLogValue = false;
-            } else if ([keyPath isEqualToString:@"hasEnabledAudio"])
-                player->hasEnabledAudioDidChange([newValue boolValue]);
-            else if ([keyPath isEqualToString:@"presentationSize"])
-                player->presentationSizeDidChange(FloatSize([newValue sizeValue]));
-            else if ([keyPath isEqualToString:@"duration"])
-                player->durationDidChange(PAL::toMediaTime([newValue CMTimeValue]));
-            else if ([keyPath isEqualToString:@"timedMetadata"] && newValue) {
-                MediaTime now;
-                CMTime itemTime = [(AVPlayerItemType *)object.get() currentTime];
-                if (CMTIME_IS_NUMERIC(itemTime))
-                    now = std::max(PAL::toMediaTime(itemTime), MediaTime::zeroTime());
-                player->metadataDidArrive(RetainPtr<NSArray>(newValue), now);
-                shouldLogValue = false;
-            } else if ([keyPath isEqualToString:@"canPlayFastReverse"])
-                player->canPlayFastReverseDidChange([newValue boolValue]);
-            else if ([keyPath isEqualToString:@"canPlayFastForward"])
-                player->canPlayFastForwardDidChange([newValue boolValue]);
-        }
</del><ins>+    if (context == MediaPlayerAVFoundationObservationContextPlayerItemTrack) {
+        if ([keyPath isEqualToString:@"enabled"])
+            function = std::bind(&MediaPlayerPrivateAVFoundationObjC::trackEnabledDidChange, m_callback, [newValue boolValue]);
+    }
</ins><span class="cx"> 
</span><del>-        if (context == MediaPlayerAVFoundationObservationContextPlayer && !willChange) {
-            // A value changed for an AVPlayer.
-            if ([keyPath isEqualToString:@"rate"])
-                player->rateDidChange([newValue doubleValue]);
</del><ins>+    if (context == MediaPlayerAVFoundationObservationContextPlayerItem && willChange) {
+        if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"])
+            function = std::bind(&MediaPlayerPrivateAVFoundationObjC::playbackLikelyToKeepUpWillChange, m_callback);
+        else if ([keyPath isEqualToString:@"playbackBufferEmpty"])
+            function = std::bind(&MediaPlayerPrivateAVFoundationObjC::playbackBufferEmptyWillChange, m_callback);
+        else if ([keyPath isEqualToString:@"playbackBufferFull"])
+            function = std::bind(&MediaPlayerPrivateAVFoundationObjC::playbackBufferFullWillChange, m_callback);
+    }
+
+    if (context == MediaPlayerAVFoundationObservationContextPlayerItem && !willChange) {
+        // A value changed for an AVPlayerItem
+        if ([keyPath isEqualToString:@"status"])
+            function = std::bind(&MediaPlayerPrivateAVFoundationObjC::playerItemStatusDidChange, m_callback, [newValue intValue]);
+        else if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"])
+            function = std::bind(&MediaPlayerPrivateAVFoundationObjC::playbackLikelyToKeepUpDidChange, m_callback, [newValue boolValue]);
+        else if ([keyPath isEqualToString:@"playbackBufferEmpty"])
+            function = std::bind(&MediaPlayerPrivateAVFoundationObjC::playbackBufferEmptyDidChange, m_callback, [newValue boolValue]);
+        else if ([keyPath isEqualToString:@"playbackBufferFull"])
+            function = std::bind(&MediaPlayerPrivateAVFoundationObjC::playbackBufferFullDidChange, m_callback, [newValue boolValue]);
+        else if ([keyPath isEqualToString:@"asset"]) {
+            function = std::bind(&MediaPlayerPrivateAVFoundationObjC::setAsset, m_callback, RetainPtr<id>(newValue));
+            shouldLogValue = false;
+        } else if ([keyPath isEqualToString:@"loadedTimeRanges"])
+            function = std::bind(&MediaPlayerPrivateAVFoundationObjC::loadedTimeRangesDidChange, m_callback, RetainPtr<NSArray>(newValue));
+        else if ([keyPath isEqualToString:@"seekableTimeRanges"])
+            function = std::bind(&MediaPlayerPrivateAVFoundationObjC::seekableTimeRangesDidChange, m_callback, RetainPtr<NSArray>(newValue));
+        else if ([keyPath isEqualToString:@"tracks"]) {
+            function = std::bind(&MediaPlayerPrivateAVFoundationObjC::tracksDidChange, m_callback, RetainPtr<NSArray>(newValue));
+            shouldLogValue = false;
+        } else if ([keyPath isEqualToString:@"hasEnabledAudio"])
+            function = std::bind(&MediaPlayerPrivateAVFoundationObjC::hasEnabledAudioDidChange, m_callback, [newValue boolValue]);
+        else if ([keyPath isEqualToString:@"presentationSize"])
+            function = std::bind(&MediaPlayerPrivateAVFoundationObjC::presentationSizeDidChange, m_callback, FloatSize([newValue sizeValue]));
+        else if ([keyPath isEqualToString:@"duration"])
+            function = std::bind(&MediaPlayerPrivateAVFoundationObjC::durationDidChange, m_callback, PAL::toMediaTime([newValue CMTimeValue]));
+        else if ([keyPath isEqualToString:@"timedMetadata"] && newValue) {
+            MediaTime now;
+            CMTime itemTime = [(AVPlayerItemType *)object currentTime];
+            if (CMTIME_IS_NUMERIC(itemTime))
+                now = std::max(PAL::toMediaTime(itemTime), MediaTime::zeroTime());
+            function = std::bind(&MediaPlayerPrivateAVFoundationObjC::metadataDidArrive, m_callback, RetainPtr<NSArray>(newValue), now);
+            shouldLogValue = false;
+        } else if ([keyPath isEqualToString:@"canPlayFastReverse"])
+            function = std::bind(&MediaPlayerPrivateAVFoundationObjC::canPlayFastReverseDidChange, m_callback, [newValue boolValue]);
+        else if ([keyPath isEqualToString:@"canPlayFastForward"])
+            function = std::bind(&MediaPlayerPrivateAVFoundationObjC::canPlayFastForwardDidChange, m_callback, [newValue boolValue]);
+    }
+
+    if (context == MediaPlayerAVFoundationObservationContextPlayer && !willChange) {
+        // A value changed for an AVPlayer.
+        if ([keyPath isEqualToString:@"rate"])
+            function = std::bind(&MediaPlayerPrivateAVFoundationObjC::rateDidChange, m_callback, [newValue doubleValue]);
</ins><span class="cx"> #if ENABLE(WIRELESS_PLAYBACK_TARGET)
</span><del>-            else if ([keyPath isEqualToString:@"externalPlaybackActive"] || [keyPath isEqualToString:@"allowsExternalPlayback"])
-                player->playbackTargetIsWirelessDidChange();
</del><ins>+        else if ([keyPath isEqualToString:@"externalPlaybackActive"] || [keyPath isEqualToString:@"allowsExternalPlayback"])
+            function = std::bind(&MediaPlayerPrivateAVFoundationObjC::playbackTargetIsWirelessDidChange, m_callback);
</ins><span class="cx"> #endif
</span><span class="cx"> #if ENABLE(LEGACY_ENCRYPTED_MEDIA) || ENABLE(ENCRYPTED_MEDIA)
</span><del>-            else if ([keyPath isEqualToString:@"outputObscuredDueToInsufficientExternalProtection"])
-                player->outputObscuredDueToInsufficientExternalProtectionChanged([newValue boolValue]);
</del><ins>+        else if ([keyPath isEqualToString:@"outputObscuredDueToInsufficientExternalProtection"])
+            function = std::bind(&MediaPlayerPrivateAVFoundationObjC::outputObscuredDueToInsufficientExternalProtectionChanged, m_callback, [newValue boolValue]);
</ins><span class="cx"> #endif
</span><del>-        }
</del><ins>+    }
</ins><span class="cx"> 
</span><span class="cx"> #if !RELEASE_LOG_DISABLED
</span><del>-        if (player->logger().willLog(player->logChannel(), WTFLogLevelDebug) && !([keyPath isEqualToString:@"loadedTimeRanges"] || [keyPath isEqualToString:@"seekableTimeRanges"])) {
-            auto identifier = Logger::LogSiteIdentifier("MediaPlayerPrivateAVFoundation", "observeValueForKeyPath", player->logIdentifier());
</del><ins>+    if (m_callback->logger().willLog(m_callback->logChannel(), WTFLogLevelDebug) && !([keyPath isEqualToString:@"loadedTimeRanges"] || [keyPath isEqualToString:@"seekableTimeRanges"])) {
+        auto identifier = Logger::LogSiteIdentifier("MediaPlayerPrivateAVFoundation", "observeValueForKeyPath", m_callback->logIdentifier());
</ins><span class="cx"> 
</span><del>-            if (shouldLogValue) {
-                if ([keyPath isEqualToString:@"duration"])
-                    player->logger().debug(player->logChannel(), identifier, "did change '", [keyPath UTF8String], "' to ", PAL::toMediaTime([newValue CMTimeValue]));
-                else {
-                    RetainPtr<NSString> valueString = adoptNS([[NSString alloc] initWithFormat:@"%@", newValue]);
-                    player->logger().debug(player->logChannel(), identifier, "did change '", [keyPath UTF8String], "' to ", [valueString.get() UTF8String]);
-                }
-            } else
-                player->logger().debug(player->logChannel(), identifier, willChange ? "will" : "did", " change '", [keyPath UTF8String], "'");
-        }
</del><ins>+        if (shouldLogValue) {
+            if ([keyPath isEqualToString:@"duration"])
+                m_callback->logger().debug(m_callback->logChannel(), identifier, "did change '", [keyPath UTF8String], "' to ", PAL::toMediaTime([newValue CMTimeValue]));
+            else {
+                RetainPtr<NSString> valueString = adoptNS([[NSString alloc] initWithFormat:@"%@", newValue]);
+                m_callback->logger().debug(m_callback->logChannel(), identifier, "did change '", [keyPath UTF8String], "' to ", [valueString.get() UTF8String]);
+            }
+        } else
+            m_callback->logger().debug(m_callback->logChannel(), identifier, willChange ? "will" : "did", " change '", [keyPath UTF8String], "'");
+    }
</ins><span class="cx"> #endif
</span><del>-    });
</del><ins>+
+    if (!function)
+        return;
+
+    auto weakThis = makeWeakPtr(*m_callback);
+    m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification([weakThis, function = WTFMove(function)]{
+        // weakThis and function both refer to the same MediaPlayerPrivateAVFoundationObjC instance. If the WeakPtr has
+        // been cleared, the underlying object has been destroyed, and it is unsafe to call function().
+        if (!weakThis)
+            return;
+        function();
+    }));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if HAVE(AVFOUNDATION_MEDIA_SELECTION_GROUP)
</span><span class="lines">@@ -3484,12 +3497,20 @@
</span><span class="cx"> - (void)legibleOutput:(id)output didOutputAttributedStrings:(NSArray *)strings nativeSampleBuffers:(NSArray *)nativeSamples forItemTime:(CMTime)itemTime
</span><span class="cx"> {
</span><span class="cx">     UNUSED_PARAM(output);
</span><ins>+    UNUSED_PARAM(nativeSamples);
</ins><span class="cx"> 
</span><del>-    m_taskQueue.enqueueTask([player = m_player, strings = retainPtr(strings), nativeSamples = retainPtr(nativeSamples), itemTime] {
-        if (!player)
</del><ins>+    if (!m_callback)
+        return;
+
+    RetainPtr<WebCoreAVFMovieObserver> protectedSelf = self;
+    RetainPtr<NSArray> protectedStrings = strings;
+    RetainPtr<NSArray> protectedNativeSamples = nativeSamples;
+    callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedStrings = WTFMove(protectedStrings), protectedNativeSamples = WTFMove(protectedNativeSamples), itemTime] {
+        MediaPlayerPrivateAVFoundationObjC* callback = protectedSelf->m_callback;
+        if (!callback)
</ins><span class="cx">             return;
</span><span class="cx">         MediaTime time = std::max(PAL::toMediaTime(itemTime), MediaTime::zeroTime());
</span><del>-        player->processCue(strings.get(), nativeSamples.get(), time);
</del><ins>+        callback->processCue(protectedStrings.get(), protectedNativeSamples.get(), time);
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -3497,9 +3518,12 @@
</span><span class="cx"> {
</span><span class="cx">     UNUSED_PARAM(output);
</span><span class="cx"> 
</span><del>-    m_taskQueue.enqueueTask([player = m_player] {
-        if (player)
-            player->flushCues();
</del><ins>+    if (!m_callback)
+        return;
+    
+    callOnMainThread([protectedSelf = RetainPtr<WebCoreAVFMovieObserver>(self)] {
+        if (MediaPlayerPrivateAVFoundationObjC* callback = protectedSelf->m_callback)
+            callback->flushCues();
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -3511,12 +3535,12 @@
</span><span class="cx"> 
</span><span class="cx"> @implementation WebCoreAVFLoaderDelegate
</span><span class="cx"> 
</span><del>-- (id)initWithPlayer:(WeakPtr<MediaPlayerPrivateAVFoundationObjC>&&)player
</del><ins>+- (id)initWithCallback:(MediaPlayerPrivateAVFoundationObjC*)callback
</ins><span class="cx"> {
</span><span class="cx">     self = [super init];
</span><span class="cx">     if (!self)
</span><span class="cx">         return nil;
</span><del>-    m_player = WTFMove(player);
</del><ins>+    m_callback = callback;
</ins><span class="cx">     return self;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -3523,17 +3547,20 @@
</span><span class="cx"> - (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest
</span><span class="cx"> {
</span><span class="cx">     UNUSED_PARAM(resourceLoader);
</span><del>-    if (!m_player)
</del><ins>+    if (!m_callback)
</ins><span class="cx">         return NO;
</span><span class="cx"> 
</span><del>-    m_taskQueue.enqueueTask([player = m_player, loadingRequest = retainPtr(loadingRequest)] {
-        if (!player) {
-            [loadingRequest finishLoadingWithError:nil];
</del><ins>+    RetainPtr<WebCoreAVFLoaderDelegate> protectedSelf = self;
+    RetainPtr<AVAssetResourceLoadingRequest> protectedLoadingRequest = loadingRequest;
+    callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedLoadingRequest = WTFMove(protectedLoadingRequest)] {
+        MediaPlayerPrivateAVFoundationObjC* callback = protectedSelf->m_callback;
+        if (!callback) {
+            [protectedLoadingRequest finishLoadingWithError:nil];
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (!player->shouldWaitForLoadingOfResource(loadingRequest.get()))
-            [loadingRequest finishLoadingWithError:nil];
</del><ins>+        if (!callback->shouldWaitForLoadingOfResource(protectedLoadingRequest.get()))
+            [protectedLoadingRequest finishLoadingWithError:nil];
</ins><span class="cx">     });
</span><span class="cx"> 
</span><span class="cx">     return YES;
</span><span class="lines">@@ -3550,12 +3577,22 @@
</span><span class="cx"> - (void)resourceLoader:(AVAssetResourceLoader *)resourceLoader didCancelLoadingRequest:(AVAssetResourceLoadingRequest *)loadingRequest
</span><span class="cx"> {
</span><span class="cx">     UNUSED_PARAM(resourceLoader);
</span><del>-    m_taskQueue.enqueueTask([player = m_player, loadingRequest = retainPtr(loadingRequest)] {
-        if (player)
-            player->didCancelLoadingRequest(loadingRequest.get());
</del><ins>+    if (!m_callback)
+        return;
+
+    RetainPtr<WebCoreAVFLoaderDelegate> protectedSelf = self;
+    RetainPtr<AVAssetResourceLoadingRequest> protectedLoadingRequest = loadingRequest;
+    callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedLoadingRequest = WTFMove(protectedLoadingRequest)] {
+        MediaPlayerPrivateAVFoundationObjC* callback = protectedSelf->m_callback;
+        if (callback)
+            callback->didCancelLoadingRequest(protectedLoadingRequest.get());
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (void)setCallback:(MediaPlayerPrivateAVFoundationObjC*)callback
+{
+    m_callback = callback;
+}
</ins><span class="cx"> @end
</span><span class="cx"> 
</span><span class="cx"> #endif
</span><span class="lines">@@ -3564,18 +3601,23 @@
</span><span class="cx"> 
</span><span class="cx"> @implementation WebCoreAVFPullDelegate
</span><span class="cx"> 
</span><del>-- (id)initWithPlayer:(WeakPtr<MediaPlayerPrivateAVFoundationObjC>&&)player
</del><ins>+- (id)initWithCallback:(MediaPlayerPrivateAVFoundationObjC *)callback
</ins><span class="cx"> {
</span><span class="cx">     self = [super init];
</span><span class="cx">     if (self)
</span><del>-        m_player = WTFMove(player);
</del><ins>+        m_callback = callback;
</ins><span class="cx">     return self;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (void)setCallback:(MediaPlayerPrivateAVFoundationObjC *)callback
+{
+    m_callback = callback;
+}
+
</ins><span class="cx"> - (void)outputMediaDataWillChange:(AVPlayerItemVideoOutputType *)output
</span><span class="cx"> {
</span><del>-    if (m_player)
-        m_player->outputMediaDataWillChange(output);
</del><ins>+    if (m_callback)
+        m_callback->outputMediaDataWillChange(output);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)outputSequenceWasFlushed:(AVPlayerItemVideoOutputType *)output
</span></span></pre>
</div>
</div>

</body>
</html>