зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1615588 - Extended nsIPromptService to support tab modal prompts. r=johannh,MattN,necko-reviewers,dragana
This patch introduces a new tab modal system prompt type. It can be opened via the nsIPromptService with a destination BrowsingContext. These tab system prompts overlap slightly with the upper chrome UI to differentiate them from content prompts (previously called tab prompts). - Extended nsIPromptService and nsIPrompt to accept 3 types of modal prompts: - Window prompts - Tab (system) prompts - Content prompts (the old tab prompts) - Removed prompt code from Prompter.jsm, always call PromptParent window actor instead - Added PromptChild window actor to forward pagehide events to parent actor - Created additional prompt methods in nsIPromptService to prompt by browsingContext and modalType - Backwards compatibility is maintained, consumers can still open content prompts calling nsIPrompt with a content window Differential Revision: https://phabricator.services.mozilla.com/D66446
This commit is contained in:
Родитель
74bd4471ab
Коммит
3075dbd453
|
@ -0,0 +1,20 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = ["PromptChild"];
|
||||
|
||||
class PromptChild extends JSWindowActorChild {
|
||||
constructor(dispatcher) {
|
||||
super(dispatcher);
|
||||
}
|
||||
|
||||
handleEvent(aEvent) {
|
||||
if (aEvent.type !== "pagehide") {
|
||||
return;
|
||||
}
|
||||
this.sendAsyncMessage("Prompt:OnPageHide", {});
|
||||
}
|
||||
}
|
|
@ -120,40 +120,35 @@ class PromptParent extends JSWindowActorParent {
|
|||
forceClosePrompts(browsingContext) {
|
||||
let prompts = gBrowserPrompts.get(browsingContext) || [];
|
||||
|
||||
for (let prompt of prompts) {
|
||||
if (prompt.tabModalPrompt) {
|
||||
prompt.tabModalPrompt.abortPrompt();
|
||||
}
|
||||
for (let [, prompt] of prompts) {
|
||||
prompt.tabModalPrompt && prompt.tabModalPrompt.abortPrompt();
|
||||
}
|
||||
}
|
||||
|
||||
receiveMessage(message) {
|
||||
let browsingContext = this.browsingContext;
|
||||
let args = message.data;
|
||||
let browsingContext = args.browsingContext || this.browsingContext;
|
||||
let id = args._remoteId;
|
||||
|
||||
switch (message.name) {
|
||||
case "Prompt:Open": {
|
||||
const COMMON_DIALOG = "chrome://global/content/commonDialog.xhtml";
|
||||
const SELECT_DIALOG = "chrome://global/content/selectDialog.xhtml";
|
||||
|
||||
let topPrincipal =
|
||||
browsingContext.top.currentWindowGlobal.documentPrincipal;
|
||||
args.showAlertOrigin = topPrincipal.equals(args.promptPrincipal);
|
||||
|
||||
if (message.data.tabPrompt) {
|
||||
return this.openTabPrompt(message.data, browsingContext, id);
|
||||
if (args.modalType === Ci.nsIPrompt.MODAL_TYPE_WINDOW) {
|
||||
return this.openWindowPrompt(args, browsingContext);
|
||||
}
|
||||
let uri =
|
||||
message.data.promptType == "select" ? SELECT_DIALOG : COMMON_DIALOG;
|
||||
|
||||
let browser = browsingContext.top.embedderElement;
|
||||
return this.openModalWindow(uri, message.data, browser);
|
||||
return this.openTabPrompt(args, browsingContext, id);
|
||||
}
|
||||
case "Prompt:ForceClose": {
|
||||
this.forceClosePrompt(browsingContext, id);
|
||||
break;
|
||||
}
|
||||
case "Prompt:OnPageHide": {
|
||||
// User navigates away, close all non window prompts
|
||||
this.forceClosePrompts(browsingContext);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
|
@ -172,12 +167,15 @@ class PromptParent extends JSWindowActorParent {
|
|||
* A unique ID to differentiate multiple Prompts coming from the same
|
||||
* BrowsingContext.
|
||||
* @return {Promise}
|
||||
* Resolves when the TabModalPrompt is dismissed.
|
||||
* @resolves {Object}
|
||||
* Resolves with the arguments returned from the TabModalPrompt when it
|
||||
* is dismissed.
|
||||
* The arguments returned from the TabModalPrompt.
|
||||
*/
|
||||
openTabPrompt(args, browsingContext, id) {
|
||||
openTabPrompt(args, browsingContext = this.browsingContext, id) {
|
||||
let browser = 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;
|
||||
|
@ -206,7 +204,7 @@ class PromptParent extends JSWindowActorParent {
|
|||
|
||||
PromptUtils.fireDialogEvent(window, "DOMModalDialogClosed", browser);
|
||||
resolver(args);
|
||||
browser.leaveModalState();
|
||||
browser.maybeLeaveModalState();
|
||||
};
|
||||
|
||||
try {
|
||||
|
@ -242,31 +240,49 @@ class PromptParent extends JSWindowActorParent {
|
|||
}
|
||||
|
||||
/**
|
||||
* Opens a window-modal prompt for a BrowsingContext, and puts the associated
|
||||
* Opens a window prompt for a BrowsingContext, and puts the associated
|
||||
* browser in the modal state until the prompt is closed.
|
||||
*
|
||||
* @param {string} uri
|
||||
* The URI to a XUL document to be loaded in a modal window.
|
||||
* @param {Object} args
|
||||
* The arguments passed up from the BrowsingContext to be passed
|
||||
* directly to the modal window.
|
||||
* @param {Element} browser
|
||||
* The <xul:browser> from which the request to open the window-modal
|
||||
* @param {BrowsingContext} browsingContext
|
||||
* The BrowsingContext from which the request to open the window-modal
|
||||
* prompt came.
|
||||
* @return {Promise}
|
||||
* Resolves when the window prompt is dismissed.
|
||||
* @resolves {Object}
|
||||
* Resolves with the arguments returned from the window-modal
|
||||
* prompt when it is dismissed.
|
||||
* The arguments returned from the window prompt.
|
||||
*/
|
||||
openModalWindow(uri, args, browser) {
|
||||
let window = browser.ownerGlobal;
|
||||
openWindowPrompt(args, browsingContext = this.browsingContext) {
|
||||
const COMMON_DIALOG = "chrome://global/content/commonDialog.xhtml";
|
||||
const SELECT_DIALOG = "chrome://global/content/selectDialog.xhtml";
|
||||
let uri = args.promptType == "select" ? SELECT_DIALOG : COMMON_DIALOG;
|
||||
|
||||
let browser = browsingContext.top.embedderElement;
|
||||
// If can't get the browser, because the BC does not have an embedder element,
|
||||
// use window associated with the BC.
|
||||
// This happens if we are passed a browsingContext of a chrome window.
|
||||
let win = (browser && browser.ownerGlobal) || browsingContext.top.window;
|
||||
|
||||
// There's a requirement for prompts to be blocked if a window is
|
||||
// passed and that window is hidden (eg, auth prompts are suppressed if the
|
||||
// passed window is the hidden window).
|
||||
// See bug 875157 comment 30 for more..
|
||||
if (win && win.winUtils && !win.winUtils.isParentWindowMainWidgetVisible) {
|
||||
throw new Error("Cannot call openModalWindow on a hidden window");
|
||||
}
|
||||
|
||||
try {
|
||||
browser.enterModalState();
|
||||
PromptUtils.fireDialogEvent(window, "DOMWillOpenModalDialog", browser);
|
||||
if (browser) {
|
||||
browser.enterModalState();
|
||||
PromptUtils.fireDialogEvent(win, "DOMWillOpenModalDialog", browser);
|
||||
}
|
||||
|
||||
let bag = PromptUtils.objectToPropBag(args);
|
||||
|
||||
Services.ww.openWindow(
|
||||
window,
|
||||
win,
|
||||
uri,
|
||||
"_blank",
|
||||
"centerscreen,chrome,modal,titlebar",
|
||||
|
@ -275,8 +291,10 @@ class PromptParent extends JSWindowActorParent {
|
|||
|
||||
PromptUtils.propBagToObject(bag, args);
|
||||
} finally {
|
||||
browser.leaveModalState();
|
||||
PromptUtils.fireDialogEvent(window, "DOMModalDialogClosed", browser);
|
||||
if (browser) {
|
||||
browser.leaveModalState();
|
||||
PromptUtils.fireDialogEvent(win, "DOMModalDialogClosed", browser);
|
||||
}
|
||||
}
|
||||
return Promise.resolve(args);
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ FINAL_TARGET_FILES.actors += [
|
|||
'PageStyleParent.jsm',
|
||||
'PluginChild.jsm',
|
||||
'PluginParent.jsm',
|
||||
'PromptChild.jsm',
|
||||
'PromptParent.jsm',
|
||||
'RFPHelperChild.jsm',
|
||||
'RFPHelperParent.jsm',
|
||||
|
|
|
@ -1252,6 +1252,10 @@ pref("browser.menu.showCharacterEncoding", "chrome://browser/locale/browser.prop
|
|||
// Allow using tab-modal prompts when possible.
|
||||
pref("prompts.tab_modal.enabled", true);
|
||||
|
||||
// Whether prompts should be content modal (1) tab modal (2) or window modal(3) by default
|
||||
// This is a fallback value for when prompt callers do not specify a modalType.
|
||||
pref("prompts.defaultModalType", 3);
|
||||
|
||||
// Activates preloading of the new tab url.
|
||||
pref("browser.newtab.preload", true);
|
||||
|
||||
|
|
|
@ -324,7 +324,15 @@ let ACTORS = {
|
|||
parent: {
|
||||
moduleURI: "resource:///actors/PromptParent.jsm",
|
||||
},
|
||||
|
||||
child: {
|
||||
moduleURI: "resource:///actors/PromptChild.jsm",
|
||||
events: {
|
||||
pagehide: {
|
||||
capture: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
includeChrome: true,
|
||||
allFrames: true,
|
||||
},
|
||||
|
||||
|
|
|
@ -11567,11 +11567,12 @@ nsresult nsDocShell::ConfirmRepost(bool* aRepost) {
|
|||
return rv;
|
||||
}
|
||||
|
||||
// Make the repost prompt tab modal to prevent malicious pages from locking
|
||||
// up the browser, see bug 1412559 for an example.
|
||||
// Make the repost prompt content modal to prevent malicious pages from
|
||||
// locking up the browser, see bug 1412559 for an example.
|
||||
if (nsCOMPtr<nsIWritablePropertyBag2> promptBag =
|
||||
do_QueryInterface(prompter)) {
|
||||
promptBag->SetPropertyAsBool(NS_LITERAL_STRING("allowTabModal"), true);
|
||||
promptBag->SetPropertyAsUint32(NS_LITERAL_STRING("modalType"),
|
||||
nsIPrompt::MODAL_TYPE_CONTENT);
|
||||
}
|
||||
|
||||
int32_t buttonPressed;
|
||||
|
|
|
@ -4939,9 +4939,10 @@ bool nsGlobalWindowOuter::AlertOrConfirm(bool aAlert, const nsAString& aMessage,
|
|||
return false;
|
||||
}
|
||||
|
||||
// Always allow tab modal prompts for alert and confirm.
|
||||
// Always allow content modal prompts for alert and confirm.
|
||||
if (nsCOMPtr<nsIWritablePropertyBag2> promptBag = do_QueryInterface(prompt)) {
|
||||
promptBag->SetPropertyAsBool(NS_LITERAL_STRING("allowTabModal"), true);
|
||||
promptBag->SetPropertyAsUint32(NS_LITERAL_STRING("modalType"),
|
||||
nsIPrompt::MODAL_TYPE_CONTENT);
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
|
@ -5028,9 +5029,10 @@ void nsGlobalWindowOuter::PromptOuter(const nsAString& aMessage,
|
|||
return;
|
||||
}
|
||||
|
||||
// Always allow tab modal prompts for prompt.
|
||||
// Always allow content modal prompts for prompt.
|
||||
if (nsCOMPtr<nsIWritablePropertyBag2> promptBag = do_QueryInterface(prompt)) {
|
||||
promptBag->SetPropertyAsBool(NS_LITERAL_STRING("allowTabModal"), true);
|
||||
promptBag->SetPropertyAsUint32(NS_LITERAL_STRING("modalType"),
|
||||
nsIPrompt::MODAL_TYPE_CONTENT);
|
||||
}
|
||||
|
||||
// Pass in the default value, if any.
|
||||
|
|
|
@ -1297,7 +1297,7 @@ interface nsIDOMWindowUtils : nsISupports {
|
|||
/**
|
||||
* Is the window is in a modal state? [See enterModalState()]
|
||||
*/
|
||||
[noscript] boolean isInModalState();
|
||||
boolean isInModalState();
|
||||
|
||||
/**
|
||||
* Request set internal desktopMode flag change.
|
||||
|
|
|
@ -61,6 +61,12 @@ interface nsIPrompt : nsISupports
|
|||
const unsigned long STD_YES_NO_BUTTONS = (BUTTON_TITLE_YES * BUTTON_POS_0) +
|
||||
(BUTTON_TITLE_NO * BUTTON_POS_1);
|
||||
|
||||
|
||||
// Indicates whether a prompt should be shown in-content, on tab level or as a separate window
|
||||
const unsigned long MODAL_TYPE_CONTENT = 1;
|
||||
const unsigned long MODAL_TYPE_TAB = 2;
|
||||
const unsigned long MODAL_TYPE_WINDOW = 3;
|
||||
|
||||
int32_t confirmEx(in wstring dialogTitle,
|
||||
in wstring text,
|
||||
in unsigned long buttonFlags,
|
||||
|
|
|
@ -41,6 +41,12 @@ class BrowserElementChild extends JSWindowActorChild {
|
|||
}
|
||||
|
||||
case "LeaveModalState": {
|
||||
if (
|
||||
!message.data.forceLeave &&
|
||||
!this.contentWindow.windowUtils.isInModalState()
|
||||
) {
|
||||
break;
|
||||
}
|
||||
this.contentWindow.windowUtils.leaveModalState();
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -26,8 +26,8 @@ Prompter.prototype = {
|
|||
|
||||
/* ---------- private members ---------- */
|
||||
|
||||
pickPrompter(domWin) {
|
||||
return new ModalPrompter(domWin);
|
||||
pickPrompter(options) {
|
||||
return new ModalPrompter(options);
|
||||
},
|
||||
|
||||
/* ---------- nsIPromptFactory ---------- */
|
||||
|
@ -48,7 +48,7 @@ Prompter.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
let p = new ModalPrompter(domWin);
|
||||
let p = new ModalPrompter({ domWin });
|
||||
p.QueryInterface(iid);
|
||||
return p;
|
||||
},
|
||||
|
@ -56,25 +56,45 @@ Prompter.prototype = {
|
|||
/* ---------- nsIPromptService ---------- */
|
||||
|
||||
alert(domWin, title, text) {
|
||||
let p = this.pickPrompter(domWin);
|
||||
let p = this.pickPrompter({ domWin });
|
||||
p.alert(title, text);
|
||||
},
|
||||
|
||||
alertBC(browsingContext, modalType, ...promptArgs) {
|
||||
let p = this.pickPrompter({ browsingContext, modalType });
|
||||
p.alert(...promptArgs);
|
||||
},
|
||||
|
||||
alertCheck(domWin, title, text, checkLabel, checkValue) {
|
||||
let p = this.pickPrompter(domWin);
|
||||
let p = this.pickPrompter({ domWin });
|
||||
p.alertCheck(title, text, checkLabel, checkValue);
|
||||
},
|
||||
|
||||
alertCheckBC(browsingContext, modalType, ...promptArgs) {
|
||||
let p = this.pickPrompter({ browsingContext, modalType });
|
||||
p.alertCheck(...promptArgs);
|
||||
},
|
||||
|
||||
confirm(domWin, title, text) {
|
||||
let p = this.pickPrompter(domWin);
|
||||
let p = this.pickPrompter({ domWin });
|
||||
return p.confirm(title, text);
|
||||
},
|
||||
|
||||
confirmBC(browsingContext, modalType, ...promptArgs) {
|
||||
let p = this.pickPrompter({ browsingContext, modalType });
|
||||
return p.confirm(...promptArgs);
|
||||
},
|
||||
|
||||
confirmCheck(domWin, title, text, checkLabel, checkValue) {
|
||||
let p = this.pickPrompter(domWin);
|
||||
let p = this.pickPrompter({ domWin });
|
||||
return p.confirmCheck(title, text, checkLabel, checkValue);
|
||||
},
|
||||
|
||||
confirmCheckBC(browsingContext, modalType, ...promptArgs) {
|
||||
let p = this.pickPrompter({ browsingContext, modalType });
|
||||
return p.confirmCheck(...promptArgs);
|
||||
},
|
||||
|
||||
confirmEx(
|
||||
domWin,
|
||||
title,
|
||||
|
@ -86,7 +106,32 @@ Prompter.prototype = {
|
|||
checkLabel,
|
||||
checkValue
|
||||
) {
|
||||
let p = this.pickPrompter(domWin);
|
||||
let p = this.pickPrompter({ domWin });
|
||||
return p.confirmEx(
|
||||
title,
|
||||
text,
|
||||
flags,
|
||||
button0,
|
||||
button1,
|
||||
button2,
|
||||
checkLabel,
|
||||
checkValue
|
||||
);
|
||||
},
|
||||
|
||||
confirmExBC(
|
||||
browsingContext,
|
||||
modalType,
|
||||
title,
|
||||
text,
|
||||
flags,
|
||||
button0,
|
||||
button1,
|
||||
button2,
|
||||
checkLabel,
|
||||
checkValue
|
||||
) {
|
||||
let p = this.pickPrompter({ browsingContext, modalType });
|
||||
return p.confirmEx(
|
||||
title,
|
||||
text,
|
||||
|
@ -100,10 +145,15 @@ Prompter.prototype = {
|
|||
},
|
||||
|
||||
prompt(domWin, title, text, value, checkLabel, checkValue) {
|
||||
let p = this.pickPrompter(domWin);
|
||||
let p = this.pickPrompter({ domWin });
|
||||
return p.nsIPrompt_prompt(title, text, value, checkLabel, checkValue);
|
||||
},
|
||||
|
||||
promptBC(browsingContext, modalType, ...promptArgs) {
|
||||
let p = this.pickPrompter({ browsingContext, modalType });
|
||||
return p.nsIPrompt_prompt(...promptArgs);
|
||||
},
|
||||
|
||||
promptUsernameAndPassword(
|
||||
domWin,
|
||||
title,
|
||||
|
@ -113,7 +163,7 @@ Prompter.prototype = {
|
|||
checkLabel,
|
||||
checkValue
|
||||
) {
|
||||
let p = this.pickPrompter(domWin);
|
||||
let p = this.pickPrompter({ domWin });
|
||||
return p.nsIPrompt_promptUsernameAndPassword(
|
||||
title,
|
||||
text,
|
||||
|
@ -124,8 +174,13 @@ Prompter.prototype = {
|
|||
);
|
||||
},
|
||||
|
||||
promptUsernameAndPasswordBC(browsingContext, modalType, ...promptArgs) {
|
||||
let p = this.pickPrompter({ browsingContext, modalType });
|
||||
return p.nsIPrompt_promptUsernameAndPassword(...promptArgs);
|
||||
},
|
||||
|
||||
promptPassword(domWin, title, text, pass, checkLabel, checkValue) {
|
||||
let p = this.pickPrompter(domWin);
|
||||
let p = this.pickPrompter({ domWin });
|
||||
return p.nsIPrompt_promptPassword(
|
||||
title,
|
||||
text,
|
||||
|
@ -135,16 +190,31 @@ Prompter.prototype = {
|
|||
);
|
||||
},
|
||||
|
||||
promptPasswordBC(browsingContext, modalType, ...promptArgs) {
|
||||
let p = this.pickPrompter({ browsingContext, modalType });
|
||||
return p.nsIPrompt_promptPassword(...promptArgs);
|
||||
},
|
||||
|
||||
select(domWin, title, text, list, selected) {
|
||||
let p = this.pickPrompter(domWin);
|
||||
let p = this.pickPrompter({ domWin });
|
||||
return p.select(title, text, list, selected);
|
||||
},
|
||||
|
||||
selectBC(browsingContext, modalType, ...promptArgs) {
|
||||
let p = this.pickPrompter({ browsingContext, modalType });
|
||||
return p.select(...promptArgs);
|
||||
},
|
||||
|
||||
promptAuth(domWin, channel, level, authInfo, checkLabel, checkValue) {
|
||||
let p = this.pickPrompter(domWin);
|
||||
let p = this.pickPrompter({ domWin });
|
||||
return p.promptAuth(channel, level, authInfo, checkLabel, checkValue);
|
||||
},
|
||||
|
||||
promptAuthBC(browsingContext, modalType, ...promptArgs) {
|
||||
let p = this.pickPrompter({ browsingContext, modalType });
|
||||
return p.promptAuth(...promptArgs);
|
||||
},
|
||||
|
||||
asyncPromptAuth(
|
||||
domWin,
|
||||
channel,
|
||||
|
@ -155,7 +225,7 @@ Prompter.prototype = {
|
|||
checkLabel,
|
||||
checkValue
|
||||
) {
|
||||
let p = this.pickPrompter(domWin);
|
||||
let p = this.pickPrompter({ domWin });
|
||||
return p.asyncPromptAuth(
|
||||
channel,
|
||||
callback,
|
||||
|
@ -166,6 +236,11 @@ Prompter.prototype = {
|
|||
checkValue
|
||||
);
|
||||
},
|
||||
|
||||
asyncPromptAuthBC(browsingContext, modalType, ...promptArgs) {
|
||||
let p = this.pickPrompter({ browsingContext, modalType });
|
||||
return p.asyncPromptAuth(...promptArgs);
|
||||
},
|
||||
};
|
||||
|
||||
// Common utils not specific to a particular prompter style.
|
||||
|
@ -369,33 +444,6 @@ var PromptUtilsTemp = {
|
|||
return text;
|
||||
},
|
||||
|
||||
getTabModalPrompt(domWin) {
|
||||
var promptBox = null;
|
||||
|
||||
try {
|
||||
// Get the topmost window, in case we're in a frame.
|
||||
var promptWin = domWin.top;
|
||||
|
||||
// Get the chrome window for the content window we're using.
|
||||
// (Unwrap because we need a non-IDL property below.)
|
||||
var chromeWin =
|
||||
promptWin.docShell.chromeEventHandler.ownerGlobal.wrappedJSObject;
|
||||
|
||||
if (chromeWin) {
|
||||
if (chromeWin.gBrowser && chromeWin.gBrowser.getTabModalPromptBox) {
|
||||
let browser = promptWin.docShell.chromeEventHandler;
|
||||
promptBox = chromeWin.gBrowser.getTabModalPromptBox(browser);
|
||||
} else if (chromeWin.getTabModalPromptBox) {
|
||||
chromeWin.getTabModalPromptBox(promptWin);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// If any errors happen, just assume no tabmodal prompter.
|
||||
}
|
||||
|
||||
return promptBox;
|
||||
},
|
||||
|
||||
getBrandFullName() {
|
||||
return this.brandBundle.GetStringFromName("brandFullName");
|
||||
},
|
||||
|
@ -434,190 +482,169 @@ XPCOMUtils.defineLazyGetter(PromptUtils, "ellipsis", function() {
|
|||
return ellipsis;
|
||||
});
|
||||
|
||||
function openModalWindow(domWin, uri, args) {
|
||||
// There's an implied contract that says modal prompts should still work
|
||||
// when no "parent" window is passed for the dialog (eg, the "Master
|
||||
// Password" dialog does this). These prompts must be shown even if there
|
||||
// are *no* visible windows at all.
|
||||
// There's also a requirement for prompts to be blocked if a window is
|
||||
// passed and that window is hidden (eg, auth prompts are supressed if the
|
||||
// passed window is the hidden window).
|
||||
// See bug 875157 comment 30 for more...
|
||||
if (domWin) {
|
||||
// a domWin was passed, so we can apply the check for it being hidden.
|
||||
let winUtils = domWin.windowUtils;
|
||||
class ModalPrompter {
|
||||
constructor({ browsingContext = null, domWin = null, modalType = null }) {
|
||||
if (browsingContext && domWin) {
|
||||
throw new Error("Pass either browsingContext or domWin");
|
||||
}
|
||||
this.browsingContext = browsingContext;
|
||||
this._domWin = domWin;
|
||||
|
||||
if (winUtils && !winUtils.isParentWindowMainWidgetVisible) {
|
||||
throw Components.Exception(
|
||||
"Cannot call openModalWindow on a hidden window",
|
||||
Cr.NS_ERROR_NOT_AVAILABLE
|
||||
if (this._domWin) {
|
||||
// We have a domWin, get the associated browsing context
|
||||
this.browsingContext = BrowsingContext.getFromWindow(this._domWin);
|
||||
} else if (this.browsingContext) {
|
||||
// We have a browsingContext, get the associated dom window
|
||||
if (this.browsingContext.window) {
|
||||
this._domWin = this.browsingContext.window;
|
||||
} else {
|
||||
this._domWin =
|
||||
this.browsingContext.embedderElement &&
|
||||
this.browsingContext.embedderElement.ownerGlobal;
|
||||
}
|
||||
}
|
||||
|
||||
// Use given modal type or fallback to default
|
||||
this.modalType = modalType || ModalPrompter.defaultModalType;
|
||||
|
||||
this.QueryInterface = ChromeUtils.generateQI([
|
||||
Ci.nsIPrompt,
|
||||
Ci.nsIAuthPrompt,
|
||||
Ci.nsIAuthPrompt2,
|
||||
Ci.nsIWritablePropertyBag2,
|
||||
]);
|
||||
}
|
||||
|
||||
set modalType(modalType) {
|
||||
// Setting modal type window is always allowed
|
||||
if (modalType == Ci.nsIPrompt.MODAL_TYPE_WINDOW) {
|
||||
this._modalType = modalType;
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have a chrome window and the browsing context isn't embedded
|
||||
// in a browser, we can't use tab/content prompts.
|
||||
// Or if we don't allow tab or content prompts, override modalType
|
||||
// argument to use window prompts
|
||||
if (
|
||||
!this.browsingContext ||
|
||||
!this._domWin ||
|
||||
(this._domWin.isChromeWindow &&
|
||||
!this.browsingContext.top.embedderElement) ||
|
||||
!ModalPrompter.tabModalEnabled
|
||||
) {
|
||||
modalType = Ci.nsIPrompt.MODAL_TYPE_WINDOW;
|
||||
|
||||
Cu.reportError(
|
||||
"Prompter: Browser not available or tab modal prompts disabled. Falling back to window prompt."
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// We try and find a window to use as the parent, but don't consider
|
||||
// if that is visible before showing the prompt.
|
||||
domWin = Services.ww.activeWindow;
|
||||
// domWin may still be null here if there are _no_ windows open.
|
||||
this._modalType = modalType;
|
||||
}
|
||||
// Note that we don't need to fire DOMWillOpenModalDialog and
|
||||
// DOMModalDialogClosed events here, wwatcher's OpenWindowInternal
|
||||
// will do that. Similarly for enterModalState / leaveModalState.
|
||||
|
||||
Services.ww.openWindow(
|
||||
domWin && domWin.docShell.rootTreeItem.domWindow,
|
||||
uri,
|
||||
"_blank",
|
||||
"centerscreen,chrome,modal,titlebar",
|
||||
args
|
||||
);
|
||||
}
|
||||
get modalType() {
|
||||
return this._modalType;
|
||||
}
|
||||
|
||||
function openTabPrompt(domWin, tabPrompt, args) {
|
||||
let docShell = domWin.docShell;
|
||||
let inPermitUnload =
|
||||
docShell.contentViewer && docShell.contentViewer.inPermitUnload;
|
||||
let eventDetail = Cu.cloneInto({ tabPrompt: true, inPermitUnload }, domWin);
|
||||
PromptUtils.fireDialogEvent(
|
||||
domWin,
|
||||
"DOMWillOpenModalDialog",
|
||||
null,
|
||||
eventDetail
|
||||
);
|
||||
/* ---------- internal methods ---------- */
|
||||
|
||||
let winUtils = domWin.windowUtils;
|
||||
winUtils.enterModalState();
|
||||
openPrompt(args) {
|
||||
if (!this.browsingContext) {
|
||||
// We don't have a browsing context, fallback to a window prompt
|
||||
|
||||
let frameMM = docShell.messageManager;
|
||||
// There's an implied contract that says modal prompts should still work
|
||||
// when no "parent" window is passed for the dialog (eg, the "Master
|
||||
// Password" dialog does this). These prompts must be shown even if there
|
||||
// are *no* visible windows at all.
|
||||
|
||||
// We provide a callback so the prompt can close itself. We don't want to
|
||||
// wait for this event loop to return... Otherwise the presence of other
|
||||
// prompts on the call stack would in this dialog appearing unresponsive
|
||||
// until the other prompts had been closed.
|
||||
let callbackInvoked = false;
|
||||
let newPrompt;
|
||||
function onPromptClose(forceCleanup) {
|
||||
if (!newPrompt && !forceCleanup) {
|
||||
// We try and find a window to use as the parent, but don't consider
|
||||
// if that is visible before showing the prompt.
|
||||
let parentWindow = Services.ww.activeWindow;
|
||||
// parentWindow may still be null here if there are _no_ windows open.
|
||||
|
||||
this.openWindowPrompt(parentWindow, args);
|
||||
return;
|
||||
}
|
||||
callbackInvoked = true;
|
||||
if (newPrompt) {
|
||||
tabPrompt.removePrompt(newPrompt);
|
||||
}
|
||||
|
||||
frameMM.removeEventListener("pagehide", pagehide, true);
|
||||
|
||||
winUtils.leaveModalState();
|
||||
|
||||
PromptUtils.fireDialogEvent(domWin, "DOMModalDialogClosed");
|
||||
}
|
||||
|
||||
frameMM.addEventListener("pagehide", pagehide, true);
|
||||
function pagehide(e) {
|
||||
// Check whether the event relates to our window or its ancestors
|
||||
let window = domWin;
|
||||
let eventWindow = e.target.defaultView;
|
||||
while (window != eventWindow && window.parent != window) {
|
||||
window = window.parent;
|
||||
}
|
||||
if (window != eventWindow) {
|
||||
return;
|
||||
}
|
||||
frameMM.removeEventListener("pagehide", pagehide, true);
|
||||
|
||||
if (newPrompt) {
|
||||
newPrompt.abortPrompt();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
let topPrincipal = domWin.top.document.nodePrincipal;
|
||||
let promptPrincipal = domWin.document.nodePrincipal;
|
||||
args.showAlertOrigin = topPrincipal.equals(promptPrincipal);
|
||||
args.promptActive = true;
|
||||
|
||||
newPrompt = tabPrompt.appendPrompt(args, onPromptClose);
|
||||
|
||||
// TODO since we don't actually open a window, need to check if
|
||||
// there's other stuff in nsWindowWatcher::OpenWindowInternal
|
||||
// that we might need to do here as well.
|
||||
|
||||
Services.tm.spinEventLoopUntil(() => !args.promptActive);
|
||||
delete args.promptActive;
|
||||
|
||||
if (args.promptAborted) {
|
||||
throw Components.Exception(
|
||||
"prompt aborted by user",
|
||||
Cr.NS_ERROR_NOT_AVAILABLE
|
||||
// Select prompts are not part of CommonDialog
|
||||
// and thus not supported as tab or content prompts yet. See Bug 1622817.
|
||||
// Once they are integrated this override should be removed.
|
||||
if (
|
||||
args.promptType == "select" &&
|
||||
this.modalType !== Ci.nsIPrompt.MODAL_TYPE_WINDOW
|
||||
) {
|
||||
Cu.reportError(
|
||||
"Prompter: 'select' prompts do not support tab/content prompting. Falling back to window prompt."
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
// If the prompt unexpectedly failed to invoke the callback, do so here.
|
||||
if (!callbackInvoked) {
|
||||
onPromptClose(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function openRemotePrompt(domWin, args) {
|
||||
let actor = domWin.windowGlobalChild.getActor("Prompt");
|
||||
|
||||
let docShell = domWin.docShell;
|
||||
let inPermitUnload =
|
||||
docShell.contentViewer && docShell.contentViewer.inPermitUnload;
|
||||
let eventDetail = Cu.cloneInto(
|
||||
{ tabPrompt: args.tabPrompt, inPermitUnload },
|
||||
domWin
|
||||
);
|
||||
PromptUtils.fireDialogEvent(
|
||||
domWin,
|
||||
"DOMWillOpenModalDialog",
|
||||
null,
|
||||
eventDetail
|
||||
);
|
||||
|
||||
let windowUtils = domWin.windowUtils;
|
||||
windowUtils.enterModalState();
|
||||
|
||||
// It is technically possible for multiple prompts to be sent from a single
|
||||
// BrowsingContext. See bug 1266353. We use a randomly generated UUID to
|
||||
// differentiate between the different prompts.
|
||||
let id =
|
||||
"id" +
|
||||
Cc["@mozilla.org/uuid-generator;1"]
|
||||
.getService(Ci.nsIUUIDGenerator)
|
||||
.generateUUID()
|
||||
.toString();
|
||||
|
||||
let frameMM = docShell.messageManager;
|
||||
let closed = false;
|
||||
|
||||
let onPageHide = e => {
|
||||
let window = domWin;
|
||||
let eventWindow = e.target.defaultView;
|
||||
while (window != eventWindow && window.parent != window) {
|
||||
window = window.parent;
|
||||
}
|
||||
if (window != eventWindow) {
|
||||
return;
|
||||
args.modalType = Ci.nsIPrompt.MODAL_TYPE_WINDOW;
|
||||
} else {
|
||||
args.modalType = this.modalType;
|
||||
}
|
||||
|
||||
actor.sendAsyncMessage("Prompt:ForceClose", { _remoteId: id });
|
||||
closed = true;
|
||||
};
|
||||
args.browsingContext = this.browsingContext;
|
||||
|
||||
frameMM.addEventListener("pagehide", onPageHide, true);
|
||||
let actor = this._domWin.windowGlobalChild.getActor("Prompt");
|
||||
|
||||
try {
|
||||
let promptPrincipal = domWin.document.nodePrincipal;
|
||||
args.promptPrincipal = promptPrincipal;
|
||||
let docShell =
|
||||
(this.browsingContext && this.browsingContext.docShell) ||
|
||||
this._domWin.docShell;
|
||||
let inPermitUnload =
|
||||
docShell.contentViewer && docShell.contentViewer.inPermitUnload;
|
||||
let eventDetail = Cu.cloneInto(
|
||||
{
|
||||
tabPrompt: this.modalType != Ci.nsIPrompt.MODAL_TYPE_WINDOW,
|
||||
inPermitUnload,
|
||||
},
|
||||
this._domWin
|
||||
);
|
||||
PromptUtils.fireDialogEvent(
|
||||
this._domWin,
|
||||
"DOMWillOpenModalDialog",
|
||||
null,
|
||||
eventDetail
|
||||
);
|
||||
|
||||
let windowUtils =
|
||||
Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT &&
|
||||
this._domWin.windowUtils;
|
||||
|
||||
// Put content windows in the modal state while the prompt is open.
|
||||
if (windowUtils) {
|
||||
windowUtils.enterModalState();
|
||||
}
|
||||
|
||||
// It is technically possible for multiple prompts to be sent from a single
|
||||
// BrowsingContext. See bug 1266353. We use a randomly generated UUID to
|
||||
// differentiate between the different prompts.
|
||||
let id =
|
||||
"id" +
|
||||
Cc["@mozilla.org/uuid-generator;1"]
|
||||
.getService(Ci.nsIUUIDGenerator)
|
||||
.generateUUID()
|
||||
.toString();
|
||||
|
||||
let closed = false;
|
||||
|
||||
args.promptPrincipal = this._domWin.document.nodePrincipal;
|
||||
args.inPermitUnload = inPermitUnload;
|
||||
args._remoteId = id;
|
||||
|
||||
let promise = actor.sendQuery("Prompt:Open", args);
|
||||
promise.then(returnedArgs => {
|
||||
// Copy the response from the closed prompt into our args, it will be
|
||||
// read by our caller.
|
||||
if (returnedArgs) {
|
||||
actor
|
||||
.sendQuery("Prompt:Open", args)
|
||||
.then(returnedArgs => {
|
||||
// Copy the response from the closed prompt into our args, it will be
|
||||
// read by our caller.
|
||||
if (!returnedArgs) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (returnedArgs.promptAborted) {
|
||||
throw Components.Exception(
|
||||
"prompt aborted by user",
|
||||
Cr.NS_ERROR_NOT_AVAILABLE
|
||||
);
|
||||
}
|
||||
|
||||
if (returnedArgs._remoteId !== id) {
|
||||
return;
|
||||
}
|
||||
|
@ -625,82 +652,34 @@ function openRemotePrompt(domWin, args) {
|
|||
for (let key in returnedArgs) {
|
||||
args[key] = returnedArgs[key];
|
||||
}
|
||||
}
|
||||
closed = true;
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
closed = true;
|
||||
});
|
||||
|
||||
Services.tm.spinEventLoopUntilOrShutdown(() => closed);
|
||||
} finally {
|
||||
frameMM.removeEventListener("pagehide", onPageHide, true);
|
||||
windowUtils.leaveModalState();
|
||||
PromptUtils.fireDialogEvent(domWin, "DOMModalDialogClosed");
|
||||
|
||||
if (windowUtils) {
|
||||
windowUtils.leaveModalState();
|
||||
}
|
||||
PromptUtils.fireDialogEvent(this._domWin, "DOMModalDialogClosed");
|
||||
}
|
||||
}
|
||||
|
||||
function ModalPrompter(domWin) {
|
||||
this.domWin = domWin;
|
||||
}
|
||||
ModalPrompter.prototype = {
|
||||
domWin: null,
|
||||
/*
|
||||
* Default to not using a tab-modal prompt, unless the caller opts in by
|
||||
* QIing to nsIWritablePropertyBag and setting the value of this property
|
||||
* to true.
|
||||
*/
|
||||
allowTabModal: false,
|
||||
|
||||
QueryInterface: ChromeUtils.generateQI([
|
||||
Ci.nsIPrompt,
|
||||
Ci.nsIAuthPrompt,
|
||||
Ci.nsIAuthPrompt2,
|
||||
Ci.nsIWritablePropertyBag2,
|
||||
]),
|
||||
|
||||
/* ---------- internal methods ---------- */
|
||||
|
||||
openPrompt(args) {
|
||||
// Check pref, if false/missing do not ever allow tab-modal prompts.
|
||||
const prefName = "prompts.tab_modal.enabled";
|
||||
let prefValue = false;
|
||||
if (Services.prefs.getPrefType(prefName) == Services.prefs.PREF_BOOL) {
|
||||
prefValue = Services.prefs.getBoolPref(prefName);
|
||||
}
|
||||
|
||||
let allowTabModal = this.allowTabModal && prefValue;
|
||||
|
||||
if (allowTabModal && this.domWin) {
|
||||
if (
|
||||
Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT
|
||||
) {
|
||||
args.tabPrompt = true;
|
||||
openRemotePrompt(this.domWin, args);
|
||||
return;
|
||||
}
|
||||
|
||||
let tabPrompt = PromptUtils.getTabModalPrompt(this.domWin);
|
||||
if (tabPrompt) {
|
||||
openTabPrompt(this.domWin, tabPrompt, args);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If we can't do a tab modal prompt, fallback to using a window-modal dialog.
|
||||
if (
|
||||
Services.appinfo.processType === Services.appinfo.PROCESS_TYPE_CONTENT
|
||||
) {
|
||||
args.tabPrompt = false;
|
||||
openRemotePrompt(this.domWin, args);
|
||||
return;
|
||||
}
|
||||
|
||||
openWindowPrompt(parentWindow, args) {
|
||||
const COMMON_DIALOG = "chrome://global/content/commonDialog.xhtml";
|
||||
const SELECT_DIALOG = "chrome://global/content/selectDialog.xhtml";
|
||||
|
||||
let uri = args.promptType == "select" ? SELECT_DIALOG : COMMON_DIALOG;
|
||||
let propBag = PromptUtils.objectToPropBag(args);
|
||||
openModalWindow(this.domWin, uri, propBag);
|
||||
Services.ww.openWindow(
|
||||
parentWindow,
|
||||
uri,
|
||||
"_blank",
|
||||
"centerscreen,chrome,modal,titlebar",
|
||||
propBag
|
||||
);
|
||||
PromptUtils.propBagToObject(propBag, args);
|
||||
},
|
||||
}
|
||||
|
||||
/*
|
||||
* ---------- interface disambiguation ----------
|
||||
|
@ -716,7 +695,7 @@ ModalPrompter.prototype = {
|
|||
return this.nsIPrompt_prompt.apply(this, arguments);
|
||||
}
|
||||
return this.nsIAuthPrompt_prompt.apply(this, arguments);
|
||||
},
|
||||
}
|
||||
|
||||
promptUsernameAndPassword() {
|
||||
// Both have 6 args, so use types.
|
||||
|
@ -724,7 +703,7 @@ ModalPrompter.prototype = {
|
|||
return this.nsIPrompt_promptUsernameAndPassword.apply(this, arguments);
|
||||
}
|
||||
return this.nsIAuthPrompt_promptUsernameAndPassword.apply(this, arguments);
|
||||
},
|
||||
}
|
||||
|
||||
promptPassword() {
|
||||
// Both have 5 args, so use types.
|
||||
|
@ -732,7 +711,7 @@ ModalPrompter.prototype = {
|
|||
return this.nsIPrompt_promptPassword.apply(this, arguments);
|
||||
}
|
||||
return this.nsIAuthPrompt_promptPassword.apply(this, arguments);
|
||||
},
|
||||
}
|
||||
|
||||
/* ---------- nsIPrompt ---------- */
|
||||
|
||||
|
@ -748,7 +727,7 @@ ModalPrompter.prototype = {
|
|||
};
|
||||
|
||||
this.openPrompt(args);
|
||||
},
|
||||
}
|
||||
|
||||
alertCheck(title, text, checkLabel, checkValue) {
|
||||
if (!title) {
|
||||
|
@ -767,7 +746,7 @@ ModalPrompter.prototype = {
|
|||
|
||||
// Checkbox state always returned, even if cancel clicked.
|
||||
checkValue.value = args.checked;
|
||||
},
|
||||
}
|
||||
|
||||
confirm(title, text) {
|
||||
if (!title) {
|
||||
|
@ -785,7 +764,7 @@ ModalPrompter.prototype = {
|
|||
|
||||
// Did user click Ok or Cancel?
|
||||
return args.ok;
|
||||
},
|
||||
}
|
||||
|
||||
confirmCheck(title, text, checkLabel, checkValue) {
|
||||
if (!title) {
|
||||
|
@ -808,7 +787,7 @@ ModalPrompter.prototype = {
|
|||
|
||||
// Did user click Ok or Cancel?
|
||||
return args.ok;
|
||||
},
|
||||
}
|
||||
|
||||
confirmEx(
|
||||
title,
|
||||
|
@ -862,7 +841,7 @@ ModalPrompter.prototype = {
|
|||
|
||||
// Get the number of the button the user clicked.
|
||||
return args.buttonNumClicked;
|
||||
},
|
||||
}
|
||||
|
||||
nsIPrompt_prompt(title, text, value, checkLabel, checkValue) {
|
||||
if (!title) {
|
||||
|
@ -889,7 +868,7 @@ ModalPrompter.prototype = {
|
|||
}
|
||||
|
||||
return ok;
|
||||
},
|
||||
}
|
||||
|
||||
nsIPrompt_promptUsernameAndPassword(
|
||||
title,
|
||||
|
@ -927,7 +906,7 @@ ModalPrompter.prototype = {
|
|||
}
|
||||
|
||||
return ok;
|
||||
},
|
||||
}
|
||||
|
||||
nsIPrompt_promptPassword(title, text, pass, checkLabel, checkValue) {
|
||||
if (!title) {
|
||||
|
@ -956,7 +935,7 @@ ModalPrompter.prototype = {
|
|||
}
|
||||
|
||||
return ok;
|
||||
},
|
||||
}
|
||||
|
||||
select(title, text, list, selected) {
|
||||
if (!title) {
|
||||
|
@ -981,7 +960,7 @@ ModalPrompter.prototype = {
|
|||
}
|
||||
|
||||
return ok;
|
||||
},
|
||||
}
|
||||
|
||||
/* ---------- nsIAuthPrompt ---------- */
|
||||
|
||||
|
@ -998,7 +977,7 @@ ModalPrompter.prototype = {
|
|||
result.value = defaultText;
|
||||
}
|
||||
return this.nsIPrompt_prompt(title, text, result, null, {});
|
||||
},
|
||||
}
|
||||
|
||||
nsIAuthPrompt_promptUsernameAndPassword(
|
||||
title,
|
||||
|
@ -1017,12 +996,12 @@ ModalPrompter.prototype = {
|
|||
null,
|
||||
{}
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
nsIAuthPrompt_promptPassword(title, text, passwordRealm, savePassword, pass) {
|
||||
// The passwordRealm and savePassword args were ignored by nsPrompt.cpp
|
||||
return this.nsIPrompt_promptPassword(title, text, pass, null, {});
|
||||
},
|
||||
}
|
||||
|
||||
/* ---------- nsIAuthPrompt2 ---------- */
|
||||
|
||||
|
@ -1058,7 +1037,7 @@ ModalPrompter.prototype = {
|
|||
PromptUtils.setAuthInfo(authInfo, userParam.value, passParam.value);
|
||||
}
|
||||
return ok;
|
||||
},
|
||||
}
|
||||
|
||||
asyncPromptAuth(
|
||||
channel,
|
||||
|
@ -1076,20 +1055,33 @@ ModalPrompter.prototype = {
|
|||
//
|
||||
// Bug 565582 will change this.
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
}
|
||||
|
||||
/* ---------- nsIWritablePropertyBag2 ---------- */
|
||||
|
||||
// Only a partial implementation, for one specific use case...
|
||||
|
||||
setPropertyAsBool(name, value) {
|
||||
if (name == "allowTabModal") {
|
||||
this.allowTabModal = value;
|
||||
// Legacy way to set modal type when prompting via nsIPrompt.
|
||||
// Please prompt via nsIPromptService. This will be removed in the future.
|
||||
setPropertyAsUint32(name, value) {
|
||||
if (name == "modalType") {
|
||||
this.modalType = value;
|
||||
} else {
|
||||
throw Cr.NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
ModalPrompter,
|
||||
"defaultModalType",
|
||||
"prompts.defaultModalType",
|
||||
Ci.nsIPrompt.MODAL_TYPE_WINDOW
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
ModalPrompter,
|
||||
"tabModalEnabled",
|
||||
"prompts.tab_modal.enabled",
|
||||
true
|
||||
);
|
||||
|
||||
function AuthPromptAdapterFactory() {}
|
||||
AuthPromptAdapterFactory.prototype = {
|
||||
|
|
|
@ -11,6 +11,8 @@ interface nsIAuthInformation;
|
|||
interface nsICancelable;
|
||||
interface nsIChannel;
|
||||
|
||||
webidl BrowsingContext;
|
||||
|
||||
/**
|
||||
* This is the interface to the embeddable prompt service; the service that
|
||||
* implements nsIPrompt. Its interface is designed to be just nsIPrompt, each
|
||||
|
@ -57,6 +59,10 @@ interface nsIPromptService : nsISupports
|
|||
void alert(in mozIDOMWindowProxy aParent,
|
||||
in wstring aDialogTitle,
|
||||
in wstring aText);
|
||||
void alertBC(in BrowsingContext aBrowsingContext,
|
||||
in unsigned long modalType,
|
||||
in wstring aDialogTitle,
|
||||
in wstring aText);
|
||||
|
||||
/**
|
||||
* Puts up an alert dialog with an OK button and a labeled checkbox.
|
||||
|
@ -78,6 +84,12 @@ interface nsIPromptService : nsISupports
|
|||
in wstring aText,
|
||||
in wstring aCheckMsg,
|
||||
inout boolean aCheckState);
|
||||
void alertCheckBC(in BrowsingContext aBrowsingContext,
|
||||
in unsigned long modalType,
|
||||
in wstring aDialogTitle,
|
||||
in wstring aText,
|
||||
in wstring aCheckMsg,
|
||||
inout boolean aCheckState);
|
||||
|
||||
/**
|
||||
* Puts up a dialog with OK and Cancel buttons.
|
||||
|
@ -94,6 +106,10 @@ interface nsIPromptService : nsISupports
|
|||
boolean confirm(in mozIDOMWindowProxy aParent,
|
||||
in wstring aDialogTitle,
|
||||
in wstring aText);
|
||||
boolean confirmBC(in BrowsingContext aBrowsingContext,
|
||||
in unsigned long modalType,
|
||||
in wstring aDialogTitle,
|
||||
in wstring aText);
|
||||
|
||||
/**
|
||||
* Puts up a dialog with OK and Cancel buttons and a labeled checkbox.
|
||||
|
@ -117,6 +133,12 @@ interface nsIPromptService : nsISupports
|
|||
in wstring aText,
|
||||
in wstring aCheckMsg,
|
||||
inout boolean aCheckState);
|
||||
boolean confirmCheckBC(in BrowsingContext aBrowsingContext,
|
||||
in unsigned long modalType,
|
||||
in wstring aDialogTitle,
|
||||
in wstring aText,
|
||||
in wstring aCheckMsg,
|
||||
inout boolean aCheckState);
|
||||
|
||||
/**
|
||||
* Button Flags
|
||||
|
@ -173,6 +195,10 @@ interface nsIPromptService : nsISupports
|
|||
const unsigned long STD_YES_NO_BUTTONS = (BUTTON_TITLE_YES * BUTTON_POS_0) +
|
||||
(BUTTON_TITLE_NO * BUTTON_POS_1);
|
||||
|
||||
// Indicates whether a prompt should be shown in-content, on tab level or as a separate window
|
||||
const unsigned long MODAL_TYPE_CONTENT = 1;
|
||||
const unsigned long MODAL_TYPE_TAB = 2;
|
||||
const unsigned long MODAL_TYPE_WINDOW = 3;
|
||||
|
||||
/**
|
||||
* Puts up a dialog with up to 3 buttons and an optional, labeled checkbox.
|
||||
|
@ -226,6 +252,16 @@ interface nsIPromptService : nsISupports
|
|||
in wstring aButton2Title,
|
||||
in wstring aCheckMsg,
|
||||
inout boolean aCheckState);
|
||||
int32_t confirmExBC(in BrowsingContext aBrowsingContext,
|
||||
in unsigned long modalType,
|
||||
in wstring aDialogTitle,
|
||||
in wstring aText,
|
||||
in unsigned long aButtonFlags,
|
||||
in wstring aButton0Title,
|
||||
in wstring aButton1Title,
|
||||
in wstring aButton2Title,
|
||||
in wstring aCheckMsg,
|
||||
inout boolean aCheckState);
|
||||
|
||||
/**
|
||||
* Puts up a dialog with an edit field and an optional, labeled checkbox.
|
||||
|
@ -255,6 +291,13 @@ interface nsIPromptService : nsISupports
|
|||
inout wstring aValue,
|
||||
in wstring aCheckMsg,
|
||||
inout boolean aCheckState);
|
||||
boolean promptBC(in BrowsingContext aBrowsingContext,
|
||||
in unsigned long modalType,
|
||||
in wstring aDialogTitle,
|
||||
in wstring aText,
|
||||
inout wstring aValue,
|
||||
in wstring aCheckMsg,
|
||||
inout boolean aCheckState);
|
||||
|
||||
/**
|
||||
* Puts up a dialog with an edit field, a password field, and an optional,
|
||||
|
@ -291,6 +334,14 @@ interface nsIPromptService : nsISupports
|
|||
inout wstring aPassword,
|
||||
in wstring aCheckMsg,
|
||||
inout boolean aCheckState);
|
||||
boolean promptUsernameAndPasswordBC(in BrowsingContext aBrowsingContext,
|
||||
in unsigned long modalType,
|
||||
in wstring aDialogTitle,
|
||||
in wstring aText,
|
||||
inout wstring aUsername,
|
||||
inout wstring aPassword,
|
||||
in wstring aCheckMsg,
|
||||
inout boolean aCheckState);
|
||||
|
||||
/**
|
||||
* Puts up a dialog with a password field and an optional, labeled checkbox.
|
||||
|
@ -320,6 +371,13 @@ interface nsIPromptService : nsISupports
|
|||
inout wstring aPassword,
|
||||
in wstring aCheckMsg,
|
||||
inout boolean aCheckState);
|
||||
boolean promptPasswordBC(in BrowsingContext aBrowsingContext,
|
||||
in unsigned long modalType,
|
||||
in wstring aDialogTitle,
|
||||
in wstring aText,
|
||||
inout wstring aPassword,
|
||||
in wstring aCheckMsg,
|
||||
inout boolean aCheckState);
|
||||
|
||||
/**
|
||||
* Puts up a dialog box which has a list box of strings from which the user
|
||||
|
@ -344,6 +402,12 @@ interface nsIPromptService : nsISupports
|
|||
in wstring aText,
|
||||
in Array<AString> aSelectList,
|
||||
out long aOutSelection);
|
||||
boolean selectBC(in BrowsingContext aBrowsingContext,
|
||||
in unsigned long modalType,
|
||||
in wstring aDialogTitle,
|
||||
in wstring aText,
|
||||
in Array<AString> aSelectList,
|
||||
out long aOutSelection);
|
||||
|
||||
// NOTE: These functions differ from their nsIAuthPrompt counterparts by
|
||||
// having additional checkbox parameters
|
||||
|
@ -359,6 +423,13 @@ interface nsIPromptService : nsISupports
|
|||
in nsIAuthInformation authInfo,
|
||||
in wstring checkboxLabel,
|
||||
inout boolean checkValue);
|
||||
boolean promptAuthBC(in BrowsingContext aBrowsingContext,
|
||||
in unsigned long modalType,
|
||||
in nsIChannel aChannel,
|
||||
in uint32_t level,
|
||||
in nsIAuthInformation authInfo,
|
||||
in wstring checkboxLabel,
|
||||
inout boolean checkValue);
|
||||
|
||||
nsICancelable asyncPromptAuth(in mozIDOMWindowProxy aParent,
|
||||
in nsIChannel aChannel,
|
||||
|
@ -368,4 +439,13 @@ interface nsIPromptService : nsISupports
|
|||
in nsIAuthInformation authInfo,
|
||||
in wstring checkboxLabel,
|
||||
inout boolean checkValue);
|
||||
nsICancelable asyncPromptAuthBC(in BrowsingContext aBrowsingContext,
|
||||
in unsigned long modalType,
|
||||
in nsIChannel aChannel,
|
||||
in nsIAuthPromptCallback aCallback,
|
||||
in nsISupports aContext,
|
||||
in uint32_t level,
|
||||
in nsIAuthInformation authInfo,
|
||||
in wstring checkboxLabel,
|
||||
inout boolean checkValue);
|
||||
};
|
||||
|
|
|
@ -2017,7 +2017,25 @@
|
|||
}
|
||||
|
||||
leaveModalState() {
|
||||
this.sendMessageToActor("LeaveModalState", {}, "BrowserElement", "roots");
|
||||
this.sendMessageToActor(
|
||||
"LeaveModalState",
|
||||
{ forceLeave: true },
|
||||
"BrowserElement",
|
||||
"roots"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be called for a window with or without modal state.
|
||||
* If the window is not in modal state, this is a no-op.
|
||||
*/
|
||||
maybeLeaveModalState() {
|
||||
this.sendMessageToActor(
|
||||
"LeaveModalState",
|
||||
{ forceLeave: false },
|
||||
"BrowserElement",
|
||||
"roots"
|
||||
);
|
||||
}
|
||||
|
||||
getDevicePermissionOrigins(key) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче