Bug 575485 - Refactor commonDialog code into a sharable JSM (Part 3, JSM). r=gavin, a=beltzner

This commit is contained in:
Justin Dolske 2010-10-27 14:16:17 -07:00
parent 7c7936c1a3
commit a6bc82164a
5 changed files with 456 additions and 288 deletions

View File

@ -45,112 +45,56 @@ const Cc = Components.classes;
const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/CommonDialog.jsm");
let gArgs, promptType, numButtons, iconClass, soundID, hasInputField = true;
let gDelayExpired = false, gBlurred = false;
let propBag, args, Dialog;
function earlyInit() {
// This is called before onload fires, so we can't be certain that any elements
// in the document have their bindings ready, so don't call any methods/properties
// here on xul elements that come from xbl bindings.
gArgs = window.arguments[0].QueryInterface(Ci.nsIWritablePropertyBag2)
.QueryInterface(Ci.nsIWritablePropertyBag);
promptType = gArgs.getProperty("promptType");
switch (promptType) {
case "alert":
case "alertCheck":
hasInputField = false;
numButtons = 1;
iconClass = "alert-icon";
soundID = Ci.nsISound.EVENT_ALERT_DIALOG_OPEN;
break;
case "confirmCheck":
case "confirm":
hasInputField = false;
numButtons = 2;
iconClass = "question-icon";
soundID = Ci.nsISound.EVENT_CONFIRM_DIALOG_OPEN;
break;
case "confirmEx":
numButtons = 0;
if (gArgs.hasKey("button0Label"))
numButtons++;
if (gArgs.hasKey("button1Label"))
numButtons++;
if (gArgs.hasKey("button2Label"))
numButtons++;
if (gArgs.hasKey("button3Label"))
numButtons++;
if (numButtons == 0)
throw "A dialog with no buttons? Can not haz.";
hasInputField = false;
iconClass = "question-icon";
soundID = Ci.nsISound.EVENT_CONFIRM_DIALOG_OPEN;
break;
case "prompt":
numButtons = 2;
iconClass = "question-icon";
soundID = Ci.nsISound.EVENT_PROMPT_DIALOG_OPEN;
initTextbox("login", gArgs.getProperty("value"));
// Clear the label, since this isn't really a username prompt.
document.getElementById("loginLabel").setAttribute("value", "");
break;
case "promptUserAndPass":
numButtons = 2;
iconClass = "authentication-icon question-icon";
soundID = Ci.nsISound.EVENT_PROMPT_DIALOG_OPEN;
initTextbox("login", gArgs.getProperty("user"));
initTextbox("password1", gArgs.getProperty("pass"));
break;
case "promptPassword":
numButtons = 2;
iconClass = "authentication-icon question-icon";
soundID = Ci.nsISound.EVENT_PROMPT_DIALOG_OPEN;
initTextbox("password1", gArgs.getProperty("pass"));
// Clear the label, since the message presumably indicates its purpose.
document.getElementById("password1Label").setAttribute("value", "");
break;
default:
Cu.reportError("commonDialog opened for unknown type: " + promptType);
window.close();
}
}
function initTextbox(aName, aValue) {
document.getElementById(aName + "Container").hidden = false;
document.getElementById(aName + "Textbox").setAttribute("value", aValue);
}
function setLabelForNode(aNode, aLabel) {
// This is for labels which may contain embedded access keys.
// If we end in (&X) where X represents the access key, optionally preceded
// by spaces and/or followed by the ':' character, store the access key and
// remove the access key placeholder + leading spaces from the label.
// Otherwise a character preceded by one but not two &s is the access key.
// Store it and remove the &.
// Note that if you change the following code, see the comment of
// nsTextBoxFrame::UpdateAccessTitle.
var accessKey = null;
if (/ *\(\&([^&])\)(:)?$/.test(aLabel)) {
aLabel = RegExp.leftContext + RegExp.$2;
accessKey = RegExp.$1;
} else if (/^(.*[^&])?\&(([^&]).*$)/.test(aLabel)) {
aLabel = RegExp.$1 + RegExp.$2;
accessKey = RegExp.$3;
function commonDialogOnLoad() {
propBag = window.arguments[0].QueryInterface(Ci.nsIWritablePropertyBag2)
.QueryInterface(Ci.nsIWritablePropertyBag);
// Convert to a JS object
args = {};
let propEnum = propBag.enumerator;
while (propEnum.hasMoreElements()) {
let prop = propEnum.getNext().QueryInterface(Ci.nsIProperty);
args[prop.name] = prop.value;
}
// && is the magic sequence to embed an & in your label.
aLabel = aLabel.replace(/\&\&/g, "&");
aNode.label = aLabel;
let dialog = document.documentElement;
// XXXjag bug 325251
// Need to set this after aNode.setAttribute("value", aLabel);
if (accessKey)
aNode.accessKey = accessKey;
let ui = {
loginContainer : document.getElementById("loginContainer"),
loginTextbox : document.getElementById("loginTextbox"),
loginLabel : document.getElementById("loginLabel"),
password1Container : document.getElementById("password1Container"),
password1Textbox : document.getElementById("password1Textbox"),
password1Label : document.getElementById("password1Label"),
infoBody : document.getElementById("info.body"),
infoTitle : document.getElementById("info.title"),
infoIcon : document.getElementById("info.icon"),
checkbox : document.getElementById("checkbox"),
checkboxContainer : document.getElementById("checkboxContainer"),
button3 : dialog.getButton("extra2"),
button2 : dialog.getButton("extra1"),
button1 : dialog.getButton("cancel"),
button0 : dialog.getButton("accept"),
focusTarget : window,
};
// limit the dialog to the screen width
document.getElementById("filler").maxWidth = screen.availWidth;
Services.obs.addObserver(softkbObserver, "softkb-change", false);
Dialog = new CommonDialog(args, ui);
Dialog.onLoad(dialog);
window.getAttention();
}
function commonDialogOnUnload() {
Services.obs.removeObserver(softkbObserver, "softkb-change");
// Convert args back into property bag
for (let propName in args)
propBag.setProperty(propName, args[propName]);
}
function softkbObserver(subject, topic, data) {
@ -163,179 +107,3 @@ function softkbObserver(subject, topic, data) {
window.moveTo(left, top);
}
}
function commonDialogOnLoad() {
// limit the dialog to the screen width
document.getElementById("filler").maxWidth = screen.availWidth;
// set the document title
let title = gArgs.getProperty("title");
document.title = title;
// OS X doesn't have a title on modal dialogs, this is hidden on other platforms.
document.getElementById("info.title").appendChild(document.createTextNode(title));
Services.obs.addObserver(softkbObserver, "softkb-change", false);
// Set button labels and visibility
let dialog = document.documentElement;
switch (numButtons) {
case 4:
setLabelForNode(dialog.getButton("extra2"), gArgs.getProperty("button3Label"));
dialog.getButton("extra2").hidden = false;
// fall through
case 3:
setLabelForNode(dialog.getButton("extra1"), gArgs.getProperty("button2Label"));
dialog.getButton("extra1").hidden = false;
// fall through
case 2:
if (gArgs.hasKey("button1Label"))
setLabelForNode(dialog.getButton("cancel"), gArgs.getProperty("button1Label"));
break;
case 1:
dialog.getButton("cancel").hidden = true;
break;
}
if (gArgs.hasKey("button0Label"))
setLabelForNode(dialog.getButton("accept"), gArgs.getProperty("button0Label"));
// display the main text
// Bug 317334 - crop string length as a workaround.
let croppedMessage = gArgs.getProperty("text").substr(0, 10000);
document.getElementById("info.body").appendChild(document.createTextNode(croppedMessage));
if (gArgs.hasKey("checkLabel")) {
let label = gArgs.getProperty("checkLabel")
// Only show the checkbox if label has a value.
if (label) {
document.getElementById("checkboxContainer").hidden = false;
let checkboxElement = document.getElementById("checkbox");
setLabelForNode(checkboxElement, label);
checkboxElement.checked = gArgs.getProperty("checked");
}
}
// set the icon
document.getElementById("info.icon").className += " " + iconClass;
// set default result to cancelled
gArgs.setProperty("ok", false);
gArgs.setProperty("buttonNumClicked", 1);
// If there are no input fields on the dialog, select the default button.
// Otherwise, select the appropriate input field.
if (!hasInputField) {
let dlgButtons = ['accept', 'cancel', 'extra1', 'extra2'];
// Set the default button and focus it on non-OS X systems
let b = 0;
if (gArgs.hasKey("defaultButtonNum"))
b = gArgs.getProperty("defaultButtonNum");
let dButton = dlgButtons[b];
// XXX shouldn't we set the default even when a textbox is focused?
dialog.defaultButton = dButton;
#ifndef XP_MACOSX
dialog.getButton(dButton).focus();
#endif
} else {
if (promptType == "promptPassword")
document.getElementById("password1Textbox").select();
else
document.getElementById("loginTextbox").select();
}
if (gArgs.hasKey("enableDelay") && gArgs.getProperty("enableDelay")) {
let delayInterval = Services.prefs.getIntPref("security.dialog_enable_delay");
setButtonsEnabledState(dialog, false);
setTimeout(function () {
// Don't automatically enable the buttons if we're not in the foreground
if (!gBlurred)
setButtonsEnabledState(dialog, true);
gDelayExpired = true;
}, delayInterval);
addEventListener("blur", commonDialogBlur, false);
addEventListener("focus", commonDialogFocus, false);
}
window.getAttention();
// play sound
try {
if (soundID) {
Cc["@mozilla.org/sound;1"].
createInstance(Ci.nsISound).
playEventSound(soundID);
}
} catch (e) { }
Services.obs.notifyObservers(window, "common-dialog-loaded", null);
}
function setButtonsEnabledState(dialog, enabled) {
dialog.getButton("accept").disabled = !enabled;
dialog.getButton("extra1").disabled = !enabled;
dialog.getButton("extra2").disabled = !enabled;
}
function commonDialogOnUnload() {
Services.obs.removeObserver(softkbObserver, "softkb-change");
}
function commonDialogBlur(aEvent) {
if (aEvent.target != document)
return;
gBlurred = true;
let dialog = document.documentElement;
setButtonsEnabledState(dialog, false);
}
function commonDialogFocus(aEvent) {
if (aEvent.target != document)
return;
gBlurred = false;
let dialog = document.documentElement;
// When refocusing the window, don't enable the buttons unless the countdown
// delay has expired.
if (gDelayExpired)
setTimeout(setButtonsEnabledState, 250, dialog, true);
}
function onCheckboxClick(aCheckboxElement) {
gArgs.setProperty("checked", aCheckboxElement.checked);
}
function commonDialogOnAccept() {
gArgs.setProperty("ok", true);
gArgs.setProperty("buttonNumClicked", 0);
let username = document.getElementById("loginTextbox").value;
let password = document.getElementById("password1Textbox").value;
// Return textfield values
switch (promptType) {
case "prompt":
gArgs.setProperty("value", username);
break;
case "promptUserAndPass":
gArgs.setProperty("user", username);
gArgs.setProperty("pass", password);
break;
case "promptPassword":
gArgs.setProperty("pass", password);
break;
}
}
function commonDialogOnExtra1() {
// .setProperty("ok", true)?
gArgs.setProperty("buttonNumClicked", 2);
window.close();
}
function commonDialogOnExtra2() {
// .setProperty("ok", true)?
gArgs.setProperty("buttonNumClicked", 3);
window.close();
}

View File

@ -11,9 +11,10 @@
aria-describedby="info.body"
onload="commonDialogOnLoad();"
onunload="commonDialogOnUnload();"
ondialogaccept="return commonDialogOnAccept();"
ondialogextra1="return commonDialogOnExtra1();"
ondialogextra2="return commonDialogOnExtra2();"
ondialogaccept="Dialog.onButton0(); return true;"
ondialogcancel="Dialog.onButton1(); return true;"
ondialogextra1="Dialog.onButton2(); window.close();"
ondialogextra2="Dialog.onButton3(); window.close();"
buttonpack="center">
<script type="application/javascript" src="chrome://global/content/commonDialog.js"/>
@ -75,16 +76,9 @@
</row>
<row id="checkboxContainer" hidden="true">
<spacer/>
<checkbox id="checkbox" oncommand="onCheckboxClick(this);"/>
<checkbox id="checkbox" oncommand="Dialog.onCheckbox()"/>
</row>
</rows>
</grid>
<!-- This method is called inline because it may unset hidden="true" on the
above boxes, causing their frames to be build and bindings to load.
So, by calling this inline, we guarantee the textboxes and checkboxes
above will have their bindings before initButtons is called, and the
dialog will be intrinsically sized correctly. -->
<script type="application/javascript">earlyInit();</script>
</dialog>

View File

@ -0,0 +1,350 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is CommonDialog.jsm code.
*
* The Initial Developer of the Original Code is the Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Justin Dolske <dolske@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
var EXPORTED_SYMBOLS = ["CommonDialog"];
const Ci = Components.interfaces;
const Cr = Components.results;
const Cc = Components.classes;
const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
function CommonDialog(args, ui) {
this.args = args;
this.ui = ui;
}
CommonDialog.prototype = {
args : null,
ui : null,
hasInputField : true,
numButtons : undefined,
iconClass : undefined,
soundID : undefined,
focusTimer : null,
onLoad : function(xulDialog) {
switch (this.args.promptType) {
case "alert":
case "alertCheck":
this.hasInputField = false;
this.numButtons = 1;
this.iconClass = ["alert-icon"];
this.soundID = Ci.nsISound.EVENT_ALERT_DIALOG_OPEN;
break;
case "confirmCheck":
case "confirm":
this.hasInputField = false;
this.numButtons = 2;
this.iconClass = ["question-icon"];
this.soundID = Ci.nsISound.EVENT_CONFIRM_DIALOG_OPEN;
break;
case "confirmEx":
var numButtons = 0;
if (this.args.button0Label)
numButtons++;
if (this.args.button1Label)
numButtons++;
if (this.args.button2Label)
numButtons++;
if (this.args.button3Label)
numButtons++;
if (numButtons == 0)
throw "A dialog with no buttons? Can not haz.";
this.numButtons = numButtons;
this.hasInputField = false;
this.iconClass = ["question-icon"];
this.soundID = Ci.nsISound.EVENT_CONFIRM_DIALOG_OPEN;
break;
case "prompt":
this.numButtons = 2;
this.iconClass = ["question-icon"];
this.soundID = Ci.nsISound.EVENT_PROMPT_DIALOG_OPEN;
this.initTextbox("login", this.args.value);
// Clear the label, since this isn't really a username prompt.
this.ui.loginLabel.setAttribute("value", "");
break;
case "promptUserAndPass":
this.numButtons = 2;
this.iconClass = ["authentication-icon", "question-icon"];
this.soundID = Ci.nsISound.EVENT_PROMPT_DIALOG_OPEN;
this.initTextbox("login", this.args.user);
this.initTextbox("password1", this.args.pass);
break;
case "promptPassword":
this.numButtons = 2;
this.iconClass = ["authentication-icon", "question-icon"];
this.soundID = Ci.nsISound.EVENT_PROMPT_DIALOG_OPEN;
this.initTextbox("password1", this.args.pass);
// Clear the label, since the message presumably indicates its purpose.
this.ui.password1Label.setAttribute("value", "");
break;
default:
Cu.reportError("commonDialog opened for unknown type: " + this.args.promptType);
throw "unknown dialog type";
}
// set the document title
let title = this.args.title;
// OS X doesn't have a title on modal dialogs, this is hidden on other platforms.
let infoTitle = this.ui.infoTitle;
infoTitle.appendChild(infoTitle.ownerDocument.createTextNode(title));
if (xulDialog)
xulDialog.ownerDocument.title = title;
// Set button labels and visibility
//
// This assumes that button0 defaults to a visible "ok" button, and
// button1 defaults to a visible "cancel" button. The other 2 buttons
// have no default labels (and are hidden).
switch (this.numButtons) {
case 4:
this.setLabelForNode(this.ui.button3, this.args.button3Label);
this.ui.button3.hidden = false;
// fall through
case 3:
this.setLabelForNode(this.ui.button2, this.args.button2Label);
this.ui.button2.hidden = false;
// fall through
case 2:
// Defaults to a visible "cancel" button
if (this.args.button1Label)
this.setLabelForNode(this.ui.button1, this.args.button1Label);
break;
case 1:
this.ui.button1.hidden = true;
break;
}
// Defaults to a visible "ok" button
if (this.args.button0Label)
this.setLabelForNode(this.ui.button0, this.args.button0Label);
// display the main text
// Bug 317334 - crop string length as a workaround.
let croppedMessage = this.args.text.substr(0, 10000);
let infoBody = this.ui.infoBody;
infoBody.appendChild(infoBody.ownerDocument.createTextNode(croppedMessage));
let label = this.args.checkLabel;
if (label) {
// Only show the checkbox if label has a value.
this.ui.checkboxContainer.hidden = false;
this.setLabelForNode(this.ui.checkbox, label);
this.ui.checkbox.checked = this.args.checked;
}
// set the icon
let icon = this.ui.infoIcon;
this.iconClass.forEach(function(el,idx,arr) icon.classList.add(el));
// set default result to cancelled
this.args.ok = false;
this.args.buttonNumClicked = 1;
// If there are no input fields on the dialog, select the default button.
// Otherwise, select the appropriate input field.
// XXX shouldn't we set an unfocused default even when a textbox is focused?
if (!this.hasInputField) {
// Set the default button (and focus it on non-OS X systems)
let b = 0;
if (this.args.defaultButtonNum)
b = this.args.defaultButtonNum;
let button = this.ui["button" + b];
if (xulDialog) {
xulDialog.defaultButton = ['accept', 'cancel', 'extra1', 'extra2'][b];
let isOSX = ("nsILocalFileMac" in Components.interfaces);
if (!isOSX)
button.focus();
}
// TODO:
// else
// (tabmodal prompts need to set a default button for Enter to act upon)
} else {
if (this.args.promptType == "promptPassword")
this.ui.password1Textbox.select();
else
this.ui.loginTextbox.select();
}
if (this.args.enableDelay) {
this.setButtonsEnabledState(false);
// Use a longer, pref-controlled delay when the dialog is first opened.
let delayTime = Services.prefs.getIntPref("security.dialog_enable_delay");
this.startOnFocusDelay(delayTime);
let self = this;
this.ui.focusTarget.addEventListener("blur", function(e) { self.onBlur(e); }, false);
this.ui.focusTarget.addEventListener("focus", function(e) { self.onFocus(e); }, false);
}
// play sound
try {
if (this.soundID) {
Cc["@mozilla.org/sound;1"].
createInstance(Ci.nsISound).
playEventSound(soundID);
}
} catch (e) { }
if (xulDialog)
Services.obs.notifyObservers(xulDialog.ownerDocument.defaultView, "common-dialog-loaded", null);
// TODO:
// else
// (notify using what as the subject?)
},
setLabelForNode: function(aNode, aLabel) {
// This is for labels which may contain embedded access keys.
// If we end in (&X) where X represents the access key, optionally preceded
// by spaces and/or followed by the ':' character, store the access key and
// remove the access key placeholder + leading spaces from the label.
// Otherwise a character preceded by one but not two &s is the access key.
// Store it and remove the &.
// Note that if you change the following code, see the comment of
// nsTextBoxFrame::UpdateAccessTitle.
var accessKey = null;
if (/ *\(\&([^&])\)(:)?$/.test(aLabel)) {
aLabel = RegExp.leftContext + RegExp.$2;
accessKey = RegExp.$1;
} else if (/^(.*[^&])?\&(([^&]).*$)/.test(aLabel)) {
aLabel = RegExp.$1 + RegExp.$2;
accessKey = RegExp.$3;
}
// && is the magic sequence to embed an & in your label.
aLabel = aLabel.replace(/\&\&/g, "&");
aNode.label = aLabel;
// XXXjag bug 325251
// Need to set this after aNode.setAttribute("value", aLabel);
if (accessKey)
aNode.accessKey = accessKey;
},
initTextbox : function (aName, aValue) {
this.ui[aName + "Container"].hidden = false;
this.ui[aName + "Textbox"].setAttribute("value", aValue);
},
setButtonsEnabledState : function(enabled) {
this.ui.button0.disabled = !enabled;
// button1 (cancel) remains enabled.
this.ui.button2.disabled = !enabled;
this.ui.button3.disabled = !enabled;
},
onBlur : function (aEvent) {
if (aEvent.target != this.ui.focusTarget)
return;
this.setButtonsEnabledState(false);
// If we blur while waiting to enable the buttons, just cancel the
// timer to ensure the delay doesn't fire while not focused.
if (this.focusTimer) {
this.focusTimer.cancel();
this.focusTimer = null;
}
},
onFocus : function (aEvent) {
if (aEvent.target != this.ui.focusTarget)
return;
this.startOnFocusDelay();
},
startOnFocusDelay : function(delayTime) {
// Shouldn't already have a timer, but just in case...
if (this.focusTimer)
return;
// If no delay specified, use 250ms. (This is the normal case for when
// after the dialog has been opened and focus shifts.)
if (!delayTime)
delayTime = 250;
let self = this;
this.focusTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
this.focusTimer.initWithCallback(function() { self.onFocusTimeout(); },
delayTime, Ci.nsITimer.TYPE_ONE_SHOT);
},
onFocusTimeout : function() {
this.focusTimer = null;
this.setButtonsEnabledState(true);
},
onCheckbox : function() {
this.args.checked = this.ui.checkbox.checked;
},
onButton0 : function() {
this.args.ok = true;
this.args.buttonNumClicked = 0;
let username = this.ui.loginTextbox.value;
let password = this.ui.password1Textbox.value;
// Return textfield values
switch (this.args.promptType) {
case "prompt":
this.args.value = username;
break;
case "promptUserAndPass":
this.args.user = username;
this.args.pass = password;
break;
case "promptPassword":
this.args.pass = password;
break;
}
},
onButton1 : function() {
this.args.buttonNumClicked = 1;
},
onButton2 : function() {
this.args.buttonNumClicked = 2;
},
onButton3 : function() {
this.args.buttonNumClicked = 3;
},
};

View File

@ -48,4 +48,8 @@ EXTRA_COMPONENTS = \
nsPrompter.manifest \
$(NULL)
EXTRA_JS_MODULES = \
CommonDialog.jsm \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -24,6 +24,20 @@ let prompter = Cc["@mozilla.org/embedcomp/prompt-service;1"].
getService(Ci.nsIPromptService2);
let ioService = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
let pollTimer;
function pollDialog(dialog) {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
if (dialog.getButton("accept").disabled)
return;
ok(true, "dialog button is enabled now");
pollTimer.cancel();
pollTimer = null;
dialog.acceptDialog();
didDialog = true;
}
function checkExpectedState(doc, state) {
let msg = doc.getElementById("info.body").textContent;
@ -654,6 +668,27 @@ function handleDialog(doc, testNum) {
checkExpectedState(doc, state);
break;
case 30:
// ConfirmEx (with delay, ok)
state = {
msg : "This is the confirmEx delay text.",
title : "TestTitle",
iconClass : "question-icon",
textHidden : true,
passHidden : true,
checkHidden : true,
textValue : "",
passValue : "",
checkMsg : "",
checked : false,
};
is(dialog.getButton("accept").label, "OK", "Checking accept-button label");
is(dialog.getButton("cancel").label, "Cancel", "Checking cancel-button label");
is(dialog.getButton("accept").disabled, true, "Checking accept-button is disabled");
is(dialog.getButton("cancel").disabled, false, "Checking cancel-button isn't disabled ");
checkExpectedState(doc, state);
break;
case 100:
// PromptAuth (no realm, ok, with checkbox)
@ -711,6 +746,14 @@ function handleDialog(doc, testNum) {
if (testNum == 28) {
dialog._doButtonCommand("extra1");
} else if (testNum == 30) {
// 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.
pollTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
pollTimer.initWithCallback(function() { pollDialog(dialog); },
100, Ci.nsITimer.TYPE_REPEATING_SLACK);
return;
} else {
if (clickOK)
dialog.acceptDialog();
@ -1049,6 +1092,15 @@ prompter.alert(null, "TestTitle", "This is the alert text.");
ok(didDialog, "handleDialog was invoked");
// ===== test 30 =====
// ConfirmEx (delay, ok)
testNum++;
startCallbackTimer();
flags = (Ci.nsIPromptService.STD_OK_CANCEL_BUTTONS | Ci.nsIPromptService.BUTTON_DELAY_ENABLE);
clickedButton = prompter.confirmEx(window, "TestTitle", "This is the confirmEx delay text.", flags, null, null, null, null, {});
is(clickedButton, 0, "checked expected button num click");
ok(didDialog, "handleDialog was invoked");
// promptAuth already tested via password manager but do a few specific things here.