summaryrefslogtreecommitdiffstats
path: root/toolkit/components/passwordmgr/test/mochitest/test_autocomplete_basic_form_insecure.html
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/passwordmgr/test/mochitest/test_autocomplete_basic_form_insecure.html')
-rw-r--r--toolkit/components/passwordmgr/test/mochitest/test_autocomplete_basic_form_insecure.html849
1 files changed, 849 insertions, 0 deletions
diff --git a/toolkit/components/passwordmgr/test/mochitest/test_autocomplete_basic_form_insecure.html b/toolkit/components/passwordmgr/test/mochitest/test_autocomplete_basic_form_insecure.html
new file mode 100644
index 0000000000..13b4e2170b
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/mochitest/test_autocomplete_basic_form_insecure.html
@@ -0,0 +1,849 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test insecure form field autocomplete</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="../../../satchel/test/satchel_common.js"></script>
+ <script type="text/javascript" src="pwmgr_common.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display"></p>
+
+<!-- we presumably can't hide the content for this test. -->
+<div id="content"></div>
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Login Manager: multiple login autocomplete. **/
+
+// Restore the form to the default state.
+function restoreForm(form) {
+ form.uname.value = "";
+ form.pword.value = "";
+ form.uname.focus();
+}
+
+function sendFakeAutocompleteEvent(element) {
+ var acEvent = document.createEvent("HTMLEvents");
+ acEvent.initEvent("DOMAutoComplete", true, false);
+ element.dispatchEvent(acEvent);
+}
+
+async function promiseACPopupClosed() {
+ return SimpleTest.promiseWaitForCondition(async () => {
+ let popupState = await getPopupState();
+ return !popupState.open;
+ }, "Wait for AC popup to be closed");
+}
+
+add_setup(async () => {
+ listenForUnexpectedPopupShown();
+});
+
+add_task(async function form1_initial_empty() {
+ const form = createLoginForm({
+ action: "http://autocomplete:8888/formtest.js"
+ });
+ await promiseFormsProcessedInSameProcess();
+
+ // Make sure initial form is empty.
+ checkLoginForm(form.uname, "", form.pword, "");
+ const popupState = await getPopupState();
+ is(popupState.open, false, "Check popup is initially closed");
+});
+
+add_task(async function form1_warning_entry() {
+ await setStoredLoginsAsync(
+ // login 0 has no username, so should be filtered out from the autocomplete list.
+ [location.origin, "http://autocomplete:8888", null, "", "pass0", "", "pword"],
+
+ [location.origin, "http://autocomplete:8888", null, "user-1", "pass-1", "uname", "pword"],
+ [location.origin, "http://autocomplete:8888", null, "user-2", "pass-2", "uname", "pword"],
+ [location.origin, "http://autocomplete:8888", null, "user-3", "pass-3", "uname", "pword"]
+ );
+ const form = createLoginForm({
+ action: "http://autocomplete:8888/formtest.js"
+ });
+ await promiseFormsProcessedInSameProcess();
+
+ // Trigger autocomplete popup
+ form.uname.focus();
+ const autocompleteItems = await popupByArrowDown();
+
+ const popupState = await getPopupState();
+ is(popupState.selectedIndex, -1, "Check no entries are selected upon opening");
+
+ const expectedMenuItems = [
+ "This connection is not secure. Logins entered here could be compromised. Learn More",
+ "user-1",
+ "user-2",
+ "user-3"
+ ];
+ checkAutoCompleteResults(autocompleteItems, expectedMenuItems, "mochi.test", "Check all menuitems are displayed correctly.");
+
+ synthesizeKey("KEY_ArrowDown"); // select insecure warning
+ checkLoginForm(form.uname, "", form.pword, ""); // value shouldn't update just by selecting
+ synthesizeKey("KEY_Enter");
+ await promiseACPopupClosed();
+ checkLoginForm(form.uname, "", form.pword, "");
+});
+
+add_task(async function form1_first_entry() {
+ await setStoredLoginsAsync(
+ [location.origin, "http://autocomplete:8888", null, "user-1", "pass-1", "uname", "pword"],
+ [location.origin, "http://autocomplete:8888", null, "user-2", "pass-2", "uname", "pword"]
+ );
+ const form = createLoginForm({
+ action: "http://autocomplete:8888/formtest.js"
+ });
+ await promiseFormsProcessedInSameProcess();
+ // Trigger autocomplete popup
+ form.uname.focus();
+ await popupByArrowDown();
+
+ let popupState = await getPopupState();
+ is(popupState.selectedIndex, -1, "Check no entries are selected upon opening");
+
+ synthesizeKey("KEY_ArrowDown"); // skip insecure warning
+ synthesizeKey("KEY_ArrowDown"); // first
+ checkLoginForm(form.uname, "", form.pword, ""); // value shouldn't update just by selecting
+ synthesizeKey("KEY_Enter");
+ await promiseFormsProcessedInSameProcess();
+ checkLoginForm(form.uname, "user-1", form.pword, "pass-1");
+});
+
+add_task(async function form1_second_entry() {
+ await setStoredLoginsAsync(
+ [location.origin, "http://autocomplete:8888", null, "user-1", "pass-1", "uname", "pword"],
+ [location.origin, "http://autocomplete:8888", null, "user-2", "pass-2", "uname", "pword"]
+ );
+ const form = createLoginForm({
+ action: "http://autocomplete:8888/formtest.js"
+ });
+ await promiseFormsProcessedInSameProcess();
+ // Trigger autocomplete popup
+ form.uname.focus();
+ await popupByArrowDown();
+
+ synthesizeKey("KEY_ArrowDown"); // skip insecure warning
+ synthesizeKey("KEY_ArrowDown"); // first
+ synthesizeKey("KEY_ArrowDown"); // second
+ synthesizeKey("KEY_Enter");
+ await promiseFormsProcessedInSameProcess();
+ checkLoginForm(form.uname, "user-2", form.pword, "pass-2");
+});
+
+add_task(async function form1_wraparound_first_entry() {
+ await setStoredLoginsAsync(
+ [location.origin, "http://autocomplete:8888", null, "user-1", "pass-1", "uname", "pword"],
+ [location.origin, "http://autocomplete:8888", null, "user-2", "pass-2", "uname", "pword"]
+ );
+ const form = createLoginForm({
+ action: "http://autocomplete:8888/formtest.js"
+ });
+ await promiseFormsProcessedInSameProcess();
+ // Trigger autocomplete popup
+ form.uname.focus();
+ await popupByArrowDown();
+
+ synthesizeKey("KEY_ArrowDown"); // skip insecure warning
+ synthesizeKey("KEY_ArrowDown"); // first
+ synthesizeKey("KEY_ArrowDown"); // second
+ synthesizeKey("KEY_ArrowDown"); // footer
+ synthesizeKey("KEY_ArrowDown"); // deselects
+ synthesizeKey("KEY_ArrowDown"); // skip insecure warning
+ synthesizeKey("KEY_ArrowDown"); // first
+ synthesizeKey("KEY_Enter");
+ await promiseACPopupClosed();
+ checkLoginForm(form.uname, "user-1", form.pword, "pass-1");
+});
+
+add_task(async function form1_wraparound_up_last_entry() {
+ await setStoredLoginsAsync(
+ [location.origin, "http://autocomplete:8888", null, "user-1", "pass-1", "uname", "pword"],
+ [location.origin, "http://autocomplete:8888", null, "user-2", "pass-2", "uname", "pword"]
+ );
+ const form = createLoginForm({
+ action: "http://autocomplete:8888/formtest.js"
+ });
+ await promiseFormsProcessedInSameProcess();
+ // Trigger autocomplete popup
+ form.uname.focus();
+ await popupByArrowDown();
+
+ synthesizeKey("KEY_ArrowUp"); // footer
+ synthesizeKey("KEY_ArrowUp"); // last (fourth)
+ synthesizeKey("KEY_Enter");
+ await promiseACPopupClosed();
+ checkLoginForm(form.uname, "user-2", form.pword, "pass-2");
+});
+
+add_task(async function form1_wraparound_down_up_up() {
+ await setStoredLoginsAsync(
+ [location.origin, "http://autocomplete:8888", null, "user-1", "pass-1", "uname", "pword"],
+ [location.origin, "http://autocomplete:8888", null, "user-2", "pass-2", "uname", "pword"]
+ );
+ const form = createLoginForm({
+ action: "http://autocomplete:8888/formtest.js"
+ });
+ await promiseFormsProcessedInSameProcess();
+ // Trigger autocomplete popup
+ form.uname.focus();
+ await popupByArrowDown();
+
+ synthesizeKey("KEY_ArrowDown"); // select first entry
+ synthesizeKey("KEY_ArrowUp"); // selects nothing!
+ synthesizeKey("KEY_ArrowUp"); // selects footer
+ synthesizeKey("KEY_ArrowUp"); // select last entry
+ synthesizeKey("KEY_Enter");
+ await promiseACPopupClosed();
+ checkLoginForm(form.uname, "user-2", form.pword, "pass-2");
+});
+
+add_task(async function form1_wraparound_up_last() {
+ await setStoredLoginsAsync(
+ [location.origin, "http://autocomplete:8888", null, "user-1", "pass-1", "uname", "pword"],
+ [location.origin, "http://autocomplete:8888", null, "user-2", "pass-2", "uname", "pword"]
+ );
+ const form = createLoginForm({
+ action: "http://autocomplete:8888/formtest.js"
+ });
+ await promiseFormsProcessedInSameProcess();
+ // Trigger autocomplete popup
+ form.uname.focus();
+ await popupByArrowDown();
+
+ synthesizeKey("KEY_ArrowDown");
+ synthesizeKey("KEY_ArrowUp"); // deselects
+ synthesizeKey("KEY_ArrowUp"); // footer
+ synthesizeKey("KEY_ArrowUp"); // last entry
+ synthesizeKey("KEY_ArrowUp"); // skip insecure warning
+ synthesizeKey("KEY_ArrowUp"); // first entry
+ synthesizeKey("KEY_ArrowUp"); // deselects
+ synthesizeKey("KEY_ArrowUp"); // footer
+ synthesizeKey("KEY_ArrowUp"); // last entry
+ synthesizeKey("KEY_Enter");
+ await promiseACPopupClosed();
+ checkLoginForm(form.uname, "user-2", form.pword, "pass-2");
+});
+
+add_task(async function form1_fill_username_without_autofill_right() {
+ await setStoredLoginsAsync(
+ [location.origin, "http://autocomplete:8888", null, "user-1", "pass-1", "uname", "pword"],
+ [location.origin, "http://autocomplete:8888", null, "user-2", "pass-2", "uname", "pword"]
+ );
+ const form = createLoginForm({
+ action: "http://autocomplete:8888/formtest.js"
+ });
+ await promiseFormsProcessedInSameProcess();
+ // Trigger autocomplete popup
+ form.uname.focus();
+ await popupByArrowDown();
+
+ // Set first entry w/o triggering autocomplete
+ synthesizeKey("KEY_ArrowDown"); // skip insecure warning
+ synthesizeKey("KEY_ArrowDown"); // first
+ synthesizeKey("KEY_ArrowRight");
+ await promiseACPopupClosed();
+ checkLoginForm(form.uname, "user-1", form.pword, ""); // empty password
+});
+
+add_task(async function form1_fill_username_without_autofill_left() {
+ await setStoredLoginsAsync(
+ [location.origin, "http://autocomplete:8888", null, "user-1", "pass-1", "uname", "pword"],
+ [location.origin, "http://autocomplete:8888", null, "user-2", "pass-2", "uname", "pword"]
+ );
+ const form = createLoginForm({
+ action: "http://autocomplete:8888/formtest.js"
+ });
+ await promiseFormsProcessedInSameProcess();
+ // Trigger autocomplete popup
+ form.uname.focus();
+ await popupByArrowDown();
+
+ // Set first entry w/o triggering autocomplete
+ synthesizeKey("KEY_ArrowDown"); // skip insecure warning
+ synthesizeKey("KEY_ArrowDown"); // first
+ synthesizeKey("KEY_ArrowLeft");
+ await promiseACPopupClosed();
+ checkLoginForm(form.uname, "user-1", form.pword, ""); // empty password
+});
+
+add_task(async function form1_pageup_first() {
+ await setStoredLoginsAsync(
+ [location.origin, "http://autocomplete:8888", null, "user-1", "pass-1", "uname", "pword"],
+ [location.origin, "http://autocomplete:8888", null, "user-2", "pass-2", "uname", "pword"]
+ );
+ const form = createLoginForm({
+ action: "http://autocomplete:8888/formtest.js"
+ });
+ await promiseFormsProcessedInSameProcess();
+ // Trigger autocomplete popup
+ form.uname.focus();
+ await popupByArrowDown();
+
+ // Check first entry (page up)
+ synthesizeKey("KEY_ArrowDown"); // first
+ synthesizeKey("KEY_ArrowDown"); // second
+ synthesizeKey("KEY_PageUp"); // first
+ synthesizeKey("KEY_ArrowDown"); // skip insecure warning
+ synthesizeKey("KEY_Enter");
+ await promiseACPopupClosed();
+ checkLoginForm(form.uname, "user-1", form.pword, "pass-1");
+});
+
+add_task(async function form1_pagedown_last() {
+ await setStoredLoginsAsync(
+ [location.origin, "http://autocomplete:8888", null, "user-1", "pass-1", "uname", "pword"],
+ [location.origin, "http://autocomplete:8888", null, "user-2", "pass-2", "uname", "pword"]
+ );
+ const form = createLoginForm({
+ action: "http://autocomplete:8888/formtest.js"
+ });
+ await promiseFormsProcessedInSameProcess();
+ // Trigger autocomplete popup
+ form.uname.focus();
+ await popupByArrowDown();
+
+ // test 13
+ // Check last entry (page down)
+ synthesizeKey("KEY_ArrowDown"); // first
+ synthesizeKey("KEY_PageDown"); // last
+ synthesizeKey("KEY_ArrowUp"); // skip footer
+ synthesizeKey("KEY_Enter");
+ await promiseACPopupClosed();
+ checkLoginForm(form.uname, "user-2", form.pword, "pass-2");
+});
+
+add_task(async function form1_untrusted_event() {
+ await setStoredLoginsAsync(
+ [location.origin, "http://autocomplete:8888", null, "user-1", "pass-1", "uname", "pword"],
+ [location.origin, "http://autocomplete:8888", null, "user-2", "pass-2", "uname", "pword"]
+ );
+ const form = createLoginForm({
+ action: "http://autocomplete:8888/formtest.js"
+ });
+ await promiseFormsProcessedInSameProcess();
+ // Trigger autocomplete popup
+ form.uname.focus();
+
+ // Send a fake (untrusted) event.
+ checkLoginForm(form.uname, "", form.pword, "");
+ form.uname.value = "user-2";
+ sendFakeAutocompleteEvent(form.uname);
+ await ensureLoginFormStaysFilledWith(form.uname, "user-2", form.pword, "");
+});
+
+add_task(async function form1_delete() {
+ await setStoredLoginsAsync(
+ [location.origin, "http://autocomplete:8888", null, "user-1", "pass-1", "uname", "pword"],
+ [location.origin, "http://autocomplete:8888", null, "user-2", "pass-2", "uname", "pword"],
+ [location.origin, "http://autocomplete:8888", null, "user-3", "pass-3", "uname", "pword"]
+ );
+ const form = createLoginForm({
+ action: "http://autocomplete:8888/formtest.js"
+ });
+ await promiseFormsProcessedInSameProcess();
+ // Trigger autocomplete popup
+ form.uname.focus();
+ await popupByArrowDown();
+ // should have 5 menu items by now: 3 logins plus insecure warning + footer
+ await notifyMenuChanged(5);
+
+ // XXX tried sending character "t" before/during dropdown to test
+ // filtering, but had no luck. Seemed like the character was getting lost.
+ // Setting uname.value didn't seem to work either. This works with a human
+ // driver, so I'm not sure what's up.
+
+ synthesizeKey("KEY_ArrowDown"); // skip insecure warning
+ // Delete the first entry (of 3), "user-1"
+ synthesizeKey("KEY_ArrowDown");
+ const numLoginsBeforeDeletion = await LoginManager.countLogins(location.origin, "http://autocomplete:8888", null);
+ is(numLoginsBeforeDeletion, 3, "Correct number of logins before deleting one");
+
+ const countChangedPromise = notifyMenuChanged(4);
+ const deletionPromise = promiseStorageChanged(["removeLogin"]);
+ // On OS X, shift-backspace and shift-delete work, just delete does not.
+ // On Win/Linux, shift-backspace does not work, delete and shift-delete do.
+ synthesizeKey("KEY_Delete", {shiftKey: true});
+ await deletionPromise;
+
+ checkLoginForm(form.uname, "", form.pword, "");
+ const numLoginsAfterDeletion = await LoginManager.countLogins(location.origin, "http://autocomplete:8888", null);
+ is(numLoginsAfterDeletion, 2, "Correct number of logins after deleting one");
+ await countChangedPromise;
+ synthesizeKey("KEY_Enter");
+ await promiseACPopupClosed();
+ checkLoginForm(form.uname, "user-2", form.pword, "pass-2");
+});
+
+add_task(async function form1_delete_second() {
+ await setStoredLoginsAsync(
+ [location.origin, "http://autocomplete:8888", null, "user-1", "pass-1", "uname", "pword"],
+ [location.origin, "http://autocomplete:8888", null, "user-2", "pass-2", "uname", "pword"],
+ [location.origin, "http://autocomplete:8888", null, "user-3", "pass-3", "uname", "pword"]
+ );
+ const form = createLoginForm({
+ action: "http://autocomplete:8888/formtest.js"
+ });
+ await promiseFormsProcessedInSameProcess();
+ // Trigger autocomplete popup
+ form.uname.focus();
+ await popupByArrowDown();
+
+ synthesizeKey("KEY_ArrowDown"); // skip insecure warning
+ // Delete the second entry (of 3), "user-2"
+ synthesizeKey("KEY_ArrowDown");
+ synthesizeKey("KEY_ArrowDown");
+ synthesizeKey("KEY_Delete", {shiftKey: true});
+ checkLoginForm(form.uname, "", form.pword, "");
+ const numLoginsAfterDeletion = await LoginManager.countLogins(location.origin, "http://autocomplete:8888", null);
+ is(numLoginsAfterDeletion, 2, "Correct number of logins after deleting one");
+ synthesizeKey("KEY_Enter");
+ await promiseACPopupClosed();
+ checkLoginForm(form.uname, "user-3", form.pword, "pass-3");
+});
+
+add_task(async function form1_delete_last() {
+ await setStoredLoginsAsync(
+ [location.origin, "http://autocomplete:8888", null, "user-1", "pass-1", "uname", "pword"],
+ [location.origin, "http://autocomplete:8888", null, "user-2", "pass-2", "uname", "pword"],
+ [location.origin, "http://autocomplete:8888", null, "user-3", "pass-3", "uname", "pword"]
+ );
+ const form = createLoginForm({
+ action: "http://autocomplete:8888/formtest.js"
+ });
+ await promiseFormsProcessedInSameProcess();
+ // Trigger autocomplete popup
+ form.uname.focus();
+ await popupByArrowDown();
+
+ /* test 54 */
+ // Delete the last entry (of 3), "user-3"
+ synthesizeKey("KEY_ArrowDown"); // skip insecure warning
+ synthesizeKey("KEY_ArrowDown");
+ synthesizeKey("KEY_ArrowDown");
+ synthesizeKey("KEY_ArrowDown");
+ const numLoginsBeforeDeletion = await LoginManager.countLogins(location.origin, "http://autocomplete:8888", null);
+ is(numLoginsBeforeDeletion, 3, "Correct number of logins before deleting one");
+ synthesizeKey("KEY_Delete", {shiftKey: true});
+ checkLoginForm(form.uname, "", form.pword, "");
+ const numLoginsAfterDeletion = await LoginManager.countLogins(location.origin, "http://autocomplete:8888", null);
+ is(numLoginsAfterDeletion, 2, "Correct number of logins after deleting one");
+ synthesizeKey("KEY_ArrowDown"); // skip insecure warning
+ synthesizeKey("KEY_ArrowDown");
+ synthesizeKey("KEY_Enter");
+ await promiseACPopupClosed();
+ checkLoginForm(form.uname, "user-1", form.pword, "pass-1");
+});
+
+// Tests for single-user forms for ignoring autocomplete=off
+
+add_task(async function password_autocomplete_off() {
+ await setStoredLoginsAsync(
+ [location.origin, "https://autocomplete2", null, "user", "pass", "uname", "pword"],
+ );
+ const form = createLoginForm({
+ action: "https://autocomplete2",
+ password: {
+ autocomplete: "off"
+ }
+ });
+ await promiseFormsProcessedInSameProcess();
+
+ checkLoginForm(form.uname, "user", form.pword, "pass");
+
+ restoreForm(form);
+ await popupByArrowDown();
+
+ synthesizeKey("KEY_ArrowDown"); // skip insecure warning
+ // Check first entry
+ synthesizeKey("KEY_ArrowDown");
+ checkLoginForm(form.uname, "", form.pword, ""); // value shouldn't update
+ synthesizeKey("KEY_Enter");
+ await promiseFormsProcessedInSameProcess();
+ checkLoginForm(form.uname, "user", form.pword, "pass");
+});
+
+add_task(async function username_autocomplete_off() {
+ await setStoredLoginsAsync(
+ [location.origin, "http://autocomplete2", null, "user", "pass", "uname", "pword"],
+ );
+ const form = createLoginForm({
+ action: "http://autocomplete2",
+ username: {
+ autocomplete: "off"
+ }
+ });
+ await promiseFormsProcessedInSameProcess();
+ checkLoginForm(form.uname, "user", form.pword, "pass");
+
+ restoreForm(form);
+ await popupByArrowDown();
+
+ synthesizeKey("KEY_ArrowDown"); // skip insecure warning
+ // Check first entry
+ synthesizeKey("KEY_ArrowDown");
+ checkLoginForm(form.uname, "", form.pword, ""); // value shouldn't update
+ synthesizeKey("KEY_Enter");
+ await promiseFormsProcessedInSameProcess();
+ await promiseACPopupClosed();
+ checkLoginForm(form.uname, "user", form.pword, "pass");
+});
+
+add_task(async function form_autocomplete_off() {
+ await setStoredLoginsAsync(
+ [location.origin, "http://autocomplete2", null, "user", "pass", "uname", "pword"],
+ );
+ const form = createLoginForm({
+ action: "http://autocomplete2",
+ autocomplete: "off"
+ });
+ await promiseFormsProcessedInSameProcess();
+
+ checkLoginForm(form.uname, "user", form.pword, "pass");
+ restoreForm(form);
+ await popupByArrowDown();
+
+ synthesizeKey("KEY_ArrowDown"); // skip insecure warning
+ // Check first entry
+ synthesizeKey("KEY_ArrowDown");
+ checkLoginForm(form.uname, "", form.pword, ""); // value shouldn't update
+ synthesizeKey("KEY_Enter");
+ await promiseFormsProcessedInSameProcess();
+ await promiseACPopupClosed();
+ checkLoginForm(form.uname, "user", form.pword, "pass");
+});
+
+add_task(async function username_and_password_autocomplete_off() {
+ await setStoredLoginsAsync(
+ [location.origin, "http://autocomplete2", null, "user", "pass", "uname", "pword"],
+ );
+ const form = createLoginForm({
+ action: "http://autocomplete2",
+ username: {
+ autocomplete: "off"
+ },
+ password: {
+ autocomplete: "off"
+ }
+ });
+ await promiseFormsProcessedInSameProcess();
+
+ checkLoginForm(form.uname, "user", form.pword, "pass");
+ restoreForm(form);
+ await popupByArrowDown();
+
+ synthesizeKey("KEY_ArrowDown"); // skip insecure warning
+ // Check first entry
+ synthesizeKey("KEY_ArrowDown");
+ checkLoginForm(form.uname, "", form.pword, ""); // value shouldn't update
+ synthesizeKey("KEY_Enter");
+ await promiseFormsProcessedInSameProcess();
+ await promiseACPopupClosed();
+ checkLoginForm(form.uname, "user", form.pword, "pass");
+});
+
+add_task(async function changing_username_does_not_touch_password() {
+ await setStoredLoginsAsync(
+ [location.origin, "http://autocomplete2", null, "user", "pass", "uname", "pword"],
+ );
+ const form = createLoginForm({
+ action: "http://autocomplete2",
+ username: {
+ autocomplete: "off"
+ },
+ password: {
+ autocomplete: "off"
+ }
+ });
+ await promiseFormsProcessedInSameProcess();
+
+ checkLoginForm(form.uname, "user", form.pword, "pass");
+
+ // Test that the password field remains filled in after changing
+ // the username.
+ form.uname.focus();
+ synthesizeKey("KEY_ArrowRight");
+ synthesizeKey("X", {shiftKey: true});
+ // Trigger the 'blur' event on uname
+ form.pword.focus();
+ await ensureLoginFormStaysFilledWith(form.uname, "userX", form.pword, "pass");
+});
+
+add_task(async function form7() {
+ await setStoredLoginsAsync(
+ [location.origin, "http://autocomplete3", null, "user-1", "pass-1", "uname", "pword"],
+ [location.origin, "http://autocomplete3", null, "user-2", "pass-2", "uname", "pword"]
+ );
+ const form = createLoginForm({
+ action: "http://autocomplete3"
+ });
+ await promiseFormsProcessedInSameProcess();
+
+ checkLoginForm(form.uname, "", form.pword, "");
+
+ // Insert a new username field into the form. We'll then make sure
+ // that invoking the autocomplete doesn't try to fill the form.
+ const newField = document.createElement("input");
+ newField.setAttribute("type", "text");
+ newField.setAttribute("name", "uname2");
+ form.insertBefore(newField, form.pword);
+ await ensureLoginFormStaysFilledWith(newField, "", form.pword, "");
+});
+
+add_task(async function form7_2() {
+ await setStoredLoginsAsync(
+ [location.origin, "http://autocomplete3", null, "user", "pass", "uname", "pword"]
+ );
+ const form = createLoginForm({
+ action: "http://autocomplete3"
+ });
+ await promiseFormsProcessedInSameProcess();
+
+ // Insert a new username field into the form. We'll then make sure
+ // that invoking the autocomplete doesn't try to fill the form.
+ const newField = document.createElement("input");
+ newField.setAttribute("type", "text");
+ newField.setAttribute("name", "uname2");
+ form.insertBefore(newField, form.pword);
+
+ restoreForm(form);
+ const autocompleteItems = await popupByArrowDown();
+ checkAutoCompleteResults(autocompleteItems, [
+ "This connection is not secure. Logins entered here could be compromised. Learn More",
+ "user"
+ ],
+ window.location.host,
+ "Check dropdown is showing all logins while field is blank");
+
+
+ synthesizeKey("KEY_ArrowDown"); // skip insecure warning
+ // Check first entry
+ synthesizeKey("KEY_ArrowDown");
+ checkLoginForm(form.uname, "", form.pword, ""); // value shouldn't update
+ synthesizeKey("KEY_Enter");
+ // The form changes, so we expect the old username field to get the
+ // selected autocomplete value, but neither the new username field nor
+ // the password field should have any values filled in.
+ await SimpleTest.promiseWaitForCondition(() => form.uname.value == "user",
+ "Wait for username to get filled");
+ await promiseACPopupClosed();
+ checkLoginForm(form.uname, "user", form.pword, "");
+ is(newField.value, "", "Verifying empty uname2");
+});
+
+add_task(async function form8() {
+ await setStoredLoginsAsync(
+ [location.origin, "http://autocomplete", null, "user", "pass", "uname", "pword"]
+ );
+ const form1 = createLoginForm({
+ num: 1,
+ action: "http://autocomplete-other"
+ });
+ const form2 = createLoginForm({
+ num: 2,
+ action: "http://autocomplete"
+ });
+ await promiseFormsProcessedInSameProcess(2);
+
+ checkLoginForm(form2.uname, "user", form2.pword, "pass");
+
+ restoreForm(form2);
+ checkLoginForm(form2.uname, "", form2.pword, "");
+
+ form1.uname.focus();
+ checkLoginForm(form2.uname, "", form2.pword, "");
+});
+
+add_task(async function form9_filtering() {
+ await setStoredLoginsAsync(
+ [location.origin, "http://autocomplete", null, "form9userAB", "pass-1", "uname", "pword"],
+ [location.origin, "http://autocomplete", null, "form9userAAB", "pass-2", "uname", "pword"]
+ );
+ const form = createLoginForm({
+ action: "http://autocomplete"
+ });
+ await promiseFormsProcessedInSameProcess();
+
+ let results = await popupBy(() => form.uname.focus());
+ checkAutoCompleteResults(results, [
+ "This connection is not secure. Logins entered here could be compromised. Learn More",
+ "form9userAAB",
+ "form9userAB"
+ ],
+ window.location.host,
+ "Check dropdown is showing all logins while field is blank");
+ synthesizeKey("KEY_Escape"); // Need to close the popup so we can get another popupshown after sending the string below.
+
+ results = await popupBy(() => sendString("form9userAB"));
+ checkAutoCompleteResults(results, [
+ "This connection is not secure. Logins entered here could be compromised. Learn More",
+ "form9userAB"
+ ],
+ window.location.host,
+ "Check dropdown is showing login with only one 'A'");
+
+ checkLoginForm(form.uname, "form9userAB", form.pword, "");
+ form.uname.focus();
+ synthesizeKey("KEY_ArrowLeft");
+ results = await popupBy(() => synthesizeKey("A", {shiftKey: true}));
+
+ checkLoginForm(form.uname, "form9userAAB", form.pword, "");
+ checkAutoCompleteResults(results, [
+ "This connection is not secure. Logins entered here could be compromised. Learn More",
+ "form9userAAB"
+ ],
+ window.location.host, "Check dropdown is updated after inserting 'A'");
+ synthesizeKey("KEY_ArrowDown"); // skip insecure warning
+ synthesizeKey("KEY_ArrowDown");
+ synthesizeKey("KEY_Enter");
+ await promiseFormsProcessedInSameProcess();
+ await promiseACPopupClosed();
+ checkLoginForm(form.uname, "form9userAAB", form.pword, "pass-2");
+});
+
+add_task(async function form9_autocomplete_cache() {
+ await setStoredLoginsAsync(
+ [location.origin, "http://autocomplete", null, "form9userAB", "pass-1", "uname", "pword"],
+ [location.origin, "http://autocomplete", null, "form9userAAB", "pass-2", "uname", "pword"]
+ );
+ const form = createLoginForm({
+ action: "http://autocomplete"
+ });
+ await promiseFormsProcessedInSameProcess();
+
+ await popupBy(() => form.uname.focus());
+
+ await addLoginsInParent(
+ [location.origin, "http://autocomplete", null, "form9userAABzz", "pass-3", "uname", "pword"]
+ );
+
+ const promise1 = notifyMenuChanged(2);
+ sendString("z");
+ const results1 = await promise1;
+ checkAutoCompleteResults(results1, [
+ "This connection is not secure. Logins entered here could be compromised. Learn More",
+ ], window.location.host,
+ "Check popup does not have any login items");
+
+ // check that empty results are cached - bug 496466
+ const promise2 = notifyMenuChanged(2);
+ sendString("z");
+ const results2 = await promise2;
+ checkAutoCompleteResults(results2, [
+ "This connection is not secure. Logins entered here could be compromised. Learn More",
+ ], window.location.host,
+ "Check popup only has the footer when it opens");
+});
+
+add_task(async function form12_recipes() {
+ await setStoredLoginsAsync(
+ [location.origin, "http://autocomplete", null, "user", "pass", "uname", "pword"]
+ );
+ const form = createLoginForm({
+ action: "http://autocomplete",
+ password: {
+ type: "text"
+ }
+ });
+
+ await loadRecipes({
+ siteRecipes: [{
+ "hosts": [window.location.host],
+ "usernameSelector": "input[name='1']",
+ "passwordSelector": "input[name='2']",
+ }],
+ });
+
+ // First test DOMAutocomplete
+ // Switch the password field to type=password so _fillForm marks the username
+ // field for autocomplete.
+ form.pword.type = "password";
+ await promiseFormsProcessedInSameProcess();
+ restoreForm(form);
+ checkLoginForm(form.uname, "", form.pword, "");
+ await popupByArrowDown();
+
+ synthesizeKey("KEY_ArrowDown"); // skip insecure warning
+ synthesizeKey("KEY_ArrowDown");
+ checkLoginForm(form.uname, "", form.pword, ""); // value shouldn't update
+ synthesizeKey("KEY_Enter");
+ await promiseFormsProcessedInSameProcess();
+ await promiseACPopupClosed();
+ checkLoginForm(form.uname, "user", form.pword, "pass");
+
+ // Now test recipes with blur on the username field.
+ restoreForm(form);
+ checkLoginForm(form.uname, "", form.pword, "");
+ form.uname.value = "user";
+ checkLoginForm(form.uname, "user", form.pword, "");
+ synthesizeKey("KEY_Tab");
+ await promiseFormsProcessedInSameProcess();
+ checkLoginForm(form.uname, "user", form.pword, "pass");
+ await resetRecipes();
+});
+
+add_task(async function form11_formless() {
+ await setStoredLoginsAsync(
+ [location.origin, location.origin, null, "user", "pass", "uname", "pword"]
+ );
+ const form = createLoginForm();
+ await promiseFormsProcessedInSameProcess();
+
+ // Test form-less autocomplete
+ restoreForm(form);
+ checkLoginForm(form.uname, "", form.pword, "");
+ await popupByArrowDown();
+
+ synthesizeKey("KEY_ArrowDown"); // skip insecure warning
+ // Trigger autocomplete
+ synthesizeKey("KEY_ArrowDown");
+ checkLoginForm(form.uname, "", form.pword, ""); // value shouldn't update
+ synthesizeKey("KEY_Enter");
+ await promiseFormsProcessedInSameProcess();
+ checkLoginForm(form.uname, "user", form.pword, "pass");
+});
+
+add_task(async function form13_stays_open_upon_empty_search() {
+ await setStoredLoginsAsync(
+ [location.origin, "http://autocomplete:8888", null, "", "pass", "", "pword"],
+ );
+ const form = createLoginForm({
+ action: "http://autocomplete:8888",
+ username: {
+ value: "prefilled"
+ },
+ password: {
+ value: "prefilled"
+ }
+ });
+ await promiseFormsProcessedInSameProcess();
+
+ checkLoginForm(form.uname, "prefilled", form.pword, "prefilled");
+
+ form.uname.scrollIntoView();
+ await popupBy(() => synthesizeMouseAtCenter(form.uname, {}));
+ form.uname.select();
+ synthesizeKey("KEY_Delete");
+
+ await ensureLoginFormStaysFilledWith(form.uname, "", form.pword, "prefilled");
+ let popupState = await getPopupState();
+ is(popupState.open, true, "Check popup is still open");
+
+ info("testing password field");
+ synthesizeMouseAtCenter(form.pword, {});
+ form.pword.select();
+ popupState = await getPopupState();
+ is(popupState.open, false, "Check popup closed since password field isn't empty");
+ await popupBy(() => synthesizeKey("KEY_Delete"));
+ checkLoginForm(form.uname, "", form.pword, "");
+});
+</script>
+</pre>
+</body>
+</html>