Bug 1680637 - Add a dialog manager for content prompts in TabDialogBox r=jaws,Gijs

The TabDialogBox will manage two separate SubDialog managers at the tab and content level. Dialogs managed at the tab level will always be on top of content ones and should always receive focus first when tab switching or refocusing the window.

Differential Revision: https://phabricator.services.mozilla.com/D100066
This commit is contained in:
Micah Tigley
2021-01-11 20:55:09 +00:00
parent 025f8bbe75
commit c784c7cf74
5 changed files with 146 additions and 19 deletions

View File

@@ -8907,6 +8907,8 @@ class TabDialogBox {
// Create parent element for dialogs
let template = document.getElementById("dialogStackTemplate");
let dialogStack = template.content.cloneNode(true).firstElementChild;
dialogStack.classList.add("tab-prompt-dialog");
this.browser.parentNode.insertBefore(
dialogStack,
this.browser.nextElementSibling
@@ -8927,7 +8929,7 @@ class TabDialogBox {
}
/**
* Open a dialog on tab level.
* Open a dialog on tab or content level.
* @param {String} aURL - URL of the dialog to load in the tab box.
* @param {Object} [aOptions]
* @param {String} [aOptions.features] - Comma separated list of window
@@ -8940,6 +8942,8 @@ class TabDialogBox {
* @param {Boolean} [aOptions.keepOpenSameOriginNav] - By default dialogs are
* aborted on any navigation.
* Set to true to keep the dialog open for same origin navigation.
* @param {Number} [aOptions.modalType] - The modal type to create the dialog for.
* By default, we show the dialog for tab prompts.
* @returns {Promise} - Resolves once the dialog has been closed.
*/
open(
@@ -8949,22 +8953,32 @@ class TabDialogBox {
allowDuplicateDialogs = true,
sizeTo,
keepOpenSameOriginNav,
modalType = null,
} = {},
...aParams
) {
return new Promise(resolve => {
if (!this._dialogManager.hasDialogs) {
// Get the dialog manager to open the prompt with.
let dialogManager =
modalType === Ci.nsIPrompt.MODAL_TYPE_CONTENT
? this.getContentDialogManager()
: this._dialogManager;
let hasDialogs =
this._dialogManager.hasDialogs ||
this._contentDialogManager?.hasDialogs;
if (!hasDialogs) {
this._onFirstDialogOpen();
}
let closingCallback = () => {
if (!this._dialogManager.hasDialogs) {
if (!hasDialogs) {
this._onLastDialogClose();
}
};
// Open dialog and resolve once it has been closed
let dialog = this._dialogManager.open(
let dialog = dialogManager.open(
aURL,
{
features,
@@ -9009,6 +9023,29 @@ class TabDialogBox {
this.tab?.removeEventListener("TabClose", this);
}
_buildContentPromptDialog() {
let template = document.getElementById("dialogStackTemplate");
let contentDialogStack = template.content.cloneNode(true).firstElementChild;
contentDialogStack.classList.add("content-prompt-dialog");
// Create a dialog manager for content prompts.
let tabPromptDialog = this.browser.parentNode.querySelector(
".tab-prompt-dialog"
);
this.browser.parentNode.insertBefore(contentDialogStack, tabPromptDialog);
let contentDialogTemplate = contentDialogStack.firstElementChild;
this._contentDialogManager = new SubDialogManager({
dialogStack: contentDialogStack,
dialogTemplate: contentDialogTemplate,
orderType: SubDialogManager.ORDER_QUEUE,
allowDuplicateDialogs: true,
dialogOptions: {
consumeOutsideClicks: false,
},
});
}
handleEvent(event) {
if (event.type !== "TabClose") {
return;
@@ -9018,10 +9055,16 @@ class TabDialogBox {
abortAllDialogs() {
this._dialogManager.abortDialogs();
this._contentDialogManager?.abortDialogs();
}
focus() {
this._dialogManager.focusTopDialog();
// Prioritize focusing the dialog manager for tab prompts
if (this._dialogManager._dialogs.length) {
this._dialogManager.focusTopDialog();
return;
}
this._contentDialogManager?.focusTopDialog();
}
/**
@@ -9052,6 +9095,7 @@ class TabDialogBox {
this._lastPrincipal = this.browser.contentPrincipal;
this._dialogManager.abortDialogs(filterFn);
this._contentDialogManager?.abortDialogs(filterFn);
}
get tab() {
@@ -9069,6 +9113,13 @@ class TabDialogBox {
getManager() {
return this._dialogManager;
}
getContentDialogManager() {
if (!this._contentDialogManager) {
this._buildContentPromptDialog();
}
return this._contentDialogManager;
}
}
TabDialogBox.prototype.QueryInterface = ChromeUtils.generateQI([