Now, callers of EventUtils.synthesizeKey() don't need to specify KeyboardEvent.code value anymore if they assume that active keyboard layout is US keyboard layout. Note that this patch changes the meaning of only test_bug551434.html. Some callers in it don't match the key value and code value but that looks like that they don't checking such odd keyboard events. So, they must be bug of the test. MozReview-Commit-ID: Itxo7yZ9rkK
237 lines
6.9 KiB
JavaScript
237 lines
6.9 KiB
JavaScript
/* eslint-env mozilla/frame-script */
|
|
|
|
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|
ChromeUtils.import("resource://gre/modules/Timer.jsm");
|
|
|
|
// Define these to make EventUtils happy.
|
|
let window = this;
|
|
let parent = {};
|
|
|
|
let EventUtils = {};
|
|
Services.scriptloader.loadSubScript(
|
|
"chrome://mochikit/content/tests/SimpleTest/EventUtils.js",
|
|
EventUtils
|
|
);
|
|
|
|
addMessageListener("handlePrompt", msg => {
|
|
handlePromptWhenItAppears(msg.action, msg.isTabModal, msg.isSelect);
|
|
});
|
|
|
|
function handlePromptWhenItAppears(action, isTabModal, isSelect) {
|
|
let interval = setInterval(() => {
|
|
if (handlePrompt(action, isTabModal, isSelect)) {
|
|
clearInterval(interval);
|
|
}
|
|
}, 100);
|
|
}
|
|
|
|
function handlePrompt(action, isTabModal, isSelect) {
|
|
let ui;
|
|
|
|
if (isTabModal) {
|
|
let browserWin = Services.wm.getMostRecentWindow("navigator:browser");
|
|
let gBrowser = browserWin.gBrowser;
|
|
let promptManager = gBrowser.getTabModalPromptBox(gBrowser.selectedBrowser);
|
|
let prompts = promptManager.listPrompts();
|
|
if (!prompts.length) {
|
|
return false; // try again in a bit
|
|
}
|
|
|
|
ui = prompts[0].Dialog.ui;
|
|
} else {
|
|
let doc = getDialogDoc();
|
|
if (!doc) {
|
|
return false; // try again in a bit
|
|
}
|
|
|
|
if (isSelect)
|
|
ui = doc;
|
|
else
|
|
ui = doc.defaultView.Dialog.ui;
|
|
|
|
}
|
|
|
|
let promptState;
|
|
if (isSelect) {
|
|
promptState = getSelectState(ui);
|
|
dismissSelect(ui, action);
|
|
} else {
|
|
promptState = getPromptState(ui);
|
|
dismissPrompt(ui, action);
|
|
}
|
|
sendAsyncMessage("promptHandled", { promptState });
|
|
return true;
|
|
}
|
|
|
|
function getSelectState(ui) {
|
|
let listbox = ui.getElementById("list");
|
|
|
|
let state = {};
|
|
state.msg = ui.getElementById("info.txt").value;
|
|
state.selectedIndex = listbox.selectedIndex;
|
|
state.items = [];
|
|
|
|
for (let i = 0; i < listbox.itemCount; i++) {
|
|
let item = listbox.getItemAtIndex(i).label;
|
|
state.items.push(item);
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
function getPromptState(ui) {
|
|
let state = {};
|
|
state.msg = ui.infoBody.textContent;
|
|
state.titleHidden = ui.infoTitle.getAttribute("hidden") == "true";
|
|
state.textHidden = ui.loginContainer.hidden;
|
|
state.passHidden = ui.password1Container.hidden;
|
|
state.checkHidden = ui.checkboxContainer.hidden;
|
|
state.checkMsg = ui.checkbox.label;
|
|
state.checked = ui.checkbox.checked;
|
|
// tab-modal prompts don't have an infoIcon
|
|
state.iconClass = ui.infoIcon ? ui.infoIcon.className : null;
|
|
state.textValue = ui.loginTextbox.getAttribute("value");
|
|
state.passValue = ui.password1Textbox.getAttribute("value");
|
|
|
|
state.butt0Label = ui.button0.label;
|
|
state.butt1Label = ui.button1.label;
|
|
state.butt2Label = ui.button2.label;
|
|
|
|
state.butt0Disabled = ui.button0.disabled;
|
|
state.butt1Disabled = ui.button1.disabled;
|
|
state.butt2Disabled = ui.button2.disabled;
|
|
|
|
function isDefaultButton(b) {
|
|
return (b.hasAttribute("default") &&
|
|
b.getAttribute("default") == "true");
|
|
}
|
|
state.defButton0 = isDefaultButton(ui.button0);
|
|
state.defButton1 = isDefaultButton(ui.button1);
|
|
state.defButton2 = isDefaultButton(ui.button2);
|
|
|
|
let e = Services.focus.focusedElement;
|
|
|
|
if (e == null) {
|
|
state.focused = null;
|
|
} else if (ui.button0.isSameNode(e)) {
|
|
state.focused = "button0";
|
|
} else if (ui.button1.isSameNode(e)) {
|
|
state.focused = "button1";
|
|
} else if (ui.button2.isSameNode(e)) {
|
|
state.focused = "button2";
|
|
} else if (ui.loginTextbox.inputField.isSameNode(e)) {
|
|
state.focused = "textField";
|
|
} else if (ui.password1Textbox.inputField.isSameNode(e)) {
|
|
state.focused = "passField";
|
|
} else if (ui.infoBody.isSameNode(e)) {
|
|
state.focused = "infoBody";
|
|
} else {
|
|
state.focused = "ERROR: unexpected element focused: " + (e ? e.localName : "<null>");
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
function dismissSelect(ui, action) {
|
|
let dialog = ui.getElementsByTagName("dialog")[0];
|
|
let listbox = ui.getElementById("list");
|
|
|
|
if (action.selectItem) {
|
|
listbox.selectedIndex = 1;
|
|
}
|
|
|
|
if (action.buttonClick == "ok") {
|
|
dialog.acceptDialog();
|
|
} else if (action.buttonClick == "cancel") {
|
|
dialog.cancelDialog();
|
|
}
|
|
}
|
|
|
|
function dismissPrompt(ui, action) {
|
|
if (action.setCheckbox) {
|
|
// Annoyingly, the prompt code is driven by oncommand.
|
|
ui.checkbox.setChecked(true);
|
|
ui.checkbox.doCommand();
|
|
}
|
|
|
|
if ("textField" in action) {
|
|
ui.loginTextbox.setAttribute("value", action.textField);
|
|
}
|
|
|
|
if ("passField" in action) {
|
|
ui.password1Textbox.setAttribute("value", action.passField);
|
|
}
|
|
|
|
switch (action.buttonClick) {
|
|
case "ok":
|
|
case 0:
|
|
ui.button0.click();
|
|
break;
|
|
case "cancel":
|
|
case 1:
|
|
ui.button1.click();
|
|
break;
|
|
case 2:
|
|
ui.button2.click();
|
|
break;
|
|
case "ESC":
|
|
// XXX This is assuming tab-modal.
|
|
let browserWin = Services.wm.getMostRecentWindow("navigator:browser");
|
|
EventUtils.synthesizeKey("KEY_Escape", {}, browserWin);
|
|
break;
|
|
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.
|
|
let interval = setInterval(() => {
|
|
if (ui.button0.disabled)
|
|
return;
|
|
ui.button0.click();
|
|
clearInterval(interval);
|
|
}, 100);
|
|
break;
|
|
|
|
default:
|
|
throw "dismissPrompt action listed unknown button.";
|
|
}
|
|
}
|
|
|
|
function getDialogDoc() {
|
|
// Trudge through all the open windows, until we find the one
|
|
// that has either commonDialog.xul or selectDialog.xul loaded.
|
|
// var enumerator = Services.wm.getEnumerator("navigator:browser");
|
|
var enumerator = Services.wm.getXULWindowEnumerator(null);
|
|
|
|
while (enumerator.hasMoreElements()) {
|
|
var win = enumerator.getNext();
|
|
var windowDocShell = win.QueryInterface(Ci.nsIXULWindow).docShell;
|
|
|
|
var containedDocShells = windowDocShell.getDocShellEnumerator(
|
|
Ci.nsIDocShellTreeItem.typeChrome,
|
|
Ci.nsIDocShell.ENUMERATE_FORWARDS);
|
|
while (containedDocShells.hasMoreElements()) {
|
|
// Get the corresponding document for this docshell
|
|
var childDocShell = containedDocShells.getNext();
|
|
// We don't want it if it's not done loading.
|
|
if (childDocShell.busyFlags != Ci.nsIDocShell.BUSY_FLAGS_NONE)
|
|
continue;
|
|
var childDoc = childDocShell.QueryInterface(Ci.nsIDocShell)
|
|
.contentViewer
|
|
.DOMDocument;
|
|
|
|
if (childDoc.location.href != "chrome://global/content/commonDialog.xul" &&
|
|
childDoc.location.href != "chrome://global/content/selectDialog.xul")
|
|
continue;
|
|
|
|
// We're expecting the dialog to be focused. If it's not yet, try later.
|
|
// (In particular, this is needed on Linux to reliably check focused elements.)
|
|
if (Services.focus.focusedWindow != childDoc.defaultView)
|
|
continue;
|
|
|
|
return childDoc;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|