Bug 1282130 - Improve error message for failing ICS import;r=philipp
authormakemyday@gmx-topmail.de
Mon, 19 Sep 2016 11:02:51 +0200
changeset 20109 dce2850d96b9a891bb078367bcf6e07c5cc5d585
parent 20108 b5b7637b26e3806e5f9a624fb04d18db59651f00
child 20110 f8b0b5f8d2ec7a8bcd4ebcf7c0e05054d4ef62f3
push id12322
push usermakemyday@gmx-topmail.de
push dateMon, 19 Sep 2016 09:15:34 +0000
treeherdercomm-central@dce2850d96b9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersphilipp
bugs1282130
Bug 1282130 - Improve error message for failing ICS import;r=philipp
calendar/base/content/import-export.js
calendar/base/src/calIcsParser.js
calendar/libical/src/libical/icalproperty.c
calendar/locales/en-US/chrome/calendar/calendar.properties
--- a/calendar/base/content/import-export.js
+++ b/calendar/base/content/import-export.js
@@ -73,32 +73,41 @@ function loadEventsFromFile(aCalendar) {
         let importer = Components.classes[contractids[filterIndex]]
                                  .getService(Components.interfaces.calIImporter);
 
         const nsIFileInputStream = Components.interfaces.nsIFileInputStream;
 
         let inputStream = Components.classes["@mozilla.org/network/file-input-stream;1"]
                                     .createInstance(nsIFileInputStream);
         let items = [];
+        let exception;
 
         try {
             inputStream.init(picker.file, MODE_RDONLY, parseInt("0444", 8), {});
             items = importer.importFromStream(inputStream, {});
         } catch (ex) {
+            exception = ex;
             switch (ex.result) {
                 case Components.interfaces.calIErrors.INVALID_TIMEZONE:
-                    showError(calGetString("calendar", "timezoneError", [filePath]));
+                    showError(cal.calGetString("calendar", "timezoneError", [filePath]));
                     break;
                 default:
-                    showError(calGetString("calendar", "unableToRead") + filePath + "\n" + ex);
+                    showError(cal.calGetString("calendar", "unableToRead") + filePath + "\n" + ex);
             }
         } finally {
             inputStream.close();
         }
 
+        if (!items.length && !exception) {
+            // the ics did not contain any events, so there's no need to proceed. But we should
+            // notify the user about it, if we haven't before.
+            showError(cal.calGetString("calendar", "noItemsInCalendarFile", [filePath]));
+            return;
+        }
+
         if (aCalendar) {
             putItemsIntoCal(aCalendar, items);
             return;
         }
 
         let calendars = cal.getCalendarManager().getCalendars({});
         calendars = calendars.filter(isCalendarWritable);
 
--- a/calendar/base/src/calIcsParser.js
+++ b/calendar/base/src/calIcsParser.js
@@ -35,18 +35,25 @@ calIcsParser.prototype = {
             if (rootComp.componentType == "VCALENDAR") {
                 calComp = rootComp;
             } else {
                 calComp = rootComp.getFirstSubcomponent("VCALENDAR");
             }
         }
 
         if (!calComp) {
-            cal.ERROR("Parser Error. Could not find 'VCALENDAR' component: \n" +
-                      rootComp + "\nStack: \n" + cal.STACK(10));
+            let message = "Parser Error. Could not find 'VCALENDAR' component.\n";
+            try {
+                // we try to also provide the parsed component - if that fails due to an error in
+                // libical, we append the error message of the caught exception, which includes
+                // already a stack trace.
+                cal.ERROR(message + rootComp + "\n" + cal.STACK(10));
+            } catch(e) {
+                cal.ERROR(message + e);
+            }
         }
 
         let self = this;
         let state = new parserState(this, aAsyncParsing);
 
         while (calComp) {
             // Get unknown properties from the VCALENDAR
             for (let prop of cal.ical.propertyIterator(calComp)) {
--- a/calendar/libical/src/libical/icalproperty.c
+++ b/calendar/libical/src/libical/icalproperty.c
@@ -129,20 +129,22 @@ icalproperty_new (icalproperty_kind kind
 
     return (icalproperty*)icalproperty_new_impl(kind);
 }
 
 
 icalproperty*
 icalproperty_new_clone(icalproperty* old)
 {
-    icalproperty *new = icalproperty_new_impl(old->kind);
+    icalproperty *new;
     pvl_elem p;
 
     icalerror_check_arg_rz((old!=0),"old");
+
+    new = icalproperty_new_impl(old->kind);
     icalerror_check_arg_rz((new!=0),"new");
 
     if (old->value !=0) {
 	new->value = icalvalue_new_clone(old->value);
     }
 
     if (old->x_name != 0) {
 
--- a/calendar/locales/en-US/chrome/calendar/calendar.properties
+++ b/calendar/locales/en-US/chrome/calendar/calendar.properties
@@ -52,16 +52,19 @@ lowPriority=Low
 importPrompt=Which calendar do you want to import these items into?
 exportPrompt=Which calendar do you want to export from?
 publishPrompt=Which calendar do you want to publish?
 
 # LOCALIZATION NOTE (importItemsFailed):
 #    %1$S will be replaced with number of failed items
 #    %2$S will be replaced with last error code / error string
 importItemsFailed=%1$S items failed to import. The last error was: %2$S
+# LOCALIZATION NOTE (noItemsInCalendarFile):
+#    %1$S will be replaced with file path
+noItemsInCalendarFile=Failed to import from %1$S. There are no importable items in this file.
 
 #spaces needed at the end of the following lines
 eventDescription=Description:
 
 unableToRead=Unable to read from file:
 unableToWrite=Unable to write to file:
 defaultFileName=MozillaCalEvents
 HTMLTitle=Mozilla Calendar