forked from mirrors/gecko-dev
Bug 1917201: Remove cancel button from modal while waiting for user to respond to Windows geolocation dialog r=Gijs a=RyanVM
The cancel button is not really useful here and is probably confusing some users, since they are pressing it anyway, and it is causing this crash. The ideal fix would be for the Windows dialog to be modal instead of just immovable, but it isn't. Differential Revision: https://phabricator.services.mozilla.com/D225154
This commit is contained in:
parent
5f342def31
commit
cc058e14a5
4 changed files with 95 additions and 15 deletions
|
|
@ -360,20 +360,37 @@ void Geolocation::ReallowWithSystemPermissionOrCancel(
|
|||
do_GetService("@mozilla.org/prompter;1", &rv);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
RefPtr<mozilla::dom::Promise> cancelDialogPromise;
|
||||
// The dialog should include a cancel button if Gecko is prompting the user
|
||||
// for system permission. It should have no buttons if the OS will be
|
||||
// doing the prompting.
|
||||
bool geckoWillPrompt =
|
||||
GetLocationOSPermission() ==
|
||||
geolocation::SystemGeolocationPermissionBehavior::GeckoWillPromptUser;
|
||||
// This combination of flags removes the default yes and no buttons and adds a
|
||||
// spinner to the title.
|
||||
const auto kSpinnerNoButtonFlags = nsIPromptService::BUTTON_TITLE_IS_STRING *
|
||||
nsIPromptService::BUTTON_POS_0 +
|
||||
nsIPromptService::BUTTON_TITLE_IS_STRING *
|
||||
nsIPromptService::BUTTON_POS_1 +
|
||||
nsIPromptService::SHOW_SPINNER;
|
||||
// This combination of flags indicates there is only one button labeled
|
||||
// "Cancel".
|
||||
const auto kCancelButtonFlags =
|
||||
nsIPromptService::BUTTON_TITLE_CANCEL * nsIPromptService::BUTTON_POS_0;
|
||||
RefPtr<mozilla::dom::Promise> tabBlockingDialogPromise;
|
||||
rv = promptSvc->AsyncConfirmEx(
|
||||
aBrowsingContext, nsIPromptService::MODAL_TYPE_TAB, title.get(),
|
||||
message.get(),
|
||||
nsIPromptService::BUTTON_TITLE_CANCEL * nsIPromptService::BUTTON_POS_0,
|
||||
nullptr, nullptr, nullptr, nullptr, false, JS::UndefinedHandleValue,
|
||||
getter_AddRefs(cancelDialogPromise));
|
||||
geckoWillPrompt ? kCancelButtonFlags : kSpinnerNoButtonFlags, nullptr,
|
||||
nullptr, nullptr, nullptr, false, JS::UndefinedHandleValue,
|
||||
getter_AddRefs(tabBlockingDialogPromise));
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
MOZ_ASSERT(cancelDialogPromise);
|
||||
MOZ_ASSERT(tabBlockingDialogPromise);
|
||||
|
||||
// If the cancel dialog promise is resolved or rejected then the dialog is no
|
||||
// longer visible so we should stop waiting for permission, whether it was
|
||||
// granted or not.
|
||||
cancelDialogPromise->AppendNativeHandler(
|
||||
// If the tab blocking dialog promise is resolved or rejected then the dialog
|
||||
// is no longer visible so we should stop waiting for permission, whether it
|
||||
// was granted or not.
|
||||
tabBlockingDialogPromise->AppendNativeHandler(
|
||||
new CancelSystemGeolocationPermissionRequest(permissionRequest));
|
||||
|
||||
cancelRequestOnError.release();
|
||||
|
|
|
|||
|
|
@ -64,9 +64,6 @@ CommonDialog.prototype = {
|
|||
if (this.args.button3Label) {
|
||||
numButtons++;
|
||||
}
|
||||
if (numButtons == 0) {
|
||||
throw new Error("A dialog with no buttons? Can not haz.");
|
||||
}
|
||||
this.numButtons = numButtons;
|
||||
this.hasInputField = false;
|
||||
this.iconClass = ["question-icon"];
|
||||
|
|
@ -139,7 +136,9 @@ CommonDialog.prototype = {
|
|||
this.setLabelForNode(this.ui.button1, this.args.button1Label);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0:
|
||||
this.ui.button0.hidden = true;
|
||||
// fall through
|
||||
case 1:
|
||||
this.ui.button1.hidden = true;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -204,12 +204,13 @@ function dismissPrompt(ui, action) {
|
|||
case 2:
|
||||
ui.button2.click();
|
||||
break;
|
||||
case "ESC":
|
||||
case "ESC": {
|
||||
// XXX This is assuming tab-modal.
|
||||
let browserWin = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
EventUtils.synthesizeKey("KEY_Escape", {}, browserWin);
|
||||
break;
|
||||
case "pollOK":
|
||||
}
|
||||
case "pollOK": {
|
||||
// Buttons are disabled at the moment, poll until they're reenabled.
|
||||
// Can't use setInterval here, because the window's in a modal state
|
||||
// and thus DOM events are suppressed.
|
||||
|
|
@ -221,6 +222,15 @@ function dismissPrompt(ui, action) {
|
|||
clearInterval(interval);
|
||||
}, 100);
|
||||
break;
|
||||
}
|
||||
case "abort_dialogs": {
|
||||
let abortDialogEvent = new ui.prompt.CustomEvent("dialogclosing", {
|
||||
bubbles: true,
|
||||
detail: { abort: true },
|
||||
});
|
||||
ui.prompt.close(abortDialogEvent);
|
||||
break;
|
||||
}
|
||||
case "none":
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -749,6 +749,60 @@ async function runTests(util) {
|
|||
|
||||
await promptDone;
|
||||
|
||||
// =====
|
||||
info("Starting test: ConfirmEx (no buttons)");
|
||||
state = {
|
||||
msg: "This is the confirmEx text.",
|
||||
title: "TestTitle",
|
||||
iconClass: "question-icon",
|
||||
titleHidden: true,
|
||||
textHidden: true,
|
||||
passHidden: true,
|
||||
checkHidden: true,
|
||||
textValue: "",
|
||||
passValue: "",
|
||||
checkMsg: "",
|
||||
checked: false,
|
||||
butt0Label: "",
|
||||
butt1Label: "",
|
||||
focused: null,
|
||||
defButton: "button0",
|
||||
};
|
||||
|
||||
if (isOSX) {
|
||||
// OS X doesn't initially focus the button, but rather the infoBody.
|
||||
state.focused = "infoBody";
|
||||
}
|
||||
|
||||
action = {
|
||||
buttonClick: "abort_dialogs",
|
||||
};
|
||||
|
||||
promptDone = handlePrompt(state, action);
|
||||
|
||||
// BUTTON_TITLE_IS_STRING with no title removes the button.
|
||||
flags =
|
||||
Ci.nsIPromptService.BUTTON_TITLE_IS_STRING * Ci.nsIPromptService.BUTTON_POS_1 +
|
||||
Ci.nsIPromptService.BUTTON_TITLE_IS_STRING * Ci.nsIPromptService.BUTTON_POS_0;
|
||||
promptArgs = [
|
||||
"TestTitle",
|
||||
"This is the confirmEx text.",
|
||||
flags,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
util.useAsync ? false : {},
|
||||
];
|
||||
result = await util.prompt("confirmEx", promptArgs);
|
||||
is(
|
||||
util.useAsync ? result.buttonNumClicked : result,
|
||||
1,
|
||||
"checked button click num unchanged from default"
|
||||
);
|
||||
|
||||
await promptDone;
|
||||
|
||||
// =====
|
||||
info("Starting test: ConfirmEx (ok/cancel, ok)");
|
||||
state = {
|
||||
|
|
|
|||
Loading…
Reference in a new issue