зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1823720 - prevent some fullscreen states while WebAuthn prompts are shown. r=edgar,keeler
This prevents fullscreen states that hide chrome while WebAuthn prompts are shown. Specifically, it 1) ensures that the navigation toolbox is shown in fullscreen windows, and 2) disallows fullscreen DOM elements. Differential Revision: https://phabricator.services.mozilla.com/D187001
This commit is contained in:
Родитель
db3aa4d9a0
Коммит
3104851fc5
|
@ -7501,6 +7501,28 @@ var WebAuthnPromptHelper = {
|
|||
},
|
||||
|
||||
observe(aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
case "fullscreen-nav-toolbox":
|
||||
// Prevent the navigation toolbox from being hidden while a WebAuthn
|
||||
// prompt is visible.
|
||||
if (aData == "hidden" && this._tid != 0) {
|
||||
FullScreen.showNavToolbox();
|
||||
}
|
||||
return;
|
||||
case "fullscreen-painted":
|
||||
// Prevent DOM elements from going fullscreen while a WebAuthn
|
||||
// prompt is shown.
|
||||
if (this._tid != 0) {
|
||||
FullScreen.exitDomFullScreen();
|
||||
}
|
||||
return;
|
||||
case this._topic:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
// aTopic is equal to this._topic
|
||||
|
||||
let data = JSON.parse(aData);
|
||||
|
||||
// If we receive a cancel, it might be a WebAuthn prompt starting in another
|
||||
|
@ -7760,6 +7782,24 @@ var WebAuthnPromptHelper = {
|
|||
options = {}
|
||||
) {
|
||||
this.reset();
|
||||
this._tid = tid;
|
||||
|
||||
// We need to prevent some fullscreen transitions while WebAuthn prompts
|
||||
// are shown. The `fullscreen-painted` topic is notified when DOM elements
|
||||
// go fullscreen.
|
||||
Services.obs.addObserver(this, "fullscreen-painted");
|
||||
|
||||
// The `fullscreen-nav-toolbox` topic is notified when the nav toolbox is
|
||||
// hidden.
|
||||
Services.obs.addObserver(this, "fullscreen-nav-toolbox");
|
||||
|
||||
// Ensure that no DOM elements are already fullscreen.
|
||||
FullScreen.exitDomFullScreen();
|
||||
|
||||
// Ensure that the nav toolbox is being shown.
|
||||
if (window.fullScreen) {
|
||||
FullScreen.showNavToolbox();
|
||||
}
|
||||
|
||||
let brandShortName = document
|
||||
.getElementById("bundle_brand")
|
||||
|
@ -7774,12 +7814,13 @@ var WebAuthnPromptHelper = {
|
|||
options.persistent = true;
|
||||
options.eventCallback = event => {
|
||||
if (event == "removed") {
|
||||
Services.obs.removeObserver(this, "fullscreen-painted");
|
||||
Services.obs.removeObserver(this, "fullscreen-nav-toolbox");
|
||||
this._current = null;
|
||||
this._tid = 0;
|
||||
}
|
||||
};
|
||||
|
||||
this._tid = tid;
|
||||
this._current = PopupNotifications.show(
|
||||
gBrowser.selectedBrowser,
|
||||
`webauthn-prompt-${id}`,
|
||||
|
|
|
@ -241,6 +241,7 @@ async function test_minimize_make() {
|
|||
|
||||
// Close window and wait for main window to be focused again.
|
||||
let windowBackPromise = waitForWindowActive(window, true);
|
||||
await BrowserTestUtils.removeTab(tab);
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
await windowBackPromise;
|
||||
}
|
||||
|
@ -271,6 +272,7 @@ async function test_minimize_get() {
|
|||
|
||||
// Close window and wait for main window to be focused again.
|
||||
let windowBackPromise = waitForWindowActive(window, true);
|
||||
await BrowserTestUtils.removeTab(tab);
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
await windowBackPromise;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,12 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
XPCOMUtils.defineLazyScriptGetter(
|
||||
this,
|
||||
["FullScreen"],
|
||||
"chrome://browser/content/browser-fullScreenAndPointerLock.js"
|
||||
);
|
||||
|
||||
const TEST_URL = "https://example.com/";
|
||||
|
||||
add_task(async function test_setup_usbtoken() {
|
||||
|
@ -16,11 +22,22 @@ add_task(async function test_setup_usbtoken() {
|
|||
});
|
||||
add_task(test_register);
|
||||
add_task(test_register_escape);
|
||||
add_task(test_register_direct_cancel);
|
||||
add_task(test_sign);
|
||||
add_task(test_sign_escape);
|
||||
add_task(test_register_direct_cancel);
|
||||
add_task(test_tab_switching);
|
||||
add_task(test_window_switching);
|
||||
add_task(async function test_setup_fullscreen() {
|
||||
return SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
["browser.fullscreen.autohide", true],
|
||||
["full-screen-api.enabled", true],
|
||||
["full-screen-api.allow-trusted-requests-only", false],
|
||||
],
|
||||
});
|
||||
});
|
||||
add_task(test_fullscreen_show_nav_toolbar);
|
||||
add_task(test_no_fullscreen_dom);
|
||||
add_task(async function test_setup_softtoken() {
|
||||
add_virtual_authenticator();
|
||||
return SpecialPowers.pushPrefEnv({
|
||||
|
@ -46,6 +63,20 @@ function promiseNotification(id) {
|
|||
});
|
||||
}
|
||||
|
||||
function promiseNavToolboxStatus(aExpectedStatus) {
|
||||
let navToolboxStatus;
|
||||
return TestUtils.topicObserved("fullscreen-nav-toolbox", (subject, data) => {
|
||||
navToolboxStatus = data;
|
||||
return data == aExpectedStatus;
|
||||
}).then(() =>
|
||||
ok(navToolboxStatus == aExpectedStatus, "nav toolbox is " + aExpectedStatus)
|
||||
);
|
||||
}
|
||||
|
||||
function promiseFullScreenPaint(aExpectedStatus) {
|
||||
return TestUtils.topicObserved("fullscreen-painted");
|
||||
}
|
||||
|
||||
function triggerMainPopupCommand(popup) {
|
||||
info("triggering main command");
|
||||
let notifications = popup.childNodes;
|
||||
|
@ -324,3 +355,77 @@ async function test_register_direct_proceed_anon() {
|
|||
// Close tab.
|
||||
await BrowserTestUtils.removeTab(tab);
|
||||
}
|
||||
|
||||
async function test_fullscreen_show_nav_toolbar() {
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
|
||||
|
||||
// Start with the window fullscreen and the nav toolbox hidden
|
||||
let fullscreenState = window.fullScreen;
|
||||
|
||||
let navToolboxHiddenPromise = promiseNavToolboxStatus("hidden");
|
||||
|
||||
window.fullScreen = true;
|
||||
FullScreen.hideNavToolbox(false);
|
||||
|
||||
await navToolboxHiddenPromise;
|
||||
|
||||
// Request a new credential and wait for the direct attestation consent
|
||||
// prompt.
|
||||
let promptPromise = promiseNotification("webauthn-prompt-register-direct");
|
||||
let navToolboxShownPromise = promiseNavToolboxStatus("shown");
|
||||
|
||||
let active = true;
|
||||
let requestPromise = promiseWebAuthnMakeCredential(tab, "direct", {})
|
||||
.then(arrivingHereIsBad)
|
||||
.catch(expectNotAllowedError)
|
||||
.then(() => (active = false));
|
||||
|
||||
await Promise.all([promptPromise, navToolboxShownPromise]);
|
||||
|
||||
ok(active, "request is active");
|
||||
ok(window.fullScreen, "window is fullscreen");
|
||||
|
||||
// Cancel the request.
|
||||
PopupNotifications.panel.firstElementChild.secondaryButton.click();
|
||||
await requestPromise;
|
||||
|
||||
window.fullScreen = fullscreenState;
|
||||
|
||||
// Close tab.
|
||||
await BrowserTestUtils.removeTab(tab);
|
||||
}
|
||||
|
||||
async function test_no_fullscreen_dom() {
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
|
||||
|
||||
let fullScreenPaintPromise = promiseFullScreenPaint();
|
||||
// Make a DOM element fullscreen
|
||||
await ContentTask.spawn(tab.linkedBrowser, [], () => {
|
||||
return content.document.body.requestFullscreen();
|
||||
});
|
||||
await fullScreenPaintPromise;
|
||||
ok(!!document.fullscreenElement, "a DOM element is fullscreen");
|
||||
|
||||
// Request a new credential and wait for the direct attestation consent
|
||||
// prompt.
|
||||
let promptPromise = promiseNotification("webauthn-prompt-register-direct");
|
||||
fullScreenPaintPromise = promiseFullScreenPaint();
|
||||
|
||||
let active = true;
|
||||
let requestPromise = promiseWebAuthnMakeCredential(tab, "direct", {})
|
||||
.then(arrivingHereIsBad)
|
||||
.catch(expectNotAllowedError)
|
||||
.then(() => (active = false));
|
||||
|
||||
await Promise.all([promptPromise, fullScreenPaintPromise]);
|
||||
|
||||
ok(active, "request is active");
|
||||
ok(!document.fullscreenElement, "no DOM element is fullscreen");
|
||||
|
||||
// Cancel the request.
|
||||
PopupNotifications.panel.firstElementChild.secondaryButton.click();
|
||||
await requestPromise;
|
||||
|
||||
// Close tab.
|
||||
await BrowserTestUtils.removeTab(tab);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче