зеркало из https://github.com/mozilla/gecko-dev.git
368 строки
12 KiB
JavaScript
368 строки
12 KiB
JavaScript
var gListener = null;
|
|
const kURL =
|
|
"data:text/html;charset=utf-8,Caret browsing is fun.<input id='in'>";
|
|
|
|
const kPrefShortcutEnabled = "accessibility.browsewithcaret_shortcut.enabled";
|
|
const kPrefWarnOnEnable = "accessibility.warn_on_browsewithcaret";
|
|
const kPrefCaretBrowsingOn = "accessibility.browsewithcaret";
|
|
|
|
var oldPrefs = {};
|
|
for (let pref of [
|
|
kPrefShortcutEnabled,
|
|
kPrefWarnOnEnable,
|
|
kPrefCaretBrowsingOn,
|
|
]) {
|
|
oldPrefs[pref] = Services.prefs.getBoolPref(pref);
|
|
}
|
|
|
|
Services.prefs.setBoolPref(kPrefShortcutEnabled, true);
|
|
Services.prefs.setBoolPref(kPrefWarnOnEnable, true);
|
|
Services.prefs.setBoolPref(kPrefCaretBrowsingOn, false);
|
|
|
|
registerCleanupFunction(function() {
|
|
for (let pref of [
|
|
kPrefShortcutEnabled,
|
|
kPrefWarnOnEnable,
|
|
kPrefCaretBrowsingOn,
|
|
]) {
|
|
Services.prefs.setBoolPref(pref, oldPrefs[pref]);
|
|
}
|
|
});
|
|
|
|
// NB: not using BrowserTestUtils.promiseAlertDialog here because there's no way to
|
|
// undo waiting for a dialog. If we don't want the window to be opened, and
|
|
// wait for it to verify that it indeed does not open, we need to be able to
|
|
// then "stop" waiting so that when we next *do* want it to open, our "old"
|
|
// listener doesn't fire and do things we don't want (like close the window...).
|
|
let gCaretPromptOpeningObserver;
|
|
function promiseCaretPromptOpened() {
|
|
return new Promise(resolve => {
|
|
function observer(subject, topic, data) {
|
|
info("Dialog opened.");
|
|
resolve(subject);
|
|
gCaretPromptOpeningObserver();
|
|
}
|
|
Services.obs.addObserver(observer, "common-dialog-loaded");
|
|
gCaretPromptOpeningObserver = () => {
|
|
Services.obs.removeObserver(observer, "common-dialog-loaded");
|
|
gCaretPromptOpeningObserver = () => {};
|
|
};
|
|
});
|
|
}
|
|
|
|
function hitF7() {
|
|
SimpleTest.executeSoon(() => EventUtils.synthesizeKey("KEY_F7"));
|
|
}
|
|
|
|
async function toggleCaretNoDialog(expected) {
|
|
let openedDialog = false;
|
|
promiseCaretPromptOpened().then(function(win) {
|
|
openedDialog = true;
|
|
win.close(); // This will eventually return focus here and allow the test to continue...
|
|
});
|
|
// Cause the dialog to appear synchronously when focused element is in chrome,
|
|
// otherwise, i.e., when focused element is in remote content, it appears
|
|
// asynchronously.
|
|
const focusedElementInChrome = Services.focus.focusedElement;
|
|
const isAsync = focusedElementInChrome?.isRemoteBrowser;
|
|
const waitForF7KeyHandled = new Promise(resolve => {
|
|
let eventCount = 0;
|
|
const expectedEventCount = isAsync ? 2 : 1;
|
|
let listener = async event => {
|
|
if (event.key == "F7") {
|
|
info("F7 keypress is fired");
|
|
if (++eventCount == expectedEventCount) {
|
|
window.removeEventListener("keypress", listener, {
|
|
capture: true,
|
|
mozSystemGroup: true,
|
|
});
|
|
// Wait for the event handled in chrome.
|
|
await TestUtils.waitForTick();
|
|
resolve();
|
|
return;
|
|
}
|
|
info(
|
|
"Waiting for next F7 keypress which is a reply event from the remote content"
|
|
);
|
|
}
|
|
};
|
|
info(
|
|
`Synthesizing "F7" key press and wait ${expectedEventCount} keypress events...`
|
|
);
|
|
window.addEventListener("keypress", listener, {
|
|
capture: true,
|
|
mozSystemGroup: true,
|
|
});
|
|
});
|
|
hitF7();
|
|
await waitForF7KeyHandled;
|
|
|
|
let expectedStr = expected ? "on." : "off.";
|
|
ok(
|
|
!openedDialog,
|
|
"Shouldn't open a dialog to turn caret browsing " + expectedStr
|
|
);
|
|
// Need to clean up if the dialog wasn't opened, so the observer doesn't get
|
|
// re-triggered later on causing "issues".
|
|
if (!openedDialog) {
|
|
gCaretPromptOpeningObserver();
|
|
}
|
|
let prefVal = Services.prefs.getBoolPref(kPrefCaretBrowsingOn);
|
|
is(prefVal, expected, "Caret browsing should now be " + expectedStr);
|
|
}
|
|
|
|
function waitForFocusOnInput(browser) {
|
|
return SpecialPowers.spawn(browser, [], async function() {
|
|
let textEl = content.document.getElementById("in");
|
|
return ContentTaskUtils.waitForCondition(() => {
|
|
return content.document.activeElement == textEl;
|
|
}, "Input should get focused.");
|
|
});
|
|
}
|
|
|
|
function focusInput(browser) {
|
|
return SpecialPowers.spawn(browser, [], async function() {
|
|
let textEl = content.document.getElementById("in");
|
|
textEl.focus();
|
|
});
|
|
}
|
|
|
|
add_task(async function checkTogglingCaretBrowsing() {
|
|
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, kURL);
|
|
await focusInput(tab.linkedBrowser);
|
|
|
|
let promiseGotKey = promiseCaretPromptOpened();
|
|
hitF7();
|
|
let prompt = await promiseGotKey;
|
|
let doc = prompt.document;
|
|
let dialog = doc.getElementById("commonDialog");
|
|
is(dialog.defaultButton, "cancel", "No button should be the default");
|
|
ok(
|
|
!doc.getElementById("checkbox").checked,
|
|
"Checkbox shouldn't be checked by default."
|
|
);
|
|
let promiseDialogUnloaded = BrowserTestUtils.waitForEvent(prompt, "unload");
|
|
|
|
dialog.cancelDialog();
|
|
await promiseDialogUnloaded;
|
|
info("Dialog unloaded");
|
|
await waitForFocusOnInput(tab.linkedBrowser);
|
|
ok(
|
|
!Services.prefs.getBoolPref(kPrefCaretBrowsingOn),
|
|
"Caret browsing should still be off after cancelling the dialog."
|
|
);
|
|
|
|
promiseGotKey = promiseCaretPromptOpened();
|
|
hitF7();
|
|
prompt = await promiseGotKey;
|
|
|
|
doc = prompt.document;
|
|
dialog = doc.getElementById("commonDialog");
|
|
is(dialog.defaultButton, "cancel", "No button should be the default");
|
|
ok(
|
|
!doc.getElementById("checkbox").checked,
|
|
"Checkbox shouldn't be checked by default."
|
|
);
|
|
promiseDialogUnloaded = BrowserTestUtils.waitForEvent(prompt, "unload");
|
|
|
|
dialog.acceptDialog();
|
|
await promiseDialogUnloaded;
|
|
info("Dialog unloaded");
|
|
await waitForFocusOnInput(tab.linkedBrowser);
|
|
ok(
|
|
Services.prefs.getBoolPref(kPrefCaretBrowsingOn),
|
|
"Caret browsing should be on after accepting the dialog."
|
|
);
|
|
|
|
await toggleCaretNoDialog(false);
|
|
|
|
promiseGotKey = promiseCaretPromptOpened();
|
|
hitF7();
|
|
prompt = await promiseGotKey;
|
|
doc = prompt.document;
|
|
dialog = doc.getElementById("commonDialog");
|
|
|
|
is(dialog.defaultButton, "cancel", "No button should be the default");
|
|
ok(
|
|
!doc.getElementById("checkbox").checked,
|
|
"Checkbox shouldn't be checked by default."
|
|
);
|
|
|
|
promiseDialogUnloaded = BrowserTestUtils.waitForEvent(prompt, "unload");
|
|
dialog.cancelDialog();
|
|
await promiseDialogUnloaded;
|
|
info("Dialog unloaded");
|
|
await waitForFocusOnInput(tab.linkedBrowser);
|
|
|
|
ok(
|
|
!Services.prefs.getBoolPref(kPrefCaretBrowsingOn),
|
|
"Caret browsing should still be off after cancelling the dialog."
|
|
);
|
|
|
|
Services.prefs.setBoolPref(kPrefShortcutEnabled, true);
|
|
Services.prefs.setBoolPref(kPrefWarnOnEnable, true);
|
|
Services.prefs.setBoolPref(kPrefCaretBrowsingOn, false);
|
|
|
|
BrowserTestUtils.removeTab(tab);
|
|
});
|
|
|
|
add_task(async function toggleCheckboxNoCaretBrowsing() {
|
|
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, kURL);
|
|
await focusInput(tab.linkedBrowser);
|
|
|
|
let promiseGotKey = promiseCaretPromptOpened();
|
|
hitF7();
|
|
let prompt = await promiseGotKey;
|
|
let doc = prompt.document;
|
|
let dialog = doc.getElementById("commonDialog");
|
|
is(dialog.defaultButton, "cancel", "No button should be the default");
|
|
let checkbox = doc.getElementById("checkbox");
|
|
ok(!checkbox.checked, "Checkbox shouldn't be checked by default.");
|
|
|
|
// Check the box:
|
|
checkbox.click();
|
|
|
|
let promiseDialogUnloaded = BrowserTestUtils.waitForEvent(prompt, "unload");
|
|
|
|
// Say no:
|
|
dialog.getButton("cancel").click();
|
|
|
|
await promiseDialogUnloaded;
|
|
info("Dialog unloaded");
|
|
await waitForFocusOnInput(tab.linkedBrowser);
|
|
ok(
|
|
!Services.prefs.getBoolPref(kPrefCaretBrowsingOn),
|
|
"Caret browsing should still be off."
|
|
);
|
|
ok(
|
|
!Services.prefs.getBoolPref(kPrefShortcutEnabled),
|
|
"Shortcut should now be disabled."
|
|
);
|
|
|
|
await toggleCaretNoDialog(false);
|
|
ok(
|
|
!Services.prefs.getBoolPref(kPrefShortcutEnabled),
|
|
"Shortcut should still be disabled."
|
|
);
|
|
|
|
Services.prefs.setBoolPref(kPrefShortcutEnabled, true);
|
|
Services.prefs.setBoolPref(kPrefWarnOnEnable, true);
|
|
Services.prefs.setBoolPref(kPrefCaretBrowsingOn, false);
|
|
|
|
BrowserTestUtils.removeTab(tab);
|
|
});
|
|
|
|
add_task(async function toggleCheckboxWantCaretBrowsing() {
|
|
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, kURL);
|
|
await focusInput(tab.linkedBrowser);
|
|
|
|
let promiseGotKey = promiseCaretPromptOpened();
|
|
hitF7();
|
|
let prompt = await promiseGotKey;
|
|
let doc = prompt.document;
|
|
let dialog = doc.getElementById("commonDialog");
|
|
is(dialog.defaultButton, "cancel", "No button should be the default");
|
|
let checkbox = doc.getElementById("checkbox");
|
|
ok(!checkbox.checked, "Checkbox shouldn't be checked by default.");
|
|
|
|
// Check the box:
|
|
checkbox.click();
|
|
|
|
let promiseDialogUnloaded = BrowserTestUtils.waitForEvent(prompt, "unload");
|
|
|
|
// Say yes:
|
|
dialog.acceptDialog();
|
|
await promiseDialogUnloaded;
|
|
info("Dialog unloaded");
|
|
await waitForFocusOnInput(tab.linkedBrowser);
|
|
ok(
|
|
Services.prefs.getBoolPref(kPrefCaretBrowsingOn),
|
|
"Caret browsing should now be on."
|
|
);
|
|
ok(
|
|
Services.prefs.getBoolPref(kPrefShortcutEnabled),
|
|
"Shortcut should still be enabled."
|
|
);
|
|
ok(
|
|
!Services.prefs.getBoolPref(kPrefWarnOnEnable),
|
|
"Should no longer warn when enabling."
|
|
);
|
|
|
|
await toggleCaretNoDialog(false);
|
|
await toggleCaretNoDialog(true);
|
|
await toggleCaretNoDialog(false);
|
|
|
|
Services.prefs.setBoolPref(kPrefShortcutEnabled, true);
|
|
Services.prefs.setBoolPref(kPrefWarnOnEnable, true);
|
|
Services.prefs.setBoolPref(kPrefCaretBrowsingOn, false);
|
|
|
|
BrowserTestUtils.removeTab(tab);
|
|
});
|
|
|
|
// Test for bug 1743878: Many repeated modal caret-browsing dialogs, if you
|
|
// accidentally hold down F7 for a few seconds
|
|
add_task(async function testF7SpamDoesNotOpenDialogs() {
|
|
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
|
|
registerCleanupFunction(() => BrowserTestUtils.removeTab(tab));
|
|
|
|
let promiseGotKey = promiseCaretPromptOpened();
|
|
hitF7();
|
|
let prompt = await promiseGotKey;
|
|
let doc = prompt.document;
|
|
let dialog = doc.getElementById("commonDialog");
|
|
|
|
let promiseDialogUnloaded = BrowserTestUtils.waitForEvent(prompt, "unload");
|
|
|
|
// Listen for an additional prompt to open, which should not happen.
|
|
let promiseDialogOrTimeout = () =>
|
|
Promise.race([
|
|
promiseCaretPromptOpened(),
|
|
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
|
|
new Promise(resolve => setTimeout(resolve, 100)),
|
|
]);
|
|
|
|
let openedPromise = promiseDialogOrTimeout();
|
|
|
|
// Hit F7 two more times: once to test that _awaitingToggleCaretBrowsingPrompt
|
|
// is applied, and again to test that its value isn't somehow reset by
|
|
// pressing F7 while the dialog is open.
|
|
for (let i = 0; i < 2; i++) {
|
|
await new Promise(resolve =>
|
|
SimpleTest.executeSoon(() => {
|
|
hitF7();
|
|
resolve();
|
|
})
|
|
);
|
|
}
|
|
|
|
// Say no:
|
|
dialog.cancelDialog();
|
|
await promiseDialogUnloaded;
|
|
info("Dialog unloaded");
|
|
|
|
let openedDialog = await openedPromise;
|
|
ok(!openedDialog, "No additional dialog should have opened.");
|
|
|
|
// If the test fails, clean up any dialogs we erroneously opened so they don't
|
|
// interfere with other tests.
|
|
let extraDialogs = 0;
|
|
while (openedDialog) {
|
|
extraDialogs += 1;
|
|
let doc = openedDialog.document;
|
|
let dialog = doc.getElementById("commonDialog");
|
|
openedPromise = promiseDialogOrTimeout();
|
|
dialog.cancelDialog();
|
|
openedDialog = await openedPromise;
|
|
}
|
|
if (extraDialogs) {
|
|
info(`Closed ${extraDialogs} extra dialogs.`);
|
|
}
|
|
|
|
// Either way, we now have an extra observer, so clean it up.
|
|
gCaretPromptOpeningObserver();
|
|
|
|
Services.prefs.setBoolPref(kPrefShortcutEnabled, true);
|
|
Services.prefs.setBoolPref(kPrefWarnOnEnable, true);
|
|
Services.prefs.setBoolPref(kPrefCaretBrowsingOn, false);
|
|
});
|