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 id1
push userbsmedberg@mozilla.com
push dateThu, 20 Mar 2008 16:49:24 +0000
treeherdermozilla-central@61007906a1f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
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>
+