Bug 1532773 - Add player controls for PictureInPicture. r=mconley

Differential Revision: https://phabricator.services.mozilla.com/D25435

--HG--
extra : moz-landing-system : lando
This commit is contained in:
meandave 2019-04-03 15:10:16 +00:00
Родитель 22ed97f045
Коммит 70cf4e4c3c
12 изменённых файлов: 190 добавлений и 1 удалений

Просмотреть файл

@ -517,6 +517,8 @@ const listeners = {
"FormValidation:HidePopup": ["FormValidationHandler"],
"PictureInPicture:Request": ["PictureInPicture"],
"PictureInPicture:Close": ["PictureInPicture"],
"PictureInPicture:Playing": ["PictureInPicture"],
"PictureInPicture:Paused": ["PictureInPicture"],
"Prompt:Open": ["RemotePrompt"],
"Reader:FaviconRequest": ["ReaderParent"],
"Reader:UpdateReaderButton": ["ReaderParent"],

Просмотреть файл

@ -16,6 +16,10 @@ var gWeakVideo = null;
var gWeakPlayerContent = null;
class PictureInPictureChild extends ActorChild {
static videoIsPlaying(video) {
return !!(video.currentTime > 0 && !video.paused && !video.ended && video.readyState > 2);
}
handleEvent(event) {
switch (event.type) {
case "MozTogglePictureInPicture": {
@ -30,6 +34,14 @@ class PictureInPictureChild extends ActorChild {
this.closePictureInPicture();
break;
}
case "play": {
this.mm.sendAsyncMessage("PictureInPicture:Playing");
break;
}
case "pause": {
this.mm.sendAsyncMessage("PictureInPicture:Paused");
break;
}
}
}
@ -73,6 +85,7 @@ class PictureInPictureChild extends ActorChild {
gWeakVideo = Cu.getWeakReference(video);
this.mm.sendAsyncMessage("PictureInPicture:Request", {
playing: PictureInPictureChild.videoIsPlaying(video),
videoHeight: video.videoHeight,
videoWidth: video.videoWidth,
});
@ -128,6 +141,14 @@ class PictureInPictureChild extends ActorChild {
this.setupPlayer();
break;
}
case "PictureInPicture:Play": {
this.play();
break;
}
case "PictureInPicture:Pause": {
this.pause();
break;
}
}
}
@ -140,6 +161,8 @@ class PictureInPictureChild extends ActorChild {
let originatingWindow = originatingVideo.ownerGlobal;
if (originatingWindow) {
originatingWindow.addEventListener("pagehide", this);
originatingVideo.addEventListener("play", this);
originatingVideo.addEventListener("pause", this);
}
}
@ -153,6 +176,8 @@ class PictureInPictureChild extends ActorChild {
let originatingWindow = originatingVideo.ownerGlobal;
if (originatingWindow) {
originatingWindow.removeEventListener("pagehide", this);
originatingVideo.removeEventListener("play", this);
originatingVideo.removeEventListener("pause", this);
}
}
@ -224,4 +249,18 @@ class PictureInPictureChild extends ActorChild {
gWeakPlayerContent = Cu.getWeakReference(this.content);
}
play() {
let video = this.weakVideo;
if (video) {
video.play();
}
}
pause() {
let video = this.weakVideo;
if (video) {
video.pause();
}
}
}

Просмотреть файл

@ -35,9 +35,25 @@ var PictureInPicture = {
this.closePipWindow();
break;
}
case "PictureInPicture:Playing": {
this.weakPipControls.classList.add("playing");
break;
}
case "PictureInPicture:Paused": {
this.weakPipControls.classList.remove("playing");
break;
}
}
},
focusTabAndClosePip() {
let gBrowser = this.browser.ownerGlobal.gBrowser;
let tab = gBrowser.getTabForBrowser(this.browser);
gBrowser.selectedTab = tab;
this.unload();
this.closePipWindow();
},
/**
* Find and close any pre-existing Picture in Picture windows.
*/
@ -48,7 +64,6 @@ var PictureInPicture = {
if (win.closed) {
continue;
}
win.close();
}
},
@ -74,12 +89,26 @@ var PictureInPicture = {
* the player component inside it has finished loading.
*/
async handlePictureInPictureRequest(browser, videoData) {
this.browser = browser;
let parentWin = browser.ownerGlobal;
this.closePipWindow();
let win = await this.openPipWindow(parentWin, videoData);
this.weakPipControls = win.document.getElementById("controls");
if (videoData.playing) {
this.weakPipControls.classList.add("playing");
}
win.setupPlayer(browser, videoData);
},
/**
* unload event has been called in player.js, cleanup our preserved
* browser object.
*/
unload() {
delete this.weakPipControls;
delete this.browser;
},
/**
* Open a Picture in Picture window on the same screen as parentWin,
* sized based on the information in videoData.

Просмотреть файл

@ -2,6 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const {PictureInPicture} = ChromeUtils.import("resource://gre/modules/PictureInPicture.jsm");
async function setupPlayer(originatingBrowser, videoData) {
window.windowUtils.setChromeMargin(0, 0, 0, 0);
let holder = document.querySelector(".player-holder");
@ -19,12 +21,33 @@ async function setupPlayer(originatingBrowser, videoData) {
let mm = browser.frameLoader.messageManager;
mm.sendAsyncMessage("PictureInPicture:SetupPlayer");
document.getElementById("play").addEventListener("click", () => {
mm.sendAsyncMessage("PictureInPicture:Play");
});
document.getElementById("pause").addEventListener("click", () => {
mm.sendAsyncMessage("PictureInPicture:Pause");
});
document.getElementById("unpip").addEventListener("click", () => {
PictureInPicture.focusTabAndClosePip();
});
// If the content process hosting the video crashes, let's
// just close the window for now.
browser.addEventListener("oop-browser-crashed", () => {
window.close();
});
browser.addEventListener("unload", () => {
PictureInPicture.unload();
});
await window.promiseDocumentFlushed(() => {});
browser.style.MozWindowDragging = "drag";
let close = document.getElementById("close");
close.addEventListener("click", () => {
window.close();
});
}

Просмотреть файл

@ -21,5 +21,11 @@
<div class="player-holder">
<xul:browser type="content" primary="true" remote="true" remoteType="web" id="browser"></xul:browser>
</div>
<div id="controls">
<div id="close" class="control-item"></div>
<div id="unpip" class="control-item"></div>
<div id="pause" class="control-item"></div>
<div id="play" class="control-item"></div>
</div>
</body>
</html>

Просмотреть файл

@ -225,6 +225,8 @@ let ACTORS = {
messages: [
"PictureInPicture:SetupPlayer",
"PictureInPicture:Play",
"PictureInPicture:Pause",
],
},
},

Просмотреть файл

@ -32,6 +32,7 @@ toolkit.jar:
skin/classic/global/icons/check.svg (../../shared/icons/check.svg)
skin/classic/global/icons/check-partial.svg (../../shared/icons/check-partial.svg)
skin/classic/global/icons/close.svg (../../shared/icons/close.svg)
skin/classic/global/pictureinpicture/close-pip.svg (../../shared/pictureinpicture/close-pip.svg)
skin/classic/global/icons/columnpicker.svg (../../shared/icons/columnpicker.svg)
skin/classic/global/icons/delete.svg (../../shared/icons/delete.svg)
skin/classic/global/icons/error.svg (../../shared/icons/error.svg)
@ -44,6 +45,8 @@ toolkit.jar:
skin/classic/global/icons/loading@2x.png (../../shared/icons/loading@2x.png)
skin/classic/global/icons/more.svg (../../shared/icons/more.svg)
skin/classic/global/icons/performance.svg (../../shared/icons/performance.svg)
skin/classic/global/pictureinpicture/pause.svg (../../shared/pictureinpicture/pause.svg)
skin/classic/global/pictureinpicture/play.svg (../../shared/pictureinpicture/play.svg)
skin/classic/global/icons/resizer.svg (../../shared/icons/resizer.svg)
skin/classic/global/icons/shortcut.svg (../../shared/icons/shortcut.svg)
skin/classic/global/icons/spinner-arrow-down.svg (../../shared/icons/spinner-arrow-down.svg)
@ -54,6 +57,7 @@ toolkit.jar:
skin/classic/global/icons/arrow-dropdown-12.svg (../../shared/icons/arrow-dropdown-12.svg)
skin/classic/global/icons/arrow-dropdown-16.svg (../../shared/icons/arrow-dropdown-16.svg)
skin/classic/global/icons/arrow-up-12.svg (../../shared/icons/arrow-up-12.svg)
skin/classic/global/pictureinpicture/unpip.svg (../../shared/pictureinpicture/unpip.svg)
skin/classic/global/icons/warning.svg (../../shared/icons/warning.svg)
skin/classic/global/illustrations/about-rights.svg (../../shared/illustrations/about-rights.svg)
skin/classic/global/icons/blocked.svg (../../shared/incontent-icons/blocked.svg)

Просмотреть файл

@ -0,0 +1,5 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M9.061 8l3.47-3.47a.75.75 0 0 0-1.061-1.06L8 6.939 4.53 3.47a.75.75 0 1 0-1.06 1.06L6.939 8 3.47 11.47a.75.75 0 1 0 1.06 1.06L8 9.061l3.47 3.47a.75.75 0 0 0 1.06-1.061z"/></svg>

После

Ширина:  |  Высота:  |  Размер: 460 B

Просмотреть файл

@ -0,0 +1,4 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g fill="#F9F9FA" fill-rule="evenodd" fill-opacity=".8"><rect x="3" y="3" width="4" height="10" rx=".5"/><rect x="9" y="3" width="4" height="10" rx=".5"/></g></svg>

После

Ширина:  |  Высота:  |  Размер: 437 B

Просмотреть файл

@ -0,0 +1,4 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="#F9F9FA" d="M4 3.995c0-.55.386-.754.856-.46l6.288 3.93c.473.295.47.776 0 1.07l-6.288 3.93c-.473.295-.856.08-.856-.46v-8.01z"/></svg>

После

Ширина:  |  Высота:  |  Размер: 417 B

Просмотреть файл

@ -2,6 +2,11 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
:root {
--btn-bg-color: rgba(50,50,50,0.55);
--close-btn-bg-color: rgb(211,216,220);
}
body {
margin: 0;
}
@ -14,5 +19,67 @@ body {
}
browser {
-moz-window-dragging: drag;
flex: 1;
}
#controls {
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
}
.control-item {
-moz-window-dragging: no-drag;
background: var(--btn-bg-color);
border-radius: 4px;
bottom: 15px;
cursor: pointer;
height: 15%;
max-height: 32px;
max-width: 32px;
min-height: 16px;
min-width: 16px;
position: absolute;
width: 10%;
}
#close {
background-color: var(--close-btn-bg-color);
background-image: url("chrome://global/skin/pictureinpicture/close-pip.svg");
right: 10px;
top: 10px;
}
#play {
background-image: url("chrome://global/skin/pictureinpicture/play.svg");
display: block;
left: 55%;
}
#pause {
background-image: url("chrome://global/skin/pictureinpicture/pause.svg");
display: none;
left: 55%;
}
.playing #play {
display: none;
}
.playing #pause {
display: block;
}
#unpip {
left: 45%;
}
#unpip {
background-image: url("chrome://global/skin/pictureinpicture/unpip.svg");
background-position: 60%;
background-repeat: no-repeat;
background-size: 80%;
}

Просмотреть файл

@ -0,0 +1,4 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg width="80%" height="80%" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path fill="#FFF" d="M0 0h16v12H0z"/><path d="M30 21h-3V2a1 1 0 0 0-1-1H2a1 1 0 0 0-1 1v24a1 1 0 0 0 1 1h15v3a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-8a1 1 0 0 0-1-1z" stroke="#FFF" stroke-width="2"/><path stroke="#FFF" stroke-width="2" d="M17 21h14v10H17z"/></g></svg>

После

Ширина:  |  Высота:  |  Размер: 594 B