Bug 678930 - ICS calendar fails when connection temporarily unavailable. r=philipp, a=philipp
authorMatthew Mecca <matthew.mecca@gmail.com>
Sun, 25 Sep 2011 22:00:39 -0400
changeset 8862 b8bad8be49ca280f7e09f483ef4214628519752e
parent 8861 d4c1eff7a5e10bbedb4ca880f22c98919baab83d
child 8863 61e68359839bfa19501ba0ef827cfc6dccf4106a
push idunknown
push userunknown
push dateunknown
reviewersphilipp, philipp
bugs678930
Bug 678930 - ICS calendar fails when connection temporarily unavailable. r=philipp, a=philipp
calendar/providers/ics/calICSCalendar.js
--- a/calendar/providers/ics/calICSCalendar.js
+++ b/calendar/providers/ics/calICSCalendar.js
@@ -211,35 +211,44 @@ calICSCalendar.prototype = {
         // Lock other changes to the item list.
         this.lock();
 
         try {
             streamLoader.init(this);
             channel.asyncOpen(streamLoader, prbForce);
         } catch(e) {
             // File not found: a new calendar. No problem.
+            cal.LOG("[calICSCalendar] Error occurred opening channel: " + e);
             this.unlock();
         }
     },
 
     // nsIChannelEventSink implementation
     asyncOnChannelRedirect: function(aOldChannel, aNewChannel, aFlags, aCallback) {
         this.prepareChannel(aNewChannel, true);
         aCallback.onRedirectVerifyCallback(Components.results.NS_OK);
     },
 
     // nsIStreamLoaderObserver impl
     // Listener for download. Parse the downloaded file
 
     onStreamComplete: function(loader, ctxt, status, resultLength, result)
     {
         let forceRefresh = ctxt.QueryInterface(Components.interfaces.nsISupportsPRBool).data;
+        let cont = false;
 
-        // Allow the hook to get needed data (like an etag) of the channel
-        let cont = this.mHooks.onAfterGet(forceRefresh);
+        if (Components.isSuccessCode(status)) {
+            // Allow the hook to get needed data (like an etag) of the channel
+            cont = this.mHooks.onAfterGet(forceRefresh);
+        } else {
+            // Failure may be due to temporary connection issue, keep old data to
+            // prevent potential data loss if it becomes available again.
+            cal.LOG("[calICSCalendar] Unable to load stream - status: " + status);
+        }
+
         if (!cont) {
             // no need to process further, we can use the previous data
             this.unlock();
             return;
         }
 
          // Clear any existing events if there was no result
         if (!resultLength) {
@@ -908,35 +917,48 @@ httpHooks.prototype = {
             var httpchannel = aChannel.QueryInterface(Components.interfaces.nsIHttpChannel);
             // Somehow the webdav header 'If' doesn't work on apache when
             // passing in a Not, so use the http version here.
             httpchannel.setRequestHeader("If-None-Match", this.mEtag, false);
         }
 
         return true;
     },
-    
+
     onAfterGet: function(aForceRefresh) {
-        var httpchannel = this.mChannel.QueryInterface(Components.interfaces.nsIHttpChannel);
+        let httpchannel = this.mChannel.QueryInterface(Components.interfaces.nsIHttpChannel);
+        let responseStatus = 0;
 
-        switch (httpchannel.responseStatus) {
+        try {
+            responseStatus = httpchannel.responseStatus;
+        } catch(e) {
+            // Error might have been a temporary connection issue, keep old data to
+            // prevent potential data loss if it becomes available again.
+            cal.LOG("[calICSCalendar] Unable to get response status.");
+            return false;
+        }
+
+        switch (responseStatus) {
             case 304:
                 // 304: Not Modified
                 // Can use the old data, so tell the caller that it can skip parsing.
+                cal.LOG("[calICSCalendar] Response status 304: Not Modified. Using the existing data.");
                 return false;
             case 404:
                 // 404: Not Found
                 // This is a new calendar. Shouldn't try to parse it. But it also
                 // isn't a failure, so don't throw.
+                cal.LOG("[calICSCalendar] Response status 404: Not Found. This is a new calendar.");
                 return false;
 
             case 401:
             case 403:
                 // 401/403: Not Authorized
                 // The user likely cancelled the login dialog.
+                cal.LOG("[calICSCalendar] Response status 401/403: Not Authorized. Login dialog cancelled.");
                 this.mCalendar.setProperty("disabled", "true");
                 this.mCalendar.setProperty("auto-enabled", "true");
                 return false;
         }
 
         try {
             this.mEtag = httpchannel.getResponseHeader("ETag");
         } catch(e) {
@@ -952,17 +974,17 @@ httpHooks.prototype = {
             var httpchannel = aChannel.QueryInterface(Components.interfaces.nsIHttpChannel);
 
             // Apache doesn't work correctly with if-match on a PUT method,
             // so use the webdav header
             httpchannel.setRequestHeader("If", '(['+this.mEtag+'])', false);
         }
         return true;
     },
-    
+
     onAfterPut: function(aChannel, aRespFunc) {
         var httpchannel = aChannel.QueryInterface(Components.interfaces.nsIHttpChannel);
         try {
             this.mEtag = httpchannel.getResponseHeader("ETag");
             aRespFunc();
         } catch(e) {
             // There was no ETag header on the response. This means that
             // putting is not atomic. This is bad. Race conditions can happen,