WebKit Bugzilla
Attachment 349452 Details for
Bug 188747
: Refactoring: eliminate raw pointer usage in Fullscreen code
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-188747-20180911141928.patch (text/plain), 166.52 KB, created by
Jer Noble
on 2018-09-11 14:19:29 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Jer Noble
Created:
2018-09-11 14:19:29 PDT
Size:
166.52 KB
patch
obsolete
>Subversion Revision: 235897 >diff --git a/Source/WTF/ChangeLog b/Source/WTF/ChangeLog >index e60abee4189f1442afc52c598099305a20175ed1..3d7807919d93901dac8b1b154ea8a2f42333a9fb 100644 >--- a/Source/WTF/ChangeLog >+++ b/Source/WTF/ChangeLog >@@ -1 +1,12 @@ >+2018-08-22 Jer Noble <jer.noble@apple.com> >+ >+ Refactoring: eliminate raw pointer usage in Fullscreen code >+ https://bugs.webkit.org/show_bug.cgi?id=188747 >+ <rdar://problem/43541164> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * WTF.xcodeproj/project.pbxproj: >+ * wtf/WeakPtrContainer.h: Added. >+ > == Rolled over to ChangeLog-2018-09-11 == >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index c7f206b6cd834dc87af6155117b157cd1c8ec13d..2ba689349b50489247e6d6e1cfe21f2d3ba5f9c5 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,164 @@ >+2018-08-22 Jer Noble <jer.noble@apple.com> >+ >+ Refactoring: eliminate raw pointer usage in Fullscreen code >+ https://bugs.webkit.org/show_bug.cgi?id=188747 >+ <rdar://problem/43541164> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Two sources of raw pointers in the Fullscreen code: >+ - Model classes (PlaybackSessionModel and VideoFullscreenModel) aren't ref-able, so >+ they are passed around as raw references. >+ - Observer classes (PlaybackSessionModelClient and VideoFullscreenModelClient, and >+ VideoFullscreenChangeObserver) are also passed around as raw pointers, but shouldn't >+ be ref-able. >+ >+ Make Model classes ref-able by adding ref() and deref() which call virtual refModel and >+ derefModel methods, overridden by implementing subclasses. Make every concrete observer >+ inherit from CanMakeWeakPtr, and every registration method take WeakPtr wrappers around >+ the client interface. >+ >+ Since every Interface class now holds a strong reference to its Model classes, and each >+ Model class holds a weak reference to all its clients, no explicit invalidate() method >+ is necessary. >+ >+ Notes: >+ >+ - Since the weak pointer methods need to be able to downcast to the abstract base class, >+ observers need to inherit publically (rather than privately) from those base classes. >+ - Media element Models should compose EventListener rather than inheriting from it, since >+ EventListener has its own RefCount. >+ - WeakPtrs can't be held in HashSets (because they change value, and therefore hash, when >+ their underlying object is destroyed), so clients should be stored in a Vector instead. >+ - Interfaces should be given all required Refs at creation time, so that they can store >+ those parameters as Refs instead of RefPtrs. >+ >+ * platform/cocoa/PlaybackSessionInterface.h: >+ (WebCore::PlaybackSessionInterface::~PlaybackSessionInterface): Deleted. >+ * platform/cocoa/PlaybackSessionModel.h: >+ (WebCore::PlaybackSessionModel::ref): >+ (WebCore::PlaybackSessionModel::deref): >+ (WebCore::PlaybackSessionModel::~PlaybackSessionModel): Deleted. >+ * platform/cocoa/PlaybackSessionModelMediaElement.h: >+ * platform/cocoa/PlaybackSessionModelMediaElement.mm: >+ (WebCore::PlaybackSessionModelMediaElement::PlaybackSessionModelMediaElement): >+ (WebCore::PlaybackSessionModelMediaElement::~PlaybackSessionModelMediaElement): >+ (WebCore::PlaybackSessionModelMediaElement::setMediaElement): >+ (WebCore::PlaybackSessionModelMediaElement::updateForEventName): >+ (WebCore::PlaybackSessionModelMediaElement::addClient): >+ (WebCore::PlaybackSessionModelMediaElement::removeClient): >+ (WebCore::PlaybackSessionModelMediaElement::updateMediaSelectionOptions): >+ (WebCore::PlaybackSessionModelMediaElement::updateMediaSelectionIndices): >+ (WebCore::PlaybackSessionModelMediaElement::handleEvent): Deleted. >+ * platform/cocoa/VideoFullscreenChangeObserver.h: >+ (WebCore::VideoFullscreenChangeObserver::~VideoFullscreenChangeObserver): Deleted. >+ * platform/cocoa/VideoFullscreenModel.h: >+ (WebCore::VideoFullscreenModel::ref): >+ (WebCore::VideoFullscreenModel::deref): >+ (WebCore::VideoFullscreenModel::~VideoFullscreenModel): Deleted. >+ * platform/cocoa/VideoFullscreenModelVideoElement.h: >+ * platform/cocoa/VideoFullscreenModelVideoElement.mm: >+ (VideoFullscreenModelVideoElement::VideoFullscreenModelVideoElement): >+ (VideoFullscreenModelVideoElement::setVideoElement): >+ (VideoFullscreenModelVideoElement::addClient): >+ (VideoFullscreenModelVideoElement::removeClient): >+ (VideoFullscreenModelVideoElement::setHasVideo): >+ (VideoFullscreenModelVideoElement::setVideoDimensions): >+ (VideoFullscreenModelVideoElement::willEnterPictureInPicture): >+ (VideoFullscreenModelVideoElement::didEnterPictureInPicture): >+ (VideoFullscreenModelVideoElement::failedToEnterPictureInPicture): >+ (VideoFullscreenModelVideoElement::willExitPictureInPicture): >+ (VideoFullscreenModelVideoElement::didExitPictureInPicture): >+ (VideoFullscreenModelVideoElement::handleEvent): Deleted. >+ * platform/ios/PlaybackSessionInterfaceAVKit.h: >+ (WebCore::PlaybackSessionInterfaceAVKit::create): >+ (WebCore::PlaybackSessionInterfaceAVKit::playbackSessionModel const): >+ (): Deleted. >+ * platform/ios/PlaybackSessionInterfaceAVKit.mm: >+ (WebCore::PlaybackSessionInterfaceAVKit::PlaybackSessionInterfaceAVKit): >+ (WebCore::PlaybackSessionInterfaceAVKit::~PlaybackSessionInterfaceAVKit): >+ (WebCore::PlaybackSessionInterfaceAVKit::invalidate): Deleted. >+ * platform/ios/VideoFullscreenInterfaceAVKit.h: >+ * platform/ios/VideoFullscreenInterfaceAVKit.mm: >+ (-[WebAVPlayerLayer layoutSublayers]): >+ (-[WebAVPlayerLayer resolveBounds]): >+ (-[WebAVPlayerLayer setVideoGravity:]): >+ (VideoFullscreenInterfaceAVKit::create): >+ (VideoFullscreenInterfaceAVKit::VideoFullscreenInterfaceAVKit): >+ (VideoFullscreenInterfaceAVKit::~VideoFullscreenInterfaceAVKit): >+ (VideoFullscreenInterfaceAVKit::setVideoFullscreenChangeObserver): >+ (VideoFullscreenInterfaceAVKit::applicationDidBecomeActive): >+ (VideoFullscreenInterfaceAVKit::setupFullscreen): >+ (VideoFullscreenInterfaceAVKit::presentingViewController): >+ (VideoFullscreenInterfaceAVKit::requestHideAndExitFullscreen): >+ (VideoFullscreenInterfaceAVKit::preparedToExitFullscreen): >+ (VideoFullscreenInterfaceAVKit::willStartPictureInPicture): >+ (VideoFullscreenInterfaceAVKit::didStartPictureInPicture): >+ (VideoFullscreenInterfaceAVKit::failedToStartPictureInPicture): >+ (VideoFullscreenInterfaceAVKit::willStopPictureInPicture): >+ (VideoFullscreenInterfaceAVKit::didStopPictureInPicture): >+ (VideoFullscreenInterfaceAVKit::shouldExitFullscreenWithReason): >+ (VideoFullscreenInterfaceAVKit::doSetup): >+ (VideoFullscreenInterfaceAVKit::setMode): >+ (VideoFullscreenInterfaceAVKit::clearMode): >+ (VideoFullscreenInterfaceAVKit::setVideoFullscreenModel): Deleted. >+ (VideoFullscreenInterfaceAVKit::invalidate): Deleted. >+ * platform/ios/WebAVPlayerController.h: >+ * platform/ios/WebAVPlayerController.mm: >+ (-[WebAVPlayerController delegate]): >+ (-[WebAVPlayerController playbackSessionInterface]): >+ (-[WebAVPlayerController setPlaybackSessionInterface:]): >+ * platform/ios/WebVideoFullscreenControllerAVKit.mm: >+ (VideoFullscreenControllerContext::didCleanupFullscreen): >+ (VideoFullscreenControllerContext::addClient): >+ (VideoFullscreenControllerContext::removeClient): >+ (VideoFullscreenControllerContext::willEnterPictureInPicture): >+ (VideoFullscreenControllerContext::didEnterPictureInPicture): >+ (VideoFullscreenControllerContext::failedToEnterPictureInPicture): >+ (VideoFullscreenControllerContext::willExitPictureInPicture): >+ (VideoFullscreenControllerContext::didExitPictureInPicture): >+ (VideoFullscreenControllerContext::setUpFullscreen): >+ * platform/mac/PlaybackSessionInterfaceMac.h: >+ * platform/mac/PlaybackSessionInterfaceMac.mm: >+ (WebCore::PlaybackSessionInterfaceMac::create): >+ (WebCore::PlaybackSessionInterfaceMac::PlaybackSessionInterfaceMac): >+ (WebCore::PlaybackSessionInterfaceMac::playbackSessionModel const): >+ (WebCore::PlaybackSessionInterfaceMac::rateChanged): >+ (WebCore::PlaybackSessionInterfaceMac::beginScrubbing): >+ (WebCore::PlaybackSessionInterfaceMac::endScrubbing): >+ (WebCore::PlaybackSessionInterfaceMac::setPlayBackControlsManager): >+ (WebCore::PlaybackSessionInterfaceMac::updatePlaybackControlsManagerTiming): >+ (WebCore::PlaybackSessionInterfaceMac::~PlaybackSessionInterfaceMac): Deleted. >+ (WebCore::PlaybackSessionInterfaceMac::invalidate): Deleted. >+ * platform/mac/VideoFullscreenInterfaceMac.h: >+ (WebCore::VideoFullscreenInterfaceMac::create): >+ (WebCore::VideoFullscreenInterfaceMac::videoFullscreenModel const): >+ (WebCore::VideoFullscreenInterfaceMac::playbackSessionModel const): >+ (WebCore::VideoFullscreenInterfaceMac::videoFullscreenChangeObserver const): >+ * platform/mac/VideoFullscreenInterfaceMac.mm: >+ (-[WebVideoFullscreenInterfaceMacObjC setUpPIPForVideoView:withFrame:inWindow:]): >+ (-[WebVideoFullscreenInterfaceMacObjC boundsDidChangeForVideoViewContainer:]): >+ (-[WebVideoFullscreenInterfaceMacObjC pipDidClose:]): >+ (-[WebVideoFullscreenInterfaceMacObjC pipActionPlay:]): >+ (-[WebVideoFullscreenInterfaceMacObjC pipActionPause:]): >+ (-[WebVideoFullscreenInterfaceMacObjC pipActionStop:]): >+ (WebCore::VideoFullscreenInterfaceMac::VideoFullscreenInterfaceMac): >+ (WebCore::VideoFullscreenInterfaceMac::~VideoFullscreenInterfaceMac): >+ (WebCore::VideoFullscreenInterfaceMac::setVideoFullscreenChangeObserver): >+ (WebCore::VideoFullscreenInterfaceMac::setMode): >+ (WebCore::VideoFullscreenInterfaceMac::clearMode): >+ (WebCore::VideoFullscreenInterfaceMac::invalidate): >+ (WebCore::VideoFullscreenInterfaceMac::requestHideAndExitPiP): >+ (WebCore::VideoFullscreenInterfaceMac::setVideoFullscreenModel): Deleted. >+ * platform/mac/WebPlaybackControlsManager.mm: >+ (-[WebPlaybackControlsManager seekToTime:toleranceBefore:toleranceAfter:]): >+ (-[WebPlaybackControlsManager setCurrentAudioTouchBarMediaSelectionOption:]): >+ (-[WebPlaybackControlsManager setCurrentLegibleTouchBarMediaSelectionOption:]): >+ (-[WebPlaybackControlsManager togglePlayback]): >+ (-[WebPlaybackControlsManager setPlaying:]): >+ (-[WebPlaybackControlsManager isPlaying]): >+ (-[WebPlaybackControlsManager togglePictureInPicture]): >+ > 2018-09-11 Woodrow Wang <woodrow_wang@apple.com> > > Add Web API Statistics Collection >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index ef4d3e4b0d8b22081123ed8784715c1bf4f74b9f..e5fce94d0841dba1fa57bdf4cb096432159327e3 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,73 @@ >+2018-08-22 Jer Noble <jer.noble@apple.com> >+ >+ Refactoring: eliminate raw pointer usage in Fullscreen code >+ https://bugs.webkit.org/show_bug.cgi?id=188747 >+ <rdar://problem/43541164> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Adopt those Ref and WeakPtr changes made in WebCore. >+ >+ * UIProcess/Cocoa/PlaybackSessionManagerProxy.h: >+ * UIProcess/Cocoa/PlaybackSessionManagerProxy.mm: >+ (WebKit::PlaybackSessionModelContext::addClient): >+ (WebKit::PlaybackSessionModelContext::removeClient): >+ (WebKit::PlaybackSessionModelContext::durationChanged): >+ (WebKit::PlaybackSessionModelContext::currentTimeChanged): >+ (WebKit::PlaybackSessionModelContext::bufferedTimeChanged): >+ (WebKit::PlaybackSessionModelContext::rateChanged): >+ (WebKit::PlaybackSessionModelContext::seekableRangesChanged): >+ (WebKit::PlaybackSessionModelContext::canPlayFastReverseChanged): >+ (WebKit::PlaybackSessionModelContext::audioMediaSelectionOptionsChanged): >+ (WebKit::PlaybackSessionModelContext::legibleMediaSelectionOptionsChanged): >+ (WebKit::PlaybackSessionModelContext::audioMediaSelectionIndexChanged): >+ (WebKit::PlaybackSessionModelContext::legibleMediaSelectionIndexChanged): >+ (WebKit::PlaybackSessionModelContext::externalPlaybackChanged): >+ (WebKit::PlaybackSessionModelContext::wirelessVideoPlaybackDisabledChanged): >+ (WebKit::PlaybackSessionModelContext::mutedChanged): >+ (WebKit::PlaybackSessionModelContext::volumeChanged): >+ (WebKit::PlaybackSessionModelContext::pictureInPictureActiveChanged): >+ (WebKit::PlaybackSessionManagerProxy::invalidate): >+ (WebKit::PlaybackSessionManagerProxy::createModelAndInterface): >+ (WebKit::PlaybackSessionManagerProxy::removeClientForContext): >+ * UIProcess/Cocoa/VideoFullscreenManagerProxy.h: >+ * UIProcess/Cocoa/VideoFullscreenManagerProxy.mm: >+ (WebKit::VideoFullscreenModelContext::create): >+ (WebKit::VideoFullscreenModelContext::VideoFullscreenModelContext): >+ (WebKit::VideoFullscreenModelContext::addClient): >+ (WebKit::VideoFullscreenModelContext::removeClient): >+ (WebKit::VideoFullscreenModelContext::willEnterPictureInPicture): >+ (WebKit::VideoFullscreenModelContext::didEnterPictureInPicture): >+ (WebKit::VideoFullscreenModelContext::failedToEnterPictureInPicture): >+ (WebKit::VideoFullscreenModelContext::willExitPictureInPicture): >+ (WebKit::VideoFullscreenModelContext::didExitPictureInPicture): >+ (WebKit::VideoFullscreenManagerProxy::invalidate): >+ (WebKit::VideoFullscreenManagerProxy::createModelAndInterface): >+ (WebKit::VideoFullscreenManagerProxy::removeClientForContext): >+ (WebKit::VideoFullscreenModelContext::~VideoFullscreenModelContext): Deleted. >+ * UIProcess/ios/fullscreen/WKFullScreenViewController.mm: >+ (WKFullScreenViewControllerPlaybackSessionModelClient::setInterface): >+ (WKFullScreenViewControllerVideoFullscreenModelClient::setInterface): >+ (-[WKFullScreenViewController videoControlsManagerDidChange]): >+ (-[WKFullScreenViewController _togglePiPAction:]): >+ * UIProcess/mac/WKFullScreenWindowController.mm: >+ (WebKit::WKFullScreenWindowControllerVideoFullscreenModelClient::setInterface): >+ * WebProcess/cocoa/PlaybackSessionManager.h: >+ * WebProcess/cocoa/PlaybackSessionManager.mm: >+ (WebKit::PlaybackSessionInterfaceContext::PlaybackSessionInterfaceContext): >+ (WebKit::PlaybackSessionManager::~PlaybackSessionManager): >+ (WebKit::PlaybackSessionManager::createModelAndInterface): >+ (WebKit::PlaybackSessionManager::removeContext): >+ (WebKit::PlaybackSessionInterfaceContext::~PlaybackSessionInterfaceContext): Deleted. >+ * WebProcess/cocoa/VideoFullscreenManager.h: >+ (WebKit::VideoFullscreenInterfaceContext::create): >+ (WebKit::VideoFullscreenInterfaceContext::createWeakPtr): >+ * WebProcess/cocoa/VideoFullscreenManager.mm: >+ (WebKit::VideoFullscreenInterfaceContext::VideoFullscreenInterfaceContext): >+ (WebKit::VideoFullscreenManager::~VideoFullscreenManager): >+ (WebKit::VideoFullscreenManager::createModelAndInterface): >+ (WebKit::VideoFullscreenManager::removeContext): >+ > 2018-09-11 Woodrow Wang <woodrow_wang@apple.com> > > Add Web API Statistics Collection >diff --git a/Source/WebKitLegacy/mac/ChangeLog b/Source/WebKitLegacy/mac/ChangeLog >index e97d88be213543193a59c3534d8a4159f0ecaa95..c6400460ac1c46c0c7de0e8ff911ee2547ce89d8 100644 >--- a/Source/WebKitLegacy/mac/ChangeLog >+++ b/Source/WebKitLegacy/mac/ChangeLog >@@ -1,3 +1,16 @@ >+2018-08-22 Jer Noble <jer.noble@apple.com> >+ >+ Refactoring: eliminate raw pointer usage in Fullscreen code >+ https://bugs.webkit.org/show_bug.cgi?id=188747 >+ <rdar://problem/43541164> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ PlaybackSessionInterface no longer has an invalidate() method. >+ >+ * WebView/WebView.mm: >+ (-[WebView _clearPlaybackControlsManager]): >+ > 2018-09-10 Fujii Hironori <Hironori.Fujii@sony.com> > > Remove unused needsDestruction class variables from HashTraits >diff --git a/Source/WTF/WTF.xcodeproj/project.pbxproj b/Source/WTF/WTF.xcodeproj/project.pbxproj >index 86f4bdbad73ce0f63a4648f03386bffc8e95f4db..e620521105ca4fca0694cef945b57566e6a9faff 100644 >--- a/Source/WTF/WTF.xcodeproj/project.pbxproj >+++ b/Source/WTF/WTF.xcodeproj/project.pbxproj >@@ -604,6 +604,7 @@ > C4F8A93619C65EB400B2B15D /* Stopwatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Stopwatch.h; sourceTree = "<group>"; }; > C6F050790D9C432A99085E75 /* ASCIILiteral.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ASCIILiteral.cpp; sourceTree = "<group>"; }; > C8F597CA2A57417FBAB92FD6 /* RandomDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RandomDevice.cpp; sourceTree = "<group>"; }; >+ CD2D0D10212C76E60018C784 /* WeakPtrContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakPtrContainer.h; sourceTree = "<group>"; }; > CD5497AA15857D0300B5BC30 /* MediaTime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaTime.cpp; sourceTree = "<group>"; }; > CD5497AB15857D0300B5BC30 /* MediaTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaTime.h; sourceTree = "<group>"; }; > CD6D9FCD1EEF3AD4008B0671 /* Algorithms.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Algorithms.h; sourceTree = "<group>"; }; >@@ -1136,6 +1137,7 @@ > 0F66B2891DC97BAB004A1D3F /* WallTime.h */, > 83ABB3C020B3823200BA3306 /* WeakObjCPtr.h */, > 974CFC8D16A4F327006D5404 /* WeakPtr.h */, >+ CD2D0D10212C76E60018C784 /* WeakPtrContainer.h */, > 0F3501631BB258C800F0A2A3 /* WeakRandom.h */, > 0FE4479A1B7AAA03009498EB /* WordLock.cpp */, > 0FE4479B1B7AAA03009498EB /* WordLock.h */, >diff --git a/Source/WTF/wtf/WeakPtrContainer.h b/Source/WTF/wtf/WeakPtrContainer.h >new file mode 100644 >index 0000000000000000000000000000000000000000..5340943a62420ed8adba8817111645825264f4e9 >--- /dev/null >+++ b/Source/WTF/wtf/WeakPtrContainer.h >@@ -0,0 +1,81 @@ >+/* >+ * Copyright (C) 2018 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#pragma once >+ >+#include <wtf/Vector.h> >+#include <wtf/WeakPtr.h> >+ >+namespace WTF { >+ >+template <typename T> >+class WeakPtrContainer { >+public: >+ void add(WeakPtr<T>&& ptr) >+ { >+ m_members.append(WTFMove(ptr)); >+ } >+ >+ void remove(T& ptr) >+ { >+ m_members.removeAll(&ptr); >+ } >+ >+ void clear() >+ { >+ m_members.clear(); >+ } >+ >+ bool isEmpty() const >+ { >+ return m_members.isEmpty(); >+ } >+ >+ void removeNullMembers() >+ { >+ m_members.removeAllMatching([] (auto& ptr) { return !ptr; }); >+ } >+ >+ template <typename F> >+ void forEachNonNullMember(F&& f) >+ { >+ bool hasNullMembers = false; >+ for (auto& member : m_members) { >+ if (member) >+ f(*member); >+ else >+ hasNullMembers = true; >+ } >+ >+ if (hasNullMembers) >+ removeNullMembers(); >+ } >+private: >+ Vector<WeakPtr<T>> m_members; >+}; >+ >+} >+ >+using WTF::WeakPtrContainer; >diff --git a/Source/WebCore/platform/cocoa/PlaybackSessionInterface.h b/Source/WebCore/platform/cocoa/PlaybackSessionInterface.h >index cdf2bbfbddd7e2f935dc2b3cd49f55081884754b..db7b58fa9e045bb349554595f42c82029147098e 100644 >--- a/Source/WebCore/platform/cocoa/PlaybackSessionInterface.h >+++ b/Source/WebCore/platform/cocoa/PlaybackSessionInterface.h >@@ -27,16 +27,11 @@ > > #if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)) > >-#include <wtf/Forward.h> >-#include <wtf/Vector.h> >- > namespace WebCore { > >-class TimeRanges; >- > class PlaybackSessionInterface { > public: >- virtual ~PlaybackSessionInterface() { }; >+ virtual ~PlaybackSessionInterface() = default; > virtual void resetMediaState() = 0; > }; > >diff --git a/Source/WebCore/platform/cocoa/PlaybackSessionModel.h b/Source/WebCore/platform/cocoa/PlaybackSessionModel.h >index c43f732fd643dd9fdbad3ca57fa917a8fa25a437..1553639d74abe06039a8d28754faace89260f637 100644 >--- a/Source/WebCore/platform/cocoa/PlaybackSessionModel.h >+++ b/Source/WebCore/platform/cocoa/PlaybackSessionModel.h >@@ -30,6 +30,7 @@ > #include <wtf/Forward.h> > #include <wtf/Ref.h> > #include <wtf/Vector.h> >+#include <wtf/WeakPtr.h> > > namespace WebCore { > >@@ -39,8 +40,12 @@ struct MediaSelectionOption; > > class PlaybackSessionModel { > public: >- virtual ~PlaybackSessionModel() { }; >- virtual void addClient(PlaybackSessionModelClient&) = 0; >+ virtual ~PlaybackSessionModel() = default; >+ >+ void ref() { refPlaybackSessionModel(); } >+ void deref() { derefPlaybackSessionModel(); } >+ >+ virtual void addClient(WeakPtr<PlaybackSessionModelClient>&&) = 0; > virtual void removeClient(PlaybackSessionModelClient&) = 0; > > virtual void play() = 0; >@@ -86,6 +91,10 @@ public: > virtual double volume() const = 0; > virtual bool isPictureInPictureSupported() const = 0; > virtual bool isPictureInPictureActive() const = 0; >+ >+private: >+ virtual void refPlaybackSessionModel() = 0; >+ virtual void derefPlaybackSessionModel() = 0; > }; > > class PlaybackSessionModelClient { >diff --git a/Source/WebCore/platform/cocoa/PlaybackSessionModelMediaElement.h b/Source/WebCore/platform/cocoa/PlaybackSessionModelMediaElement.h >index 9eefd10f2a3dceead1194ec94853139484723791..204629bc811954f10a89ff351ca7a2dca794a043 100644 >--- a/Source/WebCore/platform/cocoa/PlaybackSessionModelMediaElement.h >+++ b/Source/WebCore/platform/cocoa/PlaybackSessionModelMediaElement.h >@@ -30,9 +30,8 @@ > #include "EventListener.h" > #include "HTMLMediaElementEnums.h" > #include "PlaybackSessionModel.h" >-#include <wtf/HashSet.h> > #include <wtf/RefPtr.h> >-#include <wtf/Vector.h> >+#include <wtf/WeakPtrContainer.h> > > namespace WebCore { > >@@ -41,7 +40,10 @@ class HTMLMediaElement; > class TextTrack; > class PlaybackSessionInterface; > >-class PlaybackSessionModelMediaElement final : public PlaybackSessionModel, public EventListener { >+class PlaybackSessionModelMediaElement final >+ : public RefCounted<PlaybackSessionModelMediaElement> >+ , public CanMakeWeakPtr<PlaybackSessionModelMediaElement> >+ , public PlaybackSessionModel { > public: > static Ref<PlaybackSessionModelMediaElement> create() > { >@@ -51,11 +53,9 @@ public: > WEBCORE_EXPORT void setMediaElement(HTMLMediaElement*); > HTMLMediaElement* mediaElement() const { return m_mediaElement.get(); } > >- WEBCORE_EXPORT void handleEvent(WebCore::ScriptExecutionContext&, WebCore::Event&) final; > void updateForEventName(const WTF::AtomicString&); >- bool operator==(const EventListener& rhs) const final { return static_cast<const WebCore::EventListener*>(this) == &rhs; } > >- WEBCORE_EXPORT void addClient(PlaybackSessionModelClient&); >+ WEBCORE_EXPORT void addClient(WeakPtr<PlaybackSessionModelClient>&&); > WEBCORE_EXPORT void removeClient(PlaybackSessionModelClient&); > WEBCORE_EXPORT void play() final; > WEBCORE_EXPORT void pause() final; >@@ -98,19 +98,27 @@ public: > bool isPictureInPictureSupported() const final; > bool isPictureInPictureActive() const final; > >+ using RefCounted::ref; >+ using RefCounted::deref; >+ > protected: > WEBCORE_EXPORT PlaybackSessionModelMediaElement(); > > private: >+ void refPlaybackSessionModel() final { ref(); } >+ void derefPlaybackSessionModel() final { deref(); } >+ > void progressEventTimerFired(); > static const Vector<WTF::AtomicString>& observedEventNames(); > const WTF::AtomicString& eventNameAll(); > >+ class MediaElementEventListener; >+ > RefPtr<HTMLMediaElement> m_mediaElement; >- bool m_isListening { false }; >- HashSet<PlaybackSessionModelClient*> m_clients; >+ WeakPtrContainer<PlaybackSessionModelClient> m_clients; > Vector<RefPtr<TextTrack>> m_legibleTracksForMenu; > Vector<RefPtr<AudioTrack>> m_audioTracksForMenu; >+ Ref<MediaElementEventListener> m_eventListener; > > double playbackStartedTime() const; > void updateMediaSelectionOptions(); >diff --git a/Source/WebCore/platform/cocoa/PlaybackSessionModelMediaElement.mm b/Source/WebCore/platform/cocoa/PlaybackSessionModelMediaElement.mm >index c01792175dd33d29fa384a5e972550524739d51a..d60a443bf7e690591d1a0fb9c4b8dbdc163defcc 100644 >--- a/Source/WebCore/platform/cocoa/PlaybackSessionModelMediaElement.mm >+++ b/Source/WebCore/platform/cocoa/PlaybackSessionModelMediaElement.mm >@@ -47,13 +47,33 @@ > > namespace WebCore { > >+class PlaybackSessionModelMediaElement::MediaElementEventListener final : public EventListener { >+public: >+ MediaElementEventListener(WeakPtr<PlaybackSessionModelMediaElement>&& parent) >+ : EventListener(CPPEventListenerType) >+ , m_parent(WTFMove(parent)) >+ { >+ } >+private: >+ void handleEvent(WebCore::ScriptExecutionContext&, WebCore::Event& event) final >+ { >+ if (m_parent) >+ m_parent->updateForEventName(event.type()); >+ } >+ bool operator==(const EventListener& rhs) const final { return static_cast<const WebCore::EventListener*>(this) == &rhs; } >+ >+ WeakPtr<PlaybackSessionModelMediaElement> m_parent; >+}; >+ > PlaybackSessionModelMediaElement::PlaybackSessionModelMediaElement() >- : EventListener(EventListener::CPPEventListenerType) >+ : m_eventListener(adoptRef(*new MediaElementEventListener(makeWeakPtr(*this)))) > { > } > > PlaybackSessionModelMediaElement::~PlaybackSessionModelMediaElement() > { >+ m_clients.clear(); >+ setMediaElement(nullptr); > } > > void PlaybackSessionModelMediaElement::setMediaElement(HTMLMediaElement* mediaElement) >@@ -63,52 +83,45 @@ void PlaybackSessionModelMediaElement::setMediaElement(HTMLMediaElement* mediaEl > > auto& events = eventNames(); > >- if (m_mediaElement && m_isListening) { >+ if (m_mediaElement) { > for (auto& eventName : observedEventNames()) >- m_mediaElement->removeEventListener(eventName, *this, false); >+ m_mediaElement->removeEventListener(eventName, m_eventListener.copyRef(), false); > if (auto* audioTracks = m_mediaElement->audioTracks()) { >- audioTracks->removeEventListener(events.addtrackEvent, *this, false); >- audioTracks->removeEventListener(events.changeEvent, *this, false); >- audioTracks->removeEventListener(events.removetrackEvent, *this, false); >+ audioTracks->removeEventListener(events.addtrackEvent, m_eventListener.copyRef(), false); >+ audioTracks->removeEventListener(events.changeEvent, m_eventListener.copyRef(), false); >+ audioTracks->removeEventListener(events.removetrackEvent, m_eventListener.copyRef(), false); > } > > if (auto* textTracks = m_mediaElement->audioTracks()) { >- textTracks->removeEventListener(events.addtrackEvent, *this, false); >- textTracks->removeEventListener(events.changeEvent, *this, false); >- textTracks->removeEventListener(events.removetrackEvent, *this, false); >+ textTracks->removeEventListener(events.addtrackEvent, m_eventListener.copyRef(), false); >+ textTracks->removeEventListener(events.changeEvent, m_eventListener.copyRef(), false); >+ textTracks->removeEventListener(events.removetrackEvent, m_eventListener.copyRef(), false); > } >- } >- m_isListening = false; >- >- if (m_mediaElement) > m_mediaElement->resetPlaybackSessionState(); >+ } > > m_mediaElement = mediaElement; > > if (m_mediaElement) { > for (auto& eventName : observedEventNames()) >- m_mediaElement->addEventListener(eventName, *this, false); >+ m_mediaElement->addEventListener(eventName, m_eventListener.copyRef(), false); > > auto& audioTracks = m_mediaElement->ensureAudioTracks(); >- audioTracks.addEventListener(events.addtrackEvent, *this, false); >- audioTracks.addEventListener(events.changeEvent, *this, false); >- audioTracks.addEventListener(events.removetrackEvent, *this, false); >+ audioTracks.addEventListener(events.addtrackEvent, m_eventListener.copyRef(), false); >+ audioTracks.addEventListener(events.changeEvent, m_eventListener.copyRef(), false); >+ audioTracks.addEventListener(events.removetrackEvent, m_eventListener.copyRef(), false); > > auto& textTracks = m_mediaElement->ensureTextTracks(); >- textTracks.addEventListener(events.addtrackEvent, *this, false); >- textTracks.addEventListener(events.changeEvent, *this, false); >- textTracks.addEventListener(events.removetrackEvent, *this, false); >+ textTracks.addEventListener(events.addtrackEvent, m_eventListener.copyRef(), false); >+ textTracks.addEventListener(events.changeEvent, m_eventListener.copyRef(), false); >+ textTracks.addEventListener(events.removetrackEvent, m_eventListener.copyRef(), false); > } > > updateForEventName(eventNameAll()); > >- for (auto client : m_clients) >- client->isPictureInPictureSupportedChanged(isPictureInPictureSupported()); >-} >- >-void PlaybackSessionModelMediaElement::handleEvent(WebCore::ScriptExecutionContext&, WebCore::Event& event) >-{ >- updateForEventName(event.type()); >+ m_clients.forEachNonNullMember([isPictureInPictureSupported = isPictureInPictureSupported()] (auto& client) { >+ client.isPictureInPictureSupportedChanged(isPictureInPictureSupported); >+ }); > } > > void PlaybackSessionModelMediaElement::updateForEventName(const WTF::AtomicString& eventName) >@@ -120,51 +133,46 @@ void PlaybackSessionModelMediaElement::updateForEventName(const WTF::AtomicStrin > > if (all > || eventName == eventNames().durationchangeEvent) { >- double duration = this->duration(); >- for (auto client : m_clients) >- client->durationChanged(duration); >+ m_clients.forEachNonNullMember([duration = duration()] (auto& client) { >+ client.durationChanged(duration); >+ }); > // These is no standard event for minFastReverseRateChange; duration change is a reasonable proxy for it. > // It happens every time a new item becomes ready to play. >- bool canPlayFastReverse = this->canPlayFastReverse(); >- for (auto client : m_clients) >- client->canPlayFastReverseChanged(canPlayFastReverse); >+ m_clients.forEachNonNullMember([canPlayFastReverse = canPlayFastReverse()] (auto& client) { >+ client.canPlayFastReverseChanged(canPlayFastReverse); >+ }); > } > > if (all > || eventName == eventNames().playEvent > || eventName == eventNames().playingEvent) { >- for (auto client : m_clients) >- client->playbackStartedTimeChanged(playbackStartedTime()); >+ m_clients.forEachNonNullMember([playbackStartedTime = playbackStartedTime()] (auto& client) { >+ client.playbackStartedTimeChanged(playbackStartedTime); >+ }); > } > > if (all > || eventName == eventNames().pauseEvent > || eventName == eventNames().playEvent > || eventName == eventNames().ratechangeEvent) { >- bool isPlaying = this->isPlaying(); >- float playbackRate = this->playbackRate(); >- for (auto client : m_clients) >- client->rateChanged(isPlaying, playbackRate); >+ m_clients.forEachNonNullMember([isPlaying = isPlaying(), playbackRate = playbackRate()] (auto& client) { >+ client.rateChanged(isPlaying, playbackRate); >+ }); > } > > if (all > || eventName == eventNames().timeupdateEvent) { >- auto currentTime = this->currentTime(); >- auto anchorTime = [[NSProcessInfo processInfo] systemUptime]; >- for (auto client : m_clients) >- client->currentTimeChanged(currentTime, anchorTime); >+ m_clients.forEachNonNullMember([currentTime = currentTime(), anchorTime = [[NSProcessInfo processInfo] systemUptime]] (auto& client) { >+ client.currentTimeChanged(currentTime, anchorTime); >+ }); > } > > if (all > || eventName == eventNames().progressEvent) { >- auto bufferedTime = this->bufferedTime(); >- auto seekableRanges = this->seekableRanges(); >- auto seekableTimeRangesLastModifiedTime = this->seekableTimeRangesLastModifiedTime(); >- auto liveUpdateInterval = this->liveUpdateInterval(); >- for (auto client : m_clients) { >- client->bufferedTimeChanged(bufferedTime); >- client->seekableRangesChanged(seekableRanges, seekableTimeRangesLastModifiedTime, liveUpdateInterval); >- } >+ m_clients.forEachNonNullMember([bufferedTime = bufferedTime(), seekableRanges = seekableRanges(), seekableTimeRangesLastModifiedTime = seekableTimeRangesLastModifiedTime(), liveUpdateInterval = liveUpdateInterval()] (auto& client) { >+ client.bufferedTimeChanged(bufferedTime); >+ client.seekableRangesChanged(seekableRanges, seekableTimeRangesLastModifiedTime, liveUpdateInterval); >+ }); > } > > if (all >@@ -174,24 +182,17 @@ void PlaybackSessionModelMediaElement::updateForEventName(const WTF::AtomicStrin > > if (all > || eventName == eventNames().webkitcurrentplaybacktargetiswirelesschangedEvent) { >- bool enabled = externalPlaybackEnabled(); >- ExternalPlaybackTargetType targetType = externalPlaybackTargetType(); >- String localizedDeviceName = externalPlaybackLocalizedDeviceName(); >- >- bool wirelessVideoPlaybackDisabled = this->wirelessVideoPlaybackDisabled(); >- >- for (auto client : m_clients) { >- client->externalPlaybackChanged(enabled, targetType, localizedDeviceName); >- client->wirelessVideoPlaybackDisabledChanged(wirelessVideoPlaybackDisabled); >- } >+ m_clients.forEachNonNullMember([enabled = externalPlaybackEnabled(), targetType = externalPlaybackTargetType(), localizedDeviceName = externalPlaybackLocalizedDeviceName(), wirelessVideoPlaybackDisabled = wirelessVideoPlaybackDisabled()] (auto& client) { >+ client.externalPlaybackChanged(enabled, targetType, localizedDeviceName); >+ client.wirelessVideoPlaybackDisabledChanged(wirelessVideoPlaybackDisabled); >+ }); > } > > if (all > || eventName == eventNames().webkitpresentationmodechangedEvent) { >- bool isPictureInPictureActive = this->isPictureInPictureActive(); >- >- for (auto client : m_clients) >- client->pictureInPictureActiveChanged(isPictureInPictureActive); >+ m_clients.forEachNonNullMember([isPictureInPictureActive = isPictureInPictureActive()] (auto& client) { >+ client.pictureInPictureActiveChanged(isPictureInPictureActive); >+ }); > } > > >@@ -202,22 +203,20 @@ void PlaybackSessionModelMediaElement::updateForEventName(const WTF::AtomicStrin > > if (all > || eventName == eventNames().volumechangeEvent) { >- for (auto client : m_clients) { >- client->mutedChanged(isMuted()); >- client->volumeChanged(volume()); >- } >+ m_clients.forEachNonNullMember([isMuted = isMuted(), volume = volume()] (auto& client) { >+ client.mutedChanged(isMuted); >+ client.volumeChanged(volume); >+ }); > } > } >-void PlaybackSessionModelMediaElement::addClient(PlaybackSessionModelClient& client) >+void PlaybackSessionModelMediaElement::addClient(WeakPtr<PlaybackSessionModelClient>&& client) > { >- ASSERT(!m_clients.contains(&client)); >- m_clients.add(&client); >+ m_clients.add(WTFMove(client)); > } > > void PlaybackSessionModelMediaElement::removeClient(PlaybackSessionModelClient& client) > { >- ASSERT(m_clients.contains(&client)); >- m_clients.remove(&client); >+ m_clients.remove(client); > } > > void PlaybackSessionModelMediaElement::play() >@@ -355,26 +354,18 @@ void PlaybackSessionModelMediaElement::updateMediaSelectionOptions() > else > m_audioTracksForMenu.clear(); > >- auto audioOptions = audioMediaSelectionOptions(); >- auto audioIndex = audioMediaSelectedIndex(); >- auto legibleOptions = legibleMediaSelectionOptions(); >- auto legibleIndex = legibleMediaSelectedIndex(); >- >- for (auto client : m_clients) { >- client->audioMediaSelectionOptionsChanged(audioOptions, audioIndex); >- client->legibleMediaSelectionOptionsChanged(legibleOptions, legibleIndex); >- } >+ m_clients.forEachNonNullMember([audioOptions = audioMediaSelectionOptions(), audioIndex = audioMediaSelectedIndex(), legibleOptions = legibleMediaSelectionOptions(), legibleIndex = legibleMediaSelectedIndex()] (auto& client) { >+ client.audioMediaSelectionOptionsChanged(audioOptions, audioIndex); >+ client.legibleMediaSelectionOptionsChanged(legibleOptions, legibleIndex); >+ }); > } > > void PlaybackSessionModelMediaElement::updateMediaSelectionIndices() > { >- auto audioIndex = audioMediaSelectedIndex(); >- auto legibleIndex = legibleMediaSelectedIndex(); >- >- for (auto client : m_clients) { >- client->audioMediaSelectionIndexChanged(audioIndex); >- client->legibleMediaSelectionIndexChanged(legibleIndex); >- } >+ m_clients.forEachNonNullMember([audioIndex = audioMediaSelectedIndex(), legibleIndex = legibleMediaSelectedIndex()] (auto& client) { >+ client.audioMediaSelectionIndexChanged(audioIndex); >+ client.legibleMediaSelectionIndexChanged(legibleIndex); >+ }); > } > > double PlaybackSessionModelMediaElement::playbackStartedTime() const >diff --git a/Source/WebCore/platform/cocoa/VideoFullscreenChangeObserver.h b/Source/WebCore/platform/cocoa/VideoFullscreenChangeObserver.h >index 4eb0580c96139dd47e75812e619bc905d6b76ed5..4990813a3909e602cf5566a897f8707194dd6b9b 100644 >--- a/Source/WebCore/platform/cocoa/VideoFullscreenChangeObserver.h >+++ b/Source/WebCore/platform/cocoa/VideoFullscreenChangeObserver.h >@@ -32,7 +32,7 @@ namespace WebCore { > > class VideoFullscreenChangeObserver { > public: >- virtual ~VideoFullscreenChangeObserver() { }; >+ virtual ~VideoFullscreenChangeObserver() = default; > virtual void requestUpdateInlineRect() = 0; > virtual void requestVideoContentLayer() = 0; > virtual void returnVideoContentLayer() = 0; >diff --git a/Source/WebCore/platform/cocoa/VideoFullscreenModel.h b/Source/WebCore/platform/cocoa/VideoFullscreenModel.h >index ce513541642ffba32f7db6b8037b60b8007d1eed..6d1b7e98a9e35b67a2c371cba60afc388b6ab5be 100644 >--- a/Source/WebCore/platform/cocoa/VideoFullscreenModel.h >+++ b/Source/WebCore/platform/cocoa/VideoFullscreenModel.h >@@ -30,7 +30,7 @@ > > #include "FloatRect.h" > #include "HTMLMediaElementEnums.h" >-#include "PlaybackSessionModel.h" >+#include <wtf/WeakPtr.h> > > #if PLATFORM(IOS) > OBJC_CLASS AVPlayerViewController; >@@ -43,8 +43,15 @@ class VideoFullscreenModelClient; > > class VideoFullscreenModel { > public: >- virtual ~VideoFullscreenModel() { }; >- virtual void addClient(VideoFullscreenModelClient&) = 0; >+ virtual ~VideoFullscreenModel() = default; >+ >+ void ref() { refVideoFullscreenModel(); } >+ void deref() { derefVideoFullscreenModel(); } >+ >+ virtual void refVideoFullscreenModel() = 0; >+ virtual void derefVideoFullscreenModel() = 0; >+ >+ virtual void addClient(WeakPtr<VideoFullscreenModelClient>&&) = 0; > virtual void removeClient(VideoFullscreenModelClient&)= 0; > > virtual void requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenMode, bool finishedWithMedia = false) = 0; >diff --git a/Source/WebCore/platform/cocoa/VideoFullscreenModelVideoElement.h b/Source/WebCore/platform/cocoa/VideoFullscreenModelVideoElement.h >index 037dd02b61d3b1a824b3f9c0ec161d599f310de7..8268da5a024371d1ddfbba182196035ad95b53e4 100644 >--- a/Source/WebCore/platform/cocoa/VideoFullscreenModelVideoElement.h >+++ b/Source/WebCore/platform/cocoa/VideoFullscreenModelVideoElement.h >@@ -28,16 +28,14 @@ > > #if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)) > >-#include "EventListener.h" > #include "FloatRect.h" > #include "HTMLMediaElementEnums.h" > #include "PlatformLayer.h" > #include "VideoFullscreenModel.h" > #include <wtf/Function.h> >-#include <wtf/HashSet.h> > #include <wtf/RefPtr.h> > #include <wtf/RetainPtr.h> >-#include <wtf/Vector.h> >+#include <wtf/WeakPtrContainer.h> > > namespace WebCore { > class AudioTrack; >@@ -45,7 +43,10 @@ class HTMLVideoElement; > class TextTrack; > class PlaybackSessionModelMediaElement; > >-class VideoFullscreenModelVideoElement : public VideoFullscreenModel, public EventListener { >+class VideoFullscreenModelVideoElement >+ : public RefCounted<VideoFullscreenModelVideoElement> >+ , public CanMakeWeakPtr<VideoFullscreenModelVideoElement> >+ , public VideoFullscreenModel { > public: > static RefPtr<VideoFullscreenModelVideoElement> create() > { >@@ -58,11 +59,9 @@ public: > WEBCORE_EXPORT void willExitFullscreen(); > WEBCORE_EXPORT void waitForPreparedForInlineThen(WTF::Function<void()>&& completionHandler = [] { }); > >- WEBCORE_EXPORT void handleEvent(WebCore::ScriptExecutionContext&, WebCore::Event&) override; > void updateForEventName(const WTF::AtomicString&); >- bool operator==(const EventListener& rhs) const override { return static_cast<const WebCore::EventListener*>(this) == &rhs; } > >- WEBCORE_EXPORT void addClient(VideoFullscreenModelClient&) override; >+ WEBCORE_EXPORT void addClient(WeakPtr<VideoFullscreenModelClient>&&) override; > WEBCORE_EXPORT void removeClient(VideoFullscreenModelClient&) override; > WEBCORE_EXPORT void requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenMode, bool finishedWithMedia = false) override; > WEBCORE_EXPORT void setVideoLayerFrame(FloatRect) override; >@@ -72,6 +71,8 @@ public: > FloatSize videoDimensions() const override { return m_videoDimensions; } > bool hasVideo() const override { return m_hasVideo; } > >+ using RefCounted::ref; >+ using RefCounted::deref; > > protected: > WEBCORE_EXPORT VideoFullscreenModelVideoElement(); >@@ -80,6 +81,8 @@ private: > void setHasVideo(bool); > void setVideoDimensions(const FloatSize&); > >+ void refVideoFullscreenModel() final { ref(); } >+ void derefVideoFullscreenModel() final { deref(); } > void willEnterPictureInPicture() override; > void didEnterPictureInPicture() override; > void failedToEnterPictureInPicture() override; >@@ -89,15 +92,17 @@ private: > static const Vector<WTF::AtomicString>& observedEventNames(); > const WTF::AtomicString& eventNameAll(); > >+ class MediaElementEventListener; >+ > RefPtr<HTMLVideoElement> m_videoElement; > RetainPtr<PlatformLayer> m_videoFullscreenLayer; >- bool m_isListening { false }; >- HashSet<VideoFullscreenModelClient*> m_clients; >+ WeakPtrContainer<VideoFullscreenModelClient> m_clients; > bool m_hasVideo { false }; > FloatSize m_videoDimensions; > FloatRect m_videoFrame; > Vector<RefPtr<TextTrack>> m_legibleTracksForMenu; > Vector<RefPtr<AudioTrack>> m_audioTracksForMenu; >+ Ref<MediaElementEventListener> m_eventListener; > }; > > } >diff --git a/Source/WebCore/platform/cocoa/VideoFullscreenModelVideoElement.mm b/Source/WebCore/platform/cocoa/VideoFullscreenModelVideoElement.mm >index c0a4fa5f0eb5af0f87f585dcca5d65706a7f504e..a861cc7fd1bd6b7d72177b8bbe518546f574d75c 100644 >--- a/Source/WebCore/platform/cocoa/VideoFullscreenModelVideoElement.mm >+++ b/Source/WebCore/platform/cocoa/VideoFullscreenModelVideoElement.mm >@@ -47,8 +47,27 @@ > > using namespace WebCore; > >+ >+class VideoFullscreenModelVideoElement::MediaElementEventListener final : public EventListener { >+public: >+ MediaElementEventListener(WeakPtr<VideoFullscreenModelVideoElement>&& parent) >+ : EventListener(CPPEventListenerType) >+ , m_parent(WTFMove(parent)) >+ { >+ } >+private: >+ void handleEvent(WebCore::ScriptExecutionContext&, WebCore::Event& event) final >+ { >+ if (m_parent) >+ m_parent->updateForEventName(event.type()); >+ } >+ bool operator==(const EventListener& rhs) const final { return static_cast<const WebCore::EventListener*>(this) == &rhs; } >+ >+ WeakPtr<VideoFullscreenModelVideoElement> m_parent; >+}; >+ > VideoFullscreenModelVideoElement::VideoFullscreenModelVideoElement() >- : EventListener(EventListener::CPPEventListenerType) >+ : m_eventListener(adoptRef(*new MediaElementEventListener(makeWeakPtr(*this)))) > { > } > >@@ -64,28 +83,21 @@ void VideoFullscreenModelVideoElement::setVideoElement(HTMLVideoElement* videoEl > if (m_videoElement && m_videoElement->videoFullscreenLayer()) > m_videoElement->setVideoFullscreenLayer(nullptr); > >- if (m_videoElement && m_isListening) { >+ if (m_videoElement) { > for (auto& eventName : observedEventNames()) >- m_videoElement->removeEventListener(eventName, *this, false); >+ m_videoElement->removeEventListener(eventName, m_eventListener.copyRef(), false); > } >- m_isListening = false; > > m_videoElement = videoElement; > > if (m_videoElement) { > for (auto& eventName : observedEventNames()) >- m_videoElement->addEventListener(eventName, *this, false); >- m_isListening = true; >+ m_videoElement->addEventListener(eventName, m_eventListener.copyRef(), false); > } > > updateForEventName(eventNameAll()); > } > >-void VideoFullscreenModelVideoElement::handleEvent(WebCore::ScriptExecutionContext&, WebCore::Event& event) >-{ >- updateForEventName(event.type()); >-} >- > void VideoFullscreenModelVideoElement::updateForEventName(const WTF::AtomicString& eventName) > { > if (m_clients.isEmpty()) >@@ -195,16 +207,14 @@ void VideoFullscreenModelVideoElement::fullscreenModeChanged(HTMLMediaElementEnu > m_videoElement->fullscreenModeChanged(videoFullscreenMode); > } > >-void VideoFullscreenModelVideoElement::addClient(VideoFullscreenModelClient& client) >+void VideoFullscreenModelVideoElement::addClient(WeakPtr<VideoFullscreenModelClient>&& client) > { >- ASSERT(!m_clients.contains(&client)); >- m_clients.add(&client); >+ m_clients.add(WTFMove(client)); > } > > void VideoFullscreenModelVideoElement::removeClient(VideoFullscreenModelClient& client) > { >- ASSERT(m_clients.contains(&client)); >- m_clients.remove(&client); >+ m_clients.remove(client); > } > > bool VideoFullscreenModelVideoElement::isVisible() const >@@ -225,8 +235,9 @@ void VideoFullscreenModelVideoElement::setHasVideo(bool hasVideo) > > m_hasVideo = hasVideo; > >- for (auto& client : m_clients) >- client->hasVideoChanged(m_hasVideo); >+ m_clients.forEachNonNullMember([hasVideo] (auto& client) { >+ client.hasVideoChanged(hasVideo); >+ }); > } > > void VideoFullscreenModelVideoElement::setVideoDimensions(const FloatSize& videoDimensions) >@@ -236,38 +247,44 @@ void VideoFullscreenModelVideoElement::setVideoDimensions(const FloatSize& video > > m_videoDimensions = videoDimensions; > >- for (auto& client : m_clients) >- client->videoDimensionsChanged(m_videoDimensions); >+ m_clients.forEachNonNullMember([videoDimensions] (auto& client) { >+ client.videoDimensionsChanged(videoDimensions); >+ }); > } > > void VideoFullscreenModelVideoElement::willEnterPictureInPicture() > { >- for (auto& client : m_clients) >- client->willEnterPictureInPicture(); >+ m_clients.forEachNonNullMember([] (auto& client) { >+ client.willEnterPictureInPicture(); >+ }); > } > > void VideoFullscreenModelVideoElement::didEnterPictureInPicture() > { >- for (auto& client : m_clients) >- client->didEnterPictureInPicture(); >+ m_clients.forEachNonNullMember([] (auto& client) { >+ client.didEnterPictureInPicture(); >+ }); > } > > void VideoFullscreenModelVideoElement::failedToEnterPictureInPicture() > { >- for (auto& client : m_clients) >- client->failedToEnterPictureInPicture(); >+ m_clients.forEachNonNullMember([] (auto& client) { >+ client.failedToEnterPictureInPicture(); >+ }); > } > > void VideoFullscreenModelVideoElement::willExitPictureInPicture() > { >- for (auto& client : m_clients) >- client->willExitPictureInPicture(); >+ m_clients.forEachNonNullMember([] (auto& client) { >+ client.willExitPictureInPicture(); >+ }); > } > > void VideoFullscreenModelVideoElement::didExitPictureInPicture() > { >- for (auto& client : m_clients) >- client->didExitPictureInPicture(); >+ m_clients.forEachNonNullMember([] (auto& client) { >+ client.didExitPictureInPicture(); >+ }); > } > > #endif >diff --git a/Source/WebCore/platform/ios/PlaybackSessionInterfaceAVKit.h b/Source/WebCore/platform/ios/PlaybackSessionInterfaceAVKit.h >index 85801915e0f019680df47c816c0bddb5b60bc393..42230189034504e3781c97464ff16160dd1e082d 100644 >--- a/Source/WebCore/platform/ios/PlaybackSessionInterfaceAVKit.h >+++ b/Source/WebCore/platform/ios/PlaybackSessionInterfaceAVKit.h >@@ -51,18 +51,17 @@ class IntRect; > class PlaybackSessionModel; > class WebPlaybackSessionChangeObserver; > >-class WEBCORE_EXPORT PlaybackSessionInterfaceAVKit >+class PlaybackSessionInterfaceAVKit > : public PlaybackSessionInterface > , public PlaybackSessionModelClient > , public RefCounted<PlaybackSessionInterfaceAVKit> { >- > public: >- static Ref<PlaybackSessionInterfaceAVKit> create(PlaybackSessionModel& model) >+ static Ref<PlaybackSessionInterfaceAVKit> create(Ref<PlaybackSessionModel>&& model) > { >- return adoptRef(*new PlaybackSessionInterfaceAVKit(model)); >+ return adoptRef(*new PlaybackSessionInterfaceAVKit(WTFMove(model))); > } > virtual ~PlaybackSessionInterfaceAVKit(); >- PlaybackSessionModel* playbackSessionModel() const { return m_playbackSessionModel; } >+ PlaybackSessionModel& playbackSessionModel() const { return m_playbackSessionModel; } > > // PlaybackSessionInterface > WEBCORE_EXPORT void resetMediaState() override; >@@ -81,15 +80,14 @@ public: > WEBCORE_EXPORT void mutedChanged(bool) override; > WEBCORE_EXPORT void volumeChanged(double) override; > >- WEBCORE_EXPORT virtual void invalidate(); >- > WebAVPlayerController *playerController() const { return m_playerController.get(); } > > protected: >- WEBCORE_EXPORT PlaybackSessionInterfaceAVKit(PlaybackSessionModel&); >+ WEBCORE_EXPORT PlaybackSessionInterfaceAVKit(Ref<PlaybackSessionModel>&&); > > RetainPtr<WebAVPlayerController> m_playerController; >- PlaybackSessionModel* m_playbackSessionModel { nullptr }; >+ Ref<PlaybackSessionModel> m_playbackSessionModel; >+ WeakPtrFactory<PlaybackSessionModelClient> m_weakPtrFactory; > }; > > } >diff --git a/Source/WebCore/platform/ios/PlaybackSessionInterfaceAVKit.mm b/Source/WebCore/platform/ios/PlaybackSessionInterfaceAVKit.mm >index 0a28548b7f5951619534432da9a0007ddb9ae864..da03ebe22d3d441ebe28f38f3cce428843fae427 100644 >--- a/Source/WebCore/platform/ios/PlaybackSessionInterfaceAVKit.mm >+++ b/Source/WebCore/platform/ios/PlaybackSessionInterfaceAVKit.mm >@@ -49,32 +49,30 @@ SOFT_LINK_CLASS_OPTIONAL(AVKit, AVValueTiming) > namespace WebCore { > using namespace PAL; > >-PlaybackSessionInterfaceAVKit::PlaybackSessionInterfaceAVKit(PlaybackSessionModel& model) >+PlaybackSessionInterfaceAVKit::PlaybackSessionInterfaceAVKit(Ref<PlaybackSessionModel>&& model) > : m_playerController(adoptNS([[WebAVPlayerController alloc] init])) >- , m_playbackSessionModel(&model) >+ , m_playbackSessionModel(WTFMove(model)) > { >- model.addClient(*this); >+ m_playbackSessionModel->addClient(m_weakPtrFactory.createWeakPtr(*this)); > [m_playerController setPlaybackSessionInterface:this]; >- [m_playerController setDelegate:&model]; > >- durationChanged(model.duration()); >- currentTimeChanged(model.currentTime(), [[NSProcessInfo processInfo] systemUptime]); >- bufferedTimeChanged(model.bufferedTime()); >- rateChanged(model.isPlaying(), model.playbackRate()); >- seekableRangesChanged(model.seekableRanges(), model.seekableTimeRangesLastModifiedTime(), model.liveUpdateInterval()); >- canPlayFastReverseChanged(model.canPlayFastReverse()); >- audioMediaSelectionOptionsChanged(model.audioMediaSelectionOptions(), model.audioMediaSelectedIndex()); >- legibleMediaSelectionOptionsChanged(model.legibleMediaSelectionOptions(), model.legibleMediaSelectedIndex()); >- externalPlaybackChanged(model.externalPlaybackEnabled(), model.externalPlaybackTargetType(), model.externalPlaybackLocalizedDeviceName()); >- wirelessVideoPlaybackDisabledChanged(model.wirelessVideoPlaybackDisabled()); >+ durationChanged(m_playbackSessionModel->duration()); >+ currentTimeChanged(m_playbackSessionModel->currentTime(), [[NSProcessInfo processInfo] systemUptime]); >+ bufferedTimeChanged(m_playbackSessionModel->bufferedTime()); >+ rateChanged(m_playbackSessionModel->isPlaying(), m_playbackSessionModel->playbackRate()); >+ seekableRangesChanged(m_playbackSessionModel->seekableRanges(), m_playbackSessionModel->seekableTimeRangesLastModifiedTime(), m_playbackSessionModel->liveUpdateInterval()); >+ canPlayFastReverseChanged(m_playbackSessionModel->canPlayFastReverse()); >+ audioMediaSelectionOptionsChanged(m_playbackSessionModel->audioMediaSelectionOptions(), m_playbackSessionModel->audioMediaSelectedIndex()); >+ legibleMediaSelectionOptionsChanged(m_playbackSessionModel->legibleMediaSelectionOptions(), m_playbackSessionModel->legibleMediaSelectedIndex()); >+ externalPlaybackChanged(m_playbackSessionModel->externalPlaybackEnabled(), m_playbackSessionModel->externalPlaybackTargetType(), m_playbackSessionModel->externalPlaybackLocalizedDeviceName()); >+ wirelessVideoPlaybackDisabledChanged(m_playbackSessionModel->wirelessVideoPlaybackDisabled()); > } > > PlaybackSessionInterfaceAVKit::~PlaybackSessionInterfaceAVKit() > { >+ m_playbackSessionModel->removeClient(*this); > [m_playerController setPlaybackSessionInterface:nullptr]; > [m_playerController setExternalPlaybackActive:false]; >- >- invalidate(); > } > > void PlaybackSessionInterfaceAVKit::resetMediaState() >@@ -206,16 +204,6 @@ void PlaybackSessionInterfaceAVKit::volumeChanged(double volume) > [m_playerController volumeChanged:volume]; > } > >-void PlaybackSessionInterfaceAVKit::invalidate() >-{ >- if (!m_playbackSessionModel) >- return; >- >- [m_playerController setDelegate:nullptr]; >- m_playbackSessionModel->removeClient(*this); >- m_playbackSessionModel = nullptr; >-} >- > } > > #endif // HAVE(AVKIT) >diff --git a/Source/WebCore/platform/ios/VideoFullscreenInterfaceAVKit.h b/Source/WebCore/platform/ios/VideoFullscreenInterfaceAVKit.h >index c6d2ead9542cf843420ce953cd3f24f9272bdec6..8ee2a9586baf2b1f938a70571539f5897cd29447 100644 >--- a/Source/WebCore/platform/ios/VideoFullscreenInterfaceAVKit.h >+++ b/Source/WebCore/platform/ios/VideoFullscreenInterfaceAVKit.h >@@ -40,6 +40,7 @@ > #include <wtf/RefPtr.h> > #include <wtf/RetainPtr.h> > #include <wtf/RunLoop.h> >+#include <wtf/WeakPtr.h> > > OBJC_CLASS UIViewController; > OBJC_CLASS UIWindow; >@@ -64,12 +65,11 @@ class VideoFullscreenInterfaceAVKit final > , public ThreadSafeRefCounted<VideoFullscreenInterfaceAVKit> { > > public: >- WEBCORE_EXPORT static Ref<VideoFullscreenInterfaceAVKit> create(PlaybackSessionInterfaceAVKit&); >+ WEBCORE_EXPORT static Ref<VideoFullscreenInterfaceAVKit> create(Ref<PlaybackSessionInterfaceAVKit>&&, Ref<VideoFullscreenModel>&&); > virtual ~VideoFullscreenInterfaceAVKit(); >- WEBCORE_EXPORT void setVideoFullscreenModel(VideoFullscreenModel*); >- WEBCORE_EXPORT void setVideoFullscreenChangeObserver(VideoFullscreenChangeObserver*); >+ WEBCORE_EXPORT void setVideoFullscreenChangeObserver(WeakPtr<VideoFullscreenChangeObserver>); > PlaybackSessionInterfaceAVKit& playbackSessionInterface() const { return m_playbackSessionInterface.get(); } >- PlaybackSessionModel* playbackSessionModel() const { return m_playbackSessionInterface->playbackSessionModel(); } >+ PlaybackSessionModel& playbackSessionModel() const { return m_playbackSessionInterface->playbackSessionModel(); } > > // VideoFullscreenModelClient > WEBCORE_EXPORT void hasVideoChanged(bool) final; >@@ -82,7 +82,6 @@ public: > WEBCORE_EXPORT void enterFullscreen(); > WEBCORE_EXPORT void exitFullscreen(const IntRect& finalRect); > WEBCORE_EXPORT void cleanupFullscreen(); >- WEBCORE_EXPORT void invalidate(); > WEBCORE_EXPORT void requestHideAndExitFullscreen(); > WEBCORE_EXPORT void preparedToReturnToInline(bool visible, const IntRect& inlineRect); > WEBCORE_EXPORT void preparedToExitFullscreen(); >@@ -131,7 +130,7 @@ public: > Mode m_targetMode; > #endif > >- VideoFullscreenModel* videoFullscreenModel() const { return m_videoFullscreenModel; } >+ VideoFullscreenModel& videoFullscreenModel() const { return m_videoFullscreenModel; } > bool shouldExitFullscreenWithReason(ExitFullScreenReason); > HTMLMediaElementEnums::VideoFullscreenMode mode() const { return m_currentMode.mode(); } > bool allowsPictureInPicturePlayback() const { return m_allowsPictureInPicturePlayback; } >@@ -164,7 +163,7 @@ public: > #endif > > protected: >- WEBCORE_EXPORT VideoFullscreenInterfaceAVKit(PlaybackSessionInterfaceAVKit&); >+ WEBCORE_EXPORT VideoFullscreenInterfaceAVKit(Ref<PlaybackSessionInterfaceAVKit>&&, Ref<VideoFullscreenModel>&&); > > #if ENABLE(FULLSCREEN_API) > void doSetup(); >@@ -180,10 +179,10 @@ protected: > WebAVPlayerController *playerController() const; > > Ref<PlaybackSessionInterfaceAVKit> m_playbackSessionInterface; >+ Ref<VideoFullscreenModel> m_videoFullscreenModel; > RetainPtr<WebAVPlayerViewControllerDelegate> m_playerViewControllerDelegate; > RetainPtr<WebAVPlayerViewController> m_playerViewController; >- VideoFullscreenModel* m_videoFullscreenModel { nullptr }; >- VideoFullscreenChangeObserver* m_fullscreenChangeObserver { nullptr }; >+ WeakPtr<VideoFullscreenChangeObserver> m_fullscreenChangeObserver; > > // These are only used when fullscreen is presented in a separate window. > RetainPtr<UIWindow> m_window; >diff --git a/Source/WebCore/platform/ios/VideoFullscreenInterfaceAVKit.mm b/Source/WebCore/platform/ios/VideoFullscreenInterfaceAVKit.mm >index 5cc320e19dad39c009c73368a5871c86093e8b7d..73244eec2eb51f208f6d36e196c413161a85cf2c 100644 >--- a/Source/WebCore/platform/ios/VideoFullscreenInterfaceAVKit.mm >+++ b/Source/WebCore/platform/ios/VideoFullscreenInterfaceAVKit.mm >@@ -289,8 +289,7 @@ - (void)layoutSublayers > } else if ([getAVLayerVideoGravityResizeAspectFill() isEqualToString:self.videoGravity]) { > sourceVideoFrame = smallestRectWithAspectRatioAroundRect(videoAspectRatio, self.modelVideoLayerFrame); > self.modelVideoLayerFrame = CGRectMake(0, 0, sourceVideoFrame.width(), sourceVideoFrame.height()); >- if (auto* model = _fullscreenInterface->videoFullscreenModel()) >- model->setVideoLayerFrame(self.modelVideoLayerFrame); >+ _fullscreenInterface->videoFullscreenModel().setVideoLayerFrame(self.modelVideoLayerFrame); > targetVideoFrame = smallestRectWithAspectRatioAroundRect(videoAspectRatio, self.bounds); > } else > ASSERT_NOT_REACHED(); >@@ -325,8 +324,7 @@ - (void)resolveBounds > > if (!CGRectEqualToRect(self.modelVideoLayerFrame, [self bounds])) { > self.modelVideoLayerFrame = [self bounds]; >- if (auto* model = _fullscreenInterface->videoFullscreenModel()) >- model->setVideoLayerFrame(self.modelVideoLayerFrame); >+ _fullscreenInterface->videoFullscreenModel().setVideoLayerFrame(self.modelVideoLayerFrame); > } > [(UIView *)[_videoSublayer delegate] setTransform:CGAffineTransformIdentity]; > >@@ -350,8 +348,7 @@ - (void)setVideoGravity:(NSString *)videoGravity > else > ASSERT_NOT_REACHED(); > >- if (auto* model = _fullscreenInterface->videoFullscreenModel()) >- model->setVideoLayerGravity(gravity); >+ _fullscreenInterface->videoFullscreenModel().setVideoLayerGravity(gravity); > } > > - (NSString *)videoGravity >@@ -725,15 +722,16 @@ - (void)removeFromParentViewController > } > @end > >-Ref<VideoFullscreenInterfaceAVKit> VideoFullscreenInterfaceAVKit::create(PlaybackSessionInterfaceAVKit& playbackSessionInterface) >+Ref<VideoFullscreenInterfaceAVKit> VideoFullscreenInterfaceAVKit::create(Ref<PlaybackSessionInterfaceAVKit>&& playbackSessionInterface, Ref<VideoFullscreenModel>&& videoFullscreenModel) > { >- Ref<VideoFullscreenInterfaceAVKit> interface = adoptRef(*new VideoFullscreenInterfaceAVKit(playbackSessionInterface)); >+ Ref<VideoFullscreenInterfaceAVKit> interface = adoptRef(*new VideoFullscreenInterfaceAVKit(WTFMove(playbackSessionInterface), WTFMove(videoFullscreenModel))); > [interface->m_playerViewControllerDelegate setFullscreenInterface:interface.ptr()]; > return interface; > } > >-VideoFullscreenInterfaceAVKit::VideoFullscreenInterfaceAVKit(PlaybackSessionInterfaceAVKit& playbackSessionInterface) >- : m_playbackSessionInterface(playbackSessionInterface) >+VideoFullscreenInterfaceAVKit::VideoFullscreenInterfaceAVKit(Ref<PlaybackSessionInterfaceAVKit>&& playbackSessionInterface, Ref<VideoFullscreenModel>&& videoFullscreenModel) >+ : m_playbackSessionInterface(WTFMove(playbackSessionInterface)) >+ , m_videoFullscreenModel(WTFMove(videoFullscreenModel)) > , m_playerViewControllerDelegate(adoptNS([[WebAVPlayerViewControllerDelegate alloc] init])) > , m_watchdogTimer(RunLoop::main(), this, &VideoFullscreenInterfaceAVKit::watchdogTimerFired) > { >@@ -744,8 +742,7 @@ VideoFullscreenInterfaceAVKit::~VideoFullscreenInterfaceAVKit() > WebAVPlayerController* playerController = this->playerController(); > if (playerController && playerController.externalPlaybackActive) > externalPlaybackChanged(false, PlaybackSessionModel::TargetTypeNone, ""); >- if (m_videoFullscreenModel) >- m_videoFullscreenModel->removeClient(*this); >+ videoFullscreenModel().removeClient(*this); > } > > WebAVPlayerController *VideoFullscreenInterfaceAVKit::playerController() const >@@ -753,21 +750,7 @@ WebAVPlayerController *VideoFullscreenInterfaceAVKit::playerController() const > return m_playbackSessionInterface->playerController(); > } > >-void VideoFullscreenInterfaceAVKit::setVideoFullscreenModel(VideoFullscreenModel* model) >-{ >- if (m_videoFullscreenModel) >- m_videoFullscreenModel->removeClient(*this); >- >- m_videoFullscreenModel = model; >- >- if (m_videoFullscreenModel) >- m_videoFullscreenModel->addClient(*this); >- >- hasVideoChanged(m_videoFullscreenModel ? m_videoFullscreenModel->hasVideo() : false); >- videoDimensionsChanged(m_videoFullscreenModel ? m_videoFullscreenModel->videoDimensions() : FloatSize()); >-} >- >-void VideoFullscreenInterfaceAVKit::setVideoFullscreenChangeObserver(VideoFullscreenChangeObserver* observer) >+void VideoFullscreenInterfaceAVKit::setVideoFullscreenChangeObserver(WeakPtr<VideoFullscreenChangeObserver> observer) > { > m_fullscreenChangeObserver = observer; > } >@@ -807,7 +790,7 @@ bool VideoFullscreenInterfaceAVKit::pictureInPictureWasStartedWhenEnteringBackgr > void VideoFullscreenInterfaceAVKit::applicationDidBecomeActive() > { > LOG(Fullscreen, "VideoFullscreenInterfaceAVKit::applicationDidBecomeActive(%p)", this); >- if (m_shouldReturnToFullscreenAfterEnteringForeground && m_videoFullscreenModel && m_videoFullscreenModel->isVisible()) { >+ if (m_shouldReturnToFullscreenAfterEnteringForeground && videoFullscreenModel().isVisible()) { > [m_playerViewController stopPictureInPicture]; > return; > } >@@ -884,7 +867,7 @@ void VideoFullscreenInterfaceAVKit::setupFullscreen(UIView& videoView, const Int > [playerController() setPictureInPicturePossible:m_allowsPictureInPicturePlayback]; > > #if PLATFORM(WATCHOS) >- m_viewController = videoFullscreenModel()->createVideoFullscreenViewController(m_playerViewController.get().avPlayerViewController); >+ m_viewController = videoFullscreenModel().createVideoFullscreenViewController(m_playerViewController.get().avPlayerViewController); > #endif > > if (m_viewController) { >@@ -949,7 +932,7 @@ static UIViewController *fallbackViewController(UIView *view) > > UIViewController *VideoFullscreenInterfaceAVKit::presentingViewController() > { >- auto *controller = videoFullscreenModel()->presentingViewController(); >+ auto *controller = videoFullscreenModel().presentingViewController(); > if (!controller) > controller = fallbackViewController(m_parentView.get()); > >@@ -1077,14 +1060,6 @@ void VideoFullscreenInterfaceAVKit::cleanupFullscreen() > m_enterRequested = false; > } > >-void VideoFullscreenInterfaceAVKit::invalidate() >-{ >- m_videoFullscreenModel = nil; >- m_fullscreenChangeObserver = nil; >- >- cleanupFullscreen(); >-} >- > void VideoFullscreenInterfaceAVKit::requestHideAndExitFullscreen() > { > if (!m_enterRequested) >@@ -1098,9 +1073,9 @@ void VideoFullscreenInterfaceAVKit::requestHideAndExitFullscreen() > [m_window setHidden:YES]; > [[m_playerViewController view] setHidden:YES]; > >- if (playbackSessionModel() && m_videoFullscreenModel && !m_exitRequested) { >- playbackSessionModel()->pause(); >- m_videoFullscreenModel->requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone); >+ if (!m_exitRequested) { >+ playbackSessionModel().pause(); >+ videoFullscreenModel().requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone); > } > } > >@@ -1120,7 +1095,7 @@ void VideoFullscreenInterfaceAVKit::preparedToExitFullscreen() > return; > > m_waitingForPreparedToExit = false; >- m_videoFullscreenModel->requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone, true); >+ videoFullscreenModel().requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone, true); > } > > bool VideoFullscreenInterfaceAVKit::mayAutomaticallyShowVideoPictureInPicture() const >@@ -1139,8 +1114,7 @@ void VideoFullscreenInterfaceAVKit::willStartPictureInPicture() > { > LOG(Fullscreen, "VideoFullscreenInterfaceAVKit::willStartPictureInPicture(%p)", this); > setMode(HTMLMediaElementEnums::VideoFullscreenModePictureInPicture); >- if (m_videoFullscreenModel) >- m_videoFullscreenModel->willEnterPictureInPicture(); >+ videoFullscreenModel().willEnterPictureInPicture(); > } > > void VideoFullscreenInterfaceAVKit::didStartPictureInPicture() >@@ -1166,8 +1140,7 @@ void VideoFullscreenInterfaceAVKit::didStartPictureInPicture() > > if (m_fullscreenChangeObserver) > m_fullscreenChangeObserver->didEnterFullscreen(); >- if (m_videoFullscreenModel) >- m_videoFullscreenModel->didEnterPictureInPicture(); >+ videoFullscreenModel().didEnterPictureInPicture(); > } > > void VideoFullscreenInterfaceAVKit::failedToStartPictureInPicture() >@@ -1182,11 +1155,8 @@ void VideoFullscreenInterfaceAVKit::failedToStartPictureInPicture() > > if (m_fullscreenChangeObserver) > m_fullscreenChangeObserver->didEnterFullscreen(); >- if (m_videoFullscreenModel) >- m_videoFullscreenModel->failedToEnterPictureInPicture(); >- >- if (m_videoFullscreenModel) >- m_videoFullscreenModel->requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone); >+ videoFullscreenModel().failedToEnterPictureInPicture(); >+ videoFullscreenModel().requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone); > } > > void VideoFullscreenInterfaceAVKit::willStopPictureInPicture() >@@ -1202,10 +1172,8 @@ void VideoFullscreenInterfaceAVKit::willStopPictureInPicture() > [m_window setHidden:NO]; > [[m_playerViewController view] setHidden:NO]; > >- if (m_videoFullscreenModel) >- m_videoFullscreenModel->requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone); >- if (m_videoFullscreenModel) >- m_videoFullscreenModel->willExitPictureInPicture(); >+ videoFullscreenModel().requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone); >+ videoFullscreenModel().willExitPictureInPicture(); > } > > void VideoFullscreenInterfaceAVKit::didStopPictureInPicture() >@@ -1228,8 +1196,7 @@ void VideoFullscreenInterfaceAVKit::didStopPictureInPicture() > > if (m_fullscreenChangeObserver) > m_fullscreenChangeObserver->didExitFullscreen(); >- if (m_videoFullscreenModel) >- m_videoFullscreenModel->didExitPictureInPicture(); >+ videoFullscreenModel().didExitPictureInPicture(); > } > > void VideoFullscreenInterfaceAVKit::prepareForPictureInPictureStopWithCompletionHandler(void (^completionHandler)(BOOL restored)) >@@ -1266,9 +1233,6 @@ void VideoFullscreenInterfaceAVKit::prepareForPictureInPictureStopWithCompletion > > bool VideoFullscreenInterfaceAVKit::shouldExitFullscreenWithReason(VideoFullscreenInterfaceAVKit::ExitFullScreenReason reason) > { >- if (!m_videoFullscreenModel) >- return true; >- > if (reason == ExitFullScreenReason::PictureInPictureStarted) { > if (pictureInPictureWasStartedWhenEnteringBackground()) > return false; >@@ -1278,8 +1242,8 @@ bool VideoFullscreenInterfaceAVKit::shouldExitFullscreenWithReason(VideoFullscre > return true; > } > >- if (playbackSessionModel() && (reason == ExitFullScreenReason::DoneButtonTapped || reason == ExitFullScreenReason::RemoteControlStopEventReceived)) >- playbackSessionModel()->pause(); >+ if (reason == ExitFullScreenReason::DoneButtonTapped || reason == ExitFullScreenReason::RemoteControlStopEventReceived) >+ playbackSessionModel().pause(); > > if (!m_watchdogTimer.isActive() && !ignoreWatchdogForDebugging) > m_watchdogTimer.startOneShot(defaultWatchdogTimerInterval); >@@ -1293,7 +1257,7 @@ bool VideoFullscreenInterfaceAVKit::shouldExitFullscreenWithReason(VideoFullscre > #endif > > BOOL finished = reason == ExitFullScreenReason::DoneButtonTapped || reason == ExitFullScreenReason::PinchGestureHandled; >- m_videoFullscreenModel->requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone, finished); >+ videoFullscreenModel().requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone, finished); > > return false; > } >@@ -1385,14 +1349,6 @@ void VideoFullscreenInterfaceAVKit::cleanupFullscreen() > m_fullscreenChangeObserver->didCleanupFullscreen(); > } > >-void VideoFullscreenInterfaceAVKit::invalidate() >-{ >- m_videoFullscreenModel = nil; >- m_fullscreenChangeObserver = nil; >- >- cleanupFullscreen(); >-} >- > void VideoFullscreenInterfaceAVKit::requestHideAndExitFullscreen() > { > if (m_currentMode.hasPictureInPicture()) >@@ -1403,10 +1359,8 @@ void VideoFullscreenInterfaceAVKit::requestHideAndExitFullscreen() > [m_window setHidden:YES]; > [[m_playerViewController view] setHidden:YES]; > >- if (playbackSessionModel() && m_videoFullscreenModel) { >- playbackSessionModel()->pause(); >- m_videoFullscreenModel->requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone); >- } >+ playbackSessionModel().pause(); >+ videoFullscreenModel().requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone); > } > > void VideoFullscreenInterfaceAVKit::preparedToReturnToInline(bool visible, const IntRect& inlineRect) >@@ -1445,8 +1399,7 @@ void VideoFullscreenInterfaceAVKit::willStartPictureInPicture() > > if (!m_hasVideoContentLayer) > m_fullscreenChangeObserver->requestVideoContentLayer(); >- if (m_videoFullscreenModel) >- m_videoFullscreenModel->willEnterPictureInPicture(); >+ videoFullscreenModel().willEnterPictureInPicture(); > } > > void VideoFullscreenInterfaceAVKit::didStartPictureInPicture() >@@ -1466,8 +1419,7 @@ void VideoFullscreenInterfaceAVKit::didStartPictureInPicture() > [[m_playerViewController view] setHidden:YES]; > } > >- if (m_videoFullscreenModel) >- m_videoFullscreenModel->didEnterPictureInPicture(); >+ videoFullscreenModel().didEnterPictureInPicture(); > > if (m_enterFullscreenNeedsEnterPictureInPicture) > doEnterFullscreen(); >@@ -1485,11 +1437,8 @@ void VideoFullscreenInterfaceAVKit::failedToStartPictureInPicture() > if (m_fullscreenChangeObserver) > m_fullscreenChangeObserver->didEnterFullscreen(); > >- if (m_videoFullscreenModel) >- m_videoFullscreenModel->failedToEnterPictureInPicture(); >- >- if (m_videoFullscreenModel) >- m_videoFullscreenModel->requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone); >+ videoFullscreenModel().failedToEnterPictureInPicture(); >+ videoFullscreenModel().requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone); > } > > void VideoFullscreenInterfaceAVKit::willStopPictureInPicture() >@@ -1504,8 +1453,7 @@ void VideoFullscreenInterfaceAVKit::willStopPictureInPicture() > [m_window setHidden:NO]; > [[m_playerViewController view] setHidden:NO]; > >- if (m_videoFullscreenModel) >- m_videoFullscreenModel->willExitPictureInPicture(); >+ videoFullscreenModel().willExitPictureInPicture(); > } > > void VideoFullscreenInterfaceAVKit::didStopPictureInPicture() >@@ -1525,13 +1473,11 @@ void VideoFullscreenInterfaceAVKit::didStopPictureInPicture() > [m_playerLayerView setBackgroundColor:clearUIColor()]; > [[m_playerViewController view] setBackgroundColor:clearUIColor()]; > >- if (m_videoFullscreenModel) >- m_videoFullscreenModel->requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone); >+ videoFullscreenModel().requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone); > > clearMode(HTMLMediaElementEnums::VideoFullscreenModePictureInPicture); > >- if (m_videoFullscreenModel) >- m_videoFullscreenModel->didExitPictureInPicture(); >+ videoFullscreenModel().didExitPictureInPicture(); > > if (m_enterFullscreenNeedsExitPictureInPicture) > doEnterFullscreen(); >@@ -1567,17 +1513,14 @@ void VideoFullscreenInterfaceAVKit::prepareForPictureInPictureStopWithCompletion > > bool VideoFullscreenInterfaceAVKit::shouldExitFullscreenWithReason(VideoFullscreenInterfaceAVKit::ExitFullScreenReason reason) > { >- if (!m_videoFullscreenModel) >- return true; >- > if (reason == ExitFullScreenReason::PictureInPictureStarted) > return false; > >- if (playbackSessionModel() && (reason == ExitFullScreenReason::DoneButtonTapped || reason == ExitFullScreenReason::RemoteControlStopEventReceived)) >- playbackSessionModel()->pause(); >+ if (reason == ExitFullScreenReason::DoneButtonTapped || reason == ExitFullScreenReason::RemoteControlStopEventReceived) >+ playbackSessionModel().pause(); > > BOOL finished = reason == ExitFullScreenReason::DoneButtonTapped || reason == ExitFullScreenReason::PinchGestureHandled; >- m_videoFullscreenModel->requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone, finished); >+ videoFullscreenModel().requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone, finished); > > if (!m_watchdogTimer.isActive() && !ignoreWatchdogForDebugging) > m_watchdogTimer.startOneShot(defaultWatchdogTimerInterval); >@@ -1672,8 +1615,7 @@ void VideoFullscreenInterfaceAVKit::doSetup() > [playerLayer setModelVideoLayerFrame:modelVideoLayerFrame]; > [playerLayer setVideoDimensions:[playerController() contentDimensions]]; > playerLayer.fullscreenInterface = this; >- if (m_videoFullscreenModel) >- m_videoFullscreenModel->setVideoLayerFrame(modelVideoLayerFrame); >+ videoFullscreenModel().setVideoLayerFrame(modelVideoLayerFrame); > > if (!m_playerViewController) > m_playerViewController = adoptNS([[WebAVPlayerViewController alloc] initWithFullscreenInterface:this]); >@@ -1685,7 +1627,7 @@ void VideoFullscreenInterfaceAVKit::doSetup() > [playerController() setPictureInPicturePossible:m_allowsPictureInPicturePlayback]; > > #if PLATFORM(WATCHOS) >- m_viewController = videoFullscreenModel()->createVideoFullscreenViewController(m_playerViewController.get().avPlayerViewController); >+ m_viewController = videoFullscreenModel().createVideoFullscreenViewController(m_playerViewController.get().avPlayerViewController); > #endif > > if (m_viewController) { >@@ -1892,8 +1834,7 @@ void VideoFullscreenInterfaceAVKit::setMode(HTMLMediaElementEnums::VideoFullscre > return; > > m_currentMode.setMode(mode); >- if (m_videoFullscreenModel) >- m_videoFullscreenModel->fullscreenModeChanged(m_currentMode.mode()); >+ videoFullscreenModel().fullscreenModeChanged(m_currentMode.mode()); > } > > void VideoFullscreenInterfaceAVKit::clearMode(HTMLMediaElementEnums::VideoFullscreenMode mode) >@@ -1902,8 +1843,7 @@ void VideoFullscreenInterfaceAVKit::clearMode(HTMLMediaElementEnums::VideoFullsc > return; > > m_currentMode.clearMode(mode); >- if (m_videoFullscreenModel) >- m_videoFullscreenModel->fullscreenModeChanged(m_currentMode.mode()); >+ videoFullscreenModel().fullscreenModeChanged(m_currentMode.mode()); > } > > bool VideoFullscreenInterfaceAVKit::isPlayingVideoInEnhancedFullscreen() const >diff --git a/Source/WebCore/platform/ios/WebAVPlayerController.h b/Source/WebCore/platform/ios/WebAVPlayerController.h >index a45346cddc0f475a91a3897b5aa263b7f81c7225..1e78ab06fe4b47b13d6030501a453412d2c26862 100644 >--- a/Source/WebCore/platform/ios/WebAVPlayerController.h >+++ b/Source/WebCore/platform/ios/WebAVPlayerController.h >@@ -26,6 +26,7 @@ > #if PLATFORM(IOS) && HAVE(AVKIT) > > #import <pal/spi/cocoa/AVKitSPI.h> >+#import <wtf/WeakPtr.h> > > namespace WebCore { > class PlaybackSessionModel; >@@ -39,13 +40,14 @@ class PlaybackSessionInterfaceAVKit; > @interface WebAVPlayerController : NSObject { > WebAVMediaSelectionOption *_currentAudioMediaSelectionOption; > WebAVMediaSelectionOption *_currentLegibleMediaSelectionOption; >+ RefPtr<WebCore::PlaybackSessionInterfaceAVKit> _playbackSessionInterface; > BOOL _pictureInPictureInterrupted; > BOOL _muted; > } > > @property (retain) AVPlayerController* playerControllerProxy; >-@property (assign) WebCore::PlaybackSessionModel* delegate; >-@property (assign) WebCore::PlaybackSessionInterfaceAVKit* playbackSessionInterface; >+@property (readonly) WebCore::PlaybackSessionModel* delegate; >+@property WebCore::PlaybackSessionInterfaceAVKit* playbackSessionInterface; > > @property (readonly) BOOL canScanForward; > @property BOOL canScanBackward; >diff --git a/Source/WebCore/platform/ios/WebAVPlayerController.mm b/Source/WebCore/platform/ios/WebAVPlayerController.mm >index 3721800e10b9ff4a8106ade5ac10151d00fa2c75..6f24ab21a0ea5a0eccf9319b36c4d11914ccb9a8 100644 >--- a/Source/WebCore/platform/ios/WebAVPlayerController.mm >+++ b/Source/WebCore/platform/ios/WebAVPlayerController.mm >@@ -97,6 +97,23 @@ - (void)dealloc > [super dealloc]; > } > >+@dynamic delegate; >+- (WebCore::PlaybackSessionModel*)delegate >+{ >+ return _playbackSessionInterface ? &_playbackSessionInterface->playbackSessionModel() : nullptr; >+} >+ >+@dynamic playbackSessionInterface; >+- (WebCore::PlaybackSessionInterfaceAVKit*)playbackSessionInterface >+{ >+ return _playbackSessionInterface.get(); >+} >+ >+- (void)setPlaybackSessionInterface:(WebCore::PlaybackSessionInterfaceAVKit*)playbackSessionInterface >+{ >+ _playbackSessionInterface = playbackSessionInterface; >+} >+ > - (AVPlayer *)player > { > return nil; >diff --git a/Source/WebCore/platform/ios/WebVideoFullscreenControllerAVKit.mm b/Source/WebCore/platform/ios/WebVideoFullscreenControllerAVKit.mm >index d43b87c0d95220a17f4c10bf247ddcba30d098fd..b705ab3b6a4d8418da3941e8fdbf7994ab4c65eb 100644 >--- a/Source/WebCore/platform/ios/WebVideoFullscreenControllerAVKit.mm >+++ b/Source/WebCore/platform/ios/WebVideoFullscreenControllerAVKit.mm >@@ -99,11 +99,11 @@ -(void)didFinishFullscreen:(VideoFullscreenControllerContext*)context; > @end > > class VideoFullscreenControllerContext final >- : private VideoFullscreenModel >- , private VideoFullscreenModelClient >- , private VideoFullscreenChangeObserver >+ : public VideoFullscreenModel >+ , public VideoFullscreenModelClient >+ , public VideoFullscreenChangeObserver > , private PlaybackSessionModel >- , private PlaybackSessionModelClient >+ , public PlaybackSessionModelClient > , public ThreadSafeRefCounted<VideoFullscreenControllerContext> { > > public: >@@ -118,6 +118,9 @@ public: > void requestHideAndExitFullscreen(); > void invalidate(); > >+ using ThreadSafeRefCounted::ref; >+ using ThreadSafeRefCounted::deref; >+ > private: > VideoFullscreenControllerContext() { } > >@@ -137,7 +140,9 @@ private: > void videoDimensionsChanged(const FloatSize&) override; > > // PlaybackSessionModel >- void addClient(PlaybackSessionModelClient&) override; >+ void refPlaybackSessionModel() final { ref(); } >+ void derefPlaybackSessionModel() final { deref(); } >+ void addClient(WeakPtr<PlaybackSessionModelClient>&&) override; > void removeClient(PlaybackSessionModelClient&) override; > void play() override; > void pause() override; >@@ -191,7 +196,9 @@ private: > void volumeChanged(double) override; > > // VideoFullscreenModel >- void addClient(VideoFullscreenModelClient&) override; >+ void refVideoFullscreenModel() final { ref(); } >+ void derefVideoFullscreenModel() final { deref(); } >+ void addClient(WeakPtr<VideoFullscreenModelClient>&&) override; > void removeClient(VideoFullscreenModelClient&) override; > void requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenMode, bool finishedWithMedia = false) override; > void setVideoLayerFrame(FloatRect) override; >@@ -210,14 +217,17 @@ private: > void willExitPictureInPicture() final; > void didExitPictureInPicture() final; > >- HashSet<PlaybackSessionModelClient*> m_playbackClients; >- HashSet<VideoFullscreenModelClient*> m_fullscreenClients; >+ Vector<WeakPtr<PlaybackSessionModelClient>> m_playbackClients; >+ Vector<WeakPtr<VideoFullscreenModelClient>> m_fullscreenClients; > RefPtr<VideoFullscreenInterfaceAVKit> m_interface; > RefPtr<VideoFullscreenModelVideoElement> m_fullscreenModel; > RefPtr<PlaybackSessionModelMediaElement> m_playbackModel; > RefPtr<HTMLVideoElement> m_videoElement; > RetainPtr<UIView> m_videoFullscreenView; > RetainPtr<WebVideoFullscreenController> m_controller; >+ WeakPtrFactory<PlaybackSessionModelClient> m_playbackClientFactory; >+ WeakPtrFactory<VideoFullscreenModelClient> m_fullscreenModelClientFactory; >+ WeakPtrFactory<VideoFullscreenChangeObserver> m_fullscreenChangeObserverFactory; > }; > > #pragma mark VideoFullscreenChangeObserver >@@ -321,8 +331,6 @@ void VideoFullscreenControllerContext::didExitFullscreen() > void VideoFullscreenControllerContext::didCleanupFullscreen() > { > ASSERT(isUIThread()); >- m_interface->setVideoFullscreenModel(nullptr); >- m_interface->setVideoFullscreenChangeObserver(nullptr); > m_interface = nullptr; > m_videoFullscreenView = nil; > >@@ -331,6 +339,7 @@ void VideoFullscreenControllerContext::didCleanupFullscreen() > m_fullscreenModel->setVideoElement(nullptr); > m_playbackModel->setMediaElement(nullptr); > m_playbackModel->removeClient(*this); >+ m_playbackModel = nullptr; > m_fullscreenModel->removeClient(*this); > m_fullscreenModel = nullptr; > m_videoElement = nullptr; >@@ -545,16 +554,16 @@ void VideoFullscreenControllerContext::volumeChanged(double volume) > } > #pragma mark VideoFullscreenModel > >-void VideoFullscreenControllerContext::addClient(VideoFullscreenModelClient& client) >+void VideoFullscreenControllerContext::addClient(WeakPtr<VideoFullscreenModelClient>&& client) > { >- ASSERT(!m_fullscreenClients.contains(&client)); >- m_fullscreenClients.add(&client); >+ ASSERT(!m_fullscreenClients.contains(client)); >+ m_fullscreenClients.append(WTFMove(client)); > } > > void VideoFullscreenControllerContext::removeClient(VideoFullscreenModelClient& client) > { > ASSERT(m_fullscreenClients.contains(&client)); >- m_fullscreenClients.remove(&client); >+ m_fullscreenClients.removeAll(&client); > } > > void VideoFullscreenControllerContext::requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenMode mode, bool finishedWithMedia) >@@ -644,35 +653,35 @@ bool VideoFullscreenControllerContext::isPictureInPictureSupported() const > void VideoFullscreenControllerContext::willEnterPictureInPicture() > { > ASSERT(isUIThread()); >- for (auto* client : m_fullscreenClients) >+ for (auto& client : m_fullscreenClients) > client->willEnterPictureInPicture(); > } > > void VideoFullscreenControllerContext::didEnterPictureInPicture() > { > ASSERT(isUIThread()); >- for (auto* client : m_fullscreenClients) >+ for (auto& client : m_fullscreenClients) > client->didEnterPictureInPicture(); > } > > void VideoFullscreenControllerContext::failedToEnterPictureInPicture() > { > ASSERT(isUIThread()); >- for (auto* client : m_fullscreenClients) >+ for (auto& client : m_fullscreenClients) > client->failedToEnterPictureInPicture(); > } > > void VideoFullscreenControllerContext::willExitPictureInPicture() > { > ASSERT(isUIThread()); >- for (auto* client : m_fullscreenClients) >+ for (auto& client : m_fullscreenClients) > client->willExitPictureInPicture(); > } > > void VideoFullscreenControllerContext::didExitPictureInPicture() > { > ASSERT(isUIThread()); >- for (auto* client : m_fullscreenClients) >+ for (auto& client : m_fullscreenClients) > client->didExitPictureInPicture(); > } > >@@ -684,16 +693,16 @@ FloatSize VideoFullscreenControllerContext::videoDimensions() const > > #pragma mark - PlaybackSessionModel > >-void VideoFullscreenControllerContext::addClient(PlaybackSessionModelClient& client) >+void VideoFullscreenControllerContext::addClient(WeakPtr<PlaybackSessionModelClient>&& client) > { >- ASSERT(!m_playbackClients.contains(&client)); >- m_playbackClients.add(&client); >+ ASSERT(!m_playbackClients.contains(client)); >+ m_playbackClients.append(WTFMove(client)); > } > > void VideoFullscreenControllerContext::removeClient(PlaybackSessionModelClient& client) > { > ASSERT(m_playbackClients.contains(&client)); >- m_playbackClients.remove(&client); >+ m_playbackClients.removeAll(&client); > } > > void VideoFullscreenControllerContext::play() >@@ -954,11 +963,11 @@ void VideoFullscreenControllerContext::setUpFullscreen(HTMLVideoElement& videoEl > RetainPtr<UIView> viewRef = view; > m_videoElement = &videoElement; > m_playbackModel = PlaybackSessionModelMediaElement::create(); >- m_playbackModel->addClient(*this); >+ m_playbackModel->addClient(m_playbackClientFactory.createWeakPtr(*this)); > m_playbackModel->setMediaElement(m_videoElement.get()); > > m_fullscreenModel = VideoFullscreenModelVideoElement::create(); >- m_fullscreenModel->addClient(*this); >+ m_fullscreenModel->addClient(m_fullscreenModelClientFactory.createWeakPtr(*this)); > m_fullscreenModel->setVideoElement(m_videoElement.get()); > > bool allowsPictureInPicture = m_videoElement->webkitSupportsPresentationMode(HTMLVideoElement::VideoPresentationMode::PictureInPicture); >@@ -971,10 +980,8 @@ void VideoFullscreenControllerContext::setUpFullscreen(HTMLVideoElement& videoEl > ASSERT(isUIThread()); > > Ref<PlaybackSessionInterfaceAVKit> sessionInterface = PlaybackSessionInterfaceAVKit::create(*this); >- m_interface = VideoFullscreenInterfaceAVKit::create(sessionInterface.get()); >- m_interface->setVideoFullscreenChangeObserver(this); >- m_interface->setVideoFullscreenModel(this); >- m_interface->setVideoFullscreenChangeObserver(this); >+ m_interface = VideoFullscreenInterfaceAVKit::create(sessionInterface.get(), *this); >+ m_interface->setVideoFullscreenChangeObserver(m_fullscreenChangeObserverFactory.createWeakPtr(*this)); > > m_videoFullscreenView = adoptNS([allocUIViewInstance() init]); > >diff --git a/Source/WebCore/platform/mac/PlaybackSessionInterfaceMac.h b/Source/WebCore/platform/mac/PlaybackSessionInterfaceMac.h >index e7db397cce40fd5bdcc4f5af26e7bf327419f60e..439a19ea6efb90ee5989fd8967a8b6137a999304 100644 >--- a/Source/WebCore/platform/mac/PlaybackSessionInterfaceMac.h >+++ b/Source/WebCore/platform/mac/PlaybackSessionInterfaceMac.h >@@ -45,9 +45,9 @@ class WEBCORE_EXPORT PlaybackSessionInterfaceMac final > , public PlaybackSessionModelClient > , public RefCounted<PlaybackSessionInterfaceMac> { > public: >- static Ref<PlaybackSessionInterfaceMac> create(PlaybackSessionModel&); >- virtual ~PlaybackSessionInterfaceMac(); >- PlaybackSessionModel* playbackSessionModel() const; >+ static Ref<PlaybackSessionInterfaceMac> create(Ref<PlaybackSessionModel>&&); >+ virtual ~PlaybackSessionInterfaceMac() = default; >+ PlaybackSessionModel& playbackSessionModel() const; > > // PlaybackSessionInterface > void resetMediaState() final; >@@ -64,7 +64,6 @@ public: > void externalPlaybackChanged(bool /* enabled */, PlaybackSessionModel::ExternalPlaybackTargetType, const String& /* localizedDeviceName */) final; > void isPictureInPictureSupportedChanged(bool) final; > >- void invalidate(); > void ensureControlsManager(); > #if ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER) > void setPlayBackControlsManager(WebPlaybackControlsManager *); >@@ -76,8 +75,9 @@ public: > void endScrubbing(); > > private: >- PlaybackSessionInterfaceMac(PlaybackSessionModel&); >- PlaybackSessionModel* m_playbackSessionModel { nullptr }; >+ PlaybackSessionInterfaceMac(Ref<PlaybackSessionModel>&&); >+ Ref<PlaybackSessionModel> m_playbackSessionModel; >+ WeakPtrFactory<PlaybackSessionModelClient> m_weakPtrFactory; > #if ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER) > WebPlaybackControlsManager *m_playbackControlsManager { nullptr }; > >diff --git a/Source/WebCore/platform/mac/PlaybackSessionInterfaceMac.mm b/Source/WebCore/platform/mac/PlaybackSessionInterfaceMac.mm >index b86266d4e33d007bfd78a6fe533c7f5386d3939e..b8aa93a18ed4bf374bc7d7c466e656e7bffe77d4 100644 >--- a/Source/WebCore/platform/mac/PlaybackSessionInterfaceMac.mm >+++ b/Source/WebCore/platform/mac/PlaybackSessionInterfaceMac.mm >@@ -44,24 +44,18 @@ SOFT_LINK_CLASS_OPTIONAL(AVKit, AVValueTiming) > > namespace WebCore { > >-Ref<PlaybackSessionInterfaceMac> PlaybackSessionInterfaceMac::create(PlaybackSessionModel& model) >+Ref<PlaybackSessionInterfaceMac> PlaybackSessionInterfaceMac::create(Ref<PlaybackSessionModel>&& model) > { >- auto interface = adoptRef(*new PlaybackSessionInterfaceMac(model)); >- model.addClient(interface); >- return interface; >+ return adoptRef(*new PlaybackSessionInterfaceMac(WTFMove(model))); > } > >-PlaybackSessionInterfaceMac::PlaybackSessionInterfaceMac(PlaybackSessionModel& model) >- : m_playbackSessionModel(&model) >+PlaybackSessionInterfaceMac::PlaybackSessionInterfaceMac(Ref<PlaybackSessionModel>&& model) >+ : m_playbackSessionModel(WTFMove(model)) > { >+ playbackSessionModel().addClient(m_weakPtrFactory.createWeakPtr(*this)); > } > >-PlaybackSessionInterfaceMac::~PlaybackSessionInterfaceMac() >-{ >- invalidate(); >-} >- >-PlaybackSessionModel* PlaybackSessionInterfaceMac::playbackSessionModel() const >+PlaybackSessionModel& PlaybackSessionInterfaceMac::playbackSessionModel() const > { > return m_playbackSessionModel; > } >@@ -102,7 +96,7 @@ void PlaybackSessionInterfaceMac::rateChanged(bool isPlaying, float playbackRate > WebPlaybackControlsManager* controlsManager = playBackControlsManager(); > [controlsManager setRate:isPlaying ? playbackRate : 0.]; > [controlsManager setPlaying:isPlaying]; >- updatePlaybackControlsManagerTiming(m_playbackSessionModel ? m_playbackSessionModel->currentTime() : 0, [[NSProcessInfo processInfo] systemUptime], playbackRate, isPlaying); >+ updatePlaybackControlsManagerTiming(playbackSessionModel().currentTime(), [[NSProcessInfo processInfo] systemUptime], playbackRate, isPlaying); > #else > UNUSED_PARAM(isPlaying); > UNUSED_PARAM(playbackRate); >@@ -112,14 +106,14 @@ void PlaybackSessionInterfaceMac::rateChanged(bool isPlaying, float playbackRate > void PlaybackSessionInterfaceMac::beginScrubbing() > { > #if ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER) >- updatePlaybackControlsManagerTiming(m_playbackSessionModel ? m_playbackSessionModel->currentTime() : 0, [[NSProcessInfo processInfo] systemUptime], 0, false); >+ updatePlaybackControlsManagerTiming(playbackSessionModel().currentTime(), [[NSProcessInfo processInfo] systemUptime], 0, false); > #endif >- playbackSessionModel()->beginScrubbing(); >+ playbackSessionModel().beginScrubbing(); > } > > void PlaybackSessionInterfaceMac::endScrubbing() > { >- playbackSessionModel()->endScrubbing(); >+ playbackSessionModel().endScrubbing(); > } > > #if ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER) >@@ -198,15 +192,6 @@ void PlaybackSessionInterfaceMac::externalPlaybackChanged(bool, PlaybackSessionM > #endif > } > >-void PlaybackSessionInterfaceMac::invalidate() >-{ >- if (!m_playbackSessionModel) >- return; >- >- m_playbackSessionModel->removeClient(*this); >- m_playbackSessionModel = nullptr; >-} >- > void PlaybackSessionInterfaceMac::ensureControlsManager() > { > #if ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER) >@@ -225,32 +210,27 @@ void PlaybackSessionInterfaceMac::setPlayBackControlsManager(WebPlaybackControls > { > m_playbackControlsManager = manager; > >- if (!manager || !m_playbackSessionModel) >+ if (!manager) > return; > > NSTimeInterval anchorTimeStamp = ![manager rate] ? NAN : [[NSProcessInfo processInfo] systemUptime]; >- manager.timing = [getAVValueTimingClass() valueTimingWithAnchorValue:m_playbackSessionModel->currentTime() anchorTimeStamp:anchorTimeStamp rate:0]; >- double duration = m_playbackSessionModel->duration(); >+ manager.timing = [getAVValueTimingClass() valueTimingWithAnchorValue:playbackSessionModel().currentTime() anchorTimeStamp:anchorTimeStamp rate:0]; >+ double duration = playbackSessionModel().duration(); > manager.contentDuration = duration; > manager.hasEnabledAudio = duration > 0; > manager.hasEnabledVideo = duration > 0; >- manager.rate = m_playbackSessionModel->isPlaying() ? m_playbackSessionModel->playbackRate() : 0.; >- manager.seekableTimeRanges = timeRangesToArray(m_playbackSessionModel->seekableRanges()).get(); >+ manager.rate = playbackSessionModel().isPlaying() ? playbackSessionModel().playbackRate() : 0.; >+ manager.seekableTimeRanges = timeRangesToArray(playbackSessionModel().seekableRanges()).get(); > manager.canTogglePlayback = YES; >- manager.playing = m_playbackSessionModel->isPlaying(); >- [manager setAudioMediaSelectionOptions:m_playbackSessionModel->audioMediaSelectionOptions() withSelectedIndex:static_cast<NSUInteger>(m_playbackSessionModel->audioMediaSelectedIndex())]; >- [manager setLegibleMediaSelectionOptions:m_playbackSessionModel->legibleMediaSelectionOptions() withSelectedIndex:static_cast<NSUInteger>(m_playbackSessionModel->legibleMediaSelectedIndex())]; >+ manager.playing = playbackSessionModel().isPlaying(); >+ [manager setAudioMediaSelectionOptions:playbackSessionModel().audioMediaSelectionOptions() withSelectedIndex:static_cast<NSUInteger>(playbackSessionModel().audioMediaSelectedIndex())]; >+ [manager setLegibleMediaSelectionOptions:playbackSessionModel().legibleMediaSelectionOptions() withSelectedIndex:static_cast<NSUInteger>(playbackSessionModel().legibleMediaSelectedIndex())]; > } > > void PlaybackSessionInterfaceMac::updatePlaybackControlsManagerCanTogglePictureInPicture() > { >- PlaybackSessionModel* model = playbackSessionModel(); >- if (!model) { >- [playBackControlsManager() setCanTogglePictureInPicture:NO]; >- return; >- } >- >- [playBackControlsManager() setCanTogglePictureInPicture:model->isPictureInPictureSupported() && !model->externalPlaybackEnabled()]; >+ auto& model = playbackSessionModel(); >+ [playBackControlsManager() setCanTogglePictureInPicture:model.isPictureInPictureSupported() && !model.externalPlaybackEnabled()]; > } > > void PlaybackSessionInterfaceMac::updatePlaybackControlsManagerTiming(double currentTime, double anchorTime, double playbackRate, bool isPlaying) >@@ -259,16 +239,14 @@ void PlaybackSessionInterfaceMac::updatePlaybackControlsManagerTiming(double cur > if (!manager) > return; > >- PlaybackSessionModel *model = playbackSessionModel(); >- if (!model) >- return; >+ auto& model = playbackSessionModel(); > > double effectiveAnchorTime = playbackRate ? anchorTime : NAN; > double effectivePlaybackRate = playbackRate; > if (!isPlaying >- || model->isScrubbing() >- || (manager.rate > 0 && model->playbackStartedTime() >= currentTime) >- || (manager.rate < 0 && model->playbackStartedTime() <= currentTime)) >+ || model.isScrubbing() >+ || (manager.rate > 0 && model.playbackStartedTime() >= currentTime) >+ || (manager.rate < 0 && model.playbackStartedTime() <= currentTime)) > effectivePlaybackRate = 0; > > manager.timing = [getAVValueTimingClass() valueTimingWithAnchorValue:currentTime anchorTimeStamp:effectiveAnchorTime rate:effectivePlaybackRate]; >diff --git a/Source/WebCore/platform/mac/VideoFullscreenInterfaceMac.h b/Source/WebCore/platform/mac/VideoFullscreenInterfaceMac.h >index af2c649f57e5e1585831df8b246262b2e73d6cb5..e00573a5ae6c6225737c67e87887e3bb9cfba2f6 100644 >--- a/Source/WebCore/platform/mac/VideoFullscreenInterfaceMac.h >+++ b/Source/WebCore/platform/mac/VideoFullscreenInterfaceMac.h >@@ -33,6 +33,7 @@ > #include "VideoFullscreenModel.h" > #include <wtf/RefCounted.h> > #include <wtf/RetainPtr.h> >+#include <wtf/WeakPtr.h> > #include <wtf/text/WTFString.h> > > OBJC_CLASS NSWindow; >@@ -46,21 +47,21 @@ class VideoFullscreenChangeObserver; > > class VideoFullscreenInterfaceMac > : public VideoFullscreenModelClient >- , private PlaybackSessionModelClient >- , public RefCounted<VideoFullscreenInterfaceMac> { >+ , public PlaybackSessionModelClient >+ , public RefCounted<VideoFullscreenInterfaceMac> >+ , public CanMakeWeakPtr<VideoFullscreenInterfaceMac> { > > public: >- static Ref<VideoFullscreenInterfaceMac> create(PlaybackSessionInterfaceMac& playbackSessionInterface) >+ static Ref<VideoFullscreenInterfaceMac> create(Ref<PlaybackSessionInterfaceMac>&& playbackSessionInterface, Ref<VideoFullscreenModel> videoFullscreenModel) > { >- return adoptRef(*new VideoFullscreenInterfaceMac(playbackSessionInterface)); >+ return adoptRef(*new VideoFullscreenInterfaceMac(WTFMove(playbackSessionInterface), WTFMove(videoFullscreenModel))); > } > virtual ~VideoFullscreenInterfaceMac(); > PlaybackSessionInterfaceMac& playbackSessionInterface() const { return m_playbackSessionInterface.get(); } >- VideoFullscreenModel* videoFullscreenModel() const { return m_videoFullscreenModel; } >- PlaybackSessionModel* playbackSessionModel() const { return m_playbackSessionInterface->playbackSessionModel(); } >- WEBCORE_EXPORT void setVideoFullscreenModel(VideoFullscreenModel*); >- VideoFullscreenChangeObserver* videoFullscreenChangeObserver() const { return m_fullscreenChangeObserver; } >- WEBCORE_EXPORT void setVideoFullscreenChangeObserver(VideoFullscreenChangeObserver*); >+ VideoFullscreenModel& videoFullscreenModel() const { return m_videoFullscreenModel; } >+ PlaybackSessionModel& playbackSessionModel() const { return m_playbackSessionInterface->playbackSessionModel(); } >+ VideoFullscreenChangeObserver* videoFullscreenChangeObserver() const { return m_fullscreenChangeObserver.get(); } >+ WEBCORE_EXPORT void setVideoFullscreenChangeObserver(WeakPtr<VideoFullscreenChangeObserver>); > > // PlaybackSessionModelClient > WEBCORE_EXPORT void rateChanged(bool isPlaying, float playbackRate) override; >@@ -97,10 +98,11 @@ public: > WEBCORE_EXPORT void requestHideAndExitPiP(); > > private: >- WEBCORE_EXPORT VideoFullscreenInterfaceMac(PlaybackSessionInterfaceMac&); >+ WEBCORE_EXPORT VideoFullscreenInterfaceMac(Ref<PlaybackSessionInterfaceMac>&&, Ref<VideoFullscreenModel>&&); > Ref<PlaybackSessionInterfaceMac> m_playbackSessionInterface; >- VideoFullscreenModel* m_videoFullscreenModel { nullptr }; >- VideoFullscreenChangeObserver* m_fullscreenChangeObserver { nullptr }; >+ Ref<VideoFullscreenModel> m_videoFullscreenModel; >+ WeakPtrFactory<PlaybackSessionModelClient> m_weakPtrFactory; >+ WeakPtr<VideoFullscreenChangeObserver> m_fullscreenChangeObserver; > HTMLMediaElementEnums::VideoFullscreenMode m_mode { HTMLMediaElementEnums::VideoFullscreenModeNone }; > RetainPtr<WebVideoFullscreenInterfaceMacObjC> m_webVideoFullscreenInterfaceObjC; > }; >diff --git a/Source/WebCore/platform/mac/VideoFullscreenInterfaceMac.mm b/Source/WebCore/platform/mac/VideoFullscreenInterfaceMac.mm >index 0ae6afeade313175d2e3685cd7a2b54e8506b07b..023e765c2730447a36785f656167be64ff73b3de 100644 >--- a/Source/WebCore/platform/mac/VideoFullscreenInterfaceMac.mm >+++ b/Source/WebCore/platform/mac/VideoFullscreenInterfaceMac.mm >@@ -192,8 +192,8 @@ - (void)setUpPIPForVideoView:(NSView *)videoView withFrame:(NSRect)frame inWindo > [_pipViewController setUserCanResize:YES]; > [_pipViewController setPlaying:_playing]; > [self setVideoDimensions:NSEqualSizes(_videoDimensions, NSZeroSize) ? frame.size : _videoDimensions]; >- if (_videoFullscreenInterfaceMac && _videoFullscreenInterfaceMac->videoFullscreenModel()) >- _videoFullscreenInterfaceMac->videoFullscreenModel()->setVideoLayerGravity(VideoFullscreenModel::VideoGravityResizeAspectFill); >+ if (_videoFullscreenInterfaceMac) >+ _videoFullscreenInterfaceMac->videoFullscreenModel().setVideoLayerGravity(VideoFullscreenModel::VideoGravityResizeAspectFill); > > _videoViewContainer = adoptNS([[WebVideoViewContainer alloc] initWithFrame:frame]); > [_videoViewContainer setVideoViewContainerDelegate:self]; >@@ -246,8 +246,8 @@ - (void)boundsDidChangeForVideoViewContainer:(WebVideoViewContainer *)videoViewC > > ASSERT_UNUSED(videoViewContainer, videoViewContainer == _videoViewContainer); > >- if (_videoFullscreenInterfaceMac && _videoFullscreenInterfaceMac->videoFullscreenModel()) >- _videoFullscreenInterfaceMac->videoFullscreenModel()->setVideoLayerFrame([_videoViewContainer bounds]); >+ if (_videoFullscreenInterfaceMac) >+ _videoFullscreenInterfaceMac->videoFullscreenModel().setVideoLayerFrame([_videoViewContainer bounds]); > } > > - (void)superviewDidChangeForVideoViewContainer:(WebVideoViewContainer *)videoViewContainer >@@ -283,12 +283,12 @@ - (void)pipDidClose:(PIPViewController *)pip > { > ASSERT_UNUSED(pip, pip == _pipViewController); > >- if (_videoFullscreenInterfaceMac && _videoFullscreenInterfaceMac->videoFullscreenModel() && _videoViewContainer && _returningWindow && !NSEqualRects(_returningRect, NSZeroRect)) { >+ if (_videoFullscreenInterfaceMac && _videoViewContainer && _returningWindow && !NSEqualRects(_returningRect, NSZeroRect)) { > [NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) { > context.allowsImplicitAnimation = NO; > [_videoViewContainer setFrame:_returningRect]; >- _videoFullscreenInterfaceMac->videoFullscreenModel()->setVideoLayerFrame([_videoViewContainer bounds]); >- _videoFullscreenInterfaceMac->videoFullscreenModel()->setVideoLayerGravity(VideoFullscreenModel::VideoGravityResizeAspect); >+ _videoFullscreenInterfaceMac->videoFullscreenModel().setVideoLayerFrame([_videoViewContainer bounds]); >+ _videoFullscreenInterfaceMac->videoFullscreenModel().setVideoLayerGravity(VideoFullscreenModel::VideoGravityResizeAspect); > > [[_returningWindow contentView] addSubview:_videoViewContainer.get() positioned:NSWindowAbove relativeTo:nil]; > } completionHandler:nil]; >@@ -296,10 +296,9 @@ - (void)pipDidClose:(PIPViewController *)pip > > if (_videoFullscreenInterfaceMac) { > if (!self.isExitingToStandardFullscreen) { >- if (VideoFullscreenModel* videoFullscreenModel = _videoFullscreenInterfaceMac->videoFullscreenModel()) { >- videoFullscreenModel->didExitPictureInPicture(); >- videoFullscreenModel->setVideoLayerGravity(VideoFullscreenModel::VideoGravityResizeAspect); >- } >+ Ref<VideoFullscreenModel> videoFullscreenModel = _videoFullscreenInterfaceMac->videoFullscreenModel(); >+ videoFullscreenModel->didExitPictureInPicture(); >+ videoFullscreenModel->setVideoLayerGravity(VideoFullscreenModel::VideoGravityResizeAspect); > } > > _videoFullscreenInterfaceMac->clearMode(HTMLMediaElementEnums::VideoFullscreenModePictureInPicture); >@@ -313,16 +312,16 @@ - (void)pipActionPlay:(PIPViewController *)pip > { > ASSERT_UNUSED(pip, pip == _pipViewController); > >- if (_videoFullscreenInterfaceMac && _videoFullscreenInterfaceMac->playbackSessionModel()) >- _videoFullscreenInterfaceMac->playbackSessionModel()->play(); >+ if (_videoFullscreenInterfaceMac) >+ _videoFullscreenInterfaceMac->playbackSessionModel().play(); > } > > - (void)pipActionPause:(PIPViewController *)pip > { > ASSERT_UNUSED(pip, pip == _pipViewController); > >- if (_videoFullscreenInterfaceMac && _videoFullscreenInterfaceMac->playbackSessionModel()) >- _videoFullscreenInterfaceMac->playbackSessionModel()->pause(); >+ if (_videoFullscreenInterfaceMac) >+ _videoFullscreenInterfaceMac->playbackSessionModel().pause(); > } > > - (void)pipActionStop:(PIPViewController *)pip >@@ -332,8 +331,7 @@ - (void)pipActionStop:(PIPViewController *)pip > if (!_videoFullscreenInterfaceMac) > return; > >- if (PlaybackSessionModel* playbackSessionModel = _videoFullscreenInterfaceMac->playbackSessionModel()) >- playbackSessionModel->pause(); >+ _videoFullscreenInterfaceMac->playbackSessionModel().pause(); > > _videoFullscreenInterfaceMac->requestHideAndExitPiP(); > _pipState = PIPState::ExitingPIP; >@@ -344,33 +342,23 @@ @end > namespace WebCore { > using namespace PAL; > >-VideoFullscreenInterfaceMac::VideoFullscreenInterfaceMac(PlaybackSessionInterfaceMac& playbackSessionInterface) >- : m_playbackSessionInterface(playbackSessionInterface) >+VideoFullscreenInterfaceMac::VideoFullscreenInterfaceMac(Ref<PlaybackSessionInterfaceMac>&& playbackSessionInterface, Ref<VideoFullscreenModel>&& videoFullscreenModel) >+ : m_playbackSessionInterface(WTFMove(playbackSessionInterface)) >+ , m_videoFullscreenModel(WTFMove(videoFullscreenModel)) > { >- ASSERT(m_playbackSessionInterface->playbackSessionModel()); >- auto model = m_playbackSessionInterface->playbackSessionModel(); >- model->addClient(*this); >- [videoFullscreenInterfaceObjC() updateIsPlaying:model->isPlaying() newPlaybackRate:model->playbackRate()]; >+ auto& model = playbackSessionModel(); >+ model.addClient(m_weakPtrFactory.createWeakPtr(*this)); >+ [videoFullscreenInterfaceObjC() updateIsPlaying:model.isPlaying() newPlaybackRate:model.playbackRate()]; > } > > VideoFullscreenInterfaceMac::~VideoFullscreenInterfaceMac() > { >- if (m_playbackSessionInterface->playbackSessionModel()) >- m_playbackSessionInterface->playbackSessionModel()->removeClient(*this); >- if (m_videoFullscreenModel) >- m_videoFullscreenModel->removeClient(*this); >+ auto& model = playbackSessionModel(); >+ model.removeClient(*this); >+ m_videoFullscreenModel->removeClient(*this); > } > >-void VideoFullscreenInterfaceMac::setVideoFullscreenModel(VideoFullscreenModel* model) >-{ >- if (m_videoFullscreenModel) >- m_videoFullscreenModel->removeClient(*this); >- m_videoFullscreenModel = model; >- if (m_videoFullscreenModel) >- m_videoFullscreenModel->addClient(*this); >-} >- >-void VideoFullscreenInterfaceMac::setVideoFullscreenChangeObserver(VideoFullscreenChangeObserver* observer) >+void VideoFullscreenInterfaceMac::setVideoFullscreenChangeObserver(WeakPtr<VideoFullscreenChangeObserver> observer) > { > m_fullscreenChangeObserver = observer; > } >@@ -382,8 +370,7 @@ void VideoFullscreenInterfaceMac::setMode(HTMLMediaElementEnums::VideoFullscreen > return; > > m_mode = newMode; >- if (m_videoFullscreenModel) >- m_videoFullscreenModel->fullscreenModeChanged(m_mode); >+ m_videoFullscreenModel->fullscreenModeChanged(m_mode); > } > > void VideoFullscreenInterfaceMac::clearMode(HTMLMediaElementEnums::VideoFullscreenMode mode) >@@ -393,8 +380,7 @@ void VideoFullscreenInterfaceMac::clearMode(HTMLMediaElementEnums::VideoFullscre > return; > > m_mode = newMode; >- if (m_videoFullscreenModel) >- m_videoFullscreenModel->fullscreenModeChanged(m_mode); >+ m_videoFullscreenModel->fullscreenModeChanged(m_mode); > } > > void VideoFullscreenInterfaceMac::rateChanged(bool isPlaying, float playbackRate) >@@ -499,7 +485,6 @@ void VideoFullscreenInterfaceMac::invalidate() > { > LOG(Fullscreen, "VideoFullscreenInterfaceMac::invalidate(%p)", this); > >- m_videoFullscreenModel = nil; > m_fullscreenChangeObserver = nil; > > cleanupFullscreen(); >@@ -510,9 +495,6 @@ void VideoFullscreenInterfaceMac::invalidate() > > void VideoFullscreenInterfaceMac::requestHideAndExitPiP() > { >- if (!m_videoFullscreenModel) >- return; >- > m_videoFullscreenModel->requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone); > m_videoFullscreenModel->willExitPictureInPicture(); > } >diff --git a/Source/WebCore/platform/mac/WebPlaybackControlsManager.mm b/Source/WebCore/platform/mac/WebPlaybackControlsManager.mm >index b6eada31806402500602bfab0d32957da6f2b451..44691c47dd9412698c9d2d0c781b321ca84be2e1 100644 >--- a/Source/WebCore/platform/mac/WebPlaybackControlsManager.mm >+++ b/Source/WebCore/platform/mac/WebPlaybackControlsManager.mm >@@ -94,7 +94,7 @@ - (void)seekToTime:(NSTimeInterval)time toleranceBefore:(NSTimeInterval)toleranc > { > UNUSED_PARAM(toleranceBefore); > UNUSED_PARAM(toleranceAfter); >- _playbackSessionInterfaceMac->playbackSessionModel()->seekToTime(time); >+ _playbackSessionInterfaceMac->playbackSessionModel().seekToTime(time); > } > > - (void)cancelThumbnailAndAudioAmplitudeSampleGeneration >@@ -193,7 +193,7 @@ - (void)setCurrentAudioTouchBarMediaSelectionOption:(AVTouchBarMediaSelectionOpt > if (audioMediaSelectionOption && _audioTouchBarMediaSelectionOptions) > index = [_audioTouchBarMediaSelectionOptions indexOfObject:audioMediaSelectionOption]; > >- _playbackSessionInterfaceMac->playbackSessionModel()->selectAudioMediaOption(index != NSNotFound ? index : UINT64_MAX); >+ _playbackSessionInterfaceMac->playbackSessionModel().selectAudioMediaOption(index != NSNotFound ? index : UINT64_MAX); > } > > - (NSArray<AVTouchBarMediaSelectionOption *> *)legibleTouchBarMediaSelectionOptions >@@ -223,7 +223,7 @@ - (void)setCurrentLegibleTouchBarMediaSelectionOption:(AVTouchBarMediaSelectionO > if (legibleMediaSelectionOption && _legibleTouchBarMediaSelectionOptions) > index = [_legibleTouchBarMediaSelectionOptions indexOfObject:legibleMediaSelectionOption]; > >- _playbackSessionInterfaceMac->playbackSessionModel()->selectLegibleMediaOption(index != NSNotFound ? index : UINT64_MAX); >+ _playbackSessionInterfaceMac->playbackSessionModel().selectLegibleMediaOption(index != NSNotFound ? index : UINT64_MAX); > } > > #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300 >@@ -314,26 +314,26 @@ - (void)setPlaybackSessionInterfaceMac:(PlaybackSessionInterfaceMac*)playbackSes > > - (void)togglePlayback > { >- if (_playbackSessionInterfaceMac && _playbackSessionInterfaceMac->playbackSessionModel()) >- _playbackSessionInterfaceMac->playbackSessionModel()->togglePlayState(); >+ if (_playbackSessionInterfaceMac) >+ _playbackSessionInterfaceMac->playbackSessionModel().togglePlayState(); > } > > - (void)setPlaying:(BOOL)playing > { >- if (!_playbackSessionInterfaceMac || !_playbackSessionInterfaceMac->playbackSessionModel()) >+ if (!_playbackSessionInterfaceMac) > return; > > BOOL isCurrentlyPlaying = self.playing; > if (!isCurrentlyPlaying && playing) >- _playbackSessionInterfaceMac->playbackSessionModel()->play(); >+ _playbackSessionInterfaceMac->playbackSessionModel().play(); > else if (isCurrentlyPlaying && !playing) >- _playbackSessionInterfaceMac->playbackSessionModel()->pause(); >+ _playbackSessionInterfaceMac->playbackSessionModel().pause(); > } > > - (BOOL)isPlaying > { >- if (_playbackSessionInterfaceMac && _playbackSessionInterfaceMac->playbackSessionModel()) >- return _playbackSessionInterfaceMac->playbackSessionModel()->isPlaying(); >+ if (_playbackSessionInterfaceMac) >+ return _playbackSessionInterfaceMac->playbackSessionModel().isPlaying(); > > return NO; > } >@@ -341,8 +341,8 @@ - (BOOL)isPlaying > #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300 > - (void)togglePictureInPicture > { >- if (_playbackSessionInterfaceMac && _playbackSessionInterfaceMac->playbackSessionModel()) >- _playbackSessionInterfaceMac->playbackSessionModel()->togglePictureInPicture(); >+ if (_playbackSessionInterfaceMac) >+ _playbackSessionInterfaceMac->playbackSessionModel().togglePictureInPicture(); > } > #endif > >diff --git a/Source/WebKit/UIProcess/Cocoa/PlaybackSessionManagerProxy.h b/Source/WebKit/UIProcess/Cocoa/PlaybackSessionManagerProxy.h >index a2773e6f9f23ba2664875b5e819a272ce7543596..0017a26bc493701d3dcc0840d5acfc43a7b43b0b 100644 >--- a/Source/WebKit/UIProcess/Cocoa/PlaybackSessionManagerProxy.h >+++ b/Source/WebKit/UIProcess/Cocoa/PlaybackSessionManagerProxy.h >@@ -35,9 +35,10 @@ > #include <WebCore/TimeRanges.h> > #include <wtf/HashCountedSet.h> > #include <wtf/HashMap.h> >-#include <wtf/HashSet.h> > #include <wtf/RefCounted.h> > #include <wtf/RefPtr.h> >+#include <wtf/Vector.h> >+#include <wtf/WeakPtrContainer.h> > > #if PLATFORM(IOS) > #include <WebCore/PlaybackSessionInterfaceAVKit.h> >@@ -56,18 +57,20 @@ namespace WebKit { > class WebPageProxy; > class PlaybackSessionManagerProxy; > >-class PlaybackSessionModelContext final: public RefCounted<PlaybackSessionModelContext>, public WebCore::PlaybackSessionModel { >+class PlaybackSessionModelContext final >+ : public WebCore::PlaybackSessionModel >+ , public RefCounted<PlaybackSessionModelContext> { > public: >- static Ref<PlaybackSessionModelContext> create(PlaybackSessionManagerProxy& manager, uint64_t contextId) >+ static Ref<PlaybackSessionModelContext> create(WeakPtr<PlaybackSessionManagerProxy>&& manager, uint64_t contextId) > { >- return adoptRef(*new PlaybackSessionModelContext(manager, contextId)); >+ return adoptRef(*new PlaybackSessionModelContext(WTFMove(manager), contextId)); > } > virtual ~PlaybackSessionModelContext() { } > > void invalidate() { m_manager = nullptr; } > > // PlaybackSessionModel >- void addClient(WebCore::PlaybackSessionModelClient&) final; >+ void addClient(WeakPtr<WebCore::PlaybackSessionModelClient>&&) final; > void removeClient(WebCore::PlaybackSessionModelClient&)final; > > void durationChanged(double); >@@ -88,16 +91,21 @@ public: > void pictureInPictureSupportedChanged(bool); > void pictureInPictureActiveChanged(bool); > >+ using RefCounted::ref; >+ using RefCounted::deref; >+ > private: > friend class VideoFullscreenModelContext; > >- PlaybackSessionModelContext(PlaybackSessionManagerProxy& manager, uint64_t contextId) >- : m_manager(&manager) >+ PlaybackSessionModelContext(WeakPtr<PlaybackSessionManagerProxy>&& manager, uint64_t contextId) >+ : m_manager(WTFMove(manager)) > , m_contextId(contextId) > { > } > > // PlaybackSessionModel >+ void refPlaybackSessionModel() final { ref(); } >+ void derefPlaybackSessionModel() final { deref(); } > void play() final; > void pause() final; > void togglePlayState() final; >@@ -139,10 +147,10 @@ private: > double volume() const final { return m_volume; } > bool isPictureInPictureSupported() const final { return m_pictureInPictureSupported; } > bool isPictureInPictureActive() const final { return m_pictureInPictureActive; } >- >- PlaybackSessionManagerProxy* m_manager; >+ >+ WeakPtr<PlaybackSessionManagerProxy> m_manager; > uint64_t m_contextId; >- HashSet<WebCore::PlaybackSessionModelClient*> m_clients; >+ WeakPtrContainer<WebCore::PlaybackSessionModelClient> m_clients; > double m_playbackStartedTime { 0 }; > bool m_playbackStartedTimeNeedsUpdate { false }; > double m_duration { 0 }; >@@ -169,7 +177,10 @@ private: > bool m_pictureInPictureActive { false }; > }; > >-class PlaybackSessionManagerProxy : public RefCounted<PlaybackSessionManagerProxy>, private IPC::MessageReceiver { >+class PlaybackSessionManagerProxy >+ : public RefCounted<PlaybackSessionManagerProxy> >+ , private IPC::MessageReceiver >+ , public CanMakeWeakPtr<PlaybackSessionManagerProxy> { > public: > static RefPtr<PlaybackSessionManagerProxy> create(WebPageProxy&); > virtual ~PlaybackSessionManagerProxy(); >diff --git a/Source/WebKit/UIProcess/Cocoa/PlaybackSessionManagerProxy.mm b/Source/WebKit/UIProcess/Cocoa/PlaybackSessionManagerProxy.mm >index dc36171b7b41f62eae4be3dfd3ee3cdf9e3c06d0..699bdfd7e31ab068d1a5f5db78178c65a7812277 100644 >--- a/Source/WebKit/UIProcess/Cocoa/PlaybackSessionManagerProxy.mm >+++ b/Source/WebKit/UIProcess/Cocoa/PlaybackSessionManagerProxy.mm >@@ -38,16 +38,14 @@ using namespace WebCore; > > #pragma mark - PlaybackSessionModelContext > >-void PlaybackSessionModelContext::addClient(PlaybackSessionModelClient& client) >+void PlaybackSessionModelContext::addClient(WeakPtr<PlaybackSessionModelClient>&& client) > { >- ASSERT(!m_clients.contains(&client)); >- m_clients.add(&client); >+ m_clients.add(WTFMove(client)); > } > > void PlaybackSessionModelContext::removeClient(PlaybackSessionModelClient& client) > { >- ASSERT(m_clients.contains(&client)); >- m_clients.remove(&client); >+ m_clients.remove(client); > } > > void PlaybackSessionModelContext::play() >@@ -166,8 +164,9 @@ void PlaybackSessionModelContext::playbackStartedTimeChanged(double playbackStar > void PlaybackSessionModelContext::durationChanged(double duration) > { > m_duration = duration; >- for (auto* client : m_clients) >- client->durationChanged(duration); >+ m_clients.forEachNonNullMember([duration] (auto& client) { >+ client.durationChanged(duration); >+ }); > } > > void PlaybackSessionModelContext::currentTimeChanged(double currentTime) >@@ -177,23 +176,26 @@ void PlaybackSessionModelContext::currentTimeChanged(double currentTime) > if (m_playbackStartedTimeNeedsUpdate) > playbackStartedTimeChanged(currentTime); > >- for (auto* client : m_clients) >- client->currentTimeChanged(currentTime, anchorTime); >+ m_clients.forEachNonNullMember([currentTime, anchorTime] (auto& client) { >+ client.currentTimeChanged(currentTime, anchorTime); >+ }); > } > > void PlaybackSessionModelContext::bufferedTimeChanged(double bufferedTime) > { > m_bufferedTime = bufferedTime; >- for (auto* client : m_clients) >- client->bufferedTimeChanged(bufferedTime); >+ m_clients.forEachNonNullMember([bufferedTime] (auto& client) { >+ client.bufferedTimeChanged(bufferedTime); >+ }); > } > > void PlaybackSessionModelContext::rateChanged(bool isPlaying, float playbackRate) > { > m_isPlaying = isPlaying; > m_playbackRate = playbackRate; >- for (auto* client : m_clients) >- client->rateChanged(isPlaying, playbackRate); >+ m_clients.forEachNonNullMember([isPlaying, playbackRate] (auto& client) { >+ client.rateChanged(isPlaying, playbackRate); >+ }); > } > > void PlaybackSessionModelContext::seekableRangesChanged(WebCore::TimeRanges& seekableRanges, double lastModifiedTime, double liveUpdateInterval) >@@ -201,23 +203,26 @@ void PlaybackSessionModelContext::seekableRangesChanged(WebCore::TimeRanges& see > m_seekableRanges = seekableRanges; > m_seekableTimeRangesLastModifiedTime = lastModifiedTime; > m_liveUpdateInterval = liveUpdateInterval; >- for (auto* client : m_clients) >- client->seekableRangesChanged(seekableRanges, lastModifiedTime, liveUpdateInterval); >+ m_clients.forEachNonNullMember([seekableRanges = makeRef(seekableRanges), lastModifiedTime, liveUpdateInterval] (auto& client) { >+ client.seekableRangesChanged(seekableRanges, lastModifiedTime, liveUpdateInterval); >+ }); > } > > void PlaybackSessionModelContext::canPlayFastReverseChanged(bool canPlayFastReverse) > { > m_canPlayFastReverse = canPlayFastReverse; >- for (auto* client : m_clients) >- client->canPlayFastReverseChanged(canPlayFastReverse); >+ m_clients.forEachNonNullMember([canPlayFastReverse] (auto& client) { >+ client.canPlayFastReverseChanged(canPlayFastReverse); >+ }); > } > > void PlaybackSessionModelContext::audioMediaSelectionOptionsChanged(const Vector<MediaSelectionOption>& audioMediaSelectionOptions, uint64_t audioMediaSelectedIndex) > { > m_audioMediaSelectionOptions = audioMediaSelectionOptions; > m_audioMediaSelectedIndex = audioMediaSelectedIndex; >- for (auto* client : m_clients) >- client->audioMediaSelectionOptionsChanged(audioMediaSelectionOptions, audioMediaSelectedIndex); >+ m_clients.forEachNonNullMember([audioMediaSelectionOptions, audioMediaSelectedIndex] (auto& client) { >+ client.audioMediaSelectionOptionsChanged(audioMediaSelectionOptions, audioMediaSelectedIndex); >+ }); > } > > void PlaybackSessionModelContext::legibleMediaSelectionOptionsChanged(const Vector<MediaSelectionOption>& legibleMediaSelectionOptions, uint64_t legibleMediaSelectedIndex) >@@ -225,24 +230,27 @@ void PlaybackSessionModelContext::legibleMediaSelectionOptionsChanged(const Vect > m_legibleMediaSelectionOptions = legibleMediaSelectionOptions; > m_legibleMediaSelectedIndex = legibleMediaSelectedIndex; > >- for (auto* client : m_clients) >- client->legibleMediaSelectionOptionsChanged(legibleMediaSelectionOptions, legibleMediaSelectedIndex); >+ m_clients.forEachNonNullMember([legibleMediaSelectionOptions, legibleMediaSelectedIndex] (auto& client) { >+ client.legibleMediaSelectionOptionsChanged(legibleMediaSelectionOptions, legibleMediaSelectedIndex); >+ }); > } > > void PlaybackSessionModelContext::audioMediaSelectionIndexChanged(uint64_t selectedIndex) > { > m_audioMediaSelectedIndex = selectedIndex; > >- for (auto* client : m_clients) >- client->audioMediaSelectionIndexChanged(selectedIndex); >+ m_clients.forEachNonNullMember([selectedIndex] (auto& client) { >+ client.audioMediaSelectionIndexChanged(selectedIndex); >+ }); > } > > void PlaybackSessionModelContext::legibleMediaSelectionIndexChanged(uint64_t selectedIndex) > { > m_legibleMediaSelectedIndex = selectedIndex; > >- for (auto* client : m_clients) >- client->legibleMediaSelectionIndexChanged(selectedIndex); >+ m_clients.forEachNonNullMember([selectedIndex] (auto& client) { >+ client.legibleMediaSelectionIndexChanged(selectedIndex); >+ }); > } > > void PlaybackSessionModelContext::externalPlaybackChanged(bool enabled, PlaybackSessionModel::ExternalPlaybackTargetType type, const String& localizedName) >@@ -251,43 +259,49 @@ void PlaybackSessionModelContext::externalPlaybackChanged(bool enabled, Playback > m_externalPlaybackTargetType = type; > m_externalPlaybackLocalizedDeviceName = localizedName; > >- for (auto* client : m_clients) >- client->externalPlaybackChanged(enabled, type, localizedName); >+ m_clients.forEachNonNullMember([enabled, type, localizedName] (auto& client) { >+ client.externalPlaybackChanged(enabled, type, localizedName); >+ }); > } > > void PlaybackSessionModelContext::wirelessVideoPlaybackDisabledChanged(bool wirelessVideoPlaybackDisabled) > { > m_wirelessVideoPlaybackDisabled = wirelessVideoPlaybackDisabled; >- for (auto* client : m_clients) >- client->wirelessVideoPlaybackDisabledChanged(wirelessVideoPlaybackDisabled); >+ m_clients.forEachNonNullMember([wirelessVideoPlaybackDisabled] (auto& client) { >+ client.wirelessVideoPlaybackDisabledChanged(wirelessVideoPlaybackDisabled); >+ }); > } > > void PlaybackSessionModelContext::mutedChanged(bool muted) > { > m_muted = muted; >- for (auto* client : m_clients) >- client->mutedChanged(muted); >+ m_clients.forEachNonNullMember([muted] (auto& client) { >+ client.mutedChanged(muted); >+ }); > } > > void PlaybackSessionModelContext::volumeChanged(double volume) > { > m_volume = volume; >- for (auto* client : m_clients) >- client->volumeChanged(volume); >+ m_clients.forEachNonNullMember([volume] (auto& client) { >+ client.volumeChanged(volume); >+ }); > } > > void PlaybackSessionModelContext::pictureInPictureSupportedChanged(bool supported) > { > m_pictureInPictureSupported = supported; >- for (auto* client : m_clients) >- client->isPictureInPictureSupportedChanged(supported); >+ m_clients.forEachNonNullMember([supported] (auto& client) { >+ client.isPictureInPictureSupportedChanged(supported); >+ }); > } > > void PlaybackSessionModelContext::pictureInPictureActiveChanged(bool active) > { > m_pictureInPictureActive = active; >- for (auto* client : m_clients) >- client->pictureInPictureActiveChanged(active); >+ m_clients.forEachNonNullMember([active] (auto& client) { >+ client.pictureInPictureActiveChanged(active); >+ }); > } > > #pragma mark - PlaybackSessionManagerProxy >@@ -315,22 +329,14 @@ void PlaybackSessionManagerProxy::invalidate() > m_page->process().removeMessageReceiver(Messages::PlaybackSessionManagerProxy::messageReceiverName(), m_page->pageID()); > m_page = nullptr; > >- auto contextMap = WTFMove(m_contextMap); >+ m_contextMap.clear(); > m_clientCounts.clear(); >- >- for (auto& tuple : contextMap.values()) { >- RefPtr<PlaybackSessionModelContext> model; >- RefPtr<PlatformPlaybackSessionInterface> interface; >- std::tie(model, interface) = tuple; >- >- interface->invalidate(); >- } > } > > PlaybackSessionManagerProxy::ModelInterfaceTuple PlaybackSessionManagerProxy::createModelAndInterface(uint64_t contextId) > { >- Ref<PlaybackSessionModelContext> model = PlaybackSessionModelContext::create(*this, contextId); >- Ref<PlatformPlaybackSessionInterface> interface = PlatformPlaybackSessionInterface::create(model); >+ Ref<PlaybackSessionModelContext> model = PlaybackSessionModelContext::create(makeWeakPtr(this), contextId); >+ Ref<PlatformPlaybackSessionInterface> interface = PlatformPlaybackSessionInterface::create(model.copyRef()); > > return std::make_tuple(WTFMove(model), WTFMove(interface)); > } >@@ -360,11 +366,8 @@ void PlaybackSessionManagerProxy::addClientForContext(uint64_t contextId) > > void PlaybackSessionManagerProxy::removeClientForContext(uint64_t contextId) > { >- if (!m_clientCounts.remove(contextId)) >- return; >- >- ensureInterface(contextId).invalidate(); >- m_contextMap.remove(contextId); >+ if (m_clientCounts.remove(contextId)) >+ m_contextMap.remove(contextId); > } > > #pragma mark Messages from PlaybackSessionManager >@@ -381,7 +384,8 @@ void PlaybackSessionManagerProxy::setUpPlaybackControlsManagerWithID(uint64_t co > ensureInterface(m_controlsManagerContextId).ensureControlsManager(); > addClientForContext(m_controlsManagerContextId); > >- m_page->videoControlsManagerDidChange(); >+ if (m_page) >+ m_page->videoControlsManagerDidChange(); > } > > void PlaybackSessionManagerProxy::clearPlaybackControlsManager() >@@ -391,7 +395,8 @@ void PlaybackSessionManagerProxy::clearPlaybackControlsManager() > > removeClientForContext(m_controlsManagerContextId); > m_controlsManagerContextId = 0; >- m_page->videoControlsManagerDidChange(); >+ if (m_page) >+ m_page->videoControlsManagerDidChange(); > } > > void PlaybackSessionManagerProxy::resetMediaState(uint64_t contextId) >@@ -498,7 +503,7 @@ void PlaybackSessionManagerProxy::pictureInPictureActiveChanged(uint64_t context > void PlaybackSessionManagerProxy::handleControlledElementIDResponse(uint64_t contextId, String identifier) const > { > #if PLATFORM(MAC) >- if (contextId == m_controlsManagerContextId) >+ if (m_page && contextId == m_controlsManagerContextId) > m_page->handleControlledElementIDResponse(identifier); > #else > UNUSED_PARAM(contextId); >@@ -511,82 +516,98 @@ void PlaybackSessionManagerProxy::handleControlledElementIDResponse(uint64_t con > > void PlaybackSessionManagerProxy::play(uint64_t contextId) > { >- m_page->send(Messages::PlaybackSessionManager::Play(contextId), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManager::Play(contextId), m_page->pageID()); > } > > void PlaybackSessionManagerProxy::pause(uint64_t contextId) > { >- m_page->send(Messages::PlaybackSessionManager::Pause(contextId), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManager::Pause(contextId), m_page->pageID()); > } > > void PlaybackSessionManagerProxy::togglePlayState(uint64_t contextId) > { >- m_page->send(Messages::PlaybackSessionManager::TogglePlayState(contextId), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManager::TogglePlayState(contextId), m_page->pageID()); > } > > void PlaybackSessionManagerProxy::beginScrubbing(uint64_t contextId) > { >- m_page->send(Messages::PlaybackSessionManager::BeginScrubbing(contextId), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManager::BeginScrubbing(contextId), m_page->pageID()); > } > > void PlaybackSessionManagerProxy::endScrubbing(uint64_t contextId) > { >- m_page->send(Messages::PlaybackSessionManager::EndScrubbing(contextId), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManager::EndScrubbing(contextId), m_page->pageID()); > } > > void PlaybackSessionManagerProxy::seekToTime(uint64_t contextId, double time, double toleranceBefore, double toleranceAfter) > { >- m_page->send(Messages::PlaybackSessionManager::SeekToTime(contextId, time, toleranceBefore, toleranceAfter), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManager::SeekToTime(contextId, time, toleranceBefore, toleranceAfter), m_page->pageID()); > } > > void PlaybackSessionManagerProxy::fastSeek(uint64_t contextId, double time) > { >- m_page->send(Messages::PlaybackSessionManager::FastSeek(contextId, time), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManager::FastSeek(contextId, time), m_page->pageID()); > } > > void PlaybackSessionManagerProxy::beginScanningForward(uint64_t contextId) > { >- m_page->send(Messages::PlaybackSessionManager::BeginScanningForward(contextId), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManager::BeginScanningForward(contextId), m_page->pageID()); > } > > void PlaybackSessionManagerProxy::beginScanningBackward(uint64_t contextId) > { >- m_page->send(Messages::PlaybackSessionManager::BeginScanningBackward(contextId), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManager::BeginScanningBackward(contextId), m_page->pageID()); > } > > void PlaybackSessionManagerProxy::endScanning(uint64_t contextId) > { >- m_page->send(Messages::PlaybackSessionManager::EndScanning(contextId), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManager::EndScanning(contextId), m_page->pageID()); > } > > void PlaybackSessionManagerProxy::selectAudioMediaOption(uint64_t contextId, uint64_t index) > { >- m_page->send(Messages::PlaybackSessionManager::SelectAudioMediaOption(contextId, index), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManager::SelectAudioMediaOption(contextId, index), m_page->pageID()); > } > > void PlaybackSessionManagerProxy::selectLegibleMediaOption(uint64_t contextId, uint64_t index) > { >- m_page->send(Messages::PlaybackSessionManager::SelectLegibleMediaOption(contextId, index), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManager::SelectLegibleMediaOption(contextId, index), m_page->pageID()); > } > > void PlaybackSessionManagerProxy::togglePictureInPicture(uint64_t contextId) > { >- m_page->send(Messages::PlaybackSessionManager::TogglePictureInPicture(contextId), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManager::TogglePictureInPicture(contextId), m_page->pageID()); > } > > void PlaybackSessionManagerProxy::toggleMuted(uint64_t contextId) > { >- m_page->send(Messages::PlaybackSessionManager::ToggleMuted(contextId), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManager::ToggleMuted(contextId), m_page->pageID()); > } > > void PlaybackSessionManagerProxy::setMuted(uint64_t contextId, bool muted) > { >- m_page->send(Messages::PlaybackSessionManager::SetMuted(contextId, muted), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManager::SetMuted(contextId, muted), m_page->pageID()); > } > > void PlaybackSessionManagerProxy::setVolume(uint64_t contextId, double volume) > { >- m_page->send(Messages::PlaybackSessionManager::SetVolume(contextId, volume), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManager::SetVolume(contextId, volume), m_page->pageID()); > } > > void PlaybackSessionManagerProxy::setPlayingOnSecondScreen(uint64_t contextId, bool value) >@@ -597,7 +618,7 @@ void PlaybackSessionManagerProxy::setPlayingOnSecondScreen(uint64_t contextId, b > > void PlaybackSessionManagerProxy::requestControlledElementID() > { >- if (m_controlsManagerContextId) >+ if (m_page && m_controlsManagerContextId) > m_page->send(Messages::PlaybackSessionManager::HandleControlledElementIDRequest(m_controlsManagerContextId), m_page->pageID()); > } > >diff --git a/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.h b/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.h >index 48663c252ba878bba1a191403c2ccaee31610916..b6f74f5d41b746227c96d783c230ed515862c0ab 100644 >--- a/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.h >+++ b/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.h >@@ -33,9 +33,11 @@ > #include <WebCore/VideoFullscreenChangeObserver.h> > #include <WebCore/VideoFullscreenModel.h> > #include <wtf/HashMap.h> >-#include <wtf/HashSet.h> > #include <wtf/RefCounted.h> > #include <wtf/RefPtr.h> >+#include <wtf/UniqueRef.h> >+#include <wtf/Vector.h> >+#include <wtf/WeakPtrContainer.h> > > #if PLATFORM(IOS) > #include <WebCore/VideoFullscreenInterfaceAVKit.h> >@@ -59,12 +61,9 @@ class VideoFullscreenManagerProxy; > class VideoFullscreenModelContext final > : public RefCounted<VideoFullscreenModelContext> > , public WebCore::VideoFullscreenModel >- , public WebCore::VideoFullscreenChangeObserver { >+ , public WebCore::VideoFullscreenChangeObserver { > public: >- static Ref<VideoFullscreenModelContext> create(VideoFullscreenManagerProxy& manager, PlaybackSessionModelContext& playbackSessionModel, uint64_t contextId) >- { >- return adoptRef(*new VideoFullscreenModelContext(manager, playbackSessionModel, contextId)); >- } >+ static Ref<VideoFullscreenModelContext> create(WeakPtr<VideoFullscreenManagerProxy>&&, Ref<PlaybackSessionModelContext>&&, uint64_t contextId); > virtual ~VideoFullscreenModelContext(); > > void invalidate() { m_manager = nullptr; } >@@ -72,19 +71,26 @@ public: > PlatformView *layerHostView() const { return m_layerHostView.get(); } > void setLayerHostView(RetainPtr<PlatformView>&& layerHostView) { m_layerHostView = WTFMove(layerHostView); } > >+ WeakPtr<VideoFullscreenChangeObserver> createWeakPtr() { return m_weakPtrFactory.createWeakPtr(*this); } >+ >+ using RefCounted::ref; >+ using RefCounted::deref; >+ > private: >- VideoFullscreenModelContext(VideoFullscreenManagerProxy&, PlaybackSessionModelContext&, uint64_t); >+ VideoFullscreenModelContext(WeakPtr<VideoFullscreenManagerProxy>&&, Ref<PlaybackSessionModelContext>&&, uint64_t); > > // VideoFullscreenModel >- void addClient(WebCore::VideoFullscreenModelClient&) override; >- void removeClient(WebCore::VideoFullscreenModelClient&) override; >- void requestFullscreenMode(WebCore::HTMLMediaElementEnums::VideoFullscreenMode, bool finishedWithMedia = false) override; >- void setVideoLayerFrame(WebCore::FloatRect) override; >- void setVideoLayerGravity(VideoGravity) override; >- void fullscreenModeChanged(WebCore::HTMLMediaElementEnums::VideoFullscreenMode) override; >- bool isVisible() const override; >- bool hasVideo() const override { return m_hasVideo; } >- WebCore::FloatSize videoDimensions() const override { return m_videoDimensions; } >+ void refVideoFullscreenModel() final { ref(); } >+ void derefVideoFullscreenModel() final { deref(); } >+ void addClient(WeakPtr<WebCore::VideoFullscreenModelClient>&&) final; >+ void removeClient(WebCore::VideoFullscreenModelClient&) final; >+ void requestFullscreenMode(WebCore::HTMLMediaElementEnums::VideoFullscreenMode, bool finishedWithMedia = false) final; >+ void setVideoLayerFrame(WebCore::FloatRect) final; >+ void setVideoLayerGravity(VideoGravity) final; >+ void fullscreenModeChanged(WebCore::HTMLMediaElementEnums::VideoFullscreenMode) final; >+ bool isVisible() const final; >+ bool hasVideo() const final { return m_hasVideo; } >+ WebCore::FloatSize videoDimensions() const final { return m_videoDimensions; } > #if PLATFORM(IOS) > UIViewController *presentingViewController() final; > UIViewController *createVideoFullscreenViewController(AVPlayerViewController*) final; >@@ -106,16 +112,20 @@ private: > void didCleanupFullscreen() final; > void fullscreenMayReturnToInline() final; > >- VideoFullscreenManagerProxy* m_manager; >+ WeakPtr<VideoFullscreenManagerProxy> m_manager; > Ref<PlaybackSessionModelContext> m_playbackSessionModel; > uint64_t m_contextId; >+ WeakPtrFactory<VideoFullscreenChangeObserver> m_weakPtrFactory; > RetainPtr<PlatformView *> m_layerHostView; >- HashSet<WebCore::VideoFullscreenModelClient*> m_clients; >+ WeakPtrContainer<WebCore::VideoFullscreenModelClient> m_clients; > WebCore::FloatSize m_videoDimensions; > bool m_hasVideo { false }; > }; > >-class VideoFullscreenManagerProxy : public RefCounted<VideoFullscreenManagerProxy>, private IPC::MessageReceiver { >+class VideoFullscreenManagerProxy >+ : public RefCounted<VideoFullscreenManagerProxy> >+ , private IPC::MessageReceiver >+ , public CanMakeWeakPtr<VideoFullscreenManagerProxy> { > public: > static RefPtr<VideoFullscreenManagerProxy> create(WebPageProxy&, PlaybackSessionManagerProxy&); > virtual ~VideoFullscreenManagerProxy(); >diff --git a/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.mm b/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.mm >index bdfbc807a1c995b6e1c41b872bc48b5470d23639..8e20426bc6f9a4566d8031b9c5e2a1db160563e6 100644 >--- a/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.mm >+++ b/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.mm >@@ -158,27 +158,28 @@ void VideoFullscreenManagerProxy::applicationDidBecomeActive() > > #pragma mark - VideoFullscreenModelContext > >-VideoFullscreenModelContext::VideoFullscreenModelContext(VideoFullscreenManagerProxy& manager, PlaybackSessionModelContext& playbackSessionModel, uint64_t contextId) >- : m_manager(&manager) >- , m_playbackSessionModel(playbackSessionModel) >- , m_contextId(contextId) >+Ref<VideoFullscreenModelContext> VideoFullscreenModelContext::create(WeakPtr<VideoFullscreenManagerProxy>&& manager, Ref<PlaybackSessionModelContext>&& playbackSessionModel, uint64_t contextId) > { >+ return adoptRef(*new VideoFullscreenModelContext(WTFMove(manager), WTFMove(playbackSessionModel), contextId)); > } > >-VideoFullscreenModelContext::~VideoFullscreenModelContext() >+VideoFullscreenModelContext::VideoFullscreenModelContext(WeakPtr<VideoFullscreenManagerProxy>&& manager, Ref<PlaybackSessionModelContext>&& playbackSessionModel, uint64_t contextId) >+ : m_manager(WTFMove(manager)) >+ , m_playbackSessionModel(WTFMove(playbackSessionModel)) >+ , m_contextId(contextId) > { > } > >-void VideoFullscreenModelContext::addClient(VideoFullscreenModelClient& client) >+VideoFullscreenModelContext::~VideoFullscreenModelContext() = default; >+ >+void VideoFullscreenModelContext::addClient(WeakPtr<VideoFullscreenModelClient>&& client) > { >- ASSERT(!m_clients.contains(&client)); >- m_clients.add(&client); >+ m_clients.add(WTFMove(client)); > } > > void VideoFullscreenModelContext::removeClient(VideoFullscreenModelClient& client) > { >- ASSERT(m_clients.contains(&client)); >- m_clients.remove(&client); >+ m_clients.remove(client); > } > > void VideoFullscreenModelContext::requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenMode mode, bool finishedWithMedia) >@@ -281,32 +282,37 @@ void VideoFullscreenModelContext::fullscreenMayReturnToInline() > > void VideoFullscreenModelContext::willEnterPictureInPicture() > { >- for (auto& client : m_clients) >- client->willEnterPictureInPicture(); >+ m_clients.forEachNonNullMember([] (auto& client) { >+ client.willEnterPictureInPicture(); >+ }); > } > > void VideoFullscreenModelContext::didEnterPictureInPicture() > { >- for (auto& client : m_clients) >- client->didEnterPictureInPicture(); >+ m_clients.forEachNonNullMember([] (auto& client) { >+ client.didEnterPictureInPicture(); >+ }); > } > > void VideoFullscreenModelContext::failedToEnterPictureInPicture() > { >- for (auto& client : m_clients) >- client->failedToEnterPictureInPicture(); >+ m_clients.forEachNonNullMember([] (auto& client) { >+ client.failedToEnterPictureInPicture(); >+ }); > } > > void VideoFullscreenModelContext::willExitPictureInPicture() > { >- for (auto& client : m_clients) >- client->willExitPictureInPicture(); >+ m_clients.forEachNonNullMember([] (auto& client) { >+ client.willExitPictureInPicture(); >+ }); > } > > void VideoFullscreenModelContext::didExitPictureInPicture() > { >- for (auto& client : m_clients) >- client->didExitPictureInPicture(); >+ m_clients.forEachNonNullMember([] (auto& client) { >+ client.didExitPictureInPicture(); >+ }); > } > > #pragma mark - VideoFullscreenManagerProxy >@@ -343,7 +349,6 @@ void VideoFullscreenManagerProxy::invalidate() > RefPtr<PlatformVideoFullscreenInterface> interface; > std::tie(model, interface) = tuple; > >- interface->invalidate(); > [model->layerHostView() removeFromSuperview]; > model->setLayerHostView(nullptr); > } >@@ -401,13 +406,12 @@ void VideoFullscreenManagerProxy::applicationDidBecomeActive() > VideoFullscreenManagerProxy::ModelInterfaceTuple VideoFullscreenManagerProxy::createModelAndInterface(uint64_t contextId) > { > auto& playbackSessionModel = m_playbackSessionManagerProxy->ensureModel(contextId); >- Ref<VideoFullscreenModelContext> model = VideoFullscreenModelContext::create(*this, playbackSessionModel, contextId); > auto& playbackSessionInterface = m_playbackSessionManagerProxy->ensureInterface(contextId); >- Ref<PlatformVideoFullscreenInterface> interface = PlatformVideoFullscreenInterface::create(playbackSessionInterface); >+ Ref<VideoFullscreenModelContext> model = VideoFullscreenModelContext::create(makeWeakPtr(this), playbackSessionModel, contextId); >+ Ref<PlatformVideoFullscreenInterface> interface = PlatformVideoFullscreenInterface::create(makeRef(playbackSessionInterface), model.copyRef()); > m_playbackSessionManagerProxy->addClientForContext(contextId); > >- interface->setVideoFullscreenModel(&model.get()); >- interface->setVideoFullscreenChangeObserver(&model.get()); >+ interface->setVideoFullscreenChangeObserver(model->createWeakPtr()); > > return std::make_tuple(WTFMove(model), WTFMove(interface)); > } >@@ -446,7 +450,6 @@ void VideoFullscreenManagerProxy::removeClientForContext(uint64_t contextId) > clientCount--; > > if (clientCount <= 0) { >- ensureInterface(contextId).setVideoFullscreenModel(nullptr); > m_playbackSessionManagerProxy->removeClientForContext(contextId); > m_clientCounts.remove(contextId); > m_contextMap.remove(contextId); >diff --git a/Source/WebKit/UIProcess/ios/fullscreen/WKFullScreenViewController.mm b/Source/WebKit/UIProcess/ios/fullscreen/WKFullScreenViewController.mm >index a9ac545862140cca21647a0c30aaa72e4a131936..f17475ec818baa7315fd9bf4962dff45fffee949 100644 >--- a/Source/WebKit/UIProcess/ios/fullscreen/WKFullScreenViewController.mm >+++ b/Source/WebKit/UIProcess/ios/fullscreen/WKFullScreenViewController.mm >@@ -56,7 +56,9 @@ - (void)didEnterPictureInPicture; > - (void)failedToEnterPictureInPicture; > @end > >-class WKFullScreenViewControllerPlaybackSessionModelClient : PlaybackSessionModelClient { >+class WKFullScreenViewControllerPlaybackSessionModelClient >+ : public PlaybackSessionModelClient >+ , public CanMakeWeakPtr<WKFullScreenViewControllerPlaybackSessionModelClient> { > public: > void setParent(WKFullScreenViewController *parent) { m_parent = parent; } > >@@ -79,11 +81,11 @@ public: > if (m_interface == interface) > return; > >- if (m_interface && m_interface->playbackSessionModel()) >- m_interface->playbackSessionModel()->removeClient(*this); >+ if (m_interface) >+ m_interface->playbackSessionModel().removeClient(*this); > m_interface = interface; >- if (m_interface && m_interface->playbackSessionModel()) >- m_interface->playbackSessionModel()->addClient(*this); >+ if (m_interface) >+ m_interface->playbackSessionModel().addClient(makeWeakPtr(*this)); > } > > private: >@@ -91,7 +93,9 @@ private: > RefPtr<PlaybackSessionInterfaceAVKit> m_interface; > }; > >-class WKFullScreenViewControllerVideoFullscreenModelClient : VideoFullscreenModelClient { >+class WKFullScreenViewControllerVideoFullscreenModelClient >+ : public VideoFullscreenModelClient >+ , public CanMakeWeakPtr<WKFullScreenViewControllerVideoFullscreenModelClient> { > public: > void setParent(WKFullScreenViewController *parent) { m_parent = parent; } > >@@ -100,11 +104,11 @@ public: > if (m_interface == interface) > return; > >- if (m_interface && m_interface->videoFullscreenModel()) >- m_interface->videoFullscreenModel()->removeClient(*this); >+ if (m_interface) >+ m_interface->videoFullscreenModel().removeClient(*this); > m_interface = interface; >- if (m_interface && m_interface->videoFullscreenModel()) >- m_interface->videoFullscreenModel()->addClient(*this); >+ if (m_interface) >+ m_interface->videoFullscreenModel().addClient(makeWeakPtr(*this)); > } > > VideoFullscreenInterfaceAVKit* interface() const { return m_interface.get(); } >@@ -268,9 +272,14 @@ - (void)videoControlsManagerDidChange > _playbackClient.setInterface(playbackSessionInterface); > _videoFullscreenClient.setInterface(videoFullscreenInterface); > >- PlaybackSessionModel* playbackSessionModel = playbackSessionInterface ? playbackSessionInterface->playbackSessionModel() : nullptr; >- self.playing = playbackSessionModel ? playbackSessionModel->isPlaying() : NO; >- [_pipButton setHidden:!playbackSessionModel]; >+ if (!playbackSessionInterface) { >+ self.playing = NO; >+ [_pipButton setHidden:YES]; >+ return; >+ } >+ >+ self.playing = playbackSessionInterface->playbackSessionModel().isPlaying(); >+ [_pipButton setHidden:NO]; > } > > - (void)setPrefersStatusBarHidden:(BOOL)value >@@ -516,14 +525,8 @@ - (void)_togglePiPAction:(id)sender > return; > > PlatformPlaybackSessionInterface* playbackSessionInterface = playbackSessionManager->controlsManagerInterface(); >- if (!playbackSessionInterface) >- return; >- >- PlaybackSessionModel* playbackSessionModel = playbackSessionInterface->playbackSessionModel(); >- if (!playbackSessionModel) >- return; >- >- playbackSessionModel->togglePictureInPicture(); >+ if (playbackSessionInterface) >+ playbackSessionInterface->playbackSessionModel().togglePictureInPicture(); > } > > - (void)_touchDetected:(id)sender >diff --git a/Source/WebKit/UIProcess/mac/WKFullScreenWindowController.mm b/Source/WebKit/UIProcess/mac/WKFullScreenWindowController.mm >index 5a6bfc33cef2d206a9e06d15ddf1c87cc3712456..5ad2dbc6ebb25cfbc620ae0e71a883be01f2b237 100644 >--- a/Source/WebKit/UIProcess/mac/WKFullScreenWindowController.mm >+++ b/Source/WebKit/UIProcess/mac/WKFullScreenWindowController.mm >@@ -52,7 +52,9 @@ static const NSTimeInterval DefaultWatchdogTimerInterval = 1; > > namespace WebKit { > >-class WKFullScreenWindowControllerVideoFullscreenModelClient : WebCore::VideoFullscreenModelClient { >+class WKFullScreenWindowControllerVideoFullscreenModelClient >+ : public CanMakeWeakPtr<WKFullScreenWindowControllerVideoFullscreenModelClient> >+ , public WebCore::VideoFullscreenModelClient { > public: > void setParent(WKFullScreenWindowController *parent) { m_parent = parent; } > >@@ -61,11 +63,11 @@ public: > if (m_interface == interface) > return; > >- if (m_interface && m_interface->videoFullscreenModel()) >- m_interface->videoFullscreenModel()->removeClient(*this); >+ if (m_interface) >+ m_interface->videoFullscreenModel().removeClient(*this); > m_interface = interface; >- if (m_interface && m_interface->videoFullscreenModel()) >- m_interface->videoFullscreenModel()->addClient(*this); >+ if (m_interface) >+ m_interface->videoFullscreenModel().addClient(makeWeakPtr(this)); > } > > WebCore::VideoFullscreenInterfaceMac* interface() const { return m_interface.get(); } >diff --git a/Source/WebKit/WebProcess/cocoa/PlaybackSessionManager.h b/Source/WebKit/WebProcess/cocoa/PlaybackSessionManager.h >index f0de62b8db05a37eae7d972ba66fbc587e3240f9..91ceffa963f260d5ce241c769230f8455bde258d 100644 >--- a/Source/WebKit/WebProcess/cocoa/PlaybackSessionManager.h >+++ b/Source/WebKit/WebProcess/cocoa/PlaybackSessionManager.h >@@ -47,6 +47,8 @@ class MessageReceiver; > > namespace WebCore { > class Node; >+class PlaybackSessionModel; >+class PlaybackSessionModelClient; > } > > namespace WebKit { >@@ -55,17 +57,17 @@ class WebPage; > class PlaybackSessionManager; > > class PlaybackSessionInterfaceContext final >- : public RefCounted<PlaybackSessionInterfaceContext> >- , public WebCore::PlaybackSessionInterface >- , public WebCore::PlaybackSessionModelClient { >+ : public WebCore::PlaybackSessionInterface >+ , public WebCore::PlaybackSessionModelClient >+ , public RefCounted<PlaybackSessionInterfaceContext> { > public: >- static Ref<PlaybackSessionInterfaceContext> create(PlaybackSessionManager& manager, uint64_t contextId) >+ static Ref<PlaybackSessionInterfaceContext> create(WeakPtr<PlaybackSessionManager>&& manager, uint64_t contextId) > { >- return adoptRef(*new PlaybackSessionInterfaceContext(manager, contextId)); >+ return adoptRef(*new PlaybackSessionInterfaceContext(WTFMove(manager), contextId)); > } > virtual ~PlaybackSessionInterfaceContext(); > >- void invalidate() { m_manager = nullptr; } >+ WeakPtr<WebCore::PlaybackSessionModelClient> createWeakPtr() { return m_weakPtrFactory.createWeakPtr(*this); } > > private: > friend class VideoFullscreenInterfaceContext; >@@ -91,13 +93,17 @@ private: > void volumeChanged(double) final; > void isPictureInPictureSupportedChanged(bool) final; > >- PlaybackSessionInterfaceContext(PlaybackSessionManager&, uint64_t contextId); >+ PlaybackSessionInterfaceContext(WeakPtr<PlaybackSessionManager>&&, uint64_t contextId); > >- PlaybackSessionManager* m_manager; >+ WeakPtr<PlaybackSessionManager> m_manager; >+ WeakPtrFactory<PlaybackSessionModelClient> m_weakPtrFactory; > uint64_t m_contextId; > }; > >-class PlaybackSessionManager : public RefCounted<PlaybackSessionManager>, private IPC::MessageReceiver { >+class PlaybackSessionManager >+ : public RefCounted<PlaybackSessionManager> >+ , private IPC::MessageReceiver >+ , public CanMakeWeakPtr<PlaybackSessionManager> { > public: > static Ref<PlaybackSessionManager> create(WebPage&); > virtual ~PlaybackSessionManager(); >@@ -166,6 +172,7 @@ protected: > void setVolume(uint64_t contextId, double volume); > void setPlayingOnSecondScreen(uint64_t contextId, bool value); > >+ WeakPtrFactory<WebCore::PlaybackSessionModel> m_weakPtrFactory; > WebPage* m_page; > HashMap<WebCore::HTMLMediaElement*, uint64_t> m_mediaElements; > HashMap<uint64_t, ModelInterfaceTuple> m_contextMap; >diff --git a/Source/WebKit/WebProcess/cocoa/PlaybackSessionManager.mm b/Source/WebKit/WebProcess/cocoa/PlaybackSessionManager.mm >index d0aec25e92e97c2852b96dd35fc41671662d8d89..372ac2021e35abf7ee9fc74364c60dfbbd876208 100644 >--- a/Source/WebKit/WebProcess/cocoa/PlaybackSessionManager.mm >+++ b/Source/WebKit/WebProcess/cocoa/PlaybackSessionManager.mm >@@ -54,15 +54,13 @@ static uint64_t nextContextId() > > #pragma mark - PlaybackSessionInterfaceContext > >-PlaybackSessionInterfaceContext::PlaybackSessionInterfaceContext(PlaybackSessionManager& manager, uint64_t contextId) >- : m_manager(&manager) >+PlaybackSessionInterfaceContext::PlaybackSessionInterfaceContext(WeakPtr<PlaybackSessionManager>&& manager, uint64_t contextId) >+ : m_manager(WTFMove(manager)) > , m_contextId(contextId) > { > } > >-PlaybackSessionInterfaceContext::~PlaybackSessionInterfaceContext() >-{ >-} >+PlaybackSessionInterfaceContext::~PlaybackSessionInterfaceContext() = default; > > void PlaybackSessionInterfaceContext::resetMediaState() > { >@@ -185,10 +183,7 @@ PlaybackSessionManager::~PlaybackSessionManager() > RefPtr<PlaybackSessionModelMediaElement> model; > RefPtr<PlaybackSessionInterfaceContext> interface; > std::tie(model, interface) = tuple; >- model->removeClient(*interface); > model->setMediaElement(nullptr); >- >- interface->invalidate(); > } > > m_contextMap.clear(); >@@ -208,9 +203,9 @@ void PlaybackSessionManager::invalidate() > > PlaybackSessionManager::ModelInterfaceTuple PlaybackSessionManager::createModelAndInterface(uint64_t contextId) > { >- RefPtr<PlaybackSessionModelMediaElement> model = PlaybackSessionModelMediaElement::create(); >- RefPtr<PlaybackSessionInterfaceContext> interface = PlaybackSessionInterfaceContext::create(*this, contextId); >- model->addClient(*interface); >+ Ref<PlaybackSessionModelMediaElement> model = PlaybackSessionModelMediaElement::create(); >+ Ref<PlaybackSessionInterfaceContext> interface = PlaybackSessionInterfaceContext::create(makeWeakPtr(this), contextId); >+ model->addClient(interface->createWeakPtr()); > > return std::make_tuple(WTFMove(model), WTFMove(interface)); > } >@@ -241,8 +236,6 @@ void PlaybackSessionManager::removeContext(uint64_t contextId) > > RefPtr<HTMLMediaElement> mediaElement = model->mediaElement(); > model->setMediaElement(nullptr); >- model->removeClient(*interface); >- interface->invalidate(); > m_mediaElements.remove(mediaElement.get()); > m_contextMap.remove(contextId); > } >@@ -284,6 +277,8 @@ void PlaybackSessionManager::setUpPlaybackControlsManager(WebCore::HTMLMediaElem > > addClientForContext(m_controlsManagerContextId); > >+ if (!m_page) >+ return; > m_page->videoControlsManagerDidChange(); > m_page->send(Messages::PlaybackSessionManagerProxy::SetUpPlaybackControlsManagerWithID(m_controlsManagerContextId), m_page->pageID()); > } >@@ -296,6 +291,9 @@ void PlaybackSessionManager::clearPlaybackControlsManager() > removeClientForContext(m_controlsManagerContextId); > m_controlsManagerContextId = 0; > >+ if (!m_page) >+ return; >+ > m_page->videoControlsManagerDidChange(); > m_page->send(Messages::PlaybackSessionManagerProxy::ClearPlaybackControlsManager(), m_page->pageID()); > } >@@ -324,36 +322,45 @@ WebCore::HTMLMediaElement* PlaybackSessionManager::currentPlaybackControlsElemen > > void PlaybackSessionManager::resetMediaState(uint64_t contextId) > { >- m_page->send(Messages::PlaybackSessionManagerProxy::ResetMediaState(contextId), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManagerProxy::ResetMediaState(contextId), m_page->pageID()); > } > > void PlaybackSessionManager::durationChanged(uint64_t contextId, double duration) > { >- m_page->send(Messages::PlaybackSessionManagerProxy::DurationChanged(contextId, duration), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManagerProxy::DurationChanged(contextId, duration), m_page->pageID()); > } > > void PlaybackSessionManager::currentTimeChanged(uint64_t contextId, double currentTime, double anchorTime) > { >- m_page->send(Messages::PlaybackSessionManagerProxy::CurrentTimeChanged(contextId, currentTime, anchorTime), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManagerProxy::CurrentTimeChanged(contextId, currentTime, anchorTime), m_page->pageID()); > } > > void PlaybackSessionManager::bufferedTimeChanged(uint64_t contextId, double bufferedTime) > { >- m_page->send(Messages::PlaybackSessionManagerProxy::BufferedTimeChanged(contextId, bufferedTime), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManagerProxy::BufferedTimeChanged(contextId, bufferedTime), m_page->pageID()); > } > > void PlaybackSessionManager::playbackStartedTimeChanged(uint64_t contextId, double playbackStartedTime) > { >- m_page->send(Messages::PlaybackSessionManagerProxy::PlaybackStartedTimeChanged(contextId, playbackStartedTime), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManagerProxy::PlaybackStartedTimeChanged(contextId, playbackStartedTime), m_page->pageID()); > } > > void PlaybackSessionManager::rateChanged(uint64_t contextId, bool isPlaying, float playbackRate) > { >- m_page->send(Messages::PlaybackSessionManagerProxy::RateChanged(contextId, isPlaying, playbackRate), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManagerProxy::RateChanged(contextId, isPlaying, playbackRate), m_page->pageID()); > } > > void PlaybackSessionManager::seekableRangesChanged(uint64_t contextId, const WebCore::TimeRanges& timeRanges, double lastModifiedTime, double liveUpdateInterval) > { >+ if (!m_page) >+ return; >+ > Vector<std::pair<double, double>> rangesVector; > for (unsigned i = 0; i < timeRanges.length(); i++) { > double start = timeRanges.ranges().start(i).toDouble(); >@@ -365,47 +372,56 @@ void PlaybackSessionManager::seekableRangesChanged(uint64_t contextId, const Web > > void PlaybackSessionManager::canPlayFastReverseChanged(uint64_t contextId, bool value) > { >- m_page->send(Messages::PlaybackSessionManagerProxy::CanPlayFastReverseChanged(contextId, value), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManagerProxy::CanPlayFastReverseChanged(contextId, value), m_page->pageID()); > } > > void PlaybackSessionManager::audioMediaSelectionOptionsChanged(uint64_t contextId, const Vector<MediaSelectionOption>& options, uint64_t selectedIndex) > { >- m_page->send(Messages::PlaybackSessionManagerProxy::AudioMediaSelectionOptionsChanged(contextId, options, selectedIndex), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManagerProxy::AudioMediaSelectionOptionsChanged(contextId, options, selectedIndex), m_page->pageID()); > } > > void PlaybackSessionManager::legibleMediaSelectionOptionsChanged(uint64_t contextId, const Vector<MediaSelectionOption>& options, uint64_t selectedIndex) > { >- m_page->send(Messages::PlaybackSessionManagerProxy::LegibleMediaSelectionOptionsChanged(contextId, options, selectedIndex), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManagerProxy::LegibleMediaSelectionOptionsChanged(contextId, options, selectedIndex), m_page->pageID()); > } > > void PlaybackSessionManager::externalPlaybackChanged(uint64_t contextId, bool enabled, PlaybackSessionModel::ExternalPlaybackTargetType targetType, String localizedDeviceName) > { >- m_page->send(Messages::PlaybackSessionManagerProxy::ExternalPlaybackPropertiesChanged(contextId, enabled, static_cast<uint32_t>(targetType), localizedDeviceName), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManagerProxy::ExternalPlaybackPropertiesChanged(contextId, enabled, static_cast<uint32_t>(targetType), localizedDeviceName), m_page->pageID()); > } > > void PlaybackSessionManager::audioMediaSelectionIndexChanged(uint64_t contextId, uint64_t selectedIndex) > { >- m_page->send(Messages::PlaybackSessionManagerProxy::AudioMediaSelectionIndexChanged(contextId, selectedIndex), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManagerProxy::AudioMediaSelectionIndexChanged(contextId, selectedIndex), m_page->pageID()); > } > > void PlaybackSessionManager::legibleMediaSelectionIndexChanged(uint64_t contextId, uint64_t selectedIndex) > { >- m_page->send(Messages::PlaybackSessionManagerProxy::LegibleMediaSelectionIndexChanged(contextId, selectedIndex), m_page->pageID()); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManagerProxy::LegibleMediaSelectionIndexChanged(contextId, selectedIndex), m_page->pageID()); > } > > void PlaybackSessionManager::wirelessVideoPlaybackDisabledChanged(uint64_t contextId, bool disabled) > { >- m_page->send(Messages::PlaybackSessionManagerProxy::WirelessVideoPlaybackDisabledChanged(contextId, disabled)); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManagerProxy::WirelessVideoPlaybackDisabledChanged(contextId, disabled)); > } > > void PlaybackSessionManager::mutedChanged(uint64_t contextId, bool muted) > { >- m_page->send(Messages::PlaybackSessionManagerProxy::MutedChanged(contextId, muted)); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManagerProxy::MutedChanged(contextId, muted)); > } > > void PlaybackSessionManager::volumeChanged(uint64_t contextId, double volume) > { >- m_page->send(Messages::PlaybackSessionManagerProxy::VolumeChanged(contextId, volume)); >+ if (m_page) >+ m_page->send(Messages::PlaybackSessionManagerProxy::VolumeChanged(contextId, volume)); > } > > void PlaybackSessionManager::isPictureInPictureSupportedChanged(uint64_t contextId, bool supported) >@@ -489,8 +505,10 @@ void PlaybackSessionManager::selectLegibleMediaOption(uint64_t contextId, uint64 > > void PlaybackSessionManager::handleControlledElementIDRequest(uint64_t contextId) > { >- auto element = ensureModel(contextId).mediaElement(); >- if (element) >+ if (!m_page) >+ return; >+ >+ if (auto element = ensureModel(contextId).mediaElement()) > m_page->send(Messages::PlaybackSessionManagerProxy::HandleControlledElementIDResponse(contextId, element->getIdAttribute())); > } > >diff --git a/Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.h b/Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.h >index ff8c4baf463be3539830290ecd246ef9fcfb1dfa..d5e3a8f173284b4b0eb1a3cf619bb51dbd172f4b 100644 >--- a/Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.h >+++ b/Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.h >@@ -60,9 +60,9 @@ class VideoFullscreenInterfaceContext > : public RefCounted<VideoFullscreenInterfaceContext> > , public WebCore::VideoFullscreenModelClient { > public: >- static Ref<VideoFullscreenInterfaceContext> create(VideoFullscreenManager& manager, uint64_t contextId) >+ static Ref<VideoFullscreenInterfaceContext> create(WeakPtr<VideoFullscreenManager>&& manager, uint64_t contextId) > { >- return adoptRef(*new VideoFullscreenInterfaceContext(manager, contextId)); >+ return adoptRef(*new VideoFullscreenInterfaceContext(WTFMove(manager), contextId)); > } > virtual ~VideoFullscreenInterfaceContext(); > >@@ -86,14 +86,16 @@ public: > bool isFullscreen() const { return m_isFullscreen; } > void setIsFullscreen(bool flag) { m_isFullscreen = flag; } > >+ WeakPtr<WebCore::VideoFullscreenModelClient> createWeakPtr() { return m_weakPtrFactory.createWeakPtr(*this); } >+ > private: > // VideoFullscreenModelClient > void hasVideoChanged(bool) override; > void videoDimensionsChanged(const WebCore::FloatSize&) override; > >- VideoFullscreenInterfaceContext(VideoFullscreenManager&, uint64_t contextId); >+ VideoFullscreenInterfaceContext(WeakPtr<VideoFullscreenManager>&&, uint64_t contextId); > >- VideoFullscreenManager* m_manager; >+ WeakPtr<VideoFullscreenManager> m_manager; > uint64_t m_contextId; > std::unique_ptr<LayerHostingContext> m_layerHostingContext; > bool m_isAnimating { false }; >@@ -101,9 +103,13 @@ private: > WebCore::HTMLMediaElementEnums::VideoFullscreenMode m_fullscreenMode { WebCore::HTMLMediaElementEnums::VideoFullscreenModeNone }; > bool m_fullscreenStandby { false }; > bool m_isFullscreen { false }; >+ WeakPtrFactory<WebCore::VideoFullscreenModelClient> m_weakPtrFactory; > }; > >-class VideoFullscreenManager : public RefCounted<VideoFullscreenManager>, private IPC::MessageReceiver { >+class VideoFullscreenManager >+ : public RefCounted<VideoFullscreenManager> >+ , public CanMakeWeakPtr<VideoFullscreenManager> >+ , private IPC::MessageReceiver { > public: > static Ref<VideoFullscreenManager> create(WebPage&, PlaybackSessionManager&); > virtual ~VideoFullscreenManager(); >diff --git a/Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.mm b/Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.mm >index 719cc2bb48c7e9658d6c3b07a80dc243c61081a2..814e2c8f1f65498f3ad6d03515e69fa852c579fa 100644 >--- a/Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.mm >+++ b/Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.mm >@@ -80,8 +80,8 @@ static IntRect inlineVideoFrame(HTMLVideoElement& element) > > #pragma mark - VideoFullscreenInterfaceContext > >-VideoFullscreenInterfaceContext::VideoFullscreenInterfaceContext(VideoFullscreenManager& manager, uint64_t contextId) >- : m_manager(&manager) >+VideoFullscreenInterfaceContext::VideoFullscreenInterfaceContext(WeakPtr<VideoFullscreenManager>&& manager, uint64_t contextId) >+ : m_manager(WTFMove(manager)) > , m_contextId(contextId) > { > } >@@ -129,9 +129,6 @@ VideoFullscreenManager::~VideoFullscreenManager() > std::tie(model, interface) = tuple; > > model->setVideoElement(nullptr); >- model->removeClient(*interface); >- >- interface->invalidate(); > } > > m_contextMap.clear(); >@@ -152,11 +149,11 @@ void VideoFullscreenManager::invalidate() > VideoFullscreenManager::ModelInterfaceTuple VideoFullscreenManager::createModelAndInterface(uint64_t contextId) > { > RefPtr<VideoFullscreenModelVideoElement> model = VideoFullscreenModelVideoElement::create(); >- RefPtr<VideoFullscreenInterfaceContext> interface = VideoFullscreenInterfaceContext::create(*this, contextId); >+ RefPtr<VideoFullscreenInterfaceContext> interface = VideoFullscreenInterfaceContext::create(makeWeakPtr(*this), contextId); > m_playbackSessionManager->addClientForContext(contextId); > > interface->setLayerHostingContext(LayerHostingContext::createForExternalHostingProcess()); >- model->addClient(*interface); >+ model->addClient(interface->createWeakPtr()); > > return std::make_tuple(WTFMove(model), WTFMove(interface)); > } >@@ -189,8 +186,6 @@ void VideoFullscreenManager::removeContext(uint64_t contextId) > > RefPtr<HTMLVideoElement> videoElement = model->videoElement(); > model->setVideoElement(nullptr); >- model->removeClient(*interface); >- interface->invalidate(); > m_videoElements.remove(videoElement.get()); > m_contextMap.remove(contextId); > } >diff --git a/Source/WebKitLegacy/mac/WebView/WebView.mm b/Source/WebKitLegacy/mac/WebView/WebView.mm >index f24ea727023d1b46023b44f4817e863e546c90dc..90d8c67266baa666b5bb4b294f87f68aa1d866c2 100644 >--- a/Source/WebKitLegacy/mac/WebView/WebView.mm >+++ b/Source/WebKitLegacy/mac/WebView/WebView.mm >@@ -9425,8 +9425,6 @@ - (void)_clearPlaybackControlsManager > return; > > _private->playbackSessionModel->setMediaElement(nullptr); >- _private->playbackSessionInterface->invalidate(); >- > _private->playbackSessionModel = nullptr; > _private->playbackSessionInterface = nullptr; > [self updateTouchBar];
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 188747
:
347511
|
347515
|
347526
|
347531
|
347533
|
347537
|
347841
|
347847
|
347870
|
347922
|
349452
|
349486
|
349491
|
349784
|
349795
|
349838
|
351008
|
351130