Loading dom/media/PictureInPictureWindow.cpp +45 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,11 @@ int32_t PictureInPictureWindow::Width() const { if (!IsStateOpened()) { return 0; } RefPtr<HTMLVideoElement> videoElement = mAssociatedVideoElement.get(); if (videoElement && videoElement->OwnerDoc()->ShouldResistFingerprinting( RFPTarget::ScreenRect)) { return VideoSizeForRFP().width; } return mWidth; } Loading @@ -57,14 +62,54 @@ int32_t PictureInPictureWindow::Height() const { if (!IsStateOpened()) { return 0; } RefPtr<HTMLVideoElement> videoElement = mAssociatedVideoElement.get(); if (videoElement && videoElement->OwnerDoc()->ShouldResistFingerprinting( RFPTarget::ScreenRect)) { return VideoSizeForRFP().height; } return mHeight; } gfx::IntSize PictureInPictureWindow::VideoSizeForRFP() const { RefPtr<HTMLVideoElement> videoElement = mAssociatedVideoElement.get(); if (!videoElement) { return {0, 0}; } // From PictureInPicture.sys.mjs: "The Picture in Picture window will be a // maximum of a quarter of the screen height, and a third of the screen // width.". // Pretend we are maximizing the video in a 1920x1080 display. const uint32_t maxWidth = 1920 / 3; const uint32_t maxHeight = 1080 / 4; uint32_t width = videoElement->VideoWidth(); uint32_t height = videoElement->VideoHeight(); if ((height > maxHeight || width > maxWidth) && height > 0) { double aspectRatio = static_cast<double>(width) / height; if (width >= height) { width = maxWidth; height = static_cast<uint32_t>(round(maxWidth / aspectRatio)); } else { height = maxHeight; width = static_cast<uint32_t>(round(maxHeight * aspectRatio)); } } return {width, height}; } void PictureInPictureWindow::NotifyDimensionsChanged(int32_t aWidth, int32_t aHeight) { mWidth = aWidth; mHeight = aHeight; RefPtr<HTMLVideoElement> videoElement = mAssociatedVideoElement.get(); if (videoElement && videoElement->OwnerDoc()->ShouldResistFingerprinting( RFPTarget::ScreenRect)) { // With RFP, we spoof the window size to a fixed size that depends on the // video, therefore it does not make sense to trigger a resize event. return; } // When the size of a Picture-in-Picture window pipWindow changes, // the user agent MUST queue a task to fire an event named resize at // pipWindow. Loading dom/media/PictureInPictureWindow.h +2 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,8 @@ class PictureInPictureWindow final : public DOMEventTargetHelper { private: bool IsStateOpened() const { return mOpened; } gfx::IntSize VideoSizeForRFP() const; WeakPtr<HTMLVideoElement> mAssociatedVideoElement; int32_t mWidth = 0; int32_t mHeight = 0; Loading dom/media/mediaelement/HTMLVideoElement.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -315,7 +315,7 @@ bool HTMLVideoElement::IsInteractiveHTMLContent() const { HTMLMediaElement::IsInteractiveHTMLContent(); } gfx::IntSize HTMLVideoElement::GetVideoIntrinsicDimensions() { gfx::IntSize HTMLVideoElement::GetVideoIntrinsicDimensions() const { const auto& sz = mMediaInfo.mVideo.mDisplay; // Prefer the size of the container as it's more up to date. Loading @@ -324,7 +324,7 @@ gfx::IntSize HTMLVideoElement::GetVideoIntrinsicDimensions() { .valueOr(sz); } uint32_t HTMLVideoElement::VideoWidth() { uint32_t HTMLVideoElement::VideoWidth() const { if (!HasVideo()) { return 0; } Loading @@ -336,7 +336,7 @@ uint32_t HTMLVideoElement::VideoWidth() { return size.width; } uint32_t HTMLVideoElement::VideoHeight() { uint32_t HTMLVideoElement::VideoHeight() const { if (!HasVideo()) { return 0; } Loading dom/media/mediaelement/HTMLVideoElement.h +3 −3 Original line number Diff line number Diff line Loading @@ -96,9 +96,9 @@ class HTMLVideoElement final : public HTMLMediaElement { SetUnsignedIntAttr(nsGkAtoms::height, aValue, 0, aRv); } uint32_t VideoWidth(); uint32_t VideoWidth() const; uint32_t VideoHeight(); uint32_t VideoHeight() const; VideoRotation RotationDegrees() const { return mMediaInfo.mVideo.mRotation; } Loading Loading @@ -179,7 +179,7 @@ class HTMLVideoElement final : public HTMLMediaElement { void CreateVideoWakeLockIfNeeded(); void ReleaseVideoWakeLockIfExists(); gfx::IntSize GetVideoIntrinsicDimensions(); gfx::IntSize GetVideoIntrinsicDimensions() const; RefPtr<WakeLock> mScreenWakeLock; Loading toolkit/components/pictureinpicture/tests/browser.toml +2 −0 Original line number Diff line number Diff line Loading @@ -158,6 +158,8 @@ support-files = ["test-page-with-nan-video-duration.html"] ["browser_removeVideoElement.js"] ["browser_resistFingerprinting.js"] ["browser_resizeVideo.js"] skip-if = [ "os == 'linux' && os_version == '24.04' && arch == 'x86_64' && display == 'x11'", # Bug 1594223 Loading Loading
dom/media/PictureInPictureWindow.cpp +45 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,11 @@ int32_t PictureInPictureWindow::Width() const { if (!IsStateOpened()) { return 0; } RefPtr<HTMLVideoElement> videoElement = mAssociatedVideoElement.get(); if (videoElement && videoElement->OwnerDoc()->ShouldResistFingerprinting( RFPTarget::ScreenRect)) { return VideoSizeForRFP().width; } return mWidth; } Loading @@ -57,14 +62,54 @@ int32_t PictureInPictureWindow::Height() const { if (!IsStateOpened()) { return 0; } RefPtr<HTMLVideoElement> videoElement = mAssociatedVideoElement.get(); if (videoElement && videoElement->OwnerDoc()->ShouldResistFingerprinting( RFPTarget::ScreenRect)) { return VideoSizeForRFP().height; } return mHeight; } gfx::IntSize PictureInPictureWindow::VideoSizeForRFP() const { RefPtr<HTMLVideoElement> videoElement = mAssociatedVideoElement.get(); if (!videoElement) { return {0, 0}; } // From PictureInPicture.sys.mjs: "The Picture in Picture window will be a // maximum of a quarter of the screen height, and a third of the screen // width.". // Pretend we are maximizing the video in a 1920x1080 display. const uint32_t maxWidth = 1920 / 3; const uint32_t maxHeight = 1080 / 4; uint32_t width = videoElement->VideoWidth(); uint32_t height = videoElement->VideoHeight(); if ((height > maxHeight || width > maxWidth) && height > 0) { double aspectRatio = static_cast<double>(width) / height; if (width >= height) { width = maxWidth; height = static_cast<uint32_t>(round(maxWidth / aspectRatio)); } else { height = maxHeight; width = static_cast<uint32_t>(round(maxHeight * aspectRatio)); } } return {width, height}; } void PictureInPictureWindow::NotifyDimensionsChanged(int32_t aWidth, int32_t aHeight) { mWidth = aWidth; mHeight = aHeight; RefPtr<HTMLVideoElement> videoElement = mAssociatedVideoElement.get(); if (videoElement && videoElement->OwnerDoc()->ShouldResistFingerprinting( RFPTarget::ScreenRect)) { // With RFP, we spoof the window size to a fixed size that depends on the // video, therefore it does not make sense to trigger a resize event. return; } // When the size of a Picture-in-Picture window pipWindow changes, // the user agent MUST queue a task to fire an event named resize at // pipWindow. Loading
dom/media/PictureInPictureWindow.h +2 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,8 @@ class PictureInPictureWindow final : public DOMEventTargetHelper { private: bool IsStateOpened() const { return mOpened; } gfx::IntSize VideoSizeForRFP() const; WeakPtr<HTMLVideoElement> mAssociatedVideoElement; int32_t mWidth = 0; int32_t mHeight = 0; Loading
dom/media/mediaelement/HTMLVideoElement.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -315,7 +315,7 @@ bool HTMLVideoElement::IsInteractiveHTMLContent() const { HTMLMediaElement::IsInteractiveHTMLContent(); } gfx::IntSize HTMLVideoElement::GetVideoIntrinsicDimensions() { gfx::IntSize HTMLVideoElement::GetVideoIntrinsicDimensions() const { const auto& sz = mMediaInfo.mVideo.mDisplay; // Prefer the size of the container as it's more up to date. Loading @@ -324,7 +324,7 @@ gfx::IntSize HTMLVideoElement::GetVideoIntrinsicDimensions() { .valueOr(sz); } uint32_t HTMLVideoElement::VideoWidth() { uint32_t HTMLVideoElement::VideoWidth() const { if (!HasVideo()) { return 0; } Loading @@ -336,7 +336,7 @@ uint32_t HTMLVideoElement::VideoWidth() { return size.width; } uint32_t HTMLVideoElement::VideoHeight() { uint32_t HTMLVideoElement::VideoHeight() const { if (!HasVideo()) { return 0; } Loading
dom/media/mediaelement/HTMLVideoElement.h +3 −3 Original line number Diff line number Diff line Loading @@ -96,9 +96,9 @@ class HTMLVideoElement final : public HTMLMediaElement { SetUnsignedIntAttr(nsGkAtoms::height, aValue, 0, aRv); } uint32_t VideoWidth(); uint32_t VideoWidth() const; uint32_t VideoHeight(); uint32_t VideoHeight() const; VideoRotation RotationDegrees() const { return mMediaInfo.mVideo.mRotation; } Loading Loading @@ -179,7 +179,7 @@ class HTMLVideoElement final : public HTMLMediaElement { void CreateVideoWakeLockIfNeeded(); void ReleaseVideoWakeLockIfExists(); gfx::IntSize GetVideoIntrinsicDimensions(); gfx::IntSize GetVideoIntrinsicDimensions() const; RefPtr<WakeLock> mScreenWakeLock; Loading
toolkit/components/pictureinpicture/tests/browser.toml +2 −0 Original line number Diff line number Diff line Loading @@ -158,6 +158,8 @@ support-files = ["test-page-with-nan-video-duration.html"] ["browser_removeVideoElement.js"] ["browser_resistFingerprinting.js"] ["browser_resizeVideo.js"] skip-if = [ "os == 'linux' && os_version == '24.04' && arch == 'x86_64' && display == 'x11'", # Bug 1594223 Loading