Bug 1426767 - Don't autocomplete logins in documents with a null principal. r=Gijs
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Tue, 02 Oct 2018 21:34:57 -0700
changeset 495231 3514b960ff957d7543795626ae72ef69ec883183
parent 495230 8900229a39b1b2a783d310cd6795a878d62c621a
child 495232 52ad4fb549815521961b743e6ad797a49b3f049d
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs
bugs1426767
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1426767 - Don't autocomplete logins in documents with a null principal. r=Gijs Differential Revision: https://phabricator.services.mozilla.com/D7388
toolkit/components/passwordmgr/nsLoginManager.js
toolkit/components/passwordmgr/test/mochitest/mochitest.ini
toolkit/components/passwordmgr/test/mochitest/test_autocomplete_sandboxed.html
--- a/toolkit/components/passwordmgr/nsLoginManager.js
+++ b/toolkit/components/passwordmgr/nsLoginManager.js
@@ -5,24 +5,27 @@
 "use strict";
 
 const PERMISSION_SAVE_LOGINS = "login-saving";
 
 ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/Timer.jsm");
-ChromeUtils.import("resource://gre/modules/LoginManagerContent.jsm");
 
 ChromeUtils.defineModuleGetter(this, "BrowserUtils",
                                "resource://gre/modules/BrowserUtils.jsm");
 ChromeUtils.defineModuleGetter(this, "LoginHelper",
                                "resource://gre/modules/LoginHelper.jsm");
 ChromeUtils.defineModuleGetter(this, "LoginFormFactory",
                                "resource://gre/modules/LoginManagerContent.jsm");
+ChromeUtils.defineModuleGetter(this, "LoginManagerContent",
+                               "resource://gre/modules/LoginManagerContent.jsm");
+ChromeUtils.defineModuleGetter(this, "UserAutoCompleteResult",
+                               "resource://gre/modules/LoginManagerContent.jsm");
 ChromeUtils.defineModuleGetter(this, "InsecurePasswordUtils",
                                "resource://gre/modules/InsecurePasswordUtils.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "log", () => {
   let logger = LoginHelper.createLogger("nsLoginManager");
   return logger;
 });
 
@@ -498,18 +501,35 @@ LoginManager.prototype = {
    * We really ought to have a simple way for code to register an
    * auto-complete provider, and not have satchel calling pwmgr directly.
    */
   autoCompleteSearchAsync(aSearchString, aPreviousResult,
                           aElement, aCallback) {
     // aPreviousResult is an nsIAutoCompleteResult, aElement is
     // HTMLInputElement
 
-    let form = LoginFormFactory.createFromField(aElement);
-    let isSecure = InsecurePasswordUtils.isFormSecure(form);
+    let {isNullPrincipal} = aElement.nodePrincipal;
+    // Show the insecure login warning in the passwords field on null principal documents.
+    let isSecure = !isNullPrincipal;
+    // Avoid loading InsecurePasswordUtils.jsm in a sandboxed document (e.g. an ad. frame) if we
+    // already know it has a null principal and will therefore get the insecure autocomplete
+    // treatment.
+    // InsecurePasswordUtils doesn't handle the null principal case as not secure because we don't
+    // want the same treatment:
+    // * The web console warnings will be confusing (as they're primarily about http:) and not very
+    //   useful if the developer intentionally sandboxed the document.
+    // * The site identity insecure field warning would require LoginManagerContent being loaded and
+    //   listening to some of the DOM events we're ignoring in null principal documents. For memory
+    //   reasons it's better to not load LMC at all for these sandboxed frames. Also, if the top-
+    //   document is sandboxing a document, it probably doesn't want that sandboxed document to be
+    //   able to affect the identity icon in the address bar by adding a password field.
+    if (isSecure) {
+      let form = LoginFormFactory.createFromField(aElement);
+      isSecure = InsecurePasswordUtils.isFormSecure(form);
+    }
     let isPasswordField = aElement.type == "password";
 
     let completeSearch = (autoCompleteLookupPromise, { logins, messageManager }) => {
       // If the search was canceled before we got our
       // results, don't bother reporting them.
       if (this._autoCompleteLookupPromise !== autoCompleteLookupPromise) {
         return;
       }
@@ -518,16 +538,24 @@ LoginManager.prototype = {
       let results = new UserAutoCompleteResult(aSearchString, logins, {
         messageManager,
         isSecure,
         isPasswordField,
       });
       aCallback.onSearchCompletion(results);
     };
 
+    if (isNullPrincipal) {
+      // Don't search login storage when the field has a null principal as we don't want to fill
+      // logins for the `location` in this case.
+      let acLookupPromise = this._autoCompleteLookupPromise = Promise.resolve({ logins: [] });
+      acLookupPromise.then(completeSearch.bind(this, acLookupPromise));
+      return;
+    }
+
     if (isPasswordField && aSearchString) {
       // Return empty result on password fields with password already filled.
       let acLookupPromise = this._autoCompleteLookupPromise = Promise.resolve({ logins: [] });
       acLookupPromise.then(completeSearch.bind(this, acLookupPromise));
       return;
     }
 
     if (!this._remember) {
--- a/toolkit/components/passwordmgr/test/mochitest/mochitest.ini
+++ b/toolkit/components/passwordmgr/test/mochitest/mochitest.ini
@@ -10,16 +10,19 @@ support-files =
   ../browser/form_basic.html
   ../browser/formless_basic.html
   ../browser/form_cross_origin_secure_action.html
   ../pwmgr_common.js
   auth2/authenticate.sjs
 
 [test_autocomplete_https_upgrade.html]
 skip-if = toolkit == 'android' # autocomplete
+[test_autocomplete_sandboxed.html]
+scheme = https
+skip-if = toolkit == 'android' # autocomplete
 [test_autofill_https_upgrade.html]
 skip-if = toolkit == 'android' # Bug 1259768
 [test_autofill_sandboxed.html]
 scheme = https
 [test_autofill_password-only.html]
 [test_autofocus_js.html]
 skip-if = toolkit == 'android' # autocomplete
 [test_basic_form.html]
copy from toolkit/components/passwordmgr/test/mochitest/test_insecure_form_field_autocomplete.html
copy to toolkit/components/passwordmgr/test/mochitest/test_autocomplete_sandboxed.html
--- a/toolkit/components/passwordmgr/test/mochitest/test_insecure_form_field_autocomplete.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_autocomplete_sandboxed.html
@@ -1,861 +1,102 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <meta charset="utf-8">
-  <title>Test insecure form field autocomplete</title>
+  <title>Test form field autocomplete in sandboxed documents (null principal)</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/AddTask.js"></script>
   <script type="text/javascript" src="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>
 
 <script>
 var chromeScript = runChecksAfterCommonInit();
 
 var setupScript = runInParent(function setup() {
   ChromeUtils.import("resource://gre/modules/Services.jsm");
 
-  // Create some logins just for this form, since we'll be deleting them.
   var nsLoginInfo = Components.Constructor("@mozilla.org/login-manager/loginInfo;1",
                                            Ci.nsILoginInfo, "init");
   assert.ok(nsLoginInfo != null, "nsLoginInfo constructor");
 
-  // login0 has no username, so should be filtered out from the autocomplete list.
-  var login0 = new nsLoginInfo("http://mochi.test:8888", "http://autocomplete:8888", null,
-                               "", "user0pass", "", "pword");
-
-  var login1 = new nsLoginInfo("http://mochi.test:8888", "http://autocomplete:8888", null,
+  var login1 = new nsLoginInfo("https://example.com", "", null,
                                "tempuser1", "temppass1", "uname", "pword");
 
-  var login2 = new nsLoginInfo("http://mochi.test:8888", "http://autocomplete:8888", null,
-                               "testuser2", "testpass2", "uname", "pword");
-
-  var login3 = new nsLoginInfo("http://mochi.test:8888", "http://autocomplete:8888", null,
-                               "testuser3", "testpass3", "uname", "pword");
-
-  var login4 = new nsLoginInfo("http://mochi.test:8888", "http://autocomplete:8888", null,
-                               "zzzuser4", "zzzpass4", "uname", "pword");
-
-  // login 5 only used in the single-user forms
-  var login5 = new nsLoginInfo("http://mochi.test:8888", "http://autocomplete2", null,
-                               "singleuser5", "singlepass5", "uname", "pword");
-
-  var login6A = new nsLoginInfo("http://mochi.test:8888", "http://autocomplete3", null,
-                                "form7user1", "form7pass1", "uname", "pword");
-  var login6B = new nsLoginInfo("http://mochi.test:8888", "http://autocomplete3", null,
-                                "form7user2", "form7pass2", "uname", "pword");
-
-  var login7  = new nsLoginInfo("http://mochi.test:8888", "http://autocomplete4", null,
-                                "form8user", "form8pass", "uname", "pword");
-
-  var login8A = new nsLoginInfo("http://mochi.test:8888", "http://autocomplete5", null,
-                                "form9userAB", "form9pass", "uname", "pword");
-  var login8B = new nsLoginInfo("http://mochi.test:8888", "http://autocomplete5", null,
-                                "form9userAAB", "form9pass", "uname", "pword");
-  var login8C = new nsLoginInfo("http://mochi.test:8888", "http://autocomplete5", null,
-                                "form9userAABzz", "form9pass", "uname", "pword");
-
-  var login10 = new nsLoginInfo("http://mochi.test:8888", "http://autocomplete7", null,
-                                "testuser10", "testpass10", "uname", "pword");
-
-
   // try/catch in case someone runs the tests manually, twice.
   try {
-    Services.logins.addLogin(login0);
     Services.logins.addLogin(login1);
-    Services.logins.addLogin(login2);
-    Services.logins.addLogin(login3);
-    Services.logins.addLogin(login4);
-    Services.logins.addLogin(login5);
-    Services.logins.addLogin(login6A);
-    Services.logins.addLogin(login6B);
-    Services.logins.addLogin(login7);
-    Services.logins.addLogin(login8A);
-    Services.logins.addLogin(login8B);
-    // login8C is added later
-    Services.logins.addLogin(login10);
   } catch (e) {
     assert.ok(false, "addLogin threw: " + e);
   }
-
-  addMessageListener("addLogin", loginVariableName => {
-    // eslint-disable-next-line no-eval
-    let login = eval(loginVariableName);
-    assert.ok(!!login, "Login to add is defined: " + loginVariableName);
-    Services.logins.addLogin(login);
-  });
-  addMessageListener("removeLogin", loginVariableName => {
-    // eslint-disable-next-line no-eval
-    let login = eval(loginVariableName);
-    assert.ok(!!login, "Login to delete is defined: " + loginVariableName);
-    Services.logins.removeLogin(login);
-  });
 });
 </script>
 <p id="display"></p>
 
 <!-- we presumably can't hide the content for this test. -->
 <div id="content">
-
-  <!-- form1 tests multiple matching logins -->
-  <form id="form1" action="http://autocomplete:8888/formtest.js" onsubmit="return false;">
-    <input  type="text"       name="uname">
-    <input  type="password"   name="pword">
-    <button type="submit">Submit</button>
-  </form>
-
-  <!-- other forms test single logins, with autocomplete=off set -->
-  <form id="form2" action="http://autocomplete2" onsubmit="return false;">
-    <input  type="text"       name="uname">
-    <input  type="password"   name="pword" autocomplete="off">
-    <button type="submit">Submit</button>
-  </form>
-
-  <form id="form3" action="http://autocomplete2" onsubmit="return false;">
-    <input  type="text"       name="uname" autocomplete="off">
-    <input  type="password"   name="pword">
-    <button type="submit">Submit</button>
-  </form>
-
-  <form id="form4" action="http://autocomplete2" onsubmit="return false;" autocomplete="off">
-    <input  type="text"       name="uname">
-    <input  type="password"   name="pword">
-    <button type="submit">Submit</button>
-  </form>
-
-  <form id="form5" action="http://autocomplete2" onsubmit="return false;">
-    <input  type="text"       name="uname" autocomplete="off">
-    <input  type="password"   name="pword" autocomplete="off">
-    <button type="submit">Submit</button>
-  </form>
-
-  <!-- control -->
-  <form id="form6" action="http://autocomplete2" onsubmit="return false;">
-    <input  type="text"       name="uname">
-    <input  type="password"   name="pword">
-    <button type="submit">Submit</button>
-  </form>
-
-  <!-- This form will be manipulated to insert a different username field. -->
-  <form id="form7" action="http://autocomplete3" onsubmit="return false;">
-    <input  type="text"       name="uname">
-    <input  type="password"   name="pword">
-    <button type="submit">Submit</button>
-  </form>
-
-  <!-- test for no autofill after onblur with blank username -->
-  <form id="form8" action="http://autocomplete4" onsubmit="return false;">
-    <input  type="text"       name="uname">
-    <input  type="password"   name="pword">
-    <button type="submit">Submit</button>
-  </form>
-
-  <!-- test autocomplete dropdown -->
-  <form id="form9" action="http://autocomplete5" onsubmit="return false;">
-    <input  type="text"       name="uname">
-    <input  type="password"   name="pword">
-    <button type="submit">Submit</button>
-  </form>
-
-  <!-- test for onUsernameInput recipe testing -->
-  <form id="form11" action="http://autocomplete7" onsubmit="return false;">
-    <input  type="text"   name="1">
-    <input  type="text"   name="2">
-    <button type="submit">Submit</button>
-  </form>
-
-  <!-- tests <form>-less autocomplete -->
-  <div id="form12">
-     <input  type="text"       name="uname" id="uname">
-     <input  type="password"   name="pword" id="pword">
-     <button type="submit">Submit</button>
-   </div>
+  <iframe id="sandboxed"
+          sandbox=""
+          src="form_basic.html"></iframe>
 </div>
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
-/** Test for Login Manager: multiple login autocomplete. **/
-
-var uname = $_(1, "uname");
-var pword = $_(1, "pword");
+/** Test for Login Manager: form field autocomplete in sandboxed documents (null principal) **/
 
-// Restore the form to the default state.
-function restoreForm() {
-  uname.value = "";
-  pword.value = "";
-  uname.focus();
-}
+let sandboxed = document.getElementById("sandboxed");
+let uname;
+let pword;
 
 // Check for expected username/password in form.
 function checkACForm(expectedUsername, expectedPassword) {
   var formID = uname.parentNode.id;
   is(uname.value, expectedUsername, "Checking " + formID + " username is: " + expectedUsername);
   is(pword.value, expectedPassword, "Checking " + formID + " password is: " + expectedPassword);
 }
 
-function sendFakeAutocompleteEvent(element) {
-  var acEvent = document.createEvent("HTMLEvents");
-  acEvent.initEvent("DOMAutoComplete", true, false);
-  element.dispatchEvent(acEvent);
-}
+add_task(async function setup() {
+  await SpecialPowers.pushPrefEnv({"set": [
+    ["security.insecure_field_warning.contextual.enabled", true],
+  ]});
 
-function spinEventLoop() {
-  return Promise.resolve();
-}
-
-add_task(async function setup() {
-  await SpecialPowers.pushPrefEnv({"set": [["security.insecure_field_warning.contextual.enabled", true],
-                                           ["signon.autofillForms.http", true]]});
-  listenForUnexpectedPopupShown();
+  let frameWindow = SpecialPowers.wrap(sandboxed).contentWindow;
+  // Can't use SimpleTest.promiseFocus as it doesn't work with the sandbox.
+  await SimpleTest.promiseWaitForCondition(() => {
+    return frameWindow.document.readyState == "complete" && frameWindow.location.href != "about:blank";
+  }, "Check frame is loaded");
+  let frameDoc = SpecialPowers.wrap(sandboxed).contentDocument;
+  uname = frameDoc.getElementById("form-basic-username");
+  pword = frameDoc.getElementById("form-basic-password");
 });
 
-add_task(async function test_form1_initial_empty() {
-  await SimpleTest.promiseFocus(window);
-
-  // Make sure initial form is empty.
+add_task(async function test_no_autofill() {
+  // Make sure initial form is empty as autofill shouldn't happen in the sandboxed frame.
   checkACForm("", "");
   let popupState = await getPopupState();
   is(popupState.open, false, "Check popup is initially closed");
 });
 
-add_task(async function test_form1_warning_entry() {
-  await SimpleTest.promiseFocus(window);
-  // Trigger autocomplete popup
-  restoreForm();
+add_task(async function test_autocomplete_warning_no_logins() {
+  pword.focus();
   let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
+  synthesizeKey("KEY_ArrowDown"); // open the popup
   let results = await shownPromise;
 
   let popupState = await getPopupState();
   is(popupState.selectedIndex, -1, "Check no entries are selected upon opening");
 
-  let expectedMenuItems = ["This connection is not secure. Logins entered here could be compromised. Learn More",
-                           "tempuser1",
-                           "testuser2",
-                           "testuser3",
-                           "zzzuser4"];
+  let expectedMenuItems = [
+    "This connection is not secure. Logins entered here could be compromised. Learn More",
+  ];
   checkArrayValues(results, expectedMenuItems, "Check all menuitems are displayed correctly.");
 
-  synthesizeKey("KEY_ArrowDown"); // select insecure warning
-  checkACForm("", ""); // value shouldn't update just by selecting
-  synthesizeKey("KEY_Enter");
-  await spinEventLoop(); // let focus happen
-  checkACForm("", "");
-});
-
-add_task(async function test_form1_first_entry() {
-  await SimpleTest.promiseFocus(window);
-  // Trigger autocomplete popup
-  restoreForm();
-  let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
-  await shownPromise;
-
-  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
-  checkACForm("", ""); // value shouldn't update just by selecting
-  synthesizeKey("KEY_Enter");
-  await promiseFormsProcessed();
-  checkACForm("tempuser1", "temppass1");
-});
-
-add_task(async function test_form1_second_entry() {
-  // Trigger autocomplete popup
-  restoreForm();
-  let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
-  await shownPromise;
-
-  synthesizeKey("KEY_ArrowDown"); // skip insecure warning
-  synthesizeKey("KEY_ArrowDown"); // first
-  synthesizeKey("KEY_ArrowDown"); // second
-  synthesizeKey("KEY_Enter");
-  await promiseFormsProcessed();
-  checkACForm("testuser2", "testpass2");
-});
-
-add_task(async function test_form1_third_entry() {
-  // Trigger autocomplete popup
-  restoreForm();
-  let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
-  await shownPromise;
-
-  synthesizeKey("KEY_ArrowDown"); // skip insecure warning
-  synthesizeKey("KEY_ArrowDown"); // first
-  synthesizeKey("KEY_ArrowDown"); // second
-  synthesizeKey("KEY_ArrowDown"); // third
-  synthesizeKey("KEY_Enter");
-  await promiseFormsProcessed();
-  checkACForm("testuser3", "testpass3");
-});
-
-add_task(async function test_form1_fourth_entry() {
-  // Trigger autocomplete popup
-  restoreForm();
-  let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
-  await shownPromise;
-
-  synthesizeKey("KEY_ArrowDown"); // skip insecure warning
-  synthesizeKey("KEY_ArrowDown"); // first
-  synthesizeKey("KEY_ArrowDown"); // second
-  synthesizeKey("KEY_ArrowDown"); // third
-  synthesizeKey("KEY_ArrowDown"); // fourth
-  synthesizeKey("KEY_Enter");
-  await promiseFormsProcessed();
-  checkACForm("zzzuser4", "zzzpass4");
-});
-
-add_task(async function test_form1_wraparound_first_entry() {
-  // Trigger autocomplete popup
-  restoreForm();
-  await spinEventLoop(); // let focus happen
-  let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
-  await shownPromise;
-
-  synthesizeKey("KEY_ArrowDown"); // skip insecure warning
-  synthesizeKey("KEY_ArrowDown"); // first
-  synthesizeKey("KEY_ArrowDown"); // second
-  synthesizeKey("KEY_ArrowDown"); // third
-  synthesizeKey("KEY_ArrowDown"); // fourth
-  synthesizeKey("KEY_ArrowDown"); // deselects
-  synthesizeKey("KEY_ArrowDown"); // skip insecure warning
-  synthesizeKey("KEY_ArrowDown"); // first
-  synthesizeKey("KEY_Enter");
-  await promiseFormsProcessed();
-  checkACForm("tempuser1", "temppass1");
-});
-
-add_task(async function test_form1_wraparound_up_last_entry() {
-  // Trigger autocomplete popup
-  restoreForm();
-  let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
-  await shownPromise;
-
-  synthesizeKey("KEY_ArrowUp"); // last (fourth)
-  synthesizeKey("KEY_Enter");
-  await promiseFormsProcessed();
-  checkACForm("zzzuser4", "zzzpass4");
-});
-
-add_task(async function test_form1_wraparound_down_up_up() {
-  // Trigger autocomplete popup
-  restoreForm();
-  let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
-  await shownPromise;
-
-  synthesizeKey("KEY_ArrowDown"); // select first entry
-  synthesizeKey("KEY_ArrowUp"); // selects nothing!
-  synthesizeKey("KEY_ArrowUp"); // select last entry
-  synthesizeKey("KEY_Enter");
-  await promiseFormsProcessed();
-  checkACForm("zzzuser4", "zzzpass4");
-});
-
-add_task(async function test_form1_wraparound_up_last() {
-  restoreForm();
-  let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
-  await shownPromise;
-
-  synthesizeKey("KEY_ArrowDown");
-  synthesizeKey("KEY_ArrowUp"); // deselects
-  synthesizeKey("KEY_ArrowUp"); // last entry
-  synthesizeKey("KEY_ArrowUp");
-  synthesizeKey("KEY_ArrowUp");
-  synthesizeKey("KEY_ArrowUp"); // skip insecure warning
-  synthesizeKey("KEY_ArrowUp"); // first entry
-  synthesizeKey("KEY_ArrowUp"); // deselects
-  synthesizeKey("KEY_ArrowUp"); // last entry
-  synthesizeKey("KEY_Enter");
-  await promiseFormsProcessed();
-  checkACForm("zzzuser4", "zzzpass4");
-});
-
-add_task(async function test_form1_fill_username_without_autofill_right() {
-  restoreForm();
-  let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
-  await shownPromise;
-
-  // Set first entry w/o triggering autocomplete
-  synthesizeKey("KEY_ArrowDown"); // skip insecure warning
-  synthesizeKey("KEY_ArrowDown"); // first
-  synthesizeKey("KEY_ArrowRight");
-  await spinEventLoop();
-  checkACForm("tempuser1", ""); // empty password
-});
-
-add_task(async function test_form1_fill_username_without_autofill_left() {
-  restoreForm();
-  let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
-  await shownPromise;
-
-  // Set first entry w/o triggering autocomplete
-  synthesizeKey("KEY_ArrowDown"); // skip insecure warning
-  synthesizeKey("KEY_ArrowDown"); // first
-  synthesizeKey("KEY_ArrowLeft");
-  checkACForm("tempuser1", ""); // empty password
-});
-
-add_task(async function test_form1_pageup_first() {
-  restoreForm();
-  let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
-  await shownPromise;
-
-  // 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 promiseFormsProcessed();
-  checkACForm("tempuser1", "temppass1");
-});
-
-add_task(async function test_form1_pagedown_last() {
-  restoreForm();
-  let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
-  await shownPromise;
-
-  // test 13
-  // Check last entry (page down)
-  synthesizeKey("KEY_ArrowDown"); // first
-  synthesizeKey("KEY_PageDown"); // last
-  synthesizeKey("KEY_Enter");
-  await promiseFormsProcessed();
-  checkACForm("zzzuser4", "zzzpass4");
-});
-
-add_task(async function test_form1_untrusted_event() {
-  restoreForm();
-  await spinEventLoop();
-
-  // Send a fake (untrusted) event.
-  checkACForm("", "");
-  uname.value = "zzzuser4";
-  sendFakeAutocompleteEvent(uname);
-  await spinEventLoop();
-  checkACForm("zzzuser4", "");
-});
-
-add_task(async function test_form1_delete() {
-  restoreForm();
-  let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
-  await shownPromise;
-
-  // 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 4), "tempuser1"
-  synthesizeKey("KEY_ArrowDown");
-  var numLogins;
-  numLogins = LoginManager.countLogins("http://mochi.test:8888", "http://autocomplete:8888", null);
-  is(numLogins, 5, "Correct number of logins before deleting one");
-
-  let countChangedPromise = notifyMenuChanged(4);
-  var 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;
-
   checkACForm("", "");
-  numLogins = LoginManager.countLogins("http://mochi.test:8888", "http://autocomplete:8888", null);
-  is(numLogins, 4, "Correct number of logins after deleting one");
-  await countChangedPromise;
-  synthesizeKey("KEY_Enter");
-  await promiseFormsProcessed();
-  checkACForm("testuser2", "testpass2");
-});
-
-add_task(async function test_form1_first_after_deletion() {
-  restoreForm();
-  let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
-  await shownPromise;
-
-  synthesizeKey("KEY_ArrowDown"); // skip insecure warning
-  // Check the new first entry (of 3)
-  synthesizeKey("KEY_ArrowDown");
-  synthesizeKey("KEY_Enter");
-  await promiseFormsProcessed();
-  checkACForm("testuser2", "testpass2");
-});
-
-add_task(async function test_form1_delete_second() {
-  restoreForm();
-  let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
-  await shownPromise;
-
-  synthesizeKey("KEY_ArrowDown"); // skip insecure warning
-  // Delete the second entry (of 3), "testuser3"
-  synthesizeKey("KEY_ArrowDown");
-  synthesizeKey("KEY_ArrowDown");
-  synthesizeKey("KEY_Delete", {shiftKey: true});
-  checkACForm("", "");
-  numLogins = LoginManager.countLogins("http://mochi.test:8888", "http://autocomplete:8888", null);
-  is(numLogins, 3, "Correct number of logins after deleting one");
-  synthesizeKey("KEY_Enter");
-  await promiseFormsProcessed();
-  checkACForm("zzzuser4", "zzzpass4");
-});
-
-add_task(async function test_form1_first_after_deletion2() {
-  restoreForm();
-  let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
-  await shownPromise;
-
-  synthesizeKey("KEY_ArrowDown"); // skip insecure warning
-  // Check the new first entry (of 2)
-  synthesizeKey("KEY_ArrowDown");
-  synthesizeKey("KEY_Enter");
-  await promiseFormsProcessed();
-  checkACForm("testuser2", "testpass2");
-});
-
-add_task(async function test_form1_delete_last() {
-  restoreForm();
-  let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
-  await shownPromise;
-
-  synthesizeKey("KEY_ArrowDown"); // skip insecure warning
-  // test 54
-  // Delete the last entry (of 2), "zzzuser4"
-  synthesizeKey("KEY_ArrowDown");
-  synthesizeKey("KEY_ArrowDown");
-  synthesizeKey("KEY_Delete", {shiftKey: true});
-  checkACForm("", "");
-  numLogins = LoginManager.countLogins("http://mochi.test:8888", "http://autocomplete:8888", null);
-  is(numLogins, 2, "Correct number of logins after deleting one");
-  synthesizeKey("KEY_Enter");
-  await promiseFormsProcessed();
-  checkACForm("testuser2", "testpass2");
-});
-
-add_task(async function test_form1_first_after_3_deletions() {
-  restoreForm();
-  let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
-  await shownPromise;
-
-  synthesizeKey("KEY_ArrowDown"); // skip insecure warning
-  // Check the only remaining entry
-  synthesizeKey("KEY_ArrowDown");
-  synthesizeKey("KEY_Enter");
-  await promiseFormsProcessed();
-  checkACForm("testuser2", "testpass2");
-});
-
-add_task(async function test_form1_check_only_entry_remaining() {
-  restoreForm();
-  let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
-  await shownPromise;
-
-  synthesizeKey("KEY_ArrowDown"); // skip insecure warning
-  // test 56
-  // Delete the only remaining entry, "testuser2"
-  synthesizeKey("KEY_ArrowDown");
-  synthesizeKey("KEY_Delete", {shiftKey: true});
-  checkACForm("", "");
-  numLogins = LoginManager.countLogins("http://mochi.test:8888", "http://autocomplete:8888", null);
-  is(numLogins, 1, "Correct number of logins after deleting one");
-
-  // remove the login that's not shown in the list.
-  setupScript.sendSyncMessage("removeLogin", "login0");
-});
-
-// Tests for single-user forms for ignoring autocomplete=off
-add_task(async function test_form2() {
-  // Turn our attention to form2
-  uname = $_(2, "uname");
-  pword = $_(2, "pword");
-  checkACForm("singleuser5", "singlepass5");
-
-  restoreForm();
-  let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
-  await shownPromise;
-
-  synthesizeKey("KEY_ArrowDown"); // skip insecure warning
-  // Check first entry
-  synthesizeKey("KEY_ArrowDown");
-  checkACForm("", ""); // value shouldn't update
-  synthesizeKey("KEY_Enter");
-  await promiseFormsProcessed();
-  checkACForm("singleuser5", "singlepass5");
-});
-
-add_task(async function test_form3() {
-  uname = $_(3, "uname");
-  pword = $_(3, "pword");
-  checkACForm("singleuser5", "singlepass5");
-  restoreForm();
-  let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
-  await shownPromise;
-
-  synthesizeKey("KEY_ArrowDown"); // skip insecure warning
-  // Check first entry
-  synthesizeKey("KEY_ArrowDown");
-  checkACForm("", ""); // value shouldn't update
-  synthesizeKey("KEY_Enter");
-  await promiseFormsProcessed();
-  checkACForm("singleuser5", "singlepass5");
-});
-
-add_task(async function test_form4() {
-  uname = $_(4, "uname");
-  pword = $_(4, "pword");
-  checkACForm("singleuser5", "singlepass5");
-  restoreForm();
-  let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
-  await shownPromise;
-
-  synthesizeKey("KEY_ArrowDown"); // skip insecure warning
-  // Check first entry
-  synthesizeKey("KEY_ArrowDown");
-  checkACForm("", ""); // value shouldn't update
-  synthesizeKey("KEY_Enter");
-  await promiseFormsProcessed();
-  checkACForm("singleuser5", "singlepass5");
-});
-
-add_task(async function test_form5() {
-  uname = $_(5, "uname");
-  pword = $_(5, "pword");
-  checkACForm("singleuser5", "singlepass5");
-  restoreForm();
-  let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
-  await shownPromise;
-
-  synthesizeKey("KEY_ArrowDown"); // skip insecure warning
-  // Check first entry
-  synthesizeKey("KEY_ArrowDown");
-  checkACForm("", ""); // value shouldn't update
-  synthesizeKey("KEY_Enter");
-  await promiseFormsProcessed();
-  checkACForm("singleuser5", "singlepass5");
-});
-
-add_task(async function test_form6() {
-  // (this is a control, w/o autocomplete=off, to ensure the login
-  // that was being suppressed would have been filled in otherwise)
-  uname = $_(6, "uname");
-  pword = $_(6, "pword");
-  checkACForm("singleuser5", "singlepass5");
-});
-
-add_task(async function test_form6_changeUsername() {
-  // Test that the password field remains filled in after changing
-  // the username.
-  uname.focus();
-  synthesizeKey("KEY_ArrowRight");
-  synthesizeKey("X", {shiftKey: true});
-  // Trigger the 'blur' event on uname
-  pword.focus();
-  await spinEventLoop();
-  checkACForm("singleuser5X", "singlepass5");
-
-  setupScript.sendSyncMessage("removeLogin", "login5");
-});
-
-add_task(async function test_form7() {
-  uname = $_(7, "uname");
-  pword = $_(7, "pword");
-  checkACForm("", "");
-
-  // Insert a new username field into the form. We'll then make sure
-  // that invoking the autocomplete doesn't try to fill the form.
-  var newField = document.createElement("input");
-  newField.setAttribute("type", "text");
-  newField.setAttribute("name", "uname2");
-  pword.parentNode.insertBefore(newField, pword);
-  is($_(7, "uname2").value, "", "Verifying empty uname2");
-
-  // Delete login6B. It was created just to prevent filling in a login
-  // automatically, removing it makes it more likely that we'll catch a
-  // future regression with form filling here.
-  setupScript.sendSyncMessage("removeLogin", "login6B");
-});
-
-add_task(async function test_form7_2() {
-  restoreForm();
-  let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
-  await shownPromise;
-
-  synthesizeKey("KEY_ArrowDown"); // skip insecure warning
-  // Check first entry
-  synthesizeKey("KEY_ArrowDown");
-  checkACForm("", ""); // 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 spinEventLoop();
-  checkACForm("form7user1", "");
-  is($_(7, "uname2").value, "", "Verifying empty uname2");
-  restoreForm(); // clear field, so reloading test doesn't fail
-
-  setupScript.sendSyncMessage("removeLogin", "login6A");
-});
-
-add_task(async function test_form8() {
-  uname = $_(8, "uname");
-  pword = $_(8, "pword");
-  checkACForm("form8user", "form8pass");
-  restoreForm();
-});
-
-add_task(async function test_form8_blur() {
-  checkACForm("", "");
-  // Focus the previous form to trigger a blur.
-  $_(7, "uname").focus();
-});
-
-add_task(async function test_form8_2() {
-  checkACForm("", "");
-  restoreForm();
-});
-
-add_task(async function test_form8_3() {
-  checkACForm("", "");
-  setupScript.sendSyncMessage("removeLogin", "login7");
-});
-
-add_task(async function test_form9_filtering() {
-  // Turn our attention to form9 to test the dropdown - bug 497541
-  uname = $_(9, "uname");
-  pword = $_(9, "pword");
-  uname.focus();
-  let shownPromise = promiseACShown();
-  sendString("form9userAB");
-  await shownPromise;
-
-  checkACForm("form9userAB", "");
-  uname.focus();
-  synthesizeKey("KEY_ArrowLeft");
-  shownPromise = promiseACShown();
-  synthesizeKey("A", {shiftKey: true});
-  let results = await shownPromise;
-
-  checkACForm("form9userAAB", "");
-  checkArrayValues(results, ["This connection is not secure. Logins entered here could be compromised. Learn More", "form9userAAB"],
-                            "Check dropdown is updated after inserting 'A'");
-  synthesizeKey("KEY_ArrowDown"); // skip insecure warning
-  synthesizeKey("KEY_ArrowDown");
-  synthesizeKey("KEY_Enter");
-  await promiseFormsProcessed();
-  checkACForm("form9userAAB", "form9pass");
-});
-
-add_task(async function test_form9_autocomplete_cache() {
-  // Note that this addLogin call will only be seen by the autocomplete
-  // attempt for the synthesizeKey if we do not successfully cache the
-  // autocomplete results.
-  setupScript.sendSyncMessage("addLogin", "login8C");
-  uname.focus();
-  let promise0 = notifyMenuChanged(1);
-  let shownPromise = promiseACShown();
-  sendString("z");
-  await promise0;
-  await shownPromise;
-  let popupState = await getPopupState();
-  is(popupState.open, true, "Check popup should open");
-
-  // check that empty results are cached - bug 496466
-  promise0 = notifyMenuChanged(1);
-  sendString("z");
-  await promise0;
-  popupState = await getPopupState();
-  is(popupState.open, true, "Check popup stays opened due to cached empty result");
-});
-
-add_task(async function test_form11_recipes() {
-  await loadRecipes({
-    siteRecipes: [{
-      "hosts": ["mochi.test:8888"],
-      "usernameSelector": "input[name='1']",
-      "passwordSelector": "input[name='2']",
-    }],
-  });
-  uname = $_(11, "1");
-  pword = $_(11, "2");
-
-  // First test DOMAutocomplete
-  // Switch the password field to type=password so _fillForm marks the username
-  // field for autocomplete.
-  pword.type = "password";
-  await promiseFormsProcessed();
-  restoreForm();
-  checkACForm("", "");
-  let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
-  await shownPromise;
-
-  synthesizeKey("KEY_ArrowDown"); // skip insecure warning
-  synthesizeKey("KEY_ArrowDown");
-  checkACForm("", ""); // value shouldn't update
-  synthesizeKey("KEY_Enter");
-  await promiseFormsProcessed();
-  checkACForm("testuser10", "testpass10");
-
-  // Now test recipes with blur on the username field.
-  restoreForm();
-  checkACForm("", "");
-  uname.value = "testuser10";
-  checkACForm("testuser10", "");
-  synthesizeKey("KEY_Tab");
-  await promiseFormsProcessed();
-  checkACForm("testuser10", "testpass10");
-  await resetRecipes();
-});
-
-add_task(async function test_form12_formless() {
-  // Test form-less autocomplete
-  uname = $_(12, "uname");
-  pword = $_(12, "pword");
-  restoreForm();
-  checkACForm("", "");
-  let shownPromise = promiseACShown();
-  synthesizeKey("KEY_ArrowDown"); // open
-  await shownPromise;
-
-  synthesizeKey("KEY_ArrowDown"); // skip insecure warning
-  // Trigger autocomplete
-  synthesizeKey("KEY_ArrowDown");
-  checkACForm("", ""); // value shouldn't update
-  let processedPromise = promiseFormsProcessed();
-  synthesizeKey("KEY_Enter");
-  await processedPromise;
-  checkACForm("testuser", "testpass");
 });
 </script>
 </pre>
 </body>
 </html>