Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

/* Any copyright is dedicated to the Public Domain.
"use strict";
async function testResizePip(isRFP, src) {
clearSavedPosition();
await BrowserTestUtils.withNewTab(
{
url: TEST_PAGE,
gBrowser,
},
async browser => {
let videoID = "with-controls";
let [width, height, pipWidth, pipHeight] = await SpecialPowers.spawn(
browser,
[videoID, src],
async (videoID, src) => {
content.window.resizeEverCalled = false;
let video = content.wrappedJSObject.document.getElementById(videoID);
if (src) {
let { promise, resolve } = Promise.withResolvers();
video.addEventListener("canplay", resolve);
video.src = src;
await promise;
}
content.document.notifyUserGestureActivation();
let pip = await video.requestPictureInPicture();
pip.addEventListener(
"resize",
() => (content.window.resizeEverCalled = true)
);
return [video.width, video.height, pip.width, pip.height];
}
);
info(
`Video size is ${width}x${height}. PiP size is ${pipWidth}x${pipHeight}`
);
const { PictureInPicture } = ChromeUtils.importESModule(
"moz-src:///toolkit/components/pictureinpicture/PictureInPicture.sys.mjs"
);
let pipWindow = PictureInPicture.apiPipWindow?.get();
Assert.ok(pipWindow, "We found the chrome PiP window.");
let pipBrowser = pipWindow.document.getElementById("browser");
await SpecialPowers.spawn(pipBrowser, [], async () => {
let {
promise: setupPromise,
resolve: setupResolve,
reject: setupReject,
} = Promise.withResolvers();
content.resizePromise = new Promise(resizeResolve => {
let firstObserved = false;
// Scope the observer to the content because we need to block on the
// setup before resizing, therefore we need two separate promises and
// the observer needs to outlive this spawn call.
content.observer = new content.ResizeObserver(() => {
// Attaching the element will trigger a first call to this callback.
// Therefore, we need to ignore it.
if (firstObserved) {
resizeResolve();
} else {
firstObserved = true;
setupResolve();
}
});
let video = content.document.querySelector("video");
if (video) {
content.observer.observe(video);
} else {
setupReject(new Error("Video not found in the PiP window."));
}
});
await setupPromise;
});
pipWindow.resizeTo(pipWidth * 2, pipHeight * 2);
await SpecialPowers.spawn(pipBrowser, [], async () => {
await content.resizePromise;
content.observer.disconnect();
await new Promise(resolve => content.requestAnimationFrame(resolve));
});
let [pipWidthAfter, pipHeightAfter] = await SpecialPowers.spawn(
browser,
[videoID],
async videoID => {
let video = content.wrappedJSObject.document.getElementById(videoID);
// We already have the window, no need to simulate another user
// interaction.
let pip = await video.requestPictureInPicture();
return [pip.width, pip.height];
}
);
info(
`PiP size after resizing ${isRFP ? "with" : "without"} RFP ` +
`is ${pipWidthAfter}x${pipHeightAfter}`
);
if (isRFP) {
Assert.equal(pipWidth, pipWidthAfter, "RFP spoofed PiP width.");
Assert.equal(pipHeight, pipHeightAfter, "RFP spoofed PiP height.");
} else {
Assert.notEqual(
pipWidth,
pipWidthAfter,
"After resizing the PiP window, PiP width was updated."
);
Assert.notEqual(
pipHeight,
pipHeightAfter,
"After resizing the PiP window, PiP height was updated."
);
}
let everResized = await SpecialPowers.spawn(browser, [], async () => {
await content.document.exitPictureInPicture();
return content.window.resizeEverCalled;
});
Assert.equal(
everResized,
!isRFP,
`We expected the resize handler ${isRFP ? "not " : ""}to be ever called.`
);
}
);
}
add_task(async function test_video_pip_size() {
await testResizePip(false, "test-video.mp4");
});
add_task(async function test_video_pip_size_vertical() {
await testResizePip(false, "test-video-vertical.mp4");
});
add_task(async function test_video_pip_size_rfp() {
await SpecialPowers.pushPrefEnv({
set: [["privacy.resistFingerprinting", true]],
});
await testResizePip(true, "test-video.mp4");
await SpecialPowers.popPrefEnv();
});
add_task(async function test_video_pip_size_rfp_vertical() {
await SpecialPowers.pushPrefEnv({
set: [["privacy.resistFingerprinting", true]],
});
await testResizePip(true, "test-video-vertical.mp4");
await SpecialPowers.popPrefEnv();
});