<!DOCTYPE html>
<html>
<head>
<title>Picture-in-Picture Window Size Test</title>
</head>
<body>
<video controls preload=auto src='../bigbuck.webm'></video>
</body>
<script>
const video = document.querySelector('video');
// This video is created here in order to be used in
// `secondPictureInPicture()`. Unfortunately, the `requestPictureInPicture()`
// method has to be called during a user activation event handler so it's not
// possible to load the video on-demand.
const secondVideo = document.createElement('video');
secondVideo.src = '../bigbuck.webm';
secondVideo.load();
async function requestPictureInPictureAndDisable() {
const promise = video.requestPictureInPicture();
video.disablePictureInPicture = true;
try {
await promise;
} catch(e) {
return "rejected";
}
return true;
}
async function enterPictureInPicture() {
await _waitForMetadata();
const pip_window = await video.requestPictureInPicture();
// If the video size were 0,0 then this might not be true, but it isn't.
if (pip_window.width == 0 || pip_window.height == 0)
throw '0 is not a good initial size for a PiP window';
pip_window.addEventListener('resize', () => {
// Do not accept zero, and fail the test if so.
if (pip_window.width == 0 || pip_window.height == 0)
throw '0 is not a good updated size for a PiP window';
document.title = 'resized'
}, { once: true });
video.addEventListener('leavepictureinpicture', () => {
document.title = 'leavepictureinpicture';
}, { once: true });
return true;
}
function _waitForMetadata() {
return new Promise(resolve => {
if (video.readyState >= HTMLMediaElement.HAVE_METADATA) {
resolve();
return;
}
video.addEventListener('loadedmetadata', () => {
resolve();
}, { once: true });
});
}
function exitPictureInPicture() {
document.exitPictureInPicture();
}
function isInPictureInPicture() {
return document.pictureInPictureElement == video;
}
function isPaused() {
return video.paused;
}
function secondPictureInPicture() {
secondVideo.requestPictureInPicture();
}
async function ensureVideoIsPlaying() {
await video.play();
return true;
}
async function changeVideoSrc() {
if (video.srcObject) {
video.srcObject.getTracks().forEach(track => track.stop());
video.srcObject = null;
}
video.src = '../bigbuck.webm';
await video.play();
return true;
}
async function changeVideoSrcToMediaStream() {
const canvas = document.createElement('canvas');
canvas.getContext('2d').fillRect(0, 0, canvas.width, canvas.height);
video.srcObject = canvas.captureStream();
await video.play();
return true;
}
async function changeVideoSrcToNoAudioTrackVideo() {
video.src = '../engagement/engagement_no_audio_track.webm';
await video.play();
return true;
}
function addVisibilityChangeEventListener() {
document.addEventListener('visibilitychange', () => {
document.title = document.visibilityState;
});
}
function addPauseEventListener() {
video.addEventListener('pause', () => {
document.title = 'pause';
});
}
function addPlayEventListener() {
video.addEventListener('play', () => {
document.title = 'play';
});
}
function setMediaSessionActionHandler(name) {
navigator.mediaSession.setActionHandler(name, _ => {
document.title = name;
});
}
function unsetMediaSessionActionHandler(name) {
navigator.mediaSession.setActionHandler(name, null);
}
function addPictureInPictureEventListeners() {
video.addEventListener('enterpictureinpicture', () => {
document.title = 'enterpictureinpicture';
});
video.addEventListener('leavepictureinpicture', () => {
document.title = 'leavepictureinpicture';
});
}
function tryToEnterPictureInPictureAfterLeaving() {
video.addEventListener('leavepictureinpicture', () => {
video.requestPictureInPicture()
.then(_ => { document.title = 'entered Picture-in-Picture after leaving'; })
.catch(e => { document.title = 'failed to enter Picture-in-Picture after leaving'; });
});
}
</script>
</html>