bug 373253. Initial addition of test framework and tests for pwmgr. Patch by Justin Dolske <dolske@mozilla.com>. r=sayrer, sr=mconnor
authorsayrer@gmail.com
Sun, 22 Apr 2007 16:56:06 -0700
changeset 714 a5720d3cdbb6d54315a16e834db6f794890878d0
parent 713 929b0977b377d32f6d67f6464fba12ffaeca80c0
child 715 9a8fb569eb32dd5cba75aad8980bd01428a6746f
push idunknown
push userunknown
push dateunknown
reviewerssayrer, mconnor
bugs373253
milestone1.9a4pre
bug 373253. Initial addition of test framework and tests for pwmgr. Patch by Justin Dolske <dolske@mozilla.com>. r=sayrer, sr=mconnor
allmakefiles.sh
netwerk/base/public/nsIPasswordManagerInternal.idl
toolkit/components/passwordmgr/Makefile.in
toolkit/components/passwordmgr/base/nsPasswordManager.cpp
toolkit/components/passwordmgr/test/Makefile.in
toolkit/components/passwordmgr/test/pwmgr_common.js
toolkit/components/passwordmgr/test/test_0init.html
toolkit/components/passwordmgr/test/test_basic_form.html
toolkit/components/passwordmgr/test/test_basic_form_0pw.html
toolkit/components/passwordmgr/test/test_basic_form_1pw.html
toolkit/components/passwordmgr/test/test_basic_form_2pw_1.html
toolkit/components/passwordmgr/test/test_basic_form_2pw_2.html
toolkit/components/passwordmgr/test/test_basic_form_3pw_1.html
toolkit/components/passwordmgr/test/test_bug_221634.html
toolkit/components/passwordmgr/test/test_bug_227640.html
toolkit/components/passwordmgr/test/test_bug_242956.html
toolkit/components/passwordmgr/test/test_bug_270558.html
toolkit/components/passwordmgr/test/test_bug_360493_1.html
toolkit/components/passwordmgr/test/test_bug_360493_2.html
--- a/allmakefiles.sh
+++ b/allmakefiles.sh
@@ -977,16 +977,17 @@ toolkit/components/filepicker/Makefile
 toolkit/system/gnome/Makefile
 toolkit/components/help/Makefile
 toolkit/components/history/Makefile
 toolkit/components/history/public/Makefile
 toolkit/components/history/src/Makefile
 toolkit/components/passwordmgr/Makefile
 toolkit/components/passwordmgr/base/Makefile
 toolkit/components/passwordmgr/resources/Makefile
+toolkit/components/passwordmgr/test/Makefile
 toolkit/components/places/Makefile
 toolkit/components/places/public/Makefile
 toolkit/components/places/src/Makefile
 toolkit/components/printing/Makefile
 toolkit/components/satchel/Makefile
 toolkit/components/satchel/public/Makefile
 toolkit/components/satchel/src/Makefile
 toolkit/components/startup/Makefile
--- a/netwerk/base/public/nsIPasswordManagerInternal.idl
+++ b/netwerk/base/public/nsIPasswordManagerInternal.idl
@@ -39,17 +39,17 @@
 
 /** 
  * An optional interface for obtaining fields of
  * logins that were collected by the password manager
  */
 
 interface nsIFile;
 
-[scriptable, uuid(dc2ff152-85cb-474e-b4c2-86a3d48cf4d0)]
+[scriptable, uuid(a448531f-dc92-4dc1-9012-da841febcbe0)]
 interface nsIPasswordManagerInternal : nsISupports
 {
 
   /**
    * A Call to find a login in the password manager list that matches the
    * specified parameters. If any input parameter is null, it is
    * not tested for when looking for the match.
    *
@@ -75,16 +75,23 @@ interface nsIPasswordManagerInternal : n
    * @param aPassFieldName The name of the field that contained the password
    */
   void addUserFull(in AUTF8String aKey, 
                    in AString aUser, 
                    in AString aPassword,
                    in AString aUserFieldName,
                    in AString aPassFieldName);
 
+  void addUserFull2(in AUTF8String aKey, 
+                   in AString aUser, 
+                   in AString aPassword,
+                   in AString aUserFieldName,
+                   in AString aPassFieldName,
+                   in AUTF8String ActionURL);
+
   /**
    * Reads logins from a Mozilla Password Manager file, augmenting the current 
    * in-memory set. If a duplicate entry is encountered, the data from the file
    * being read replaces that currently held.
    * 
    * @param aPasswordFile The file to read logins from.
    */
   void readPasswords(in nsIFile aPasswordFile);
--- a/toolkit/components/passwordmgr/Makefile.in
+++ b/toolkit/components/passwordmgr/Makefile.in
@@ -39,9 +39,13 @@ DEPTH		= ../../..
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 DIRS = base resources
 
+ifdef ENABLE_TESTS
+DIRS  += test
+endif
+
 include $(topsrcdir)/config/rules.mk
--- a/toolkit/components/passwordmgr/base/nsPasswordManager.cpp
+++ b/toolkit/components/passwordmgr/base/nsPasswordManager.cpp
@@ -604,16 +604,27 @@ nsPasswordManager::FindPasswordEntry(con
 
 NS_IMETHODIMP
 nsPasswordManager::AddUserFull(const nsACString& aKey,
                                const nsAString& aUser,
                                const nsAString& aPassword,
                                const nsAString& aUserFieldName,
                                const nsAString& aPassFieldName)
 {
+	return AddUserFull2(aKey, aUser, aPassword, aUserFieldName, aPassFieldName, NS_LITERAL_CSTRING(""));
+}
+
+NS_IMETHODIMP
+nsPasswordManager::AddUserFull2(const nsACString& aKey,
+                                const nsAString& aUser,
+                                const nsAString& aPassword,
+                                const nsAString& aUserFieldName,
+                                const nsAString& aPassFieldName,
+                                const nsACString& aActionURL)
+{
   // Silently ignore an empty username/password entry.
   // There's no point in taking up space in the signon file with this.
   if (aUser.IsEmpty() && aPassword.IsEmpty())
     return NS_OK;
 
   // Check for an existing entry for this host + user
   if (!aKey.IsEmpty()) {
     SignonHashEntry *hashEnt;
@@ -628,16 +639,17 @@ nsPasswordManager::AddUserFull(const nsA
         entry->userField.Assign(aUserFieldName);
         entry->passField.Assign(aPassFieldName);
         return NS_OK;
       }
     }
   }
 
   SignonDataEntry* entry = new SignonDataEntry();
+  entry->actionOrigin.Assign(aActionURL);
   entry->userField.Assign(aUserFieldName);
   entry->passField.Assign(aPassFieldName);
   EncryptDataUCS2(aUser, entry->userValue);
   EncryptDataUCS2(aPassword, entry->passValue);
 
   AddSignonData(aKey, entry);
   WritePasswords(mSignonFile);
 
new file mode 100644
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/Makefile.in
@@ -0,0 +1,73 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is Mozilla.
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#  Justin Dolske <dolske@mozilla.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+relativesrcdir  = toolkit/components/passwordmgr/test
+
+include $(DEPTH)/config/autoconf.mk
+
+# Module name for xpcshell tests.
+MODULE		= test_passwordmgr
+
+# Test files for Mochitest
+MOCHI_TESTS = \
+		pwmgr_common.js \
+		test_0init.html \
+		test_basic_form.html \
+		test_basic_form_0pw.html \
+		test_basic_form_1pw.html \
+		test_basic_form_2pw_1.html \
+		test_basic_form_2pw_2.html \
+		test_basic_form_3pw_1.html \
+		test_bug_221634.html \
+		test_bug_227640.html \
+		test_bug_242956.html \
+		test_bug_270558.html \
+		test_bug_360493_1.html \
+		test_bug_360493_2.html \
+		$(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+# Note: Invoke any additional (non-xpcshell) test programs here.
+check::
+
+libs:: $(MOCHI_TESTS)
+	$(INSTALL) $^ $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/pwmgr_common.js
@@ -0,0 +1,15 @@
+/*
+ * $_
+ *
+ * Returns the element with the specified |name| attribute.
+ */
+function $_(name) {
+  var elements = document.getElementsByName(name);
+
+  if (!elements || elements.length < 1) { return null; }
+  if (elements.length > 2) {
+    logWarning("found multiple elements with name="+name);
+  }
+
+  return elements[0];
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/test_0init.html
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test initialization for Password Manager</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <script type="text/javascript" src="pwmgr_common.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+Password Manager test: initialization.
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Password Manger: initialization **/
+
+netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+
+
+// Get the pwmgr service
+var Cc_pwmgr = Components.classes["@mozilla.org/passwordmanager;1"];
+ok(Cc_pwmgr != null, "Access Cc[@mozilla.org/passwordmanager;1]");
+
+var Ci_pwmgr = Components.interfaces.nsIPasswordManager;
+ok(Ci_pwmgr != null, "Access Ci.nsIPasswordManager");
+
+var pwmgr = Cc_pwmgr.getService(Ci_pwmgr);
+ok(pwmgr != null, "pwmgr getService()");
+
+
+// Make sure it's not already initialized somehow
+var count, enum;
+count = 0;
+enum = pwmgr.enumerator;
+while (enum.hasMoreElements()) { count++; enum.getNext(); }
+ok(count == 0, "ensure no pre-existing logins");
+if (count != 0) { throw "Aborting test."; }
+
+count = 0;
+enum = pwmgr.rejectEnumerator;
+while (enum.hasMoreElements()) { count++; enum.getNext(); }
+ok(count == 0, "ensure no pre-existing disabled logins");
+if (count != 0) { throw "Aborting test"; }
+
+
+pwmgr = pwmgr.QueryInterface(Components.interfaces.nsIPasswordManagerInternal);
+// Add some logins for testing.
+const TESTHOST = "http://localhost:8888";
+for (var u = 1; u <= 15; u++) {
+  pwmgr.addUserFull2(TESTHOST, "testuser"+u, "testpass"+u, "uname"+u, "pword"+u, TESTHOST);
+}
+
+// Simple check to see if everything was added fine.
+count = 0;
+enum = pwmgr.enumerator;
+while (enum.hasMoreElements()) { count++; enum.getNext(); }
+ok(count == 15, "check number of added logins");
+
+count = 0;
+enum = pwmgr.rejectEnumerator;
+while (enum.hasMoreElements()) { count++; enum.getNext(); }
+ok(count == 0, "check no disable logins");
+
+</script>
+</pre>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/test_basic_form.html
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Password Manager</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>  
+  <script type="text/javascript" src="pwmgr_common.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+Password Manager test: simple form fill
+<p id="display"></p>
+
+<div id="content" style="display: none">
+  <form action="formtest.js" method="get">
+    <p>This is form 1.</p>
+    <input  type="text"       name="uname1" value="">
+    <input  type="password"   name="pword1" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <form action="formtest.js" method="get">
+    <p>This is form 2.</p>
+    <input  type="text"       name="uname2" value="">
+    <input  type="password"   name="pword2" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <form action="formtest.js" method="get">
+    <p>This is form 3.</p>
+    <input  type="text"       name="uname3" value="">
+    <input  type="password"   name="pword3" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+</div>
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Password Manger: form fill, multiple forms. **/
+
+// Make sure that all forms in a document are processed.
+
+function startTest() {
+  // Check form 1
+  is($_("uname1").value, "testuser1", "Checking for filled username1");
+  is($_("pword1").value, "testpass1", "Checking for filled password1");
+
+  // Check form 2
+  is($_("uname2").value, "testuser2", "Checking for filled username2");
+  is($_("pword2").value, "testpass2", "Checking for filled password2");
+
+  // Check form 3
+  is($_("uname3").value, "testuser3", "Checking for filled username3");
+  is($_("pword3").value, "testpass3", "Checking for filled password3");
+
+  SimpleTest.finish();
+}
+
+window.onload = startTest;
+
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/test_basic_form_0pw.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Password Manager</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>  
+  <script type="text/javascript" src="pwmgr_common.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+Password Manager test: forms with no password fields
+<p id="display"></p>
+
+<div id="content" style="display: none">
+
+  <!-- Form with no user field or password field -->
+  <form action="formtest.js" method="get">
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- Form with no user field or password field, but one other field -->
+  <form action="formtest.js" method="get">
+    <input type="checkbox">
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- Form user a user field, but no password field -->
+  <form action="formtest.js" method="get">
+    <input  type="text"       name="uname1" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+</div>
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Password Manger: form fill, no password fields. **/
+
+function startTest() {
+  is($_("uname1").value, "", "Checking for unfilled username 1");
+
+  SimpleTest.finish();
+}
+
+window.onload = startTest;
+
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/test_basic_form_1pw.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Password Manager</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>  
+  <script type="text/javascript" src="pwmgr_common.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+Password Manager test: forms with 1 password field
+<p id="display"></p>
+
+<div id="content" style="display: none">
+  <form action="formtest.js" method="get">
+    <input  type="text"       name="uname1" value="">
+    <input  type="text"       name="foo1"   value="">
+    <input  type="password"   name="pword1" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <form action="formtest.js" method="get">
+    <input  type="text"       name="uname2" value="testuser2">
+    <input  type="text"       name="foo2"   value="">
+    <input  type="password"   name="pword2" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <form action="formtest.js" method="get">
+    <input  type="text"       name="uname3" value="testuser3">
+    <input  type="text"       name="foo3"   value="">
+    <input  type="password"   name="pword3" value="testpass3">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+</div>
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Password Manger: simple form fill **/
+
+function startTest() {
+  // Check username
+  is($_("uname1").value, "testuser1", "Checking filled username 1");
+  // Check password
+  is($_("pword1").value, "testpass1", "Checking filled password 1");
+  // Check dummy field just for paranoia's sake
+  is($_("foo1").value,   "",    "Checking unused field");
+
+  // Check username
+  is($_("uname2").value, "testuser2", "Checking filled username 2");
+  // Check password
+  is($_("pword2").value, "testpass2", "Checking filled password 2");
+  is($_("foo2").value,   "",    "Checking unused field");
+
+  // Check username
+  is($_("uname3").value, "testuser3", "Checking filled username 3");
+  // Check password
+  is($_("pword3").value, "testpass3", "Checking filled password 3");
+  is($_("foo3").value,   "",    "Checking unused field");
+
+  SimpleTest.finish();
+}
+
+window.onload = startTest;
+
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/test_basic_form_2pw_1.html
@@ -0,0 +1,125 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Password Manager</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>  
+  <script type="text/javascript" src="pwmgr_common.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+Password Manager test: forms with 2 password fields (form filling)
+<p id="display"></p>
+
+<div id="content" style="display: none">
+  <p>The next three forms are <b>user/pass/pass-new</b>, as all-empty, prefilled user(only), and prefilled user/pass</p>
+  <form id="form1" onsubmit="return checkSubmit(1)" action="formtest.js" method="get">
+    <input  type="text"       name="uname1"  value="">
+    <input  type="password"   name="pword1"  value="">
+    <input  type="password"   name="pword1B" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <form id="form2" onsubmit="return checkSubmit(2)" action="formtest.js" method="get">
+    <input  type="text"       name="uname2"  value="testuser2">
+    <input  type="password"   name="pword2"  value="">
+    <input  type="password"   name="pword2B" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <form id="form3" onsubmit="return checkSubmit(3)" action="formtest.js" method="get">
+    <input  type="text"       name="uname3"  value="testuser3">
+    <input  type="password"   name="pword3"  value="testpass3">
+    <input  type="password"   name="pword3B" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+
+  <p>The next three forms are <b>user/pass-new/pass</b>, as all-empty, prefilled user(only), and prefilled user/pass</p>
+  <form id="form4" onsubmit="return checkSubmit(4)" action="formtest.js" method="get">
+    <input  type="text"       name="uname4"  value="">
+    <input  type="password"   name="pword4B" value="">
+    <input  type="password"   name="pword4"  value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <form id="form5" onsubmit="return checkSubmit(5)" action="formtest.js" method="get">
+    <input  type="text"       name="uname5"  value="testuser5">
+    <input  type="password"   name="pword5B" value="">
+    <input  type="password"   name="pword5"  value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <form id="form6" onsubmit="return checkSubmit(6)" action="formtest.js" method="get">
+    <input  type="text"       name="uname6"  value="testuser6">
+    <input  type="password"   name="pword6B" value="">
+    <input  type="password"   name="pword6"  value="testpass6">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+</div>
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Password Manger: form fill, 2 password fields **/
+
+// This test simply checks to make sure pwmgr can autofill forms with 2 password fields.
+
+var numSubmittedForms = 0;
+var numStartingLogins = 0;
+
+function startTest() {
+  // Check for unfilled form 1
+  is($_("uname1").value,  "testuser1", "Checking username1");
+  is($_("pword1").value,  "testpass1", "Checking password1");
+  is($_("pword1B").value, "", "Checking password1B");
+
+  // Check for unfilled form 2
+  is($_("uname2").value,  "testuser2", "Checking username2");
+  is($_("pword2").value,  "testpass2", "Checking password2");
+  is($_("pword2B").value, "", "Checking password2B");
+
+  // Check for unfilled form 3
+  is($_("uname3").value,  "testuser3", "Checking username3");
+  is($_("pword3").value,  "testpass3", "Checking password3");
+  is($_("pword3B").value, "", "Checking password3B");
+
+  // Check for unfilled form 4
+  is($_("uname4").value,  "testuser4", "Checking username4");
+  is($_("pword4").value,  "testpass4", "Checking password4");
+  is($_("pword4B").value, "", "Checking password4B");
+
+  // Check for unfilled form 5
+  is($_("uname5").value,  "testuser5", "Checking username5");
+  is($_("pword5").value,  "testpass5", "Checking password5");
+  is($_("pword5B").value, "", "Checking password5B");
+
+  // Check for unfilled form 6
+  is($_("uname6").value,  "testuser6", "Checking username6");
+  is($_("pword6").value,  "testpass6", "Checking password6");
+  is($_("pword6B").value, "", "Checking password6B");
+
+  SimpleTest.finish();
+}
+
+window.onload = startTest;
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/test_basic_form_2pw_2.html
@@ -0,0 +1,224 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Password Manager</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>  
+  <script type="text/javascript" src="pwmgr_common.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+Password Manager test: forms with 2 password fields (adding new logins)
+<p id="display"></p>
+
+<div id="content" style="display: none">
+  <p>The next three forms are <b>user/pass/pass-new</b>, as all-empty, prefilled user(only), and prefilled user/pass</p>
+  <form id="form1" onsubmit="return checkSubmit(1)" action="formtest.js" method="get">
+    <input  type="text"       name="new-uname1"  value="">
+    <input  type="password"   name="new-pword1"  value="">
+    <input  type="password"   name="new-pword1B" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <form id="form2" onsubmit="return checkSubmit(2)" action="formtest.js" method="get">
+    <input  type="text"       name="new-uname2"  value="newuser2">
+    <input  type="password"   name="new-pword2"  value="">
+    <input  type="password"   name="new-pword2B" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <form id="form3" onsubmit="return checkSubmit(3)" action="formtest.js" method="get">
+    <input  type="text"       name="new-uname3"  value="newuser3">
+    <input  type="password"   name="new-pword3"  value="newpass3">
+    <input  type="password"   name="new-pword3B" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+
+  <p>The next three forms are <b>user/pass-new/pass</b>, as all-empty, prefilled user(only), and prefilled user/pass</p>
+  <form id="form4" onsubmit="return checkSubmit(4)" action="formtest.js" method="get">
+    <input  type="text"       name="new-uname4"  value="">
+    <input  type="password"   name="new-pword4B" value="">
+    <input  type="password"   name="new-pword4"  value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <form id="form5" onsubmit="return checkSubmit(5)" action="formtest.js" method="get">
+    <input  type="text"       name="new-uname5"  value="newuser5">
+    <input  type="password"   name="new-pword5B" value="">
+    <input  type="password"   name="new-pword5"  value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <form id="form6" onsubmit="return checkSubmit(6)" action="formtest.js" method="get">
+    <input  type="text"       name="new-uname6"  value="newuser6">
+    <input  type="password"   name="new-pword6B" value="">
+    <input  type="password"   name="new-pword6"  value="newpass6">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+</div>
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Password Manger: form fill, 2 password fields **/
+
+// If a form has two password fields, other things may be going on....
+//
+// 1 - The user might be creating a new login (2nd field for typo checking)
+// 2 - The user is changing their password (old and new password each have field)
+//
+// This test is for case #1.
+
+var numSubmittedForms = 0;
+var numStartingLogins = 0;
+
+function startTest() {
+  // Check for unfilled form 1
+  is($_("new-uname1").value,  "", "Checking username1");
+  is($_("new-pword1").value,  "", "Checking password1");
+  is($_("new-pword1B").value, "", "Checking password1B");
+
+  // Check for unfilled form 2
+  is($_("new-uname2").value,  "newuser2", "Checking username2");
+  is($_("new-pword2").value,  "", "Checking password2");
+  is($_("new-pword2B").value, "", "Checking password2B");
+
+  // Check for unfilled form 3
+  is($_("new-uname3").value,  "newuser3", "Checking username3");
+  is($_("new-pword3").value,  "newpass3", "Checking password3");
+  is($_("new-pword3B").value, "", "Checking password3B");
+
+  // Check for unfilled form 4
+  is($_("new-uname4").value,  "", "Checking username4");
+  is($_("new-pword4").value,  "", "Checking password4");
+  is($_("new-pword4B").value, "", "Checking password4B");
+
+  // Check for unfilled form 5
+  is($_("new-uname5").value,  "newuser5", "Checking username5");
+  is($_("new-pword5").value,  "", "Checking password5");
+  is($_("new-pword5B").value, "", "Checking password5B");
+
+  // Check for unfilled form 6
+  is($_("new-uname6").value,  "newuser6", "Checking username6");
+  is($_("new-pword6").value,  "newpass6", "Checking password6");
+  is($_("new-pword6B").value, "", "Checking password6B");
+
+
+  // Fill in the username and password fields, as if we are creating new accounts.
+  // Form 1
+  $_("new-uname1").value  = "newuser1";
+  $_("new-pword1").value  = "newpass1";
+  $_("new-pword1B").value = "newpass1";
+  // Form 2
+  //$_("new-uname2").value  = "newuser2";  (already set in form)
+  $_("new-pword2").value  = "newpass2";
+  $_("new-pword2B").value = "newpass2";
+  // Form 3
+  //$_("new-uname3").value  = "newuser3";
+  //$_("new-pword3").value  = "newpass3";
+  $_("new-pword3B").value = "newpass3";
+  // Form 4
+  $_("new-uname4").value  = "newuser4";
+  $_("new-pword4").value  = "newpass4";
+  $_("new-pword4B").value = "newpass4";
+  // Form 5
+  //$_("new-uname5").value  = "newuser5";
+  $_("new-pword5").value  = "newpass5";
+  $_("new-pword5B").value = "newpass5";
+  // Form 6
+  //$_("new-uname6").value  = "newuser6";
+  //$_("new-pword6").value  = "newpass6";
+  $_("new-pword6B").value = "newpass6";
+
+
+  var button = getFormSubmitButton(1);
+  button.click();
+}
+
+
+// Called by each form's onsubmit handler.
+function checkSubmit(formNum) {
+  numSubmittedForms++;
+
+  // End the test at the last form.
+  if (formNum == 6) {
+    is(numSubmittedForms, 6, "Ensuring all forms were submitted for testing.");;
+
+    var numEndingLogins = countLogins();
+
+    todo(false, "Need a mechanism to auto-save submitted logins, so we can check to see if it worked.");
+    if (false) {
+      ok(numEndingLogins > 0, "counting logins at end");
+      is(numStartingLogins, numEndingLogins + 6, "counting logins at end");
+    }
+
+    SimpleTest.finish();
+    return false; // return false to cancel current form submission
+  }
+
+  // submit the next form.
+  var button = getFormSubmitButton(formNum + 1);
+  button.click();
+
+  return false; // return false to cancel current form submission
+}
+
+
+function getFormSubmitButton(formNum) {
+  var form = $("form" + formNum); // by id, not name
+  ok(form != null, "getting form " + formNum);
+
+  // we can't just call form.submit(), because that doesn't seem to invoke the form onsubmit handler.
+  var button = form.firstChild;
+  while (button && button.type != "submit") { button = button.nextSibling; }
+  ok(button != null, "getting form submit button");
+
+  return button;
+}
+
+
+// Counts the number of logins currently stored by password manager.
+function countLogins() {
+  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+
+  var count = 0;
+  var enum = pwmgr.enumerator;
+  while (enum.hasMoreElements()) { count++; enum.getNext(); }
+
+  return count;
+}
+
+// Get the pwmgr service
+netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+
+var Cc_pwmgr = Components.classes["@mozilla.org/passwordmanager;1"];
+ok(Cc_pwmgr != null, "Access Cc[@mozilla.org/passwordmanager;1]");
+
+var Ci_pwmgr = Components.interfaces.nsIPasswordManager;
+ok(Ci_pwmgr != null, "Access Ci.nsIPasswordManager");
+
+var pwmgr = Cc_pwmgr.getService(Ci_pwmgr);
+ok(pwmgr != null, "pwmgr getService()");
+
+
+window.onload = startTest;
+
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/test_basic_form_3pw_1.html
@@ -0,0 +1,178 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Password Manager</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>  
+  <script type="text/javascript" src="pwmgr_common.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+Password Manager test: forms with 3 password fields (form filling)
+<p id="display"></p>
+
+<div id="content" style="display: none">
+  <p>The next three forms are <b>user/pass/passB/passC</b>, as all-empty, preuser(only), and preuser/pass</p>
+  <form action="formtest.js" method="get">
+    <input  type="text"       name="uname1"  value="">
+    <input  type="password"   name="pword1"  value="">
+    <input  type="password"   name="pword1B" value="">
+    <input  type="password"   name="pword1C" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <form action="formtest.js" method="get">
+    <input  type="text"       name="uname2"  value="testuser2">
+    <input  type="password"   name="pword2"  value="">
+    <input  type="password"   name="pword2B" value="">
+    <input  type="password"   name="pword2C" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <form action="formtest.js" method="get">
+    <input  type="text"       name="uname3"  value="testuser3">
+    <input  type="password"   name="pword3"  value="testpass3">
+    <input  type="password"   name="pword3B" value="">
+    <input  type="password"   name="pword3C" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+
+  <p>The next three forms are <b>user/passB/pass/passC</b>, as all-empty, preuser(only), and preuser/pass</p>
+  <form action="formtest.js" method="get">
+    <input  type="text"       name="uname4"  value="">
+    <input  type="password"   name="pword4B" value="">
+    <input  type="password"   name="pword4"  value="">
+    <input  type="password"   name="pword4C" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <form action="formtest.js" method="get">
+    <input  type="text"       name="uname5"  value="testuser5">
+    <input  type="password"   name="pword5B" value="">
+    <input  type="password"   name="pword5"  value="">
+    <input  type="password"   name="pword5C" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <form action="formtest.js" method="get">
+    <input  type="text"       name="uname6"  value="testuser6">
+    <input  type="password"   name="pword6B" value="">
+    <input  type="password"   name="pword6"  value="testpass6">
+    <input  type="password"   name="pword6C" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <p>The next three forms are <b>user/passB/passC/pass</b>, as all-empty, preuser(only), and preuser/pass</p>
+  <form action="formtest.js" method="get">
+    <input  type="text"       name="uname7"  value="">
+    <input  type="password"   name="pword7B" value="">
+    <input  type="password"   name="pword7C" value="">
+    <input  type="password"   name="pword7"  value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <form action="formtest.js" method="get">
+    <input  type="text"       name="uname8"  value="testuser8">
+    <input  type="password"   name="pword8B" value="">
+    <input  type="password"   name="pword8C" value="">
+    <input  type="password"   name="pword8"  value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <form action="formtest.js" method="get">
+    <input  type="text"       name="uname9"  value="testuser9">
+    <input  type="password"   name="pword9B" value="">
+    <input  type="password"   name="pword9C" value="">
+    <input  type="password"   name="pword9"  value="testpass9">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+</div>
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Password Manger: form fill, 3 password fields **/
+
+// Test to make sure 3-password forms are filled properly.
+
+function startTest() {
+  // Check form 1
+  is($_("uname1").value,  "testuser1", "Checking username1");
+  is($_("pword1").value,  "testpass1", "Checking password1");
+  is($_("pword1B").value, "",    "Checking password1B");
+  is($_("pword1C").value, "",    "Checking password1C");
+  // Check form 2
+  is($_("uname2").value,  "testuser2", "Checking username2");
+  is($_("pword2").value,  "testpass2", "Checking password2");
+  is($_("pword2B").value, "",    "Checking password2B");
+  is($_("pword2C").value, "",    "Checking password2C");
+  // Check form 3
+  is($_("uname3").value,  "testuser3", "Checking username3");
+  is($_("pword3").value,  "testpass3", "Checking password3");
+  is($_("pword3B").value, "",    "Checking password3B");
+  is($_("pword3C").value, "",    "Checking password3C");
+
+  // Check form 4
+  is($_("uname4").value,  "testuser4", "Checking username4");
+  is($_("pword4").value,  "testpass4", "Checking password4");
+  is($_("pword4B").value, "",    "Checking password4B");
+  is($_("pword4C").value, "",    "Checking password4C");
+  // Check form 5
+  is($_("uname5").value,  "testuser5", "Checking username5");
+  is($_("pword5").value,  "testpass5", "Checking password5");
+  is($_("pword5B").value, "",    "Checking password5B");
+  is($_("pword5C").value, "",    "Checking password5C");
+  // Check form 6
+  is($_("uname6").value,  "testuser6", "Checking username6");
+  is($_("pword6").value,  "testpass6", "Checking password6");
+  is($_("pword6B").value, "",    "Checking password6B");
+  is($_("pword6C").value, "",    "Checking password6C");
+
+  // Check form 7
+  is($_("uname7").value,  "testuser7", "Checking username7");
+  is($_("pword7").value,  "testpass7", "Checking password7");
+  is($_("pword7B").value, "",    "Checking password7B");
+  is($_("pword7C").value, "",    "Checking password7C");
+  // Check form 8
+  is($_("uname8").value,  "testuser8", "Checking username8");
+  is($_("pword8").value,  "testpass8", "Checking password8");
+  is($_("pword8B").value, "",    "Checking password8B");
+  is($_("pword8C").value, "",    "Checking password8C");
+  // Check form 9
+  is($_("uname9").value,  "testuser9", "Checking username9");
+  is($_("pword9").value,  "testpass9", "Checking password9");
+  is($_("pword9B").value, "",    "Checking password9B");
+  is($_("pword9C").value, "",    "Checking password9C");
+
+  // TODO: as with the 2-password cases, add tests to check for creating new
+  // logins and changing passwords.
+  SimpleTest.finish();
+}
+
+window.onload = startTest;
+
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/test_bug_221634.html
@@ -0,0 +1,100 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Password Manager</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>  
+  <script type="text/javascript" src="pwmgr_common.js"></script>  
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="endTest();">
+Password Manager test: 221634
+<p id="display"></p>
+<div id="content" style="display: none">
+
+  <form action="formtest.js" method="get">
+    <input  type="text"       name="uname1" value="">
+    <input  type="password"   name="pword1" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset</button>
+  </form>
+  
+  <img onload="performTest();" src="data:image/png;base64,
+    iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGdBTUEAALGP
+    C/xhBQAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9YGARc5KB0XV+IA
+    AAAddEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q72QlbgAAAF1J
+    REFUGNO9zL0NglAAxPEfdLTs4BZM4DIO4C7OwQg2JoQ9LE1exdlYvBBeZ7jq
+    ch9//q1uH4TLzw4d6+ErXMMcXuHWxId3KOETnnXXV6MJpcq2MLaI97CER3N0
+    vr4MkhoXe0rZigAAAABJRU5ErkJggg==">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Password Manger: 221634 (password manager needs to fill in forms before the page finishes loading) **/
+
+var dclHappened      = false;
+var testHappened     = false;
+var pageloadHappened = false;
+
+// We're still loading the page, so make sure nothing has filled in yet.
+is($_("uname1").value, "", "Checking unfilled username 1");
+is($_("pword1").value, "", "Checking unfilled password 1");
+
+document.addEventListener("DOMContentLoaded", contentLoaded, false);
+
+SimpleTest.waitForExplicitFinish();
+
+
+// Step 1 - Fires at DOMContentLoaded
+function contentLoaded() {
+  ok(!testHappened,     "Sanity check to ensure test hasn't happened yet.")
+  ok(!pageloadHappened, "Sanity check to ensure pageload hasn't happened yet.")
+
+  // We're in DOMContentLoaded, so the pwmgr may or may not have filled in yet.
+
+  // Set a 0-second timeout, which should execute before the pageload event.
+  // setTimeout(reallyDoTest, 0);
+  // ha-ha... That doesn't work. The pageload event comes first, although
+  // it can be hacked into working by adding <img src="404_non_existant_file.gif">
+
+  dclHappened = true;
+}
+
+// Step 2 - Fires when the image loads, which should be immediately after DOMContentLoaded (but before pageload)
+function performTest() {
+  ok(dclHappened,       "Sanity check to make sure DOMContentLoaded already happened");
+  ok(!pageloadHappened, "Sanity check to ensure pageload hasn't happened yet.")
+
+  // Check form1
+  is($_("uname1").value, "testuser1", "Checking filled username 1");
+  is($_("pword1").value, "testpass1", "Checking filled password 1");
+
+  testHappened = true;
+}
+
+// Step 3 - Fired by |body| onload.
+function endTest() {
+  ok(dclHappened, "Sanity check to make sure DOMContentLoaded already happened");
+  ok(testHappened, "Sanity check to make sure our test ran before pageload");
+  
+  // Check form1
+  is($_("uname1").value, "testuser1", "Rechecking filled username 1");
+  is($_("pword1").value, "testpass1", "Rechecking filled password 1");
+
+  pageloadHappened = true;
+
+  // Make sure the expected number of tests (for this page) have run.
+  // If the event execution gets out of order, only a subset get counted.
+  // (Although there should still be other failures... Belt-n-suspenders!)
+  is(SimpleTest._tests.length, 12, "expected number of executed tests");
+
+  SimpleTest.finish();
+}
+
+</script>
+
+</pre>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/test_bug_227640.html
@@ -0,0 +1,251 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Password Manager</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>  
+  <script type="text/javascript" src="pwmgr_common.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+Password Manager test: 227640
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+  <!-- no autocomplete for password field -->
+  <form id="form1" onsubmit="return checkSubmit(1)" method="get">
+    <input  type="text"       name="uname1" value="">
+    <input  type="password"   name="pword1" value="" autocomplete=off>
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- no autocomplete for username field -->
+  <form id="form2" onsubmit="return checkSubmit(2);" method="get">
+    <input  type="text"       name="uname2" value="" autocomplete=off>
+    <input  type="password"   name="pword2" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- no autocomplete for username or password fields -->
+  <form id="form3" onsubmit="return checkSubmit(3);" method="get">
+    <input  type="text"       name="uname3" value="" autocomplete=off>
+    <input  type="password"   name="pword3" value="" autocomplete=off>
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- no autocomplete for entire form -->
+  <form id="form4" onsubmit="return checkSubmit(4);" method="get" autocomplete=off>
+    <input  type="text"       name="uname4" value="">
+    <input  type="password"   name="pword4" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- no autocomplete for entire form and password field -->
+  <form id="form5" onsubmit="return checkSubmit(5);" method="get">
+    <input  type="text"       name="uname5" value="">
+    <input  type="password"   name="pword5" value="" autocomplete=off>
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- no autocomplete for entire form and username field -->
+  <form id="form6" onsubmit="return checkSubmit(6);" method="get">
+    <input  type="text"       name="uname6" value="" autocomplete=off>
+    <input  type="password"   name="pword6" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- no autocomplete for entire form, userfield, and password field -->
+  <form id="form7" onsubmit="return checkSubmit(7);" method="get" autocomplete=off>
+    <input  type="text"       name="uname7" value="" autocomplete=off>
+    <input  type="password"   name="pword7" value="" autocomplete=off>
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+
+  <!-- ===== repeat, but with logins not previously stored ===== -->
+
+
+  <!-- no autocomplete for password field -->
+  <form id="form8" onsubmit="return checkSubmit(8);" method="get">
+    <input  type="text"       name="xxxuname1" value="newuser1">
+    <input  type="password"   name="xxxpword1" value="newpass1" autocomplete=off>
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- no autocomplete for username field -->
+  <form id="form9" onsubmit="return checkSubmit(9);" method="get">
+    <input  type="text"       name="xxxuname2" value="newuser2" autocomplete=off>
+    <input  type="password"   name="xxxpword2" value="newpass2">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- no autocomplete for username or password fields -->
+  <form id="form10" onsubmit="return checkSubmit(10);" method="get">
+    <input  type="text"       name="xxxuname3" value="newuser3" autocomplete=off>
+    <input  type="password"   name="xxxpword3" value="newpass3" autocomplete=off>
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- no autocomplete for entire form -->
+  <form id="form11" onsubmit="return checkSubmit(11);" method="get" autocomplete=off>
+    <input  type="text"       name="xxxuname4" value="newuser4">
+    <input  type="password"   name="xxxpword4" value="newpass4">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- no autocomplete for entire form and password field -->
+  <form id="form12" onsubmit="return checkSubmit(12);" method="get">
+    <input  type="text"       name="xxxuname5" value="newuser5">
+    <input  type="password"   name="xxxpword5" value="newpass5" autocomplete=off>
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- no autocomplete for entire form and username field -->
+  <form id="form13" onsubmit="return checkSubmit(13);" method="get">
+    <input  type="text"       name="xxxuname6" value="newuser6" autocomplete=off>
+    <input  type="password"   name="xxxpword6" value="newpass6">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- no autocomplete for entire form, userfield, and password field -->
+  <form id="form14" onsubmit="return checkSubmit(14);" method="get" autocomplete=off>
+    <input  type="text"       name="xxxuname7" value="newuser7" autocomplete=off>
+    <input  type="password"   name="xxxpword7" value="newpass7" autocomplete=off>
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Password Manger: 227640 (password is saved even when the password field has autocomplete="off") **/
+
+// This test ensures that pwmgr does not save a username or password when
+// autocomplete=off is present.
+
+var numStartingLogins = 0;
+var numSubmittedForms = 0;
+
+function startTest() {
+  // Get current number of logins, to make sure we don't end up storing new logins.
+  numStartingLogins = countLogins();
+  ok(numStartingLogins > 0, "counting logins at start");
+
+  // Check first set of forms, which should be filled by pwmgr.
+  for (var i = 1; i <= 7; i++) {
+    is($_("uname" + i).value, "testuser" + i, "Checking for filled username " + i);
+    is($_("pword" + i).value, "testpass" + i, "Checking for filled password " + i);
+  }
+
+  // Check second set of forms, which should have preset values (and are unknown to pwmgr).
+  for (var i = 1; i <= 7; i++) {
+    is($_("xxxuname" + i).value, "newuser" + i, "Checking for unmodified username " + i);
+    is($_("xxxpword" + i).value, "newpass" + i, "Checking for unmodified password " + i);
+  }
+
+  var button = getFormSubmitButton(1);
+
+  // submit the first form.
+  button.click();
+}
+
+
+// Called by each form's onsubmit handler.
+function checkSubmit(formNum) {
+  numSubmittedForms++;
+
+  // End the test at the last form.
+  if (formNum == 14) {
+    is(numSubmittedForms, 14, "Ensuring all forms were submitted for testing.");;
+
+    var numEndingLogins = countLogins();
+    ok(numEndingLogins > 0, "counting logins at end");
+
+    is(numStartingLogins, numEndingLogins, "counting logins at end");
+
+    SimpleTest.finish();
+    return false; // return false to cancel current form submission
+  }
+
+  var button = getFormSubmitButton(formNum + 1);
+
+  // submit the next form.
+  button.click();
+
+  return false; // return false to cancel current form submission
+}
+
+
+function getFormSubmitButton(formNum) {
+  var form = $("form" + formNum); // by id, not name
+  ok(form != null, "getting form " + formNum);
+
+  // we can't just call form.submit(), because that doesn't seem to invoke the form onsubmit handler.
+  var button = form.firstChild;
+  while (button && button.type != "submit") { button = button.nextSibling; }
+  ok(button != null, "getting form submit button");
+
+  return button;
+}
+
+// Counts the number of logins currently stored by password manager.
+function countLogins() {
+  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+
+  var count = 0;
+  var enum = pwmgr.enumerator;
+  while (enum.hasMoreElements()) { count++; enum.getNext(); }
+
+  return count;
+}
+
+// Get the pwmgr service
+netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+
+var Cc_pwmgr = Components.classes["@mozilla.org/passwordmanager;1"];
+ok(Cc_pwmgr != null, "Access Cc[@mozilla.org/passwordmanager;1]");
+
+var Ci_pwmgr = Components.interfaces.nsIPasswordManager;
+ok(Ci_pwmgr != null, "Access Ci.nsIPasswordManager");
+
+var pwmgr = Cc_pwmgr.getService(Ci_pwmgr);
+ok(pwmgr != null, "pwmgr getService()");
+
+
+window.onload = startTest;
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/test_bug_242956.html
@@ -0,0 +1,209 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Password Manager</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>  
+  <script type="text/javascript" src="pwmgr_common.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+Password Manager test: 242956
+<p id="display"></p>
+<div id="content" style="display: none">
+  <!-- pword1 is not a type=password input -->
+  <form action="formtest.js" method="get">
+    <input  type="text" name="uname1" value="">
+    <input  type="text" name="pword1" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- uname2 is not a type=text input -->
+  <form action="formtest.js" method="get">
+    <input  type="password" name="uname2" value="">
+    <input  type="password" name="pword2" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- two "pword3" inputs, (text + password) -->
+  <form action="formtest.js" method="get">
+    <input  type="text"       name="uname3" value="">
+    <input  type="text"       name="pword3" value="">
+    <input  type="password"   name="pword3" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- same thing, different order -->
+  <form action="formtest.js" method="get">
+    <input  type="text"       name="uname4" value="">
+    <input  type="password"   name="pword4" value="">
+    <input  type="text"       name="pword4" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- two "uname5" inputs, (text + password) -->
+  <form action="formtest.js" method="get">
+    <input  type="text"       name="uname5" value="">
+    <input  type="password"   name="uname5" value="">
+    <input  type="password"   name="pword5" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+ 
+  <!-- same thing, different order -->
+  <form action="formtest.js" method="get">
+    <input  type="password"   name="uname6" value="">
+    <input  type="text"       name="uname6" value="">
+    <input  type="password"   name="pword6" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+  
+  <!-- uname7 is not a type=text input (try a checkbox just for variety) -->
+  <form action="formtest.js" method="get">
+    <input  type="checkbox" name="uname7" value="">
+    <input  type="password" name="pword7" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- pword8 is not a type=password input (try a checkbox just for variety) -->
+  <form action="formtest.js" method="get">
+    <input  type="text"     name="uname8" value="">
+    <input  type="checkbox" name="pword8" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- pword9 is not a type=password input -->
+  <form action="formtest.js" method="get">
+    <input  type="text" name="uname9" value="testuser9">
+    <input  type="text" name="pword9" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- uname10 is not a type=text input -->
+  <form action="formtest.js" method="get">
+    <input  type="password" name="uname10" value="testuser10">
+    <input  type="password" name="pword10" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Password Manger: 242956 (Stored password is inserted into a readable text input on a second page) **/
+
+// Make sure that pwmgr only puts passwords into type=password <input>s.
+// Might as well test the converse, too (username in password field).
+
+function startTest() {
+  for (var i = 1; i <= 8; i++) {
+    if (i >= 3 && i <= 6) { continue; } // handle these below.
+    // Check form i
+    is($_("uname" + i).value, "", "Checking for unfilled username " + i);
+    is($_("pword" + i).value, "", "Checking for unfilled password " + i);
+  }
+
+  // Forms 3 and 4 have two password inputs with the same name
+  var form, input;
+
+  form  = document.forms[2];
+  input = form.elements[0];
+  is(input.type,  "text",      "confirming user field 3 type");
+  is(input.name,  "uname3",    "confirming user field 3 name");
+  //is(input.value, "testuser3", "checking user field 3 value");
+  todo(input.value == "testuser3", "ignore bogus <input> and fill testuser3");
+  input = form.elements[1];
+  is(input.type,  "text",      "confirming bogus password field 3 type");
+  is(input.name,  "pword3",    "confirming bogus password field 3 name");
+  is(input.value, "",    "checking bogus password field 3 value");
+  input = form.elements[2];
+  is(input.type,  "password",  "confirming legit password field 3 type");
+  is(input.name,  "pword3",    "confirming legit password field 3 type");
+  //is(input.value, "testpass3", "checking legit password field 3 value");
+  todo(input.value == "testpass3", "ignore bogus <input> and fill testpass3");
+
+  form  = document.forms[3];
+  input = form.elements[0];
+  is(input.type,  "text",      "confirming user field 4 type");
+  is(input.name,  "uname4",    "confirming user field 4 name");
+  //is(input.value, "testuser4", "checking user field 4 value");
+  todo(input.value == "testuser4", "ignore bogus <input> and fill testuser4");
+  input = form.elements[1];
+  is(input.type,  "password",  "confirming legit password field 4 type");
+  is(input.name,  "pword4",    "confirming legit password field 4 type");
+  //is(input.value, "testpass4", "checking legit password field 4 value");
+  todo(input.value == "testpass4", "ignore bogus <input> and fill testpass4");
+  input = form.elements[2];
+  is(input.type,  "text",      "confirming bogus password field 4 type");
+  is(input.name,  "pword4",    "confirming bogus password field 4 name");
+  is(input.value, "",    "checking bogus password field 4 value");
+
+  // Forms 5 and 6 have two username inputs with the same name
+  form  = document.forms[4];
+  input = form.elements[0];
+  is(input.type,  "text",      "confirming legit user field 5 type");
+  is(input.name,  "uname5",    "confirming legit user field 5 name");
+  //is(input.value, "testuser5", "checking legit user field 5 value");
+  todo(input.value == "testuser5", "ignore bogus <input> and fill testuser5");
+  input = form.elements[1];
+  is(input.type,  "password",  "confirming bogus user field 5 type");
+  is(input.name,  "uname5",    "confirming bogus user field 5 name");
+  is(input.value, "",    "checking bogus user field 5 value");
+  input = form.elements[2];
+  is(input.type,  "password",  "confirming password field 5 ");
+  is(input.name,  "pword5",    "confirming password field 5 ");
+  //is(input.value, "testpass5", "checking password field 5 value");
+  todo(input.value == "testpass5", "ignore bogus <input> and fill testpass5");
+
+  form  = document.forms[5];
+  input = form.elements[0];
+  is(input.type,  "password",  "confirming bogus user field 6 type");
+  is(input.name,  "uname6",    "confirming bogus user field 6 name");
+  is(input.value, "",    "checking bogus user field 6 value");
+  input = form.elements[1];
+  is(input.type,  "text",      "confirming legit user field 6 type");
+  is(input.name,  "uname6",    "confirming legit user field 6 name");
+  //is(input.value, "testuser6", "checking legit user field 6 value");
+  todo(input.value == "testuser6", "ignore bogus <input> and fill testuser6");
+  input = form.elements[2];
+  is(input.type,  "password",  "confirming password field 6 type");
+  is(input.name,  "pword6",    "confirming password field 6 name");
+  //is(input.value, "testpass6", "");
+  todo(input.value == "testpass6", "ignore bogus <input> and fill testpass6");
+
+  is($_("uname9").value, "testuser9", "Checking for unmodified username 9");
+  is($_("pword9").value, "",    "Checking for unfilled password 9");
+
+  is($_("uname10").value, "testuser10", "Checking for unmodified username 10");
+  is($_("pword10").value, "",     "Checking for unfilled password 10");
+
+  SimpleTest.finish();
+}
+
+window.onload = startTest;
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/test_bug_270558.html
@@ -0,0 +1,135 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Password Manager</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>  
+  <script type="text/javascript" src="pwmgr_common.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+Password Manager test: 270558
+<p id="display"></p>
+<div id="content" style="display: none">
+
+  <!-- normal, simple form. -->
+  <form action="formtest.js" method="get">
+    <input  type="text"       name="uname1" value="">
+    <input  type="password"   name="pword1" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- prefilled with correct username -->
+  <form action="formtest.js" method="get">
+    <input  type="text"       name="uname2" value="testuser2">
+    <input  type="password"   name="pword2" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- prefilled with correct password -->
+  <form action="formtest.js" method="get">
+    <input  type="text"       name="uname3" value="">
+    <input  type="password"   name="pword3" value="testpass3">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- prefilled with correct username and password -->
+  <form action="formtest.js" method="get">
+    <input  type="text"       name="uname4" value="testuser4">
+    <input  type="password"   name="pword4" value="testpass4">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- prefilled with an unknown username (don't clobber it!) -->
+  <form action="formtest.js" method="get">
+    <input  type="text"       name="uname5" value="xxORIG5xx">
+    <input  type="password"   name="pword5" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- prefilled with an unknown password (don't clobber it!) -->
+  <form action="formtest.js" method="get">
+    <input  type="text"       name="uname6" value="">
+    <input  type="password"   name="pword6" value="xxORIG6xx">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- prefilled with an unknown username and password (don't clobber it!) -->
+  <form action="formtest.js" method="get">
+    <input  type="text"       name="uname7" value="xxORIG7Uxx">
+    <input  type="password"   name="pword7" value="xxORIG7Pxx">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!--  prefilled with a known username, but not for these inputs. -->
+  <form action="formtest.js" method="get">
+    <input  type="text"       name="uname8" value="testuser9">
+    <input  type="password"   name="pword8" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- TODO: test when multiple matching accounts are known -->
+  <!-- TODO: test with prefilled known login for some other site and/or action url. -->
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Password Manger: 270558 (Password manager should not fill in username and
+    password if the username field is pre-filled by the server to a different username.
+    (frequent problem with phpBB admin interface)) **/
+
+// This test ensures pwmgr will not overwrite a prefilled username or password.
+
+function startTest() {
+  // These form are partially filled with correct login info.
+  for (var i = 1; i <= 4; i++) {
+    // Check form i
+    is($_("uname" + i).value, "testuser" + i, "Checking for filled username " + i);
+    is($_("pword" + i).value, "testpass" + i, "Checking for filled password " + i);
+  }
+
+  // These test forms partially filled with unknown login info (so pwmgr shouldn't touch them).
+  is($_("uname5").value, "xxORIG5xx", "Checking for filled username ");
+  is($_("pword5").value, "", "Checking for filled password ");
+
+  todo(false, "pwmgr will clobber the prefilled data in this weird edge case.");
+  if (false) {
+    is($_("uname6").value, "", "Checking for filled username ");
+    is($_("pword6").value, "xxORIG6xx", "Checking for filled password ");
+  }
+
+  is($_("uname7").value, "xxORIG7Uxx", "Checking for filled username ");
+  is($_("pword7").value, "xxORIG7Pxx", "Checking for filled password ");
+
+  // This tests a form with a known username, but in the wrong inputs.
+  is($_("uname8").value, "testuser9", "Checking for filled username ");
+  is($_("pword8").value, "", "Checking for filled password ");
+
+  SimpleTest.finish();
+}
+
+window.onload = startTest;
+
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/test_bug_360493_1.html
@@ -0,0 +1,138 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Password Manager</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>  
+  <script type="text/javascript" src="pwmgr_common.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+Password Manager test: 360493
+<p id="display"></p>
+<div id="content" style="display: none">
+
+  <!-- normal form with normal relative action. -->
+  <form action="formtest.js" method="get">
+    <input  type="text"       name="uname1" value="">
+    <input  type="password"   name="pword1" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- fully specify the action URL -->
+  <form action="http://localhost:8888/tests/toolkit/components/passwordmgr/test/formtest.js" method="get">
+    <input  type="text"       name="uname2" value="">
+    <input  type="password"   name="pword2" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- fully specify the action URL, and change the path -->
+  <form action="http://localhost:8888/zomg/wtf/bbq/passwordmgr/test/formtest.js" method="get">
+    <input  type="text"       name="uname3" value="">
+    <input  type="password"   name="pword3" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- fully specify the action URL, and change the path and filename -->
+  <form action="http://localhost:8888/zomg/wtf/bbq/passwordmgr/test/not_a_test.js" method="get">
+    <input  type="text"       name="uname4" value="">
+    <input  type="password"   name="pword4" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- specify the action URL relative to the current document-->
+  <form action="./formtest.js" method="get">
+    <input  type="text"       name="uname5" value="">
+    <input  type="password"   name="pword5" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- specify the action URL relative to the current server -->
+  <form action="/tests/toolkit/components/passwordmgr/test/formtest.js" method="get">
+    <input  type="text"       name="uname6" value="">
+    <input  type="password"   name="pword6" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- Change the method from get to post -->
+  <form action="formtest.js" method="POST">
+    <input  type="text"       name="uname7" value="">
+    <input  type="password"   name="pword7" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- Blank action URL specified -->
+  <form action="" method="get">
+    <input  type="text"       name="uname8" value="">
+    <input  type="password"   name="pword8" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- |action| attribute entirely missing -->
+  <form method="get">
+    <input  type="text"       name="uname9" value="">
+    <input  type="password"   name="pword9" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- action url as javascript -->
+  <form action="javascript:alert('this form is not submitted so this alert should not be invoked');">
+    <input  type="text"       name="uname10" value="">
+    <input  type="password"   name="pword10" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- TODO: action=IP.ADDRESS instead of HOSTNAME? -->
+  <!-- TODO: test with |base href="http://othersite//"| ? -->
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Password Manger: 360493 (Cross-Site Forms + Password Manager = Security Failure) **/
+
+// This test is designed to make sure variations on the form's |action| and |method|
+// continue to work with the fix for 360493.
+
+function startTest() {
+  for (var i = 1; i <= 9; i++) {
+    // Check form i
+    is($_("uname" + i).value, "testuser" + i, "Checking for filled username " + i);
+    is($_("pword" + i).value, "testpass" + i, "Checking for filled password " + i);
+  }
+
+  // Not sure if we spec'd how JS urls should be handled here.
+  todo($_("uname10") == "testuser10", "Checking for filled username when action is js: URL");
+  todo($_("upass10") == "testpass10", "Checking for filled password when action is js: URL");
+
+  SimpleTest.finish();
+}
+
+window.onload = startTest;
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/test_bug_360493_2.html
@@ -0,0 +1,172 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Password Manager</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>  
+  <script type="text/javascript" src="pwmgr_common.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+Password Manager test: 360493
+<p id="display"></p>
+<div id="content" style="display: none">
+
+  <!-- The tests in this page exercise things that shouldn't work. -->
+
+  <!-- Change port # of action URL from 8888 to 7777 -->
+  <form action="http://localhost:7777/tests/toolkit/components/passwordmgr/test/formtest.js" method="get">
+    <input  type="text"       name="uname1" value="">
+    <input  type="password"   name="pword1" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- No port # in action URL -->
+  <form action="http://localhost/tests/toolkit/components/passwordmgr/test/formtest.js" method="get">
+    <input  type="text"       name="uname2" value="">
+    <input  type="password"   name="pword2" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- Change protocol from http:// to ftp://, include the expected 8888 port # -->
+  <form action="ftp://localhost:8888/tests/toolkit/components/passwordmgr/test/formtest.js" method="get">
+    <input  type="text"       name="uname3" value="">
+    <input  type="password"   name="pword3" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- Change protocol from http:// to ftp://, no port # specified -->
+  <form action="ftp://localhost/tests/toolkit/components/passwordmgr/test/formtest.js" method="get">
+    <input  type="text"       name="uname4" value="">
+    <input  type="password"   name="pword4" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- Try a weird URL. -->
+  <form action="about:blank" method="get">
+    <input  type="text"       name="uname5" value="">
+    <input  type="password"   name="pword5" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- Try a weird URL. (If the normal embedded action URL doesn't work, that should mean other URLs won't either) -->
+  <form action="view-source:http://localhost:8888/tests/toolkit/components/passwordmgr/test/formtest.js" method="get">
+    <input  type="text"       name="uname6" value="">
+    <input  type="password"   name="pword6" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- Try a weird URL. -->
+  <form action="view-source:formtest.js" method="get">
+    <input  type="text"       name="uname7" value="">
+    <input  type="password"   name="pword7" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- Action URL points to a different host (this is the archetypical exploit) -->
+  <form action="http://www.cnn.com/" method="get">
+    <input  type="text"       name="uname8" value="">
+    <input  type="password"   name="pword8" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- Action URL points to a different host, user field prefilled -->
+  <form action="http://www.cnn.com/" method="get">
+    <input  type="text"       name="uname9" value="testuser9">
+    <input  type="password"   name="pword9" value="">
+
+    <button type="submit">Submit</button>
+    <button type="reset"> Reset </button>
+  </form>
+
+  <!-- Try wrapping a evil form around a good form, to see if we can confuse the parser. -->
+  <form action="http://www.cnn.com/" method="get">
+   <form action="formtest.js" method="get">
+    <input  type="text"       name="uname10" value="">
+    <input  type="password"   name="pword10" value="">
+
+    <button type="submit">Submit (inner)</button>
+    <button type="reset"> Reset  (inner)</button>
+   </form>
+   <button type="submit" id="neutered_submit10">Submit (outer)</button>
+   <button type="reset">Reset (outer)</button>
+  </form>
+
+  <!-- Try wrapping a good form around an evil form, to see if we can confuse the parser. -->
+  <form action="formtest.js" method="get">
+   <form action="http://www.cnn.com/" method="get">
+    <input  type="text"       name="uname11" value="">
+    <input  type="password"   name="pword11" value="">
+
+    <button type="submit">Submit (inner)</button>
+    <button type="reset"> Reset  (inner)</button>
+   </form>
+   <button type="submit" id="neutered_submit11">Submit (outer)</button>
+   <button type="reset">Reset (outer)</button>
+  </form>
+
+<!-- TODO: probably should have some accounts which have no port # in the action url. JS too. And different host/proto. -->
+<!-- TODO: www.site.com vs. site.com? -->
+<!-- TODO: foo.site.com vs. bar.site.com? -->
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Password Manger: 360493 (Cross-Site Forms + Password Manager = Security Failure) **/
+
+function startTest() {
+  for (var i = 1; i <= 8; i++) {
+    // Check form i
+    is($_("uname" + i).value, "", "Checking for unfilled username " + i);
+    is($_("pword" + i).value, "", "Checking for unfilled password " + i);
+  }
+
+  is($_("uname9").value, "testuser9", "Checking for unmodified username 9");
+  is($_("pword9").value, "",    "Checking for unfilled password 9");
+
+  is($_("uname10").value, "", "Checking for unfilled username 10");
+  is($_("pword10").value, "", "Checking for unfilled password 10");
+
+  // The DOM indicates this form could be filled, as the evil inner form
+  // is discarded. And yet pwmgr seems not to fill it. Not sure why.
+  todo(false, "Mangled form combo not being filled when maybe it could be?");
+  is($_("uname11").value, "", "Checking for unfilled username 11");
+  is($_("pword11").value, "", "Checking for unfilled password 11");
+
+  // Verify this by making sure there are no extra forms in the document, and that
+  // the submit button for the neutered forms don't do anything.
+  // If the test finds extra forms the submit() causes the test to timeout, then
+  // there may be a security issue.
+  is(document.forms.length,  11,  "Checking for unexpected forms");
+  $("neutered_submit10").click();
+  $("neutered_submit11").click();
+
+  SimpleTest.finish();
+}
+
+window.onload = startTest;
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
+