Bug 1705440 - remove old modal prompt implementation, r=mconley,webdriver-reviewers,extension-reviewers,desktop-theme-reviewers,tabbrowser-reviewers,whimboo,rpl

Differential Revision: https://phabricator.services.mozilla.com/D204759
This commit is contained in:
Gijs Kruitbosch 2024-03-20 10:10:26 +00:00
Родитель 5d1af6669c
Коммит a3568826b0
29 изменённых файлов: 24 добавлений и 1228 удалений

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

@ -18,6 +18,4 @@ skip-if = [
["test_tree.xhtml"]
["test_ui_modalprompt.html"]
["test_update.html"]

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

@ -1,111 +0,0 @@
<html>
<head>
<title>Modal prompts</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../relations.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript"
src="../browser.js"></script>
<script type="application/javascript">
SpecialPowers.pushPrefEnv({
set: [["prompts.contentPromptSubDialog", false]],
});
function showAlert() {
this.eventSeq = [
{
type: EVENT_SHOW,
match(aEvent) {
return aEvent.accessible.role == ROLE_DIALOG;
},
},
];
this.invoke = function showAlert_invoke() {
window.setTimeout(
function() {
currentTabDocument().defaultView.alert("hello");
}, 0);
};
this.check = function showAlert_finalCheck(aEvent) {
if(aEvent.type === EVENT_HIDE) {
return;
}
var dialog = aEvent.accessible.DOMNode;
var info = dialog.querySelector(".tabmodalprompt-infoBody");
testRelation(info, RELATION_DESCRIPTION_FOR, dialog);
testRelation(dialog, RELATION_DESCRIBED_BY, info);
};
this.getID = function showAlert_getID() {
return "show alert";
};
}
function closeAlert() {
this.eventSeq = [
{
type: EVENT_HIDE,
match(aEvent) {
return aEvent.accessible.role == ROLE_DIALOG;
},
},
];
this.invoke = function showAlert_invoke() {
synthesizeKey("VK_RETURN", {}, browserWindow());
};
this.getID = function showAlert_getID() {
return "cleanup alert";
};
}
// gA11yEventDumpToConsole = true; // debug
var gQueue = null;
function doTests() {
gQueue = new eventQueue();
gQueue.push(new showAlert());
gQueue.push(new closeAlert());
gQueue.onFinish = function() {
closeBrowserWindow();
};
gQueue.invoke(); // will call SimpleTest.finish()
}
SimpleTest.waitForExplicitFinish();
openBrowserWindow(doTests);
</script>
</head>
<body id="body">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=661293"
title="The tabmodalprompt dialog's prompt label doesn't get the text properly associated for accessibility">
Mozilla Bug 661293
</a>
<br>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
</body>
</html>

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

@ -9,21 +9,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
PromptUtils: "resource://gre/modules/PromptUtils.sys.mjs",
BrowserUtils: "resource://gre/modules/BrowserUtils.sys.mjs",
});
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
XPCOMUtils.defineLazyPreferenceGetter(
lazy,
"tabChromePromptSubDialog",
"prompts.tabChromePromptSubDialog",
false
);
XPCOMUtils.defineLazyPreferenceGetter(
lazy,
"contentPromptSubDialog",
"prompts.contentPromptSubDialog",
false
);
ChromeUtils.defineLazyGetter(lazy, "gTabBrowserLocalization", function () {
return new Localization(["browser/tabbrowser.ftl"], true);
@ -109,116 +94,18 @@ export class PromptParent extends JSWindowActorParent {
}
receiveMessage(message) {
let args = message.data;
let id = args._remoteId;
switch (message.name) {
case "Prompt:Open":
if (!this.windowContext.isActiveInTab) {
return undefined;
}
if (
(args.modalType === Ci.nsIPrompt.MODAL_TYPE_CONTENT &&
!lazy.contentPromptSubDialog) ||
(args.modalType === Ci.nsIPrompt.MODAL_TYPE_TAB &&
!lazy.tabChromePromptSubDialog)
) {
return this.openContentPrompt(args, id);
}
return this.openPromptWithTabDialogBox(args);
return this.openPromptWithTabDialogBox(message.data);
}
return undefined;
}
/**
* Opens a TabModalPrompt for a BrowsingContext, and puts the associated browser
* in the modal state until the TabModalPrompt is closed.
*
* @param {Object} args
* The arguments passed up from the BrowsingContext to be passed directly
* to the TabModalPrompt.
* @param {string} id
* A unique ID to differentiate multiple Prompts coming from the same
* BrowsingContext.
* @return {Promise}
* Resolves when the TabModalPrompt is dismissed.
* @resolves {Object}
* The arguments returned from the TabModalPrompt.
*/
openContentPrompt(args, id) {
let browser = this.browsingContext.top.embedderElement;
if (!browser) {
throw new Error("Cannot tab-prompt without a browser!");
}
let window = browser.ownerGlobal;
let tabPrompt = window.gBrowser.getTabModalPromptBox(browser);
let newPrompt;
let needRemove = false;
// If the page which called the prompt is different from the the top context
// where we show the prompt, ask the prompt implementation to display the origin.
// For example, this can happen if a cross origin subframe shows a prompt.
args.showCallerOrigin =
args.promptPrincipal &&
!browser.contentPrincipal.equals(args.promptPrincipal);
let onPromptClose = () => {
// NOTE: this code is totally bust now, as `gBrowserDialogs` won't produce
// the right objects for it. It's also unused though, and removed in the
// next commit.
let promptData = gBrowserDialogs.get(this.browsingContext);
if (!promptData || !promptData.has(id)) {
throw new Error(
"Failed to close a prompt since it wasn't registered for some reason."
);
}
let { resolver, tabModalPrompt } = promptData.get(id);
// It's possible that we removed the prompt during the
// appendPrompt call below. In that case, newPrompt will be
// undefined. We set the needRemove flag to remember to remove
// it right after we've finished adding it.
if (tabModalPrompt) {
tabPrompt.removePrompt(tabModalPrompt);
} else {
needRemove = true;
}
lazy.PromptUtils.fireDialogEvent(
window,
"DOMModalDialogClosed",
browser,
this.getClosingEventDetail(args)
);
resolver(args);
browser.maybeLeaveModalState();
};
try {
browser.enterModalState();
lazy.PromptUtils.fireDialogEvent(
window,
"DOMWillOpenModalDialog",
browser,
this.getOpenEventDetail(args)
);
args.promptActive = true;
newPrompt = tabPrompt.appendPrompt(args, onPromptClose);
if (needRemove) {
tabPrompt.removePrompt(newPrompt);
}
} catch (ex) {
console.error(ex);
onPromptClose(true);
}
return null;
}
/**
* Opens either a window prompt or TabDialogBox at the content or tab level
* for a BrowsingContext, and puts the associated browser in the modal state

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

@ -1680,15 +1680,6 @@ pref("browser.topsites.contile.sov.enabled", true);
pref("browser.partnerlink.attributionURL", "https://topsites.services.mozilla.com/cid/");
pref("browser.partnerlink.campaign.topsites", "amzn_2020_a1");
// Whether to show tab level system prompts opened via nsIPrompt(Service) as
// SubDialogs in the TabDialogBox (true) or as TabModalPrompt in the
// TabModalPromptBox (false).
pref("prompts.tabChromePromptSubDialog", true);
// Whether to show the dialogs opened at the content level, such as
// alert() or prompt(), using a SubDialogManager in the TabDialogBox.
pref("prompts.contentPromptSubDialog", true);
// Whether to show window-modal dialogs opened for browser windows
// in a SubDialog inside their parent, instead of an OS level window.
pref("prompts.windowPromptSubDialog", true);

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

@ -916,7 +916,7 @@ menupopup[emptyplacesresult="true"] > .hide-if-empty-places-result {
position: absolute;
}
browser[tabmodalPromptShowing], browser[tabDialogShowing] {
browser[tabDialogShowing] {
-moz-user-focus: none !important;
}

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

@ -79,7 +79,6 @@ ChromeUtils.defineESModuleGetters(this, {
SubDialog: "resource://gre/modules/SubDialog.sys.mjs",
SubDialogManager: "resource://gre/modules/SubDialog.sys.mjs",
TabCrashHandler: "resource:///modules/ContentCrashHandlers.sys.mjs",
TabModalPrompt: "chrome://global/content/tabprompts.sys.mjs",
TabsSetupFlowManager:
"resource:///modules/firefox-view-tabs-setup-manager.sys.mjs",
TelemetryEnvironment: "resource://gre/modules/TelemetryEnvironment.sys.mjs",
@ -691,7 +690,6 @@ function shouldSuppressPopupNotifications() {
// don't cover up the prompt.
return (
window.windowState == window.STATE_MINIMIZED ||
gBrowser?.selectedBrowser.hasAttribute("tabmodalChromePromptShowing") ||
gBrowser?.selectedBrowser.hasAttribute("tabDialogShowing") ||
gDialogBox?.isOpen
);
@ -9440,221 +9438,6 @@ TabDialogBox.prototype.QueryInterface = ChromeUtils.generateQI([
"nsISupportsWeakReference",
]);
function TabModalPromptBox(browser) {
this._weakBrowserRef = Cu.getWeakReference(browser);
/*
* These WeakMaps holds the TabModalPrompt instances, key to the <tabmodalprompt> prompt
* in the DOM. We don't want to hold the instances directly to avoid leaking.
*
* WeakMap also prevents us from reading back its insertion order.
* Order of the elements in the DOM should be the only order to consider.
*/
this._contentPrompts = new WeakMap();
this._tabPrompts = new WeakMap();
}
TabModalPromptBox.prototype = {
_promptCloseCallback(
onCloseCallback,
principalToAllowFocusFor,
allowFocusCheckbox,
...args
) {
if (
principalToAllowFocusFor &&
allowFocusCheckbox &&
allowFocusCheckbox.checked
) {
Services.perms.addFromPrincipal(
principalToAllowFocusFor,
"focus-tab-by-prompt",
Services.perms.ALLOW_ACTION
);
}
onCloseCallback.apply(this, args);
},
getPrompt(promptEl) {
if (promptEl.classList.contains("tab-prompt")) {
return this._tabPrompts.get(promptEl);
}
return this._contentPrompts.get(promptEl);
},
appendPrompt(args, onCloseCallback) {
let browser = this.browser;
let newPrompt = new TabModalPrompt(browser.ownerGlobal);
if (args.modalType === Ci.nsIPrompt.MODAL_TYPE_TAB) {
newPrompt.element.classList.add("tab-prompt");
this._tabPrompts.set(newPrompt.element, newPrompt);
} else {
newPrompt.element.classList.add("content-prompt");
this._contentPrompts.set(newPrompt.element, newPrompt);
}
browser.parentNode.insertBefore(
newPrompt.element,
browser.nextElementSibling
);
browser.setAttribute("tabmodalPromptShowing", true);
// Indicate if a tab modal chrome prompt is being shown so that
// PopupNotifications are suppressed.
if (
args.modalType === Ci.nsIPrompt.MODAL_TYPE_TAB &&
!browser.hasAttribute("tabmodalChromePromptShowing")
) {
browser.setAttribute("tabmodalChromePromptShowing", true);
// Notify popup notifications of the UI change so they hide their
// notification panels.
UpdatePopupNotificationsVisibility();
}
let prompts = this.listPrompts(args.modalType);
if (prompts.length > 1) {
// Let's hide ourself behind the current prompt.
newPrompt.element.hidden = true;
}
let principalToAllowFocusFor = this._allowTabFocusByPromptPrincipal;
delete this._allowTabFocusByPromptPrincipal;
let allowFocusCheckbox; // Define outside the if block so we can bind it into the callback.
let hostForAllowFocusCheckbox = "";
try {
hostForAllowFocusCheckbox = principalToAllowFocusFor.URI.host;
} catch (ex) {
/* Ignore exceptions for host-less URIs */
}
if (hostForAllowFocusCheckbox) {
let allowFocusRow = document.createElement("div");
let spacer = document.createElement("div");
allowFocusRow.appendChild(spacer);
allowFocusCheckbox = document.createXULElement("checkbox");
document.l10n.setAttributes(
allowFocusCheckbox,
"tabbrowser-allow-dialogs-to-get-focus",
{ domain: hostForAllowFocusCheckbox }
);
allowFocusRow.appendChild(allowFocusCheckbox);
newPrompt.ui.rows.append(allowFocusRow);
}
let tab = gBrowser.getTabForBrowser(browser);
let closeCB = this._promptCloseCallback.bind(
null,
onCloseCallback,
principalToAllowFocusFor,
allowFocusCheckbox
);
newPrompt.init(args, tab, closeCB);
return newPrompt;
},
removePrompt(aPrompt) {
let { modalType } = aPrompt.args;
if (modalType === Ci.nsIPrompt.MODAL_TYPE_TAB) {
this._tabPrompts.delete(aPrompt.element);
} else {
this._contentPrompts.delete(aPrompt.element);
}
let browser = this.browser;
aPrompt.element.remove();
let prompts = this.listPrompts(modalType);
if (prompts.length) {
let prompt = prompts[prompts.length - 1];
prompt.element.hidden = false;
// Because we were hidden before, this won't have been possible, so do it now:
prompt.Dialog.setDefaultFocus();
} else if (modalType === Ci.nsIPrompt.MODAL_TYPE_TAB) {
// If we remove the last tab chrome prompt, also remove the browser
// attribute.
browser.removeAttribute("tabmodalChromePromptShowing");
// Notify popup notifications of the UI change so they show notification
// panels again.
UpdatePopupNotificationsVisibility();
}
// Check if all prompts are closed
if (!this._hasPrompts()) {
browser.removeAttribute("tabmodalPromptShowing");
browser.focus();
}
},
/**
* Checks if the prompt box has prompt elements.
* @returns {Boolean} - true if there are prompt elements.
*/
_hasPrompts() {
return !!this._getPromptElements().length;
},
/**
* Get list of current prompt elements.
* @param {Number} [aModalType] - Optionally filter by
* Ci.nsIPrompt.MODAL_TYPE_.
* @returns {NodeList} - A list of tabmodalprompt elements.
*/
_getPromptElements(aModalType = null) {
let selector = "tabmodalprompt";
if (aModalType != null) {
if (aModalType === Ci.nsIPrompt.MODAL_TYPE_TAB) {
selector += ".tab-prompt";
} else {
selector += ".content-prompt";
}
}
return this.browser.parentNode.querySelectorAll(selector);
},
/**
* Get a list of all TabModalPrompt objects associated with the prompt box.
* @param {Number} [aModalType] - Optionally filter by
* Ci.nsIPrompt.MODAL_TYPE_.
* @returns {TabModalPrompt[]} - An array of TabModalPrompt objects.
*/
listPrompts(aModalType = null) {
// Get the nodelist, then return the TabModalPrompt instances as an array
let promptMap;
if (aModalType) {
if (aModalType === Ci.nsIPrompt.MODAL_TYPE_TAB) {
promptMap = this._tabPrompts;
} else {
promptMap = this._contentPrompts;
}
}
let elements = this._getPromptElements(aModalType);
if (promptMap) {
return [...elements].map(el => promptMap.get(el));
}
return [...elements].map(
el => this._contentPrompts.get(el) || this._tabPrompts.get(el)
);
},
onNextPromptShowAllowFocusCheckboxFor(principal) {
this._allowTabFocusByPromptPrincipal = principal;
},
get browser() {
let browser = this._weakBrowserRef.get();
if (!browser) {
throw new Error("Stale promptbox! The associated browser is gone.");
}
return browser;
},
};
// Handle window-modal prompts that we want to display with the same style as
// tab-modal prompts.
var gDialogBox = {

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

@ -131,7 +131,6 @@
"PanicButtonNotifier",
"SafeBrowsingNotificationBox",
"TabDialogBox",
"TabModalPromptBox",
"gDialogBox",
"ConfirmationHint",
"FirefoxViewHandler",
@ -196,7 +195,6 @@
"SubDialog",
"SubDialogManager",
"TabCrashHandler",
"TabModalPrompt",
"TabsSetupFlowManager",
"TelemetryEnvironment",
"TranslationsParent",

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

@ -38,9 +38,6 @@
both "content" and "skin" packages, which bug 1385444 will unify later. -->
<link rel="stylesheet" href="chrome://global/skin/global.css" />
<link rel="stylesheet" href="chrome://global/content/tabprompts.css" />
<link rel="stylesheet" href="chrome://global/skin/tabprompts.css" />
<link rel="stylesheet" href="chrome://browser/content/browser.css" />
<link rel="stylesheet" href="chrome://browser/content/tabbrowser.css" />
<link

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

@ -893,14 +893,6 @@
: "";
},
getTabModalPromptBox(aBrowser) {
let browser = aBrowser || this.selectedBrowser;
if (!browser.tabModalPromptBox) {
browser.tabModalPromptBox = new TabModalPromptBox(browser);
}
return browser.tabModalPromptBox;
},
getTabDialogBox(aBrowser) {
if (!aBrowser) {
throw new Error("aBrowser is required");
@ -1320,31 +1312,6 @@
this.addToMultiSelectedTabs(oldTab);
}
if (oldBrowser != newBrowser && oldBrowser.getInPermitUnload) {
oldBrowser.getInPermitUnload(inPermitUnload => {
if (!inPermitUnload) {
return;
}
// Since the user is switching away from a tab that has
// a beforeunload prompt active, we remove the prompt.
// This prevents confusing user flows like the following:
// 1. User attempts to close Firefox
// 2. User switches tabs (ingoring a beforeunload prompt)
// 3. User returns to tab, presses "Leave page"
let promptBox = this.getTabModalPromptBox(oldBrowser);
let prompts = promptBox.listPrompts();
// There might not be any prompts here if the tab was closed
// while in an onbeforeunload prompt, which will have
// destroyed aforementioned prompt already, so check there's
// something to remove, first:
if (prompts.length) {
// NB: This code assumes that the beforeunload prompt
// is the top-most prompt on the tab.
prompts[prompts.length - 1].abortPrompt();
}
});
}
if (!gMultiProcessBrowser) {
this._adjustFocusBeforeTabSwitch(oldTab, newTab);
this._adjustFocusAfterTabSwitch(newTab);
@ -1439,19 +1406,6 @@
newBrowser.tabDialogBox.focus();
return;
}
if (newBrowser.hasAttribute("tabmodalPromptShowing")) {
// If there's a tabmodal prompt showing, focus it.
let prompts = newBrowser.tabModalPromptBox.listPrompts();
let prompt = prompts[prompts.length - 1];
// @tabmodalPromptShowing is also set for other tab modal prompts
// (e.g. the Payment Request dialog) so there may not be a <tabmodalprompt>.
// Bug 1492814 will implement this for the Payment Request dialog.
if (prompt) {
prompt.Dialog.setDefaultFocus();
return;
}
}
// Focus the location bar if it was previously focused for that tab.
// In full screen mode, only bother making the location bar visible
// if the tab is a blank one.
@ -6103,12 +6057,7 @@
);
if (permission != Services.perms.ALLOW_ACTION) {
// Tell the prompt box we want to show the user a checkbox:
let tabPrompt = Services.prefs.getBoolPref(
"prompts.contentPromptSubDialog"
)
? this.getTabDialogBox(tabForEvent.linkedBrowser)
: this.getTabModalPromptBox(tabForEvent.linkedBrowser);
let tabPrompt = this.getTabDialogBox(tabForEvent.linkedBrowser);
tabPrompt.onNextPromptShowAllowFocusCheckboxFor(
promptPrincipal
);

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

@ -125,22 +125,12 @@ function getBrowser(panel) {
return readyPromise.then(initBrowser);
}
// Stub tabbrowser implementation for use by the tab-modal alert code.
// Stub tabbrowser implementation to make sure that links from inside
// extension sidebar panels open in new tabs, see bug 1488055.
var gBrowser = {
get selectedBrowser() {
return document.getElementById("webext-panels-browser");
},
getTabForBrowser() {
return null;
},
getTabModalPromptBox(browser) {
if (!browser.tabModalPromptBox) {
browser.tabModalPromptBox = new TabModalPromptBox(browser);
}
return browser.tabModalPromptBox;
},
};
function updatePosition() {

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

@ -157,16 +157,10 @@ function promiseAlertDialogObserved() {
async function observer(subject) {
info("alert dialog observed as expected");
Services.obs.removeObserver(observer, "common-dialog-loaded");
Services.obs.removeObserver(observer, "tabmodal-dialog-loaded");
if (subject.Dialog) {
subject.Dialog.ui.button0.click();
} else {
subject.querySelector(".tabmodalprompt-button0").click();
}
subject.Dialog.ui.button0.click();
resolve();
}
Services.obs.addObserver(observer, "common-dialog-loaded");
Services.obs.addObserver(observer, "tabmodal-dialog-loaded");
});
}

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

@ -8,12 +8,6 @@ const kTestPage = "https://example.org/browser/dom/html/test/bug436200.html";
async function run_test(shouldShowPrompt, msg) {
let promptShown = false;
function tabModalObserver(subject) {
promptShown = true;
subject.querySelector(".tabmodalprompt-button0").click();
}
Services.obs.addObserver(tabModalObserver, "tabmodal-dialog-loaded");
function commonDialogObserver(subject) {
let dialog = subject.Dialog;
promptShown = true;
@ -27,7 +21,6 @@ async function run_test(shouldShowPrompt, msg) {
let form = content.document.getElementById("test_form");
form.submit();
});
Services.obs.removeObserver(tabModalObserver, "tabmodal-dialog-loaded");
Services.obs.removeObserver(commonDialogObserver, "common-dialog-loaded");
is(promptShown, shouldShowPrompt, msg);

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

@ -31,17 +31,9 @@ function runTest() {
var os = Services.obs;
os.addObserver(onPromptLoad, "common-dialog-loaded");
os.addObserver(onPromptLoad, "tabmodal-dialog-loaded");
function onPromptLoad(subject) {
let ui = subject.Dialog ? subject.Dialog.ui : undefined;
if (!ui) {
// subject is an tab prompt, find the elements ourselves
ui = {
loginTextbox: subject.querySelector(".tabmodalprompt-loginTextbox"),
button0: subject.querySelector(".tabmodalprompt-button0"),
};
}
let ui = subject.Dialog.ui;
sendAsyncMessage("ok", [true, "onPromptLoad is called"]);
gPromptInput = ui.loginTextbox;
gPromptInput.addEventListener("focus", onPromptFocus);
@ -77,7 +69,6 @@ function runTest() {
}
addMessageListener("destroy", function() {
os.removeObserver(onPromptLoad, "tabmodal-dialog-loaded");
os.removeObserver(onPromptLoad, "common-dialog-loaded");
});
});

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

@ -144,23 +144,6 @@ browser.Context = class {
};
}
/**
* Retrieves the current tabmodal UI object. According to the browser
* associated with the currently selected tab.
*/
getTabModal() {
let br = this.contentBrowser;
if (!br.hasAttribute("tabmodalPromptShowing")) {
return null;
}
// The modal is a direct sibling of the browser element.
// See tabbrowser.xml's getTabModalPromptBox.
let modalElements = br.parentNode.getElementsByTagName("tabmodalprompt");
return br.tabModalPromptBox.getPrompt(modalElements[0]);
}
/**
* Close the current window.
*

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

@ -77,18 +77,6 @@ modal.findPrompt = function (context) {
return new modal.Dialog(() => context, dialogs[0].frameContentWindow);
}
}
// If no modal dialog has been found yet, check for old non SubDialog based
// content modal dialogs. Even with those deprecated in Firefox 89 we should
// keep supporting applications that don't have them implemented yet.
if (contentBrowser?.tabModalPromptBox) {
const prompts = contentBrowser.tabModalPromptBox.listPrompts();
if (prompts.length) {
lazy.logger.trace("Found open old-style content prompt");
return new modal.Dialog(() => context, null);
}
}
return null;
};
@ -136,11 +124,7 @@ modal.Dialog = class {
}
get tabModal() {
let win = this.window;
if (win) {
return win.Dialog;
}
return this.curBrowser_.getTabModal();
return this.window?.Dialog;
}
get promptType() {

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

@ -1,119 +0,0 @@
/* 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/. */
/* Tab Modal Prompt boxes */
.tabModalBackground {
justify-content: center;
flex-direction: column;
}
.tabModalBackground,
tabmodalprompt {
width: 100%;
height: 100%;
}
tabmodalprompt {
--tabmodalprompt-padding: 20px;
overflow: hidden;
text-shadow: none; /* remove lightweight theme text-shadow */
}
tabmodalprompt:not([hidden]) {
display: grid;
grid-template-rows: 1fr [dialog-start] auto [dialog-end] 2fr;
justify-items: center;
}
/*
Adjustments for chrome level tab-prompts to make them
overlap with the upper chrome UI and move them in
front of content prompts.
*/
tabmodalprompt.tab-prompt {
overflow: visible;
z-index: 1;
grid-template-rows: [dialog-start] auto [dialog-end] 1fr;
}
tabmodalprompt.tab-prompt .tabmodalprompt-mainContainer {
margin-top: -5px;
}
.tabmodalprompt-mainContainer {
min-width: 20em;
min-height: 12em;
max-width: calc(60% + calc(var(--tabmodalprompt-padding) * 2));
-moz-user-focus: normal;
grid-row: dialog;
display: flex;
flex-direction: column;
}
.tabmodalprompt-topContainer {
flex-grow: 1;
padding: var(--tabmodalprompt-padding);
display: grid;
grid-template-columns: auto 1fr;
align-items: baseline;
align-content: center; /* center content vertically */
max-width: 100%;
min-height: 0;
max-height: 60vh;
box-sizing: border-box;
}
.tabmodalprompt-topContainer > div:not(.tabmodalprompt-infoContainer, [hidden]) {
display: contents;
}
.tabmodalprompt-infoContainer {
grid-column: span 2;
display: block;
margin-block: auto;
max-width: 100%;
height: 100%;
min-height: 0;
justify-self: center; /* center text, but only when it fits in one line */
}
/* When all elements in the first column are hidden, prevent the second column
from becoming the first one because it won't have the right fraction */
.tabmodalprompt-topContainer > div > *:nth-child(2) {
grid-column: 2;
}
.infoTitle {
margin-bottom: 1em !important;
font-weight: bold;
}
.infoBody {
margin: 0 !important;
-moz-user-focus: normal;
user-select: text;
cursor: text !important;
white-space: pre-wrap;
unicode-bidi: plaintext;
outline: none; /* remove focus outline */
overflow: auto;
max-width: 100%;
max-height: 100%;
}
tabmodalprompt label[value=""] {
display: none;
}
.tabmodalprompt-buttonContainer {
display: flex;
padding: 12px var(--tabmodalprompt-padding) 15px;
}
.tabmodalprompt-buttonSpacer {
flex-grow: 1;
}

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

@ -1,298 +0,0 @@
/* 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/. */
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
export var TabModalPrompt = class {
constructor(win) {
this.win = win;
let newPrompt = (this.element =
win.document.createElement("tabmodalprompt"));
win.MozXULElement.insertFTLIfNeeded("toolkit/global/tabprompts.ftl");
newPrompt.setAttribute("role", "dialog");
let randomIdSuffix = Math.random().toString(32).substring(2);
newPrompt.setAttribute("aria-describedby", `infoBody-${randomIdSuffix}`);
newPrompt.appendChild(
win.MozXULElement.parseXULToFragment(
`
<div class="tabmodalprompt-mainContainer" xmlns="http://www.w3.org/1999/xhtml" xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<div class="tabmodalprompt-topContainer">
<div class="tabmodalprompt-infoContainer">
<div class="tabmodalprompt-infoTitle infoTitle" hidden="hidden"/>
<div class="tabmodalprompt-infoBody infoBody" id="infoBody-${randomIdSuffix}" tabindex="-1"/>
</div>
<div class="tabmodalprompt-loginContainer" hidden="hidden">
<xul:label class="tabmodalprompt-loginLabel" data-l10n-id="tabmodalprompt-username" control="loginTextbox-${randomIdSuffix}"/>
<input class="tabmodalprompt-loginTextbox" id="loginTextbox-${randomIdSuffix}"/>
</div>
<div class="tabmodalprompt-password1Container" hidden="hidden">
<xul:label class="tabmodalprompt-password1Label" data-l10n-id="tabmodalprompt-password" control="password1Textbox-${randomIdSuffix}"/>
<input class="tabmodalprompt-password1Textbox" type="password" id="password1Textbox-${randomIdSuffix}"/>
</div>
<div class="tabmodalprompt-checkboxContainer" hidden="hidden">
<div/>
<xul:checkbox class="tabmodalprompt-checkbox"/>
</div>
<!-- content goes here -->
</div>
<div class="tabmodalprompt-buttonContainer">
<xul:button class="tabmodalprompt-button3" hidden="true"/>
<div class="tabmodalprompt-buttonSpacer"/>
<xul:button class="tabmodalprompt-button0" data-l10n-id="tabmodalprompt-ok-button"/>
<xul:button class="tabmodalprompt-button2" hidden="true"/>
<xul:button class="tabmodalprompt-button1" data-l10n-id="tabmodalprompt-cancel-button"/>
</div>
</div>`
)
);
this.ui = {
prompt: this,
promptContainer: this.element,
mainContainer: newPrompt.querySelector(".tabmodalprompt-mainContainer"),
loginContainer: newPrompt.querySelector(".tabmodalprompt-loginContainer"),
loginTextbox: newPrompt.querySelector(".tabmodalprompt-loginTextbox"),
loginLabel: newPrompt.querySelector(".tabmodalprompt-loginLabel"),
password1Container: newPrompt.querySelector(
".tabmodalprompt-password1Container"
),
password1Textbox: newPrompt.querySelector(
".tabmodalprompt-password1Textbox"
),
password1Label: newPrompt.querySelector(".tabmodalprompt-password1Label"),
infoContainer: newPrompt.querySelector(".tabmodalprompt-infoContainer"),
infoBody: newPrompt.querySelector(".tabmodalprompt-infoBody"),
infoTitle: newPrompt.querySelector(".tabmodalprompt-infoTitle"),
infoIcon: null,
rows: newPrompt.querySelector(".tabmodalprompt-topContainer"),
checkbox: newPrompt.querySelector(".tabmodalprompt-checkbox"),
checkboxContainer: newPrompt.querySelector(
".tabmodalprompt-checkboxContainer"
),
button3: newPrompt.querySelector(".tabmodalprompt-button3"),
button2: newPrompt.querySelector(".tabmodalprompt-button2"),
button1: newPrompt.querySelector(".tabmodalprompt-button1"),
button0: newPrompt.querySelector(".tabmodalprompt-button0"),
// focusTarget (for BUTTON_DELAY_ENABLE) not yet supported
};
if (AppConstants.XP_UNIX) {
// Reorder buttons on Linux
let buttonContainer = newPrompt.querySelector(
".tabmodalprompt-buttonContainer"
);
buttonContainer.appendChild(this.ui.button3);
buttonContainer.appendChild(this.ui.button2);
buttonContainer.appendChild(
newPrompt.querySelector(".tabmodalprompt-buttonSpacer")
);
buttonContainer.appendChild(this.ui.button1);
buttonContainer.appendChild(this.ui.button0);
}
this.ui.button0.addEventListener(
"command",
this.onButtonClick.bind(this, 0)
);
this.ui.button1.addEventListener(
"command",
this.onButtonClick.bind(this, 1)
);
this.ui.button2.addEventListener(
"command",
this.onButtonClick.bind(this, 2)
);
this.ui.button3.addEventListener(
"command",
this.onButtonClick.bind(this, 3)
);
// Anonymous wrapper used here because |Dialog| doesn't exist until init() is called!
this.ui.checkbox.addEventListener("command", () => {
this.Dialog.onCheckbox();
});
/**
* Based on dialog.xml handlers
*/
this.element.addEventListener(
"keypress",
event => {
switch (event.keyCode) {
case KeyEvent.DOM_VK_RETURN:
this.onKeyAction("default", event);
break;
case KeyEvent.DOM_VK_ESCAPE:
this.onKeyAction("cancel", event);
break;
default:
if (
AppConstants.platform == "macosx" &&
event.key == "." &&
event.metaKey
) {
this.onKeyAction("cancel", event);
}
break;
}
},
{ mozSystemGroup: true }
);
this.element.addEventListener(
"focus",
event => {
let bnum = this.args.defaultButtonNum || 0;
let defaultButton = this.ui["button" + bnum];
if (AppConstants.platform == "macosx") {
// On OS X, the default button always stays marked as such (until
// the entire prompt blurs).
defaultButton.setAttribute("default", "true");
} else {
// On other platforms, the default button is only marked as such
// when no other button has focus. XUL buttons on not-OSX will
// react to pressing enter as a command, so you can't trigger the
// default without tabbing to it or something that isn't a button.
let focusedDefault = event.originalTarget == defaultButton;
let someButtonFocused =
event.originalTarget.localName == "button" ||
event.originalTarget.localName == "toolbarbutton";
if (focusedDefault || !someButtonFocused) {
defaultButton.setAttribute("default", "true");
}
}
},
true
);
this.element.addEventListener("blur", () => {
// If focus shifted to somewhere else in the browser, don't make
// the default button look active.
let bnum = this.args.defaultButtonNum || 0;
let button = this.ui["button" + bnum];
button.removeAttribute("default");
});
}
init(args, linkedTab, onCloseCallback) {
this.args = args;
this.linkedTab = linkedTab;
this.onCloseCallback = onCloseCallback;
if (args.enableDelay) {
throw new Error(
"BUTTON_DELAY_ENABLE not yet supported for tab-modal prompts"
);
}
// Apply styling depending on modalType (content or tab prompt)
if (args.modalType === Ci.nsIPrompt.MODAL_TYPE_TAB) {
this.element.classList.add("tab-prompt");
} else {
this.element.classList.add("content-prompt");
}
// We need to remove the prompt when the tab or browser window is closed or
// the page navigates, else we never unwind the event loop and that's sad times.
// Remember to cleanup in shutdownPrompt()!
this.win.addEventListener("resize", this);
this.win.addEventListener("unload", this);
if (linkedTab) {
linkedTab.addEventListener("TabClose", this);
}
// Note:
// nsPrompter.js or in e10s mode browser-parent.js call abortPrompt,
// when the domWindow, for which the prompt was created, generates
// a "pagehide" event.
let { CommonDialog } = ChromeUtils.importESModule(
"resource://gre/modules/CommonDialog.sys.mjs"
);
this.Dialog = new CommonDialog(args, this.ui);
this.Dialog.onLoad(null);
// For content prompts display the tabprompt title that shows the prompt origin when
// the prompt origin is not the same as that of the top window.
if (
args.modalType == Ci.nsIPrompt.MODAL_TYPE_CONTENT &&
args.showCallerOrigin
) {
this.ui.infoTitle.removeAttribute("hidden");
}
// TODO: should unhide buttonSpacer on Windows when there are 4 buttons.
// Better yet, just drop support for 4-button dialogs. (bug 609510)
}
shutdownPrompt() {
// remove our event listeners
try {
this.win.removeEventListener("resize", this);
this.win.removeEventListener("unload", this);
if (this.linkedTab) {
this.linkedTab.removeEventListener("TabClose", this);
}
} catch (e) {}
// invoke callback
this.onCloseCallback();
this.win = null;
this.ui = null;
// Intentionally not cleaning up |this.element| here --
// TabModalPromptBox.removePrompt() would need it and it might not
// be called yet -- see browser_double_close_tabs.js.
}
abortPrompt() {
// Called from other code when the page changes.
this.Dialog.abortPrompt();
this.shutdownPrompt();
}
handleEvent(aEvent) {
switch (aEvent.type) {
case "unload":
case "TabClose":
this.abortPrompt();
break;
}
}
onButtonClick(buttonNum) {
// We want to do all the work her asynchronously off a Gecko
// runnable, because of situations like the one described in
// https://bugzilla.mozilla.org/show_bug.cgi?id=1167575#c35 : we
// get here off processing of an OS event and will also process
// one more Gecko runnable before we break out of the event loop
// spin whoever posted the prompt is doing. If we do all our
// work sync, we will exit modal state _before_ processing that
// runnable, and if exiting moral state posts a runnable we will
// incorrectly process that runnable before leaving our event
// loop spin.
Services.tm.dispatchToMainThread(() => {
this.Dialog["onButton" + buttonNum]();
this.shutdownPrompt();
});
}
onKeyAction(action, event) {
if (event.defaultPrevented) {
return;
}
event.stopPropagation();
if (action == "default") {
let bnum = this.args.defaultButtonNum || 0;
this.onButtonClick(bnum);
} else {
// action == "cancel"
this.onButtonClick(1); // Cancel button
}
}
};

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

@ -9,5 +9,3 @@ toolkit.jar:
content/global/commonDialog.css (content/commonDialog.css)
content/global/selectDialog.js (content/selectDialog.js)
content/global/selectDialog.xhtml (content/selectDialog.xhtml)
content/global/tabprompts.css (content/tabprompts.css)
content/global/tabprompts.sys.mjs (content/tabprompts.sys.mjs)

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

@ -30,11 +30,10 @@ CommonDialog.prototype = {
initialFocusResolver: null,
/**
* @param [commonDialogEl] - Dialog element from commonDialog.xhtml,
* null for TabModalPrompts.
* @param [commonDialogEl] - Dialog element from commonDialog.xhtml.
*/
async onLoad(commonDialogEl = null) {
let isEmbedded = !!commonDialogEl?.ownerGlobal.docShell.chromeEventHandler;
async onLoad(commonDialogEl) {
let isEmbedded = !!commonDialogEl.ownerGlobal.docShell.chromeEventHandler;
switch (this.args.promptType) {
case "alert":
@ -106,36 +105,19 @@ CommonDialog.prototype = {
throw new Error("unknown dialog type");
}
if (commonDialogEl) {
commonDialogEl.setAttribute(
"windowtype",
"prompt:" + this.args.promptType
);
}
commonDialogEl.setAttribute("windowtype", "prompt:" + this.args.promptType);
// set the document title
let title = this.args.title;
let infoTitle = this.ui.infoTitle;
infoTitle.appendChild(infoTitle.ownerDocument.createTextNode(title));
// Specific check to prevent showing the title on the old content prompts for macOS.
// This should be removed when the old content prompts are removed.
let contentSubDialogPromptEnabled = Services.prefs.getBoolPref(
"prompts.contentPromptSubDialog"
);
let isOldContentPrompt =
!contentSubDialogPromptEnabled &&
this.args.modalType == Ci.nsIPrompt.MODAL_TYPE_CONTENT;
// After making these preventative checks, we can determine to show it if we're on
// macOS (where there is no titlebar) or if the prompt is a common dialog document
// and has been embedded (has a chromeEventHandler).
infoTitle.hidden =
isOldContentPrompt || !(AppConstants.platform === "macosx" || isEmbedded);
infoTitle.hidden = !(AppConstants.platform === "macosx" || isEmbedded);
if (commonDialogEl) {
commonDialogEl.ownerDocument.title = title;
}
commonDialogEl.ownerDocument.title = title;
// Set button labels and visibility
//
@ -202,15 +184,7 @@ CommonDialog.prototype = {
// Set the default button
let b = this.args.defaultButtonNum || 0;
let button = this.ui["button" + b];
if (commonDialogEl) {
commonDialogEl.defaultButton = ["accept", "cancel", "extra1", "extra2"][
b
];
} else {
button.setAttribute("default", "true");
}
commonDialogEl.defaultButton = ["accept", "cancel", "extra1", "extra2"][b];
if (!isEmbedded && !this.ui.promptContainer?.hidden) {
// Set default focus and select textbox contents if applicable. If we're
@ -229,7 +203,7 @@ CommonDialog.prototype = {
// Play a sound (unless we're showing a content prompt -- don't want those
// to feel like OS prompts).
try {
if (commonDialogEl && this.soundID && !this.args.openedWithTabDialog) {
if (this.soundID && !this.args.openedWithTabDialog) {
Cc["@mozilla.org/sound;1"]
.getService(Ci.nsISound)
.playEventSound(this.soundID);
@ -238,20 +212,12 @@ CommonDialog.prototype = {
console.error("Couldn't play common dialog event sound: ", e);
}
if (commonDialogEl) {
if (isEmbedded) {
// If we delayed default focus above, wait for it to be ready before
// sending the notification.
await this.initialFocusPromise;
}
Services.obs.notifyObservers(this.ui.prompt, "common-dialog-loaded");
} else {
// ui.promptContainer is the <tabmodalprompt> element.
Services.obs.notifyObservers(
this.ui.promptContainer,
"tabmodal-dialog-loaded"
);
if (isEmbedded) {
// If we delayed default focus above, wait for it to be ready before
// sending the notification.
await this.initialFocusPromise;
}
Services.obs.notifyObservers(this.ui.prompt, "common-dialog-loaded");
},
setLabelForNode(aNode, aLabel) {

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

@ -31,52 +31,6 @@ async function handlePromptWhenItAppears(action, modalType, isSelect) {
}
}
function checkTabModal(prompt, browser) {
let doc = browser.ownerDocument;
let { bottom: toolboxBottom } = doc
.getElementById("navigator-toolbox")
.getBoundingClientRect();
let { mainContainer } = prompt.ui;
let { x, y } = mainContainer.getBoundingClientRect();
ok(y > 0, "Container should have y > 0");
// Inset by 1px since the corner point doesn't return the frame due to the
// border-radius.
is(
doc.elementFromPoint(x + 1, y + 1).parentNode,
mainContainer,
"Check tabmodalprompt is visible"
);
info("Click to the left of the dialog over the content area");
isnot(
doc.elementFromPoint(x - 10, y + 50),
browser,
"Check clicks on the content area don't go to the browser"
);
is(
doc.elementFromPoint(x - 10, y + 50),
prompt.element,
"Check clicks on the content area go to the prompt dialog background"
);
if (prompt.args.modalType == Ci.nsIPrompt.MODAL_TYPE_TAB) {
ok(
y <= toolboxBottom - 5,
"Dialog should overlap the toolbox by at least 5px"
);
} else {
ok(y >= toolboxBottom, "Dialog must not overlap with toolbox.");
}
ok(
browser.hasAttribute("tabmodalPromptShowing"),
"Check browser has @tabmodalPromptShowing"
);
}
async function handlePrompt(action, modalType, isSelect) {
let ui;
let browserWin = Services.wm.getMostRecentWindow("navigator:browser");
@ -142,8 +96,7 @@ function getPromptState(ui) {
state.checkHidden = ui.checkboxContainer.hidden;
state.checkMsg = state.checkHidden ? "" : ui.checkbox.label;
state.checked = state.checkHidden ? false : ui.checkbox.checked;
// TabModalPrompts don't have an infoIcon
state.iconClass = ui.infoIcon ? ui.infoIcon.className : null;
state.iconClass = ui.infoIcon.className;
state.textValue = ui.loginTextbox.value;
state.passValue = ui.password1Textbox.value;

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

@ -17,10 +17,6 @@ function propBagToObject(bag) {
}
var modalType;
var tabSubDialogsEnabled = SpecialPowers.Services.prefs.getBoolPref(
"prompts.tabChromePromptSubDialog",
false
);
var isSelectDialog = false;
var isOSX = "nsILocalFileMac" in SpecialPowers.Ci;
var isE10S = SpecialPowers.Services.appinfo.processType == 2;
@ -227,7 +223,7 @@ function checkPromptState(promptState, expectedState) {
is(promptState.checked, expectedState.checked, "Checking checkbox checked");
if (
modalType === Ci.nsIPrompt.MODAL_TYPE_WINDOW ||
(modalType === Ci.nsIPrompt.MODAL_TYPE_TAB && tabSubDialogsEnabled)
modalType === Ci.nsIPrompt.MODAL_TYPE_TAB
) {
is(
promptState.iconClass,

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

@ -1,13 +0,0 @@
# 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/.
tabmodalprompt-username =
.value = User Name:
tabmodalprompt-password =
.value = Password:
tabmodalprompt-ok-button =
.label = OK
tabmodalprompt-cancel-button =
.label = Cancel

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

@ -13,9 +13,6 @@
content="default-src chrome:; style-src chrome: 'unsafe-inline'; img-src chrome: file: jar: https: http:; connect-src chrome: data: https: http:; object-src 'none'"
/>
<meta name="color-scheme" content="light dark" />
<link rel="stylesheet" href="chrome://global/content/tabprompts.css" />
<link rel="stylesheet" href="chrome://global/skin/tabprompts.css" />
<link rel="stylesheet" href="chrome://global/skin/in-content/common.css" />
<link
rel="stylesheet"

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

@ -5,7 +5,7 @@
"use strict";
/* exported attachUpdateHandler, detachUpdateHandler, gBrowser,
/* exported attachUpdateHandler, detachUpdateHandler,
* getBrowserElement, installAddonsFromFilePicker,
* isCorrectlySigned, isDisabledUnsigned, isDiscoverEnabled,
* isPending, loadReleaseNotes, openOptionsInTab, promiseEvent,
@ -196,21 +196,6 @@ function showPermissionsPrompt(addon) {
});
}
// Stub tabbrowser implementation for use by the tab-modal alert code
// when an alert/prompt/confirm method is called in a WebExtensions options_ui
// page (See Bug 1385548 for rationale).
var gBrowser = {
getTabModalPromptBox(browser) {
const parentWindow = window.docShell.chromeEventHandler.ownerGlobal;
if (parentWindow.gBrowser) {
return parentWindow.gBrowser.getTabModalPromptBox(browser);
}
return null;
},
};
function isCorrectlySigned(addon) {
// Add-ons without an "isCorrectlySigned" property are correctly signed as
// they aren't the correct type for signing.

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

@ -133,7 +133,6 @@ var Harness = {
Services.obs.addObserver(this, "addon-install-failed");
// For browser_auth tests which trigger auth dialogs.
Services.obs.addObserver(this, "tabmodal-dialog-loaded");
Services.obs.addObserver(this, "common-dialog-loaded");
this._boundWin = Cu.getWeakReference(win); // need this so our addon manager listener knows which window to use.
@ -157,7 +156,6 @@ var Harness = {
Services.obs.removeObserver(self, "addon-install-blocked");
Services.obs.removeObserver(self, "addon-install-failed");
Services.obs.removeObserver(self, "tabmodal-dialog-loaded");
Services.obs.removeObserver(self, "common-dialog-loaded");
AddonManager.removeInstallListener(self);
@ -553,11 +551,6 @@ var Harness = {
);
}, this);
break;
case "tabmodal-dialog-loaded":
let browser = subject.ownerGlobal.gBrowser.selectedBrowser;
let prompt = browser.tabModalPromptBox.getPrompt(subject);
this.promptReady(prompt.Dialog);
break;
case "common-dialog-loaded":
this.promptReady(subject.Dialog);
break;

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

@ -12,7 +12,6 @@ toolkit.jar:
skin/classic/global/menu.css
skin/classic/global/menulist.css
skin/classic/global/richlistbox.css
skin/classic/global/tabprompts.css
skin/classic/global/tabbox.css
skin/classic/global/toolbar.css
skin/classic/global/wizard.css

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

@ -1,62 +0,0 @@
/* 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/. */
/* Tab Modal Prompt boxes */
.tabModalBackground,
tabmodalprompt {
background-color: hsla(0,0%,10%,.5);
}
tabmodalprompt {
font-family: sans-serif; /* use content font not system UI font */
font-size: 110%;
}
.tabmodalprompt-mainContainer {
color: black;
background-color: hsla(0,0%,100%,.95);
background-clip: padding-box;
border-radius: 2px;
border: 1px solid hsla(0,0%,0%,.5);
}
.tabmodalprompt-buttonContainer {
background-color: hsla(0,0%,0%,.05);
border-top: 1px solid hsla(0,0%,0%,.05);
}
.tabmodalprompt-buttonContainer > button {
appearance: none;
padding: 2px 0;
margin: 0;
margin-inline-start: 8px;
border-radius: 2px;
color: black !important;
background-color: hsl(0,0%,90%);
background-image: linear-gradient(hsla(0,0%,100%,.7), transparent);
background-clip: padding-box;
border: 1px solid;
border-color: hsl(0,0%,65%) hsl(0,0%,60%) hsl(0,0%,50%);
box-shadow: 0 1px 0 hsla(0,0%,100%,.9) inset,
0 1px 2px hsla(0,0%,0%,.1);
}
.tabmodalprompt-buttonContainer > button[default=true] {
background-color: hsl(0,0%,79%);
}
.tabmodalprompt-buttonContainer > button:hover {
background-color: hsl(0,0%,96%);
}
.tabmodalprompt-buttonContainer > button:hover:active {
background-image: linear-gradient(hsla(0,0%,100%,.2), transparent);
background-color: hsl(0,0%,70%);
box-shadow: 0 1px 0 hsla(0,0%,100%,.2) inset,
0 1px 3px hsla(0,0%,0%,.2);
}
.tabmodalprompt-buttonContainer > button:focus-visible {
outline: var(--focus-outline);
}

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

@ -11,7 +11,6 @@
#include desktop-jar.inc.mn
skin/classic/global/dialog.css (../../windows/global/dialog.css)
skin/classic/global/tabprompts.css (../../windows/global/tabprompts.css)
skin/classic/global/wizard.css (../../windows/global/wizard.css)
skin/classic/global/arrow/panelarrow-vertical.svg (../../windows/global/arrow/panelarrow-vertical.svg)

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

@ -1,25 +0,0 @@
/* 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/. */
/* Tab Modal Prompt boxes */
.tabModalBackground,
tabmodalprompt {
background-color: hsla(0,0%,10%,.5);
}
tabmodalprompt {
font-family: sans-serif; /* use content font not system UI font */
}
.tabmodalprompt-mainContainer {
color: FieldText;
background-color: Field;
border-radius: 2px;
border: 1px solid threeDDarkShadow;
}
.tabmodalprompt-buttonContainer {
background-color: hsla(0,0%,0%,.05);
border-top: 1px solid hsla(0,0%,0%,.05);
}