forked from mirrors/gecko-dev
		
	After fixing bug 1520263, `F7` key handling in chrome becomes async when focused element is a remote content. Therefore, the test should wait a reply event from remote content in the cases. Differential Revision: https://phabricator.services.mozilla.com/D106749
		
			
				
	
	
		
			300 lines
		
	
	
	
		
			9.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			300 lines
		
	
	
	
		
			9.4 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);
 | 
						|
});
 |