fix bug 671965, failure to report invalid pop3 account password when auth login fails, r+a=standard8
authorDavid Bienvenu <bienvenu@nventure.com>
Mon, 08 Aug 2011 15:33:13 -0700
changeset 8372 9ef10c2815edbd84f226af283f1edffc81214aa1
parent 8371 a166416526d2dfeab16b40918e409f2f26f2946d
child 8373 4eb158b9555d8b6e2d516b3daf7cdb77ed1d5954
push idunknown
push userunknown
push dateunknown
bugs671965
fix bug 671965, failure to report invalid pop3 account password when auth login fails, r+a=standard8
mailnews/local/src/nsPop3Protocol.cpp
mailnews/local/test/unit/test_pop3PasswordFailure3.js
mailnews/local/test/unit/xpcshell.ini
--- a/mailnews/local/src/nsPop3Protocol.cpp
+++ b/mailnews/local/src/nsPop3Protocol.cpp
@@ -977,17 +977,18 @@ NS_IMETHODIMP nsPop3Protocol::OnStopRequ
   // we call nsMsgProtocol::OnStopRequest. The call will force a close socket,
   // but we still want to go through the state machine one more time to cleanup
   // the protocol object.
   if (m_socketIsOpen)
   {
     // Check if the connection was dropped before getting back an auth error.
     // If we got the auth error, the next state would be
     // POP3_OBTAIN_PASSWORD_EARLY.
-    if (m_pop3ConData->next_state_after_response == POP3_NEXT_AUTH_STEP &&
+    if ((m_pop3ConData->next_state_after_response == POP3_NEXT_AUTH_STEP ||
+         m_pop3ConData->next_state_after_response == POP3_AUTH_LOGIN_RESPONSE) &&
         m_pop3ConData->next_state != POP3_OBTAIN_PASSWORD_EARLY)
     {
       PR_LOG(POP3LOGMODULE, PR_LOG_MAX, ("dropped connection before auth error"));
       SetFlag(POP3_AUTH_FAILURE);
       m_pop3ConData->command_succeeded = PR_FALSE;
       m_needToRerunUrl = PR_TRUE;
       m_pop3ConData->next_state = POP3_NEXT_AUTH_STEP;
       ProcessProtocolState(nsnull, nsnull, 0, 0);
new file mode 100644
--- /dev/null
+++ b/mailnews/local/test/unit/test_pop3PasswordFailure3.js
@@ -0,0 +1,237 @@
+/**
+ * This test checks to see if the pop3 password failure is handled correctly
+ * in the case of the server dropping the connection during auth login.
+ * We use POP3_RFC5034_handler so auth=login will be supported.
+ * The steps are:
+ *   - Have an invalid password in the password database.
+ *   - Check we get a prompt asking what to do.
+ *   - Check retry does what it should do.
+ *   - Check cancel does what it should do.
+ *   - Re-initiate connection, this time select enter new password, check that
+ *     we get a new password prompt and can enter the password.
+ */
+
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+Components.utils.import("resource:///modules/mailServices.js");
+Components.utils.import("resource://gre/modules/Services.jsm");
+load("../../../resources/logHelper.js");
+load("../../../resources/mailTestUtils.js");
+load("../../../resources/asyncTestUtils.js");
+load("../../../resources/alertTestUtils.js");
+
+var test = null;
+var server;
+var daemon;
+var incomingServer;
+var attempt = 0;
+var loginMgr = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
+var count = {};
+var logins;
+
+const kUserName = "testpop3";
+const kInvalidPassword = "pop3test";
+const kValidPassword = "testpop3";
+
+var dummyDocShell =
+{
+  getInterface: function (iid) {
+    if (iid.equals(Ci.nsIAuthPrompt)) {
+      return Cc["@mozilla.org/login-manager/prompter;1"]
+               .getService(Ci.nsIAuthPrompt);
+    }
+
+    throw Components.results.NS_ERROR_FAILURE;
+  },
+
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDocShell,
+                                         Ci.nsIInterfaceRequestor])
+}
+
+// Dummy message window that ensures we get prompted for logins.
+var dummyMsgWindow =
+{
+  rootDocShell: dummyDocShell,
+  promptDialog: alertUtilsPrompts,
+
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIMsgWindow,
+                                         Ci.nsISupportsWeakReference])
+};
+
+function alert(aDialogText, aText)
+{
+  // The first few attempts may prompt about the password problem, the last
+  // attempt shouldn't.
+  do_check_true(attempt < 4);
+
+  // Log the fact we've got an alert, but we don't need to test anything here.
+  dump("Alert Title: " + aDialogText + "\nAlert Text: " + aText + "\n");
+}
+
+function confirmEx(aDialogTitle, aText, aButtonFlags, aButton0Title,
+                   aButton1Title, aButton2Title, aCheckMsg, aCheckState) {
+  switch (++attempt) {
+    // First attempt, retry.
+    case 1:
+      dump("\nAttempting retry\n");
+      return 0;
+    // Second attempt, cancel.
+    case 2:
+      dump("\nCancelling login attempt\n");
+      return 1;
+    // Third attempt, retry.
+    case 3:
+      dump("\nAttempting Retry\n");
+      return 0;
+    // Fourth attempt, enter a new password.
+    case 4:
+      dump("\nEnter new password\n");
+      return 2;
+    default:
+      do_throw("unexpected attempt number " + attempt);
+      return 1;
+  }
+}
+
+function promptPasswordPS(aParent, aDialogTitle, aText, aPassword, aCheckMsg,
+                          aCheckState) {
+  if (attempt == 4) {
+    aPassword.value = kValidPassword;
+    aCheckState.value = true;
+    return true;
+  }
+  return false;
+}
+
+function getPopMail() {
+  MailServices.pop3.GetNewMail(dummyMsgWindow, urlListener, gLocalInboxFolder,
+                               incomingServer);
+}
+
+var urlListener =
+{
+  OnStartRunningUrl: function (url) {
+  },
+  OnStopRunningUrl: function (url, result) {
+    try {
+      // On the last attempt, we should have successfully got one mail.
+      do_check_eq(gLocalInboxFolder.getTotalMessages(false),
+                  attempt == 4 ? 1 : 0);
+
+      // If we've just cancelled, expect failure rather than success
+      // because the server dropped the connection.
+      dump("in onStopRunning, result = " + result + "\n");
+      do_check_eq(result, attempt == 2 ? Cr.NS_ERROR_FAILURE : 0);
+      async_driver();
+    }
+    catch (e) {
+      // If we have an error, clean up nicely before we throw it.
+      server.stop();
+
+      var thread = gThreadManager.currentThread;
+      while (thread.hasPendingEvents())
+        thread.processNextEvent(true);
+
+      do_throw(e);
+    }
+  }
+};
+
+// Definition of tests
+var tests = [
+  getMail1,
+  getMail2,
+  endTest
+]
+
+function actually_run_test() {
+  server.start(POP3_PORT);
+  daemon.setMessages(["message1.eml"]);
+  async_run_tests(tests);
+}
+
+function getMail1() {
+  dump("\nGet Mail 1\n");
+
+  // Now get mail
+  getPopMail();
+  yield false;
+  dump("\nGot Mail 1\n");
+
+  do_check_eq(attempt, 2);
+
+  // Check that we haven't forgetton the login even though we've retried and
+  // canceled.
+  logins = loginMgr.findLogins(count, "mailbox://localhost", null,
+                                   "mailbox://localhost");
+
+  do_check_eq(count.value, 1);
+  do_check_eq(logins[0].username, kUserName);
+  do_check_eq(logins[0].password, kInvalidPassword);
+
+  server.resetTest();
+  yield true;
+}
+
+function getMail2() {
+  dump("\nGet Mail 2\n");
+
+  // Now get the mail
+  getPopMail();
+  yield false;
+  dump("\nGot Mail 2\n");
+}
+
+function endTest() {
+  // Now check the new one has been saved.
+  logins = loginMgr.findLogins(count, "mailbox://localhost", null,
+                               "mailbox://localhost");
+
+  do_check_eq(count.value, 1);
+  do_check_eq(logins[0].username, kUserName);
+  do_check_eq(logins[0].password, kValidPassword);
+  yield true;
+}
+
+function run_test()
+{
+  // Disable new mail notifications
+  Services.prefs.setBoolPref("mail.biff.play_sound", false);
+  Services.prefs.setBoolPref("mail.biff.show_alert", false);
+  Services.prefs.setBoolPref("mail.biff.show_tray_icon", false);
+  Services.prefs.setBoolPref("mail.biff.animate_dock_icon", false);
+  Services.prefs.setBoolPref("signon.debug", true);
+
+  // Passwords File (generated from Mozilla 1.8 branch).
+  let signons = do_get_file("../../../data/signons-mailnews1.8.txt");
+
+  // Copy the file to the profile directory for a PAB
+  signons.copyTo(gProfileDir, "signons.txt");
+
+  registerAlertTestUtils();
+
+  // Set up the Server
+  daemon = new pop3Daemon();
+  var handler = new POP3_RFC5034_handler(daemon);
+  server = new nsMailServer(handler);
+  handler.dropOnAuthFailure = true;
+
+  // Set the server expected username & password to what we have in signons.txt
+  handler.kUsername = kUserName;
+  handler.kPassword = kValidPassword;
+
+  // Set up the basic accounts and folders.
+  // We would use createPop3ServerAndLocalFolders() however we want to have
+  // a different username and NO password for this test (as we expect to load
+  // it from signons.txt).
+  loadLocalMailAccount();
+
+  incomingServer = MailServices.accounts
+                    .createIncomingServer(kUserName, "localhost", "pop3");
+  incomingServer.port = POP3_PORT;
+
+  // Check that we haven't got any messages in the folder, if we have its a test
+  // setup issue.
+  do_check_eq(gLocalInboxFolder.getTotalMessages(false), 0);
+
+  actually_run_test();
+}
--- a/mailnews/local/test/unit/xpcshell.ini
+++ b/mailnews/local/test/unit/xpcshell.ini
@@ -14,14 +14,15 @@ tail = tail_local.js
 [test_pop3Duplicates.js]
 [test_pop3GSSAPIFail.js]
 [test_pop3GetNewMail.js]
 [test_pop3Password.js]
 [test_pop3Password2.js]
 [test_pop3Password3.js]
 [test_pop3PasswordFailure.js]
 [test_pop3PasswordFailure2.js]
+[test_pop3PasswordFailure3.js]
 [test_pop3Pump.js]
 [test_pop3ServerBrokenCRAMDisconnect.js]
 [test_pop3ServerBrokenCRAMFail.js]
 [test_preview.js]
 [test_verifyLogon.js]