зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1546954 - Refactor player.js to break up large anonymous functions into smaller pieces. r=JSON_voorhees
Differential Revision: https://phabricator.services.mozilla.com/D37885 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
3ff0a02c54
Коммит
47499265e5
|
@ -51,16 +51,16 @@ var PictureInPicture = {
|
|||
break;
|
||||
}
|
||||
case "PictureInPicture:Playing": {
|
||||
let controls = this.weakPipControls && this.weakPipControls.get();
|
||||
if (controls) {
|
||||
controls.classList.add("playing");
|
||||
let player = this.weakPipPlayer && this.weakPipPlayer.get();
|
||||
if (player) {
|
||||
player.setIsPlayingState(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "PictureInPicture:Paused": {
|
||||
let controls = this.weakPipControls && this.weakPipControls.get();
|
||||
if (controls) {
|
||||
controls.classList.remove("playing");
|
||||
let player = this.weakPipPlayer && this.weakPipPlayer.get();
|
||||
if (player) {
|
||||
player.setIsPlayingState(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -131,16 +131,14 @@ var PictureInPicture = {
|
|||
let parentWin = browser.ownerGlobal;
|
||||
this.browser = browser;
|
||||
let win = await this.openPipWindow(parentWin, videoData);
|
||||
let controls = win.document.getElementById("controls");
|
||||
this.weakPipControls = Cu.getWeakReference(controls);
|
||||
if (videoData.playing) {
|
||||
controls.classList.add("playing");
|
||||
}
|
||||
this.weakPipPlayer = Cu.getWeakReference(win);
|
||||
win.setIsPlayingState(videoData.playing);
|
||||
|
||||
// set attribute which shows pip icon in tab
|
||||
let tab = parentWin.gBrowser.getTabForBrowser(browser);
|
||||
tab.setAttribute("pictureinpicture", true);
|
||||
|
||||
win.setupPlayer(gNextWindowID.toString(), browser, videoData);
|
||||
win.setupPlayer(gNextWindowID.toString(), browser);
|
||||
gNextWindowID++;
|
||||
},
|
||||
|
||||
|
@ -162,7 +160,7 @@ var PictureInPicture = {
|
|||
);
|
||||
|
||||
this.clearPipTabIcon();
|
||||
delete this.weakPipControls;
|
||||
delete this.weakPipPlayer;
|
||||
delete this.browser;
|
||||
},
|
||||
|
||||
|
|
|
@ -14,88 +14,221 @@ const { DeferredTask } = ChromeUtils.import(
|
|||
const CONTROLS_FADE_TIMEOUT_MS = 3000;
|
||||
const RESIZE_DEBOUNCE_RATE_MS = 500;
|
||||
|
||||
async function setupPlayer(id, originatingBrowser, videoData) {
|
||||
let holder = document.querySelector(".player-holder");
|
||||
let browser = document.getElementById("browser");
|
||||
browser.remove();
|
||||
/**
|
||||
* Public function to be called from PictureInPicture.jsm. This is the main
|
||||
* entrypoint for initializing the player window.
|
||||
*
|
||||
* @param id (Number)
|
||||
* A unique numeric ID for the window, used for Telemetry Events.
|
||||
* @param originatingBrowser (xul:browser)
|
||||
* The <xul:browser> that the Picture-in-Picture video is coming from.
|
||||
*/
|
||||
function setupPlayer(id, originatingBrowser) {
|
||||
Player.init(id, originatingBrowser);
|
||||
}
|
||||
|
||||
browser.setAttribute("nodefaultsrc", "true");
|
||||
browser.sameProcessAsFrameLoader = originatingBrowser.frameLoader;
|
||||
holder.appendChild(browser);
|
||||
/**
|
||||
* Public function to be called from PictureInPicture.jsm. This update the
|
||||
* controls based on whether or not the video is playing.
|
||||
*
|
||||
* @param isPlaying (Boolean)
|
||||
* True if the Picture-in-Picture video is playing.
|
||||
*/
|
||||
function setIsPlayingState(isPlaying) {
|
||||
Player.isPlaying = isPlaying;
|
||||
}
|
||||
|
||||
browser.loadURI("about:blank", {
|
||||
triggeringPrincipal: originatingBrowser.contentPrincipal,
|
||||
});
|
||||
/**
|
||||
* The Player object handles initializing the player, holds state, and handles
|
||||
* events for updating state.
|
||||
*/
|
||||
let Player = {
|
||||
WINDOW_EVENTS: ["click", "mouseout", "resize", "unload"],
|
||||
mm: null,
|
||||
/**
|
||||
* Used for resizing Telemetry to avoid recording an event for every resize
|
||||
* event. Instead, we wait until RESIZE_DEBOUNCE_RATE_MS has passed since the
|
||||
* last resize event before recording.
|
||||
*/
|
||||
resizeDebouncer: null,
|
||||
/**
|
||||
* Used for window movement Telemetry to determine if the player window has
|
||||
* moved since the last time we checked.
|
||||
*/
|
||||
lastScreenX: -1,
|
||||
lastScreenY: -1,
|
||||
id: -1,
|
||||
|
||||
let mm = browser.frameLoader.messageManager;
|
||||
mm.sendAsyncMessage("PictureInPicture:SetupPlayer");
|
||||
/**
|
||||
* Initializes the player browser, and sets up the initial state.
|
||||
*
|
||||
* @param id (Number)
|
||||
* A unique numeric ID for the window, used for Telemetry Events.
|
||||
* @param originatingBrowser (xul:browser)
|
||||
* The <xul:browser> that the Picture-in-Picture video is coming from.
|
||||
*/
|
||||
init(id, originatingBrowser) {
|
||||
this.id = id;
|
||||
|
||||
document.getElementById("play").addEventListener("click", () => {
|
||||
mm.sendAsyncMessage("PictureInPicture:Play");
|
||||
});
|
||||
let holder = document.querySelector(".player-holder");
|
||||
let browser = document.getElementById("browser");
|
||||
browser.remove();
|
||||
|
||||
document.getElementById("pause").addEventListener("click", () => {
|
||||
mm.sendAsyncMessage("PictureInPicture:Pause");
|
||||
});
|
||||
browser.setAttribute("nodefaultsrc", "true");
|
||||
browser.sameProcessAsFrameLoader = originatingBrowser.frameLoader;
|
||||
holder.appendChild(browser);
|
||||
|
||||
document.getElementById("unpip").addEventListener("click", () => {
|
||||
PictureInPicture.focusTabAndClosePip();
|
||||
});
|
||||
browser.loadURI("about:blank", {
|
||||
triggeringPrincipal: originatingBrowser.contentPrincipal,
|
||||
});
|
||||
|
||||
// If the content process hosting the video crashes, let's
|
||||
// just close the window for now.
|
||||
browser.addEventListener("oop-browser-crashed", () => {
|
||||
PictureInPicture.closePipWindow({ reason: "browser-crash" });
|
||||
});
|
||||
this.mm = browser.frameLoader.messageManager;
|
||||
this.mm.sendAsyncMessage("PictureInPicture:SetupPlayer");
|
||||
|
||||
let close = document.getElementById("close");
|
||||
close.addEventListener("click", () => {
|
||||
PictureInPicture.closePipWindow({ reason: "close-button" });
|
||||
});
|
||||
for (let eventType of this.WINDOW_EVENTS) {
|
||||
addEventListener(eventType, this);
|
||||
}
|
||||
|
||||
document.getElementById("controls").setAttribute("showing", true);
|
||||
setTimeout(() => {
|
||||
document.getElementById("controls").removeAttribute("showing");
|
||||
}, CONTROLS_FADE_TIMEOUT_MS);
|
||||
// If the content process hosting the video crashes, let's
|
||||
// just close the window for now.
|
||||
browser.addEventListener("oop-browser-crashed", this);
|
||||
|
||||
Services.telemetry.setEventRecordingEnabled("pictureinpicture", true);
|
||||
// Show the controls immediately, but set them up to fade out after
|
||||
// CONTROLS_FADE_TIMEOUT_MS if the mouse isn't hovering them.
|
||||
this.controls.setAttribute("showing", true);
|
||||
setTimeout(() => {
|
||||
this.controls.removeAttribute("showing");
|
||||
}, CONTROLS_FADE_TIMEOUT_MS);
|
||||
|
||||
let resizeDebouncer = new DeferredTask(() => {
|
||||
Services.telemetry.recordEvent("pictureinpicture", "resize", "player", id, {
|
||||
Services.telemetry.setEventRecordingEnabled("pictureinpicture", true);
|
||||
|
||||
this.resizeDebouncer = new DeferredTask(() => {
|
||||
this.recordEvent("resize", {
|
||||
width: window.outerWidth.toString(),
|
||||
height: window.outerHeight.toString(),
|
||||
});
|
||||
}, RESIZE_DEBOUNCE_RATE_MS);
|
||||
|
||||
this.lastScreenX = window.screenX;
|
||||
this.lastScreenY = window.screenY;
|
||||
|
||||
this.recordEvent("create", {
|
||||
width: window.outerWidth.toString(),
|
||||
height: window.outerHeight.toString(),
|
||||
screenX: window.screenX.toString(),
|
||||
screenY: window.screenY.toString(),
|
||||
});
|
||||
}, RESIZE_DEBOUNCE_RATE_MS);
|
||||
},
|
||||
|
||||
addEventListener("resize", e => {
|
||||
resizeDebouncer.disarm();
|
||||
resizeDebouncer.arm();
|
||||
});
|
||||
uninit() {
|
||||
this.resizeDebouncer.disarm();
|
||||
PictureInPicture.unload(window);
|
||||
},
|
||||
|
||||
let lastScreenX = window.screenX;
|
||||
let lastScreenY = window.screenY;
|
||||
handleEvent(event) {
|
||||
switch (event.type) {
|
||||
case "click": {
|
||||
this.onClick(event);
|
||||
break;
|
||||
}
|
||||
|
||||
addEventListener("mouseout", e => {
|
||||
if (window.screenX != lastScreenX || window.screenY != lastScreenY) {
|
||||
Services.telemetry.recordEvent("pictureinpicture", "move", "player", id, {
|
||||
case "mouseout": {
|
||||
this.onMouseOut(event);
|
||||
break;
|
||||
}
|
||||
|
||||
case "oop-browser-crashed": {
|
||||
PictureInPicture.closePipWindow({ reason: "browser-crash" });
|
||||
break;
|
||||
}
|
||||
|
||||
case "resize": {
|
||||
this.onResize(event);
|
||||
break;
|
||||
}
|
||||
|
||||
case "unload": {
|
||||
this.uninit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onClick(event) {
|
||||
switch (event.target.id) {
|
||||
case "close": {
|
||||
PictureInPicture.closePipWindow({ reason: "close-button" });
|
||||
break;
|
||||
}
|
||||
|
||||
case "play": {
|
||||
this.mm.sendAsyncMessage("PictureInPicture:Play");
|
||||
break;
|
||||
}
|
||||
|
||||
case "pause": {
|
||||
this.mm.sendAsyncMessage("PictureInPicture:Pause");
|
||||
break;
|
||||
}
|
||||
|
||||
case "unpip": {
|
||||
PictureInPicture.focusTabAndClosePip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onMouseOut(event) {
|
||||
if (
|
||||
window.screenX != this.lastScreenX ||
|
||||
window.screenY != this.lastScreenY
|
||||
) {
|
||||
this.recordEvent("move", {
|
||||
screenX: window.screenX.toString(),
|
||||
screenY: window.screenY.toString(),
|
||||
});
|
||||
}
|
||||
|
||||
lastScreenX = window.screenX;
|
||||
lastScreenY = window.screenY;
|
||||
});
|
||||
this.lastScreenX = window.screenX;
|
||||
this.lastScreenY = window.screenY;
|
||||
},
|
||||
|
||||
Services.telemetry.recordEvent("pictureinpicture", "create", "player", id, {
|
||||
width: window.outerWidth.toString(),
|
||||
height: window.outerHeight.toString(),
|
||||
screenX: window.screenX.toString(),
|
||||
screenY: window.screenY.toString(),
|
||||
});
|
||||
onResize(event) {
|
||||
this.resizeDebouncer.disarm();
|
||||
this.resizeDebouncer.arm();
|
||||
},
|
||||
|
||||
window.addEventListener("unload", () => {
|
||||
resizeDebouncer.disarm();
|
||||
PictureInPicture.unload(window);
|
||||
});
|
||||
}
|
||||
get controls() {
|
||||
delete this.controls;
|
||||
return (this.controls = document.getElementById("controls"));
|
||||
},
|
||||
|
||||
_isPlaying: false,
|
||||
/**
|
||||
* isPlaying returns true if the video is currently playing.
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
get isPlaying() {
|
||||
return this._isPlaying;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set isPlaying to true if the video is playing, false otherwise. This will
|
||||
* update the internal state and displayed controls.
|
||||
*/
|
||||
set isPlaying(isPlaying) {
|
||||
this._isPlaying = isPlaying;
|
||||
this.controls.classList.toggle("playing", isPlaying);
|
||||
},
|
||||
|
||||
recordEvent(type, args) {
|
||||
Services.telemetry.recordEvent(
|
||||
"pictureinpicture",
|
||||
type,
|
||||
"player",
|
||||
this.id,
|
||||
args
|
||||
);
|
||||
},
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче