mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 1755748 - Keep PiP tabs in active state. r=mconley,dthayer
Differential Revision: https://phabricator.services.mozilla.com/D140394
This commit is contained in:
parent
3f93068a72
commit
8df33a3b36
@ -63,6 +63,7 @@
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
E10SUtils: "resource://gre/modules/E10SUtils.jsm",
|
||||
PictureInPicture: "resource://gre/modules/PictureInPicture.jsm",
|
||||
});
|
||||
XPCOMUtils.defineLazyServiceGetters(this, {
|
||||
MacSharingService: [
|
||||
@ -5290,7 +5291,8 @@
|
||||
(aBrowser == this.selectedBrowser &&
|
||||
window.windowState != window.STATE_MINIMIZED &&
|
||||
!window.isFullyOccluded) ||
|
||||
this._printPreviewBrowsers.has(aBrowser)
|
||||
this._printPreviewBrowsers.has(aBrowser) ||
|
||||
this.PictureInPicture.isOriginatingBrowser(aBrowser)
|
||||
);
|
||||
},
|
||||
|
||||
|
@ -12,6 +12,7 @@ const { XPCOMUtils } = ChromeUtils.import(
|
||||
);
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
AppConstants: "resource://gre/modules/AppConstants.jsm",
|
||||
PictureInPicture: "resource://gre/modules/PictureInPicture.jsm",
|
||||
Services: "resource://gre/modules/Services.jsm",
|
||||
});
|
||||
|
||||
@ -649,8 +650,7 @@ class AsyncTabSwitcher {
|
||||
let numPending = 0;
|
||||
let numWarming = 0;
|
||||
for (let [tab, state] of this.tabState) {
|
||||
// Skip print preview browsers since they shouldn't affect tab switching.
|
||||
if (this.tabbrowser._printPreviewBrowsers.has(tab.linkedBrowser)) {
|
||||
if (!this.shouldDeactivateDocShell(tab.linkedBrowser)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -726,7 +726,7 @@ class AsyncTabSwitcher {
|
||||
|
||||
// Unload any tabs that can be unloaded.
|
||||
for (let [tab, state] of this.tabState) {
|
||||
if (this.tabbrowser._printPreviewBrowsers.has(tab.linkedBrowser)) {
|
||||
if (!this.shouldDeactivateDocShell(tab.linkedBrowser)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -852,8 +852,7 @@ class AsyncTabSwitcher {
|
||||
onSizeModeOrOcclusionStateChange() {
|
||||
if (this.minimizedOrFullyOccluded) {
|
||||
for (let [tab, state] of this.tabState) {
|
||||
// Skip print preview browsers since they shouldn't affect tab switching.
|
||||
if (this.tabbrowser._printPreviewBrowsers.has(tab.linkedBrowser)) {
|
||||
if (!this.shouldDeactivateDocShell(tab.linkedBrowser)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -915,6 +914,19 @@ class AsyncTabSwitcher {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the browser should be deactivated. If the browser is a print preivew or
|
||||
* PiP browser then we won't deactive it.
|
||||
* @param browser The browser to check if it should be deactivated
|
||||
* @returns false if a print preview or PiP browser else true
|
||||
*/
|
||||
shouldDeactivateDocShell(browser) {
|
||||
return !(
|
||||
this.tabbrowser._printPreviewBrowsers.has(browser) ||
|
||||
PictureInPicture.isOriginatingBrowser(browser)
|
||||
);
|
||||
}
|
||||
|
||||
shouldActivateDocShell(browser) {
|
||||
let tab = this.tabbrowser.getTabForBrowser(browser);
|
||||
let state = this.getTabState(tab);
|
||||
@ -1220,6 +1232,8 @@ class AsyncTabSwitcher {
|
||||
let linkedBrowser = tab.linkedBrowser;
|
||||
let isActive = linkedBrowser && linkedBrowser.docShellIsActive;
|
||||
let isRendered = linkedBrowser && linkedBrowser.renderLayers;
|
||||
let isPiP =
|
||||
linkedBrowser && PictureInPicture.isOriginatingBrowser(linkedBrowser);
|
||||
|
||||
if (tab === this.lastVisibleTab) {
|
||||
tabString += "V";
|
||||
@ -1253,6 +1267,9 @@ class AsyncTabSwitcher {
|
||||
if (isRendered) {
|
||||
extraStates += "R";
|
||||
}
|
||||
if (isPiP) {
|
||||
extraStates += "P";
|
||||
}
|
||||
if (extraStates != "") {
|
||||
tabString += `(${extraStates})`;
|
||||
}
|
||||
|
@ -148,6 +148,9 @@ var PictureInPicture = {
|
||||
// Maps PiP player windows to their originating content's browser
|
||||
weakWinToBrowser: new WeakMap(),
|
||||
|
||||
// Maps a browser to the number of PiP windows it has
|
||||
browserWeakMap: new WeakMap(),
|
||||
|
||||
/**
|
||||
* Returns the player window if one exists and if it hasn't yet been closed.
|
||||
*
|
||||
@ -173,12 +176,39 @@ var PictureInPicture = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Increase the count of PiP windows for a given browser
|
||||
* @param browser The browser to increase PiP count in browserWeakMap
|
||||
*/
|
||||
addPiPBrowserToWeakMap(browser) {
|
||||
let count = this.browserWeakMap.has(browser)
|
||||
? this.browserWeakMap.get(browser)
|
||||
: 0;
|
||||
this.browserWeakMap.set(browser, count + 1);
|
||||
},
|
||||
|
||||
/**
|
||||
* Decrease the count of PiP windows for a given browser.
|
||||
* If the count becomes 0, we will remove the browser from the WeakMap
|
||||
* @param browser The browser to decrease PiP count in browserWeakMap
|
||||
*/
|
||||
removePiPBrowserFromWeakMap(browser) {
|
||||
let count = this.browserWeakMap.get(browser);
|
||||
if (count <= 1) {
|
||||
this.browserWeakMap.delete(browser);
|
||||
} else {
|
||||
this.browserWeakMap.set(browser, count - 1);
|
||||
}
|
||||
},
|
||||
|
||||
onPipSwappedBrowsers(event) {
|
||||
let otherTab = event.detail;
|
||||
if (otherTab) {
|
||||
for (let win of Services.wm.getEnumerator(WINDOW_TYPE)) {
|
||||
if (this.weakWinToBrowser.get(win) === event.target.linkedBrowser) {
|
||||
this.weakWinToBrowser.set(win, otherTab.linkedBrowser);
|
||||
this.removePiPBrowserFromWeakMap(event.target.linkedBrowser);
|
||||
this.addPiPBrowserToWeakMap(otherTab.linkedBrowser);
|
||||
}
|
||||
}
|
||||
otherTab.addEventListener("TabSwapPictureInPicture", this);
|
||||
@ -285,6 +315,8 @@ var PictureInPicture = {
|
||||
if (!win) {
|
||||
return;
|
||||
}
|
||||
this.removePiPBrowserFromWeakMap(this.weakWinToBrowser.get(win));
|
||||
|
||||
await this.closePipWindow(win);
|
||||
gCloseReasons.set(win, reason);
|
||||
},
|
||||
@ -335,6 +367,7 @@ var PictureInPicture = {
|
||||
gNextWindowID++;
|
||||
|
||||
this.weakWinToBrowser.set(win, browser);
|
||||
this.addPiPBrowserToWeakMap(browser);
|
||||
|
||||
Services.prefs.setBoolPref(
|
||||
"media.videocontrols.picture-in-picture.video-toggle.has-used",
|
||||
@ -719,6 +752,18 @@ var PictureInPicture = {
|
||||
Services.prefs.setBoolPref(TOGGLE_ENABLED_PREF, false);
|
||||
},
|
||||
|
||||
/**
|
||||
* This is used in AsyncTabSwitcher.jsm and tabbrowser.js to check if the browser
|
||||
* currently has a PiP window.
|
||||
* If the browser has a PiP window we want to keep the browser in an active state because
|
||||
* the browser is still partially visible.
|
||||
* @param browser The browser to check if it has a PiP window
|
||||
* @returns true if browser has PiP window else false
|
||||
*/
|
||||
isOriginatingBrowser(browser) {
|
||||
return this.browserWeakMap.has(browser);
|
||||
},
|
||||
|
||||
moveToggle() {
|
||||
// Get the current position
|
||||
let position = Services.prefs.getStringPref(
|
||||
|
@ -37,6 +37,7 @@ prefs =
|
||||
media.videocontrols.picture-in-picture.video-toggle.position="right"
|
||||
|
||||
[browser_aaa_run_first_firstTimePiPToggleEvents.js]
|
||||
[browser_backgroundTab.js]
|
||||
[browser_cannotTriggerFromContent.js]
|
||||
[browser_close_unpip_focus.js]
|
||||
[browser_closePipPause.js]
|
||||
|
@ -0,0 +1,71 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
/**
|
||||
* This test creates a PiP window, then switches to another tab and confirms
|
||||
* that the PiP tab is still active.
|
||||
*/
|
||||
add_task(async () => {
|
||||
let videoID = "no-controls";
|
||||
let firstTab = gBrowser.selectedTab;
|
||||
await BrowserTestUtils.withNewTab(
|
||||
{
|
||||
url: TEST_PAGE,
|
||||
gBrowser,
|
||||
},
|
||||
async browser => {
|
||||
let originatingTab = gBrowser.getTabForBrowser(browser);
|
||||
let pipWin = await triggerPictureInPicture(browser, videoID);
|
||||
ok(pipWin, "Got Picture-in-Picture window.");
|
||||
|
||||
await BrowserTestUtils.switchTab(gBrowser, firstTab);
|
||||
|
||||
let switcher = gBrowser._getSwitcher();
|
||||
|
||||
Assert.equal(
|
||||
switcher.getTabState(originatingTab),
|
||||
switcher.STATE_LOADED,
|
||||
"The originating browser tab should be in STATE_LOADED."
|
||||
);
|
||||
|
||||
await BrowserTestUtils.closeWindow(pipWin);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* This test creates a PiP window, then minimizes the browser and confirms
|
||||
* that the PiP tab is still active.
|
||||
*/
|
||||
add_task(async () => {
|
||||
let videoID = "no-controls";
|
||||
await BrowserTestUtils.withNewTab(
|
||||
{
|
||||
url: TEST_PAGE,
|
||||
gBrowser,
|
||||
},
|
||||
async browser => {
|
||||
let originatingTab = gBrowser.getTabForBrowser(browser);
|
||||
let pipWin = await triggerPictureInPicture(browser, videoID);
|
||||
ok(pipWin, "Got Picture-in-Picture window.");
|
||||
|
||||
let promiseSizeModeChange = BrowserTestUtils.waitForEvent(
|
||||
window,
|
||||
"sizemodechange"
|
||||
);
|
||||
window.minimize();
|
||||
await promiseSizeModeChange;
|
||||
|
||||
let switcher = gBrowser._getSwitcher();
|
||||
|
||||
Assert.equal(
|
||||
switcher.getTabState(originatingTab),
|
||||
switcher.STATE_LOADED,
|
||||
"The originating browser tab should be in STATE_LOADED."
|
||||
);
|
||||
|
||||
await BrowserTestUtils.closeWindow(pipWin);
|
||||
}
|
||||
);
|
||||
});
|
Loading…
Reference in New Issue
Block a user