var gListener = null; const kURL = "data:text/html;charset=utf-8,Caret browsing is fun."; 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.domWindowOpened here because there's no way to // undo waiting for a window open. 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) { if (topic == "domwindowopened") { Services.ww.unregisterNotification(observer); let win = subject.QueryInterface(Ci.nsIDOMWindow); BrowserTestUtils.waitForEvent(win, "load", false, e => e.target.location.href != "about:blank").then(() => resolve(win)); gCaretPromptOpeningObserver = null; } } Services.ww.registerNotification(observer); gCaretPromptOpeningObserver = observer; }); } function hitF7(async = true) { let f7 = () => EventUtils.sendKey("F7"); // Need to not stop execution inside this task: if (async) { executeSoon(f7); } else { f7(); } } function syncToggleCaretNoDialog(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 sync, if it still does. hitF7(false); 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) { Services.ww.unregisterNotification(gCaretPromptOpeningObserver); gCaretPromptOpeningObserver = null; } let prefVal = Services.prefs.getBoolPref(kPrefCaretBrowsingOn); is(prefVal, expected, "Caret browsing should now be " + expectedStr); } function waitForFocusOnInput(browser) { return ContentTask.spawn(browser, null, function* () { let textEl = content.document.getElementById("in"); return ContentTaskUtils.waitForCondition(() => { return content.document.activeElement == textEl; }, "Input should get focused."); }); } function focusInput(browser) { return ContentTask.spawn(browser, null, function* () { let textEl = content.document.getElementById("in"); textEl.focus(); }); } add_task(function* checkTogglingCaretBrowsing() { let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, kURL); yield focusInput(tab.linkedBrowser); let promiseGotKey = promiseCaretPromptOpened(); hitF7(); let prompt = yield promiseGotKey; let doc = prompt.document; is(doc.documentElement.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"); doc.documentElement.cancelDialog(); yield promiseDialogUnloaded; info("Dialog unloaded"); yield waitForFocusOnInput(tab.linkedBrowser); ok(!Services.prefs.getBoolPref(kPrefCaretBrowsingOn), "Caret browsing should still be off after cancelling the dialog."); promiseGotKey = promiseCaretPromptOpened(); hitF7(); prompt = yield promiseGotKey; doc = prompt.document; is(doc.documentElement.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"); doc.documentElement.acceptDialog(); yield promiseDialogUnloaded; info("Dialog unloaded"); yield waitForFocusOnInput(tab.linkedBrowser); ok(Services.prefs.getBoolPref(kPrefCaretBrowsingOn), "Caret browsing should be on after accepting the dialog."); syncToggleCaretNoDialog(false); promiseGotKey = promiseCaretPromptOpened(); hitF7(); prompt = yield promiseGotKey; doc = prompt.document; is(doc.documentElement.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"); doc.documentElement.cancelDialog(); yield promiseDialogUnloaded; info("Dialog unloaded"); yield 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); yield BrowserTestUtils.removeTab(tab); }); add_task(function* toggleCheckboxNoCaretBrowsing() { let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, kURL); yield focusInput(tab.linkedBrowser); let promiseGotKey = promiseCaretPromptOpened(); hitF7(); let prompt = yield promiseGotKey; let doc = prompt.document; is(doc.documentElement.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: doc.documentElement.getButton("cancel").click(); yield promiseDialogUnloaded; info("Dialog unloaded"); yield waitForFocusOnInput(tab.linkedBrowser); ok(!Services.prefs.getBoolPref(kPrefCaretBrowsingOn), "Caret browsing should still be off."); ok(!Services.prefs.getBoolPref(kPrefShortcutEnabled), "Shortcut should now be disabled."); syncToggleCaretNoDialog(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); yield BrowserTestUtils.removeTab(tab); }); add_task(function* toggleCheckboxWantCaretBrowsing() { let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, kURL); yield focusInput(tab.linkedBrowser); let promiseGotKey = promiseCaretPromptOpened(); hitF7(); let prompt = yield promiseGotKey; let doc = prompt.document; is(doc.documentElement.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: doc.documentElement.acceptDialog(); yield promiseDialogUnloaded; info("Dialog unloaded"); yield 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."); syncToggleCaretNoDialog(false); syncToggleCaretNoDialog(true); syncToggleCaretNoDialog(false); Services.prefs.setBoolPref(kPrefShortcutEnabled, true); Services.prefs.setBoolPref(kPrefWarnOnEnable, true); Services.prefs.setBoolPref(kPrefCaretBrowsingOn, false); yield BrowserTestUtils.removeTab(tab); });