Cleanup fullscreen logic
https://bugs.webkit.org/show_bug.cgi?id=241811
Patch by Youssef Soliman <youssefdevelops@gmail.com> on 2022-06-21
Reviewed by Eric Carlson.
Cleaned up the logic used when entering fullscreen.
* Source/WebCore/html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::enterFullscreen):
* Source/WebCore/page/ChromeClient.h:
(WebCore::ChromeClient::canEnterVideoFullscreen const):
* Source/WebCore/page/Quirks.cpp:
(WebCore::Quirks::allowLayeredFullscreenVideos const):
* Source/WebCore/page/Quirks.h:
* Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::canEnterVideoFullscreen const):
* Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h:
* Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.h:
* Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.mm:
(WebKit::VideoFullscreenManager::canEnterVideoFullscreen const):
(WebKit::VideoFullscreenManager::enterVideoFullscreenForVideoElement):
(WebKit::VideoFullscreenManager::exitVideoFullscreenForVideoElement):
(WebKit::VideoFullscreenManager::exitVideoFullscreenToModeWithoutAnimation):
(WebKit::VideoFullscreenManager::setCurrentlyInFullscreen):
* Source/WebKitLegacy/mac/WebCoreSupport/WebChromeClient.h:
* Source/WebKitLegacy/mac/WebCoreSupport/WebChromeClient.mm:
(WebChromeClient::canEnterVideoFullscreen const):
Canonical link: https://commits.webkit.org/251714@main
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@295709 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/html/HTMLMediaElement.cpp b/Source/WebCore/html/HTMLMediaElement.cpp
index dacf909..fb415f9 100644
--- a/Source/WebCore/html/HTMLMediaElement.cpp
+++ b/Source/WebCore/html/HTMLMediaElement.cpp
@@ -6386,20 +6386,21 @@
}
#endif
- queueTaskKeepingObjectAlive(*this, TaskSource::MediaElement, [this, mode] {
+ queueTaskKeepingObjectAlive(*this, TaskSource::MediaElement, [this, mode, logIdentifier = LOGIDENTIFIER] {
if (isContextStopped())
return;
if (document().hidden()) {
- ALWAYS_LOG(LOGIDENTIFIER, " returning because document is hidden");
+ ALWAYS_LOG(logIdentifier, " returning because document is hidden");
m_changingVideoFullscreenMode = false;
return;
}
if (is<HTMLVideoElement>(*this)) {
HTMLVideoElement& asVideo = downcast<HTMLVideoElement>(*this);
- if (document().page()->chrome().client().supportsVideoFullscreen(mode)) {
- ALWAYS_LOG(LOGIDENTIFIER, "Entering fullscreen mode ", mode, ", m_videoFullscreenStandby = ", m_videoFullscreenStandby);
+ auto& client = document().page()->chrome().client();
+ if (client.supportsVideoFullscreen(mode) && client.canEnterVideoFullscreen()) {
+ ALWAYS_LOG(logIdentifier, "Entering fullscreen mode ", mode, ", m_videoFullscreenStandby = ", m_videoFullscreenStandby);
m_temporarilyAllowingInlinePlaybackAfterFullscreen = false;
if (mode == VideoFullscreenModeStandard)
@@ -6409,7 +6410,7 @@
setFullscreenMode(mode);
configureMediaControls();
- document().page()->chrome().client().enterVideoFullscreenForVideoElement(asVideo, m_videoFullscreenMode, m_videoFullscreenStandby);
+ client.enterVideoFullscreenForVideoElement(asVideo, m_videoFullscreenMode, m_videoFullscreenStandby);
if (m_videoFullscreenStandby)
return;
diff --git a/Source/WebCore/page/ChromeClient.h b/Source/WebCore/page/ChromeClient.h
index 4a65cd8..81a36fc 100644
--- a/Source/WebCore/page/ChromeClient.h
+++ b/Source/WebCore/page/ChromeClient.h
@@ -415,6 +415,7 @@
virtual GraphicsDeviceAdapter* graphicsDeviceAdapter() const { return nullptr; }
#endif
+ virtual bool canEnterVideoFullscreen() const { return false; }
virtual bool supportsVideoFullscreen(HTMLMediaElementEnums::VideoFullscreenMode) { return false; }
virtual bool supportsVideoFullscreenStandby() { return false; }
diff --git a/Source/WebCore/page/Quirks.cpp b/Source/WebCore/page/Quirks.cpp
index 3c8c4e1..b6e035b 100644
--- a/Source/WebCore/page/Quirks.cpp
+++ b/Source/WebCore/page/Quirks.cpp
@@ -1481,4 +1481,20 @@
return *m_shouldDisableWebSharePolicy;
}
+#if PLATFORM(IOS)
+bool Quirks::allowLayeredFullscreenVideos() const
+{
+ if (!needsQuirks())
+ return false;
+
+ if (!m_allowLayeredFullscreenVideos) {
+ auto domain = RegistrableDomain(m_document->topDocument().url());
+
+ m_allowLayeredFullscreenVideos = domain == "espn.com"_s;
+ }
+
+ return *m_allowLayeredFullscreenVideos;
+}
+#endif
+
}
diff --git a/Source/WebCore/page/Quirks.h b/Source/WebCore/page/Quirks.h
index 2f57d64..1def418 100644
--- a/Source/WebCore/page/Quirks.h
+++ b/Source/WebCore/page/Quirks.h
@@ -158,7 +158,11 @@
#endif
bool shouldDisableWebSharePolicy() const;
-
+
+#if PLATFORM(IOS)
+ WEBCORE_EXPORT bool allowLayeredFullscreenVideos() const;
+#endif
+
private:
bool needsQuirks() const;
@@ -205,6 +209,9 @@
mutable std::optional<bool> m_blocksReturnToFullscreenFromPictureInPictureQuirk;
mutable std::optional<bool> m_shouldDisableEndFullscreenEventWhenEnteringPictureInPictureFromFullscreenQuirk;
mutable std::optional<bool> m_shouldDisableWebSharePolicy;
+#if PLATFORM(IOS)
+ mutable std::optional<bool> m_allowLayeredFullscreenVideos;
+#endif
};
} // namespace WebCore
diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp
index 62fb577..ceb0dee 100644
--- a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp
+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp
@@ -1030,6 +1030,11 @@
m_page.videoFullscreenManager();
}
+bool WebChromeClient::canEnterVideoFullscreen() const
+{
+ return m_page.videoFullscreenManager().canEnterVideoFullscreen();
+}
+
bool WebChromeClient::supportsVideoFullscreen(HTMLMediaElementEnums::VideoFullscreenMode mode)
{
return m_page.videoFullscreenManager().supportsVideoFullscreen(mode);
diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h
index c7a4325..8f02de3 100644
--- a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h
+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h
@@ -281,6 +281,7 @@
#if ENABLE(VIDEO_PRESENTATION_MODE)
void prepareForVideoFullscreen() final;
+ bool canEnterVideoFullscreen() const final;
bool supportsVideoFullscreen(WebCore::HTMLMediaElementEnums::VideoFullscreenMode) final;
bool supportsVideoFullscreenStandby() final;
void setMockVideoPresentationModeEnabled(bool) final;
diff --git a/Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.h b/Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.h
index e3502ba..b27a80f 100644
--- a/Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.h
+++ b/Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.h
@@ -124,6 +124,7 @@
void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override;
// Interface to WebChromeClient
+ bool canEnterVideoFullscreen() const;
bool supportsVideoFullscreen(WebCore::HTMLMediaElementEnums::VideoFullscreenMode) const;
bool supportsVideoFullscreenStandby() const;
void enterVideoFullscreenForVideoElement(WebCore::HTMLVideoElement&, WebCore::HTMLMediaElementEnums::VideoFullscreenMode, bool standby);
@@ -166,6 +167,8 @@
void fullscreenModeChanged(PlaybackSessionContextIdentifier, WebCore::HTMLMediaElementEnums::VideoFullscreenMode);
void fullscreenMayReturnToInline(PlaybackSessionContextIdentifier, bool isPageVisible);
void requestRouteSharingPolicyAndContextUID(PlaybackSessionContextIdentifier, Messages::VideoFullscreenManager::RequestRouteSharingPolicyAndContextUIDAsyncReply&&);
+
+ void setCurrentlyInFullscreen(VideoFullscreenInterfaceContext&, bool);
WebPage* m_page;
Ref<PlaybackSessionManager> m_playbackSessionManager;
@@ -174,6 +177,7 @@
PlaybackSessionContextIdentifier m_controlsManagerContextId;
HashMap<PlaybackSessionContextIdentifier, int> m_clientCounts;
WeakPtr<WebCore::HTMLVideoElement> m_videoElementInPictureInPicture;
+ bool m_currentlyInFullscreen { false };
};
} // namespace WebKit
diff --git a/Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.mm b/Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.mm
index 0aa05b0..0878095 100644
--- a/Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.mm
+++ b/Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.mm
@@ -229,6 +229,15 @@
#pragma mark Interface to ChromeClient:
+bool VideoFullscreenManager::canEnterVideoFullscreen() const
+{
+#if PLATFORM(IOS)
+ if (m_currentlyInFullscreen)
+ return false;
+#endif
+ return true;
+}
+
bool VideoFullscreenManager::supportsVideoFullscreen(WebCore::HTMLMediaElementEnums::VideoFullscreenMode mode) const
{
#if PLATFORM(IOS_FAMILY)
@@ -260,6 +269,18 @@
{
ASSERT(m_page);
ASSERT(standby || mode != HTMLMediaElementEnums::VideoFullscreenModeNone);
+
+#if PLATFORM(IOS)
+ auto allowLayeredFullscreenVideos = videoElement.document().quirks().allowLayeredFullscreenVideos();
+ if (m_currentlyInFullscreen
+ && mode == HTMLMediaElementEnums::VideoFullscreenModeStandard
+ && !allowLayeredFullscreenVideos) {
+ LOG(Fullscreen, "VideoFullscreenManager::enterVideoFullscreenForVideoElement(%p) already in fullscreen, aborting", this);
+ ASSERT_NOT_REACHED();
+ return;
+ }
+#endif
+
LOG(Fullscreen, "VideoFullscreenManager::enterVideoFullscreenForVideoElement(%p)", this);
auto contextId = m_playbackSessionManager->contextIdForMediaElement(videoElement);
@@ -279,10 +300,10 @@
auto videoRect = inlineVideoFrame(videoElement);
FloatRect videoLayerFrame = FloatRect(0, 0, videoRect.width(), videoRect.height());
- if (mode != HTMLMediaElementEnums::VideoFullscreenModeNone)
- interface->setTargetIsFullscreen(true);
- else
- interface->setTargetIsFullscreen(false);
+#if PLATFORM(IOS)
+ if (!allowLayeredFullscreenVideos)
+#endif
+ setCurrentlyInFullscreen(*interface, mode != HTMLMediaElementEnums::VideoFullscreenModeNone);
if (mode == HTMLMediaElementEnums::VideoFullscreenModePictureInPicture)
m_videoElementInPictureInPicture = videoElement;
@@ -345,7 +366,7 @@
m_videoElementInPictureInPicture = nullptr;
auto& interface = ensureInterface(contextId);
- interface.setTargetIsFullscreen(false);
+ protectedThis->setCurrentlyInFullscreen(interface, false);
interface.setAnimationState(VideoFullscreenInterfaceContext::AnimationType::FromFullscreen);
completionHandler(true);
});
@@ -364,7 +385,7 @@
auto contextId = m_videoElements.get(&videoElement);
auto& interface = ensureInterface(contextId);
- interface.setTargetIsFullscreen(false);
+ setCurrentlyInFullscreen(interface, false);
// didCleanupFullscreen() will call removeClientForContext() on Mac
#if PLATFORM(IOS_FAMILY)
@@ -597,6 +618,12 @@
{
ensureModel(contextId).requestRouteSharingPolicyAndContextUID(WTFMove(reply));
}
+
+void VideoFullscreenManager::setCurrentlyInFullscreen(VideoFullscreenInterfaceContext& interface, bool currentlyInFullscreen)
+{
+ interface.setTargetIsFullscreen(currentlyInFullscreen);
+ m_currentlyInFullscreen = currentlyInFullscreen;
+}
void VideoFullscreenManager::setVideoLayerFrameFenced(PlaybackSessionContextIdentifier contextId, WebCore::FloatRect bounds, const WTF::MachSendRight& machSendRight)
{
diff --git a/Source/WebKitLegacy/mac/WebCoreSupport/WebChromeClient.h b/Source/WebKitLegacy/mac/WebCoreSupport/WebChromeClient.h
index cf3cef5..4b4f156 100644
--- a/Source/WebKitLegacy/mac/WebCoreSupport/WebChromeClient.h
+++ b/Source/WebKitLegacy/mac/WebCoreSupport/WebChromeClient.h
@@ -207,6 +207,7 @@
#endif
#if ENABLE(VIDEO)
+ bool canEnterVideoFullscreen() const final;
bool supportsVideoFullscreen(WebCore::HTMLMediaElementEnums::VideoFullscreenMode) final;
#if ENABLE(VIDEO_PRESENTATION_MODE)
void setMockVideoPresentationModeEnabled(bool) final;
diff --git a/Source/WebKitLegacy/mac/WebCoreSupport/WebChromeClient.mm b/Source/WebKitLegacy/mac/WebCoreSupport/WebChromeClient.mm
index b4fc500..936a2fc 100644
--- a/Source/WebKitLegacy/mac/WebCoreSupport/WebChromeClient.mm
+++ b/Source/WebKitLegacy/mac/WebCoreSupport/WebChromeClient.mm
@@ -944,6 +944,15 @@
#if ENABLE(VIDEO)
+bool WebChromeClient::canEnterVideoFullscreen() const
+{
+#if !PLATFORM(IOS_FAMILY) || HAVE(AVKIT)
+ return true;
+#else
+ return false;
+#endif
+}
+
bool WebChromeClient::supportsVideoFullscreen(HTMLMediaElementEnums::VideoFullscreenMode)
{
#if !PLATFORM(IOS_FAMILY) || HAVE(AVKIT)