Fix bug 1006536 - After a (caldav) password change multiple password dialogs are still shown after bug 991723. r=redDragon GECKO2450_2014042411_RELBRANCH
authorPhilipp Kewisch <mozilla@kewis.ch>
Tue, 06 May 2014 16:24:20 +0200
branchGECKO2450_2014042411_RELBRANCH
changeset 16104 372518bc64054961175f8845102d46c01a0c7765
parent 16101 ddb9f31a2bcabd1add27b98d85923ff3dbee6295
child 16106 af50ef7041e6cb587b73928038d576a0c60db5eb
push id56
push usermozilla@kewis.ch
push dateThu, 22 May 2014 15:15:26 +0000
reviewersredDragon
bugs1006536, 991723
Fix bug 1006536 - After a (caldav) password change multiple password dialogs are still shown after bug 991723. r=redDragon
calendar/base/modules/calAuthUtils.jsm
--- a/calendar/base/modules/calAuthUtils.jsm
+++ b/calendar/base/modules/calAuthUtils.jsm
@@ -277,38 +277,80 @@ cal.auth.Prompt.prototype = {
     asyncPromptAuth : function capAPA(aChannel,   // nsIChannel
                                       aCallback,  // nsIAuthPromptCallback
                                       aContext,   // nsISupports
                                       aLevel,     // PRUint32
                                       aAuthInfo   // nsIAuthInformation
                                 ) {
         var self = this;
         let promptlistener = {
-
             onPromptStart: function() {
                 res=self.promptAuth(aChannel, aLevel, aAuthInfo);
 
                 if (res) {
+                    gAuthCache.setAuthInfo(hostKey, aAuthInfo);
                     this.onPromptAuthAvailable();
                     return true;
                 }
 
                 this.onPromptCanceled();
                 return false;
             },
 
             onPromptAuthAvailable : function() {
+                let authInfo = gAuthCache.retrieveAuthInfo(hostKey);
+                if (authInfo) {
+                    aAuthInfo.username = authInfo.username;
+                    aAuthInfo.password = authInfo.password;
+                }
                 aCallback.onAuthAvailable(aContext, aAuthInfo);
             },
 
             onPromptCanceled : function() {
+                gAuthCache.retrieveAuthInfo(hostKey);
                 aCallback.onAuthCancelled(aContext, true);
             }
         };
 
+        let hostKey = aChannel.URI.prePath + ":" + aAuthInfo.realm;
+        gAuthCache.planForAuthInfo(hostKey);
 
-        let hostKey = (aChannel.URI.host + ":" + aChannel.URI.port + " (" + aAuthInfo.realm + ")");
-
-        var asyncprompter = Components.classes["@mozilla.org/messenger/msgAsyncPrompter;1"]
+        let asyncprompter = Components.classes["@mozilla.org/messenger/msgAsyncPrompter;1"]
                                       .getService(Components.interfaces.nsIMsgAsyncPrompter);
         asyncprompter.queueAsyncAuthPrompt(hostKey, false, promptlistener);
     }
 };
+
+// Cache for authentication information since onAuthInformation in the prompt
+// listener is called without further information. If the password is not
+// saved, there is no way to retrieve it. We use ref counting to avoid keeping
+// the password in memory longer than needed.
+let gAuthCache = {
+    _authInfoCache: new Map(),
+    planForAuthInfo: function(hostKey) {
+        let authInfo = this._authInfoCache.get(hostKey);
+        if (authInfo) {
+            authInfo.refCnt++;
+        } else {
+            this._authInfoCache.set(hostKey, { refCnt: 1 });
+        }
+    },
+
+    setAuthInfo: function(hostKey, aAuthInfo) {
+        let authInfo = this._authInfoCache.get(hostKey);
+        if (authInfo) {
+            authInfo.username = aAuthInfo.username;
+            authInfo.password = aAuthInfo.password;
+        }
+    },
+
+    retrieveAuthInfo: function(hostKey) {
+        let authInfo = this._authInfoCache.get(hostKey);
+        if (authInfo) {
+            authInfo.refCnt--;
+
+            if (authInfo.refCnt == 0) {
+                this._authInfoCache.delete(hostKey);
+            }
+        }
+        return authInfo;
+    }
+};