Fix bug 1189109 - Errors in import of .ics file: "Component does not have requested interface [calIOperationListener.onOperationComplete]" nsresult: "0x80004002 (NS_NOINTERFACE)". r=redDragon
authorPhilipp Kewisch <mozilla@kewis.ch>
Sat, 08 Aug 2015 12:38:57 +0100
changeset 18282 a5636e8549a4eda92ee30a7e08445267512ca9c3
parent 18281 f5e8bee91fc8b2a4a4146bb5b6b24f44ba11decd
child 18283 e6c5bce2b8fb6859970e1197ca0027a251693dc1
push id11222
push usermozilla@kewis.ch
push dateTue, 25 Aug 2015 09:07:01 +0000
treeherdercomm-central@e6c5bce2b8fb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersredDragon
bugs1189109
Fix bug 1189109 - Errors in import of .ics file: "Component does not have requested interface [calIOperationListener.onOperationComplete]" nsresult: "0x80004002 (NS_NOINTERFACE)". r=redDragon
calendar/base/content/agenda-listbox.js
calendar/base/content/calendar-base-view.xml
calendar/base/content/calendar-invitations-manager.js
calendar/base/content/calendar-task-tree.xml
calendar/base/content/calendar-unifinder.js
calendar/base/content/calendar-views.js
calendar/base/content/dialogs/calendar-event-dialog.js
calendar/base/content/dialogs/calendar-invitations-dialog.js
calendar/base/content/dialogs/calendar-print-dialog.js
calendar/base/content/import-export.js
calendar/base/modules/calAsyncUtils.jsm
calendar/base/modules/calItipUtils.jsm
calendar/base/src/calAlarmService.js
calendar/base/src/calCachedCalendar.js
calendar/base/src/calFilter.js
calendar/lightning/content/imip-bar.js
calendar/lightning/content/messenger-overlay-sidebar.js
calendar/providers/caldav/calDavCalendar.js
calendar/providers/gdata/modules/shim/Calendar.jsm
calendar/providers/ics/calICSCalendar.js
calendar/providers/storage/calStorageCalendar.js
calendar/providers/wcap/calWcapCalendarItems.js
calendar/resources/content/publish.js
--- a/calendar/base/content/agenda-listbox.js
+++ b/calendar/base/content/agenda-listbox.js
@@ -1,14 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 Components.utils.import("resource://gre/modules/Services.jsm");
 Components.utils.import("resource://gre/modules/Preferences.jsm");
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 function Synthetic(aOpen, aDuration) {
     this.open = aOpen;
     this.duration = aDuration;
 }
 
 var agendaListbox = {
     agendaListboxControl: null,
@@ -614,16 +615,17 @@ function setupContextMenu(popup) {
  * @param aStart        (optional) The start date for the item query.
  * @param aEnd          (optional) The end date for the item query.
  * @param aCalendar     (optional) If specified, the single calendar from
  *                                   which the refresh will occur.
  */
 agendaListbox.refreshCalendarQuery =
 function refreshCalendarQuery(aStart, aEnd, aCalendar) {
     let refreshJob = {
+        QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
         agendaListbox: this,
         calendar: null,
         calId: null,
         operation: null,
         cancelled: false,
 
         onOperationComplete: function(aCalendar, aStatus, aOperationType, aId, aDateTime) {
             if (this.agendaListbox.mPendingRefreshJobs.has(this.calId)) {
--- a/calendar/base/content/calendar-base-view.xml
+++ b/calendar/base/content/calendar-base-view.xml
@@ -448,16 +448,17 @@
           this.addItemsFromCalendar(this.mCalendar);
         ]]></body>
       </method>
 
       <method name="addItemsFromCalendar">
         <parameter name="aCalendar"/>
         <body><![CDATA[
           let refreshJob = {
+              QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
               calView: this,
               calendar: null,
               calId: null,
               operation: null,
               cancelled: false,
 
               onOperationComplete: function(aCalendar, aStatus, aOperationType, aId, aDateTime) {
                   this.calView.mLog.info("Refresh complete of calendar " + this.calId);
--- a/calendar/base/content/calendar-invitations-manager.js
+++ b/calendar/base/content/calendar-invitations-manager.js
@@ -1,15 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 Components.utils.import("resource://calendar/modules/calUtils.jsm");
 Components.utils.import("resource://calendar/modules/calItipUtils.jsm");
 Components.utils.import("resource://gre/modules/Preferences.jsm");
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 /**
  * This object contains functions to take care of manipulating requests.
  */
 var gInvitationsRequestManager = {
     mRequestStatusList: {},
 
     /**
@@ -125,16 +126,17 @@ InvitationsManager.prototype = {
 
         gInvitationsRequestManager.cancelPendingRequests();
         this.updateStartDate();
         this.deleteAllItems();
 
         var cals = getCalendarManager().getCalendars({});
 
         var opListener = {
+            QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             mCount: cals.length,
             mRequestManager: gInvitationsRequestManager,
             mInvitationsManager: this,
             mHandledItems: {},
 
             // calIOperationListener
             onOperationComplete: function(aCalendar,
                                           aStatus,
@@ -266,16 +268,17 @@ InvitationsManager.prototype = {
                                                  jobQueueFinishedCallBack) {
         // TODO: undo/redo
         function operationListener(mgr, queueCallback, oldItem_) {
             this.mInvitationsManager = mgr;
             this.mJobQueueFinishedCallBack = queueCallback;
             this.mOldItem = oldItem_;
         }
         operationListener.prototype = {
+            QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             onOperationComplete: function (aCalendar,
                                            aStatus,
                                            aOperationType,
                                            aId,
                                            aDetail) {
                 if (Components.isSuccessCode(aStatus) &&
                     aOperationType == Components.interfaces.calIOperationListener.MODIFY) {
                     cal.itip.checkAndSend(aOperationType, aDetail, this.mOldItem);
--- a/calendar/base/content/calendar-task-tree.xml
+++ b/calendar/base/content/calendar-task-tree.xml
@@ -912,16 +912,17 @@
 
         ]]></body>
       </method>
 
       <method name="refreshFromCalendar">
         <parameter name="aCalendar"/>
         <body><![CDATA[
           let refreshJob = {
+              QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
               binding: this,
               calendar: null,
               items: null,
               operation: null,
 
               onOperationComplete: function(aCalendar, aStatus, aOperationType, aId, aDateTime) {
                   if (aCalendar.id in this.binding.mPendingRefreshJobs) {
                       delete this.binding.mPendingRefreshJobs[aCalendar.id];
--- a/calendar/base/content/calendar-unifinder.js
+++ b/calendar/base/content/calendar-unifinder.js
@@ -874,16 +874,17 @@ function addItemsFromSingleCalendarInter
 
 function addItemsFromCalendar(aCalendar, aAddItemsInternalFunc) {
     if (isUnifinderHidden()) {
         // If the unifinder is hidden, don't refresh the events to reduce needed
         // getItems calls.
         return;
     }
     var refreshListener = {
+        QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
         mEventArray: [],
 
         onOperationComplete: function rET_onOperationComplete(aCalendar,
                                                               aStatus,
                                                               aOperationType,
                                                               aId,
                                                               aDateTime) {
             var refreshTreeInternalFunc = function() {
--- a/calendar/base/content/calendar-views.js
+++ b/calendar/base/content/calendar-views.js
@@ -627,16 +627,17 @@ function editSelectedEvents() {
 }
 
 /**
  * Select all events from all calendars. Use with care.
  */
 function selectAllEvents() {
     var items = [];
     var listener = {
+        QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
         onOperationComplete: function selectAll_ooc(aCalendar, aStatus,
                                                     aOperationType, aId,
                                                     aDetail) {
             currentView().setSelectedItems(items.length, items, false);
         },
         onGetResult: function selectAll_ogr(aCalendar, aStatus, aItemType,
                                             aDetail, aCount, aItems) {
             for each (var item in aItems) {
--- a/calendar/base/content/dialogs/calendar-event-dialog.js
+++ b/calendar/base/content/dialogs/calendar-event-dialog.js
@@ -3,16 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 Components.utils.import("resource://calendar/modules/calUtils.jsm");
 Components.utils.import("resource://gre/modules/Services.jsm");
 Components.utils.import("resource://calendar/modules/calRecurrenceUtils.jsm");
 Components.utils.import("resource:///modules/mailServices.js");
 Components.utils.import("resource://gre/modules/PluralForm.jsm");
 Components.utils.import("resource://gre/modules/Preferences.jsm");
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 try {
     Components.utils.import("resource:///modules/cloudFileAccounts.js");
 } catch (e) {
     // This will fail on Seamonkey, but thats ok since the pref for cloudfiles
     // is false, which means the UI will not be shown
 }
 
@@ -2879,16 +2880,17 @@ function onCommandSave(aIsClosing) {
     // When the call is complete, we need to set the new item, so that the
     // dialog is up to date.
 
     // XXX Do we want to disable the dialog or at least the save button until
     // the call is complete? This might help when the user tries to save twice
     // before the call is complete. In that case, we do need a progress bar and
     // the ability to cancel the operation though.
     var listener = {
+        QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
         onOperationComplete: function(aCalendar, aStatus, aOpType, aId, aItem) {
             // Check if the current window has a calendarItem first, because in case of undo
             // window refers to the main window and we would get a 'calendarItem is undefined' warning.
             if ("calendarItem" in window) {
                 // If we changed the calendar of the item, onOperationComplete will be called multiple
                 // times. We need to make sure we're receiving the update on the right calendar.
                 if ((!window.calendarItem.id ||aId == window.calendarItem.id) &&
                     (aCalendar.id == window.calendarItem.calendar.id) &&
@@ -2906,17 +2908,18 @@ function onCommandSave(aIsClosing) {
                     }
 
                     // We now have an item, so we must change to an edit.
                     window.mode = "modify";
                     updateTitle();
                     eventDialogCalendarObserver.observe(window.calendarItem.calendar);
                 }
             }
-        }
+        },
+        onGetResult: function() {}
     };
 
     // Let the caller decide how to handle the modified/added item. Only pass
     // the above item if we are not closing, otherwise the listener will be
     // missing its window afterwards.
     window.onAcceptCallback(item, calendar, originalItem, !aIsClosing && listener);
 
 }
--- a/calendar/base/content/dialogs/calendar-invitations-dialog.js
+++ b/calendar/base/content/dialogs/calendar-invitations-dialog.js
@@ -1,21 +1,23 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 Components.utils.import("resource://calendar/modules/calUtils.jsm");
 Components.utils.import("resource://calendar/modules/calAlarmUtils.jsm");
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 /**
  * Sets up the invitations dialog from the window arguments, retrieves the
  * invitations from the invitations manager.
  */
 function onLoad() {
     var operationListener = {
+        QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
         onOperationComplete: function oL_onOperationComplete(aCalendar,
                                                              aStatus,
                                                              aOperationType,
                                                              aId,
                                                              aDetail) {
             var updatingBox = document.getElementById("updating-box");
             updatingBox.setAttribute("hidden", "true");
             var richListBox = document.getElementById("invitations-listbox");
--- a/calendar/base/content/dialogs/calendar-print-dialog.js
+++ b/calendar/base/content/dialogs/calendar-print-dialog.js
@@ -1,13 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 Components.utils.import("resource://calendar/modules/calUtils.jsm");
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 /**
  * Gets the calendar view from the opening window
  */
 function getCalendarView() {
     let theView = window.opener.currentView();
     if (!theView.startDay) {
         theView = null;
@@ -126,16 +127,17 @@ function getPrintSettings(receiverFunc) 
     default:
         dump("Error : no case in printDialog.js::printCalendar()");
     }
 
     // Some filters above might have filled the events list themselves. If not,
     // then fetch the items here.
     if (requiresFetch) {
         let listener = {
+            QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             onOperationComplete:
             function onOperationComplete(aCalendar, aStatus, aOperationType, aId, aDateTime) {
                 receiverFunc(settings);
             },
             onGetResult:
             function onGetResult(aCalendar, aStatus, aItemType, aDetail, aCount, aItems) {
                 settings.eventList = settings.eventList.concat(aItems);
                 if (!settings.printTasksWithNoDueDate) {
--- a/calendar/base/content/import-export.js
+++ b/calendar/base/content/import-export.js
@@ -1,12 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
 // File constants copied from file-utils.js
 const MODE_RDONLY   = 0x01;
 const MODE_WRONLY   = 0x02;
 const MODE_RDWR     = 0x04;
 const MODE_CREATE   = 0x08;
 const MODE_APPEND   = 0x10;
 const MODE_TRUNCATE = 0x20;
 const MODE_SYNC     = 0x40;
@@ -147,16 +149,17 @@ function putItemsIntoCal(destCal, aItems
     var duplicateCount = 0;
     // Used to store the last error. Only the last error, because we don't
     // wan't to bomb the user with thousands of error messages in case
     // something went really wrong.
     // (example of something very wrong: importing the same file twice.
     //  quite easy to trigger, so we really should do this)
     var lastError;
     var listener = {
+        QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
         onOperationComplete: function(aCalendar, aStatus, aOperationType, aId, aDetail) {
             count++;
             if (!Components.isSuccessCode(aStatus)) {
                 if (aStatus == Components.interfaces.calIErrors.DUPLICATE_ID) {
                     duplicateCount++;
                 } else {
                     failedCount++;
                     lastError = aStatus;
@@ -313,16 +316,17 @@ function saveEventsToFile(calendarEventA
  * Exports all the events and tasks in a calendar.  If aCalendar is not specified,
  * the user will be prompted with a list of calendars to choose which one to export.
  *
  * @param aCalendar     (optional) A specific calendar to export
  */
 function exportEntireCalendar(aCalendar) {
     var itemArray = [];
     var getListener = {
+        QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
         onOperationComplete: function(aCalendar, aStatus, aOperationType, aId, aDetail)
         {
             saveEventsToFile(itemArray, aCalendar.name);
         },
         onGetResult: function(aCalendar, aStatus, aItemType, aDetail, aCount, aItems)
         {
             for each (let item in aItems) {
                 itemArray.push(item);
--- a/calendar/base/modules/calAsyncUtils.jsm
+++ b/calendar/base/modules/calAsyncUtils.jsm
@@ -1,15 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 Components.utils.import("resource://calendar/modules/calUtils.jsm");
 Components.utils.import("resource://gre/modules/Promise.jsm");
 Components.utils.import("resource://gre/modules/PromiseUtils.jsm");
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 /*
  * Asynchronous tools for handling calendar operations.
  */
 
 this.EXPORTED_SYMBOLS = ["cal"]; // even though it's defined in calUtils.jsm, import needs this
 const cIOL = Components.interfaces.calIOperationListener;
 const cIC = Components.interfaces.calICalendar;
@@ -87,16 +88,17 @@ cal.async = {
      * See also promisifyCalendar, where the above can be replaced with:
      *   function promiseAddItem(aItem) {
      *     let calendar = cal.async.promisifyCalendar(aItem.calendar);
      *     return calendar.addItem(aItem);
      *   }
      */
     promiseOperationListener: function(deferred) {
         return {
+            QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             items: [],
             itemStatus: Components.results.NS_OK,
             onGetResult: function(aCalendar, aStatus, aItemType, aDetail,
                                   aCount, aItems) {
                 this.itemStatus = aStatus;
                 if (Components.isSuccessCode(aStatus)) {
                     this.items = this.items.concat(aItems);
                 } else {
--- a/calendar/base/modules/calItipUtils.jsm
+++ b/calendar/base/modules/calItipUtils.jsm
@@ -1038,16 +1038,17 @@ function sendMessage(aItem, aMethod, aRe
  * @param opListener operation listener to forward
  * @param oldItem the previous item before modification (if any)
  */
 function ItipOpListener(opListener, oldItem) {
     this.mOpListener = opListener;
     this.mOldItem = oldItem;
 }
 ItipOpListener.prototype = {
+    QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
     onOperationComplete: function ItipOpListener_onOperationComplete(aCalendar,
                                                                      aStatus,
                                                                      aOperationType,
                                                                      aId,
                                                                      aDetail) {
         cal.ASSERT(Components.isSuccessCode(aStatus), "error on iTIP processing");
         if (Components.isSuccessCode(aStatus)) {
             cal.itip.checkAndSend(aOperationType, aDetail, this.mOldItem);
--- a/calendar/base/src/calAlarmService.js
+++ b/calendar/base/src/calAlarmService.js
@@ -476,16 +476,17 @@ calAlarmService.prototype = {
                 }
                 delete this.mTimerMap[calendar.id]
             }
         }
     },
 
     findAlarms: function cAS_findAlarms(aCalendars, aStart, aUntil) {
         let getListener = {
+            QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             alarmService: this,
             addRemovePromise: PromiseUtils.defer(),
             onOperationComplete: function cAS_fA_onOperationComplete(aCalendar,
                                                                      aStatus,
                                                                      aOperationType,
                                                                      aId,
                                                                      aDetail) {
                 this.addRemovePromise.promise.then((aValue) => {
--- a/calendar/base/src/calCachedCalendar.js
+++ b/calendar/base/src/calCachedCalendar.js
@@ -7,16 +7,17 @@ Components.utils.import("resource://gre/
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 Components.utils.import("resource://gre/modules/Preferences.jsm");
 
 const calICalendar = Components.interfaces.calICalendar;
 const cICL = Components.interfaces.calIChangeLog;
 const cIOL = Components.interfaces.calIOperationListener;
 
 let gNoOpListener = {
+    QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
     onGetResult: function(calendar, status, itemType, detail, count, items) {
     },
 
     onOperationComplete: function(calendar, status, opType, id, detail) {
     }
 };
 
 /**
@@ -50,16 +51,17 @@ function isUnavailableCode(result) {
     }
 }
 
 function calCachedCalendarObserverHelper(home, isCachedObserver) {
     this.home = home;
     this.isCachedObserver = isCachedObserver;
 }
 calCachedCalendarObserverHelper.prototype = {
+    QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIObserver]),
     isCachedObserver: false,
 
     onStartBatch: function() {
         this.home.mObservers.notify("onStartBatch");
     },
 
     onEndBatch: function() {
         this.home.mObservers.notify("onEndBatch");
@@ -219,16 +221,17 @@ calCachedCalendar.prototype = {
             Components.utils.reportError(exc);
         }
     },
 
     getOfflineAddedItems: function cCC_getOfflineAddedItems(callbackFunc) {
         let this_ = this;
         this_.offlineCachedItems = {};
         let getListener = {
+            QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             onGetResult: function cCC_oOC_cL_onGetResult(aCalendar, aStatus, aItemType, aDetail, aCount, aItems) {
                 for each (let item in aItems) {
                     this_.offlineCachedItems[item.hashId] = item;
                     this_.offlineCachedItemFlags[item.hashId] = cICL.OFFLINE_FLAG_CREATED_RECORD;
                 }
             },
 
             onOperationComplete: function cCC_oOC_cL_onOperationComplete(aCalendar, aStatus, aOpType, aId, aDetail) {
@@ -237,16 +240,17 @@ calCachedCalendar.prototype = {
         };
         this.mCachedCalendar.getItems(calICalendar.ITEM_FILTER_ALL_ITEMS | calICalendar.ITEM_FILTER_OFFLINE_CREATED,
                                       0, null, null, getListener);
     },
 
     getOfflineModifiedItems: function cCC_getOfflineModifiedItems(callbackFunc) {
         let this_ = this;
         let getListener = {
+            QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             onGetResult: function cCC_oOC_cL_onGetResult(aCalendar, aStatus, aItemType, aDetail, aCount, aItems) {
                 for each (let item in aItems) {
                     this_.offlineCachedItems[item.hashId] = item;
                     this_.offlineCachedItemFlags[item.hashId] = cICL.OFFLINE_FLAG_MODIFIED_RECORD;
                 }
             },
 
             onOperationComplete: function cCC_oOC_cL_onOperationComplete(aCalendar, aStatus, aOpType, aId, aDetail) {
@@ -255,16 +259,17 @@ calCachedCalendar.prototype = {
         };
         this.mCachedCalendar.getItems(calICalendar.ITEM_FILTER_OFFLINE_MODIFIED | calICalendar.ITEM_FILTER_ALL_ITEMS,
                                       0, null, null, getListener);
     },
 
     getOfflineDeletedItems: function cCC_getOfflineDeletedItems(callbackFunc) {
         let this_ = this;
         let getListener = {
+            QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             onGetResult: function cCC_oOC_cL_onGetResult(aCalendar, aStatus, aItemType, aDetail, aCount, aItems) {
                 for each (let item in aItems) {
                     this_.offlineCachedItems[item.hashId] = item;
                     this_.offlineCachedItemFlags[item.hashId] = cICL.OFFLINE_FLAG_DELETED_RECORD;
                 }
             },
 
             onOperationComplete: function cCC_oOC_cL_onOperationComplete(aCalendar, aStatus, aOpType, aId, aDetail) {
@@ -330,16 +335,17 @@ calCachedCalendar.prototype = {
                 }
             };
             this.mPendingSync = this.mUncachedCalendar.replayChangesOn(opListener);
             return this.mPendingSync;
         }
 
         cal.LOG("[calCachedCalendar] Doing full sync for calendar " + this.uri.spec);
         let completeListener = {
+            QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             modifiedTimes: {},
             hasRenewedCalendar: false,
             getsCompleted: 0,
             getsReceived: 0,
             opCompleted: false,
 
             onGetResult: function cCC_oOC_cL_onGetResult(aCalendar,
                                                          aStatus,
--- a/calendar/base/src/calFilter.js
+++ b/calendar/base/src/calFilter.js
@@ -1,13 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 Components.utils.import("resource://gre/modules/Preferences.jsm");
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 Components.utils.import("resource://calendar/modules/calUtils.jsm");
 
 /**
  * Object that contains a set of filter properties that may be used by a calFilter object
  * to filter a set of items.
  * Supported filter properties:
  *   start, end:   Specifies the relative date range to use when calculating the filter date
  *               range. The relative date range may relative to the current date and time, the
@@ -860,16 +861,17 @@ calFilter.prototype = {
         }
         let props = this.mFilterProperties;
 
         // we use a local proxy listener for the calICalendar.getItems() call, and use it
         // to handle occurrence expansion and filter the results before forwarding them to
         // the listener passed in the aListener argument.
         let self = this;
         let listener = {
+            QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             onOperationComplete: aListener.onOperationComplete.bind(aListener),
 
             onGetResult: function(aCalendar, aStatus, aItemType, aDetail, aCount, aItems) {
                 let items;
                 if (props.occurrences == props.FILTER_OCCURRENCES_PAST_AND_NEXT) {
                     // with the FILTER_OCCURRENCES_PAST_AND_NEXT occurrence filter we will
                     // get parent items returned here, so we need to let the getOccurrences
                     // function handle occurrence expansion.
--- a/calendar/lightning/content/imip-bar.js
+++ b/calendar/lightning/content/imip-bar.js
@@ -2,16 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 Components.utils.import("resource://calendar/modules/calUtils.jsm");
 Components.utils.import("resource://calendar/modules/calItipUtils.jsm");
 Components.utils.import("resource://calendar/modules/calXMLUtils.jsm");
 Components.utils.import("resource://calendar/modules/ltnInvitationUtils.jsm");
 Components.utils.import("resource://gre/modules/Preferences.jsm");
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 /**
  * This bar lives inside the message window.
  * Its lifetime is the lifetime of the main thunderbird message window.
  */
 var ltnImipBar = {
 
     actionFunc: null,
@@ -244,16 +245,17 @@ var ltnImipBar = {
                     partstat = "";
                 }
                 // hide the buttons now, to disable pressing them twice...
                 if(aPartStat == partStat) {
                     ltnImipBar.resetButtons();
                 }
 
                 let opListener = {
+                    QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
                     onOperationComplete: function ltnItipActionListener_onOperationComplete(aCalendar,
                                                                                             aStatus,
                                                                                             aOperationType,
                                                                                             aId,
                                                                                             aDetail) {
                         // For now, we just state the status for the user something very simple
                         let imipBar = document.getElementById("imip-bar");
                         let label = cal.itip.getCompleteText(aStatus, aOperationType);
--- a/calendar/lightning/content/messenger-overlay-sidebar.js
+++ b/calendar/lightning/content/messenger-overlay-sidebar.js
@@ -433,16 +433,17 @@ function ltnFinish() {
 const FIRST_DELAY_STARTUP = 100;
 const FIRST_DELAY_RESCHEDULE = 100;
 const FIRST_DELAY_REGISTER = 10000;
 const FIRST_DELAY_UNREGISTER = 0;
 
 var gInvitationsOperationListener = {
     mCount: 0,
 
+    QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
     onOperationComplete: function sBOL_onOperationComplete(aCalendar,
                                                            aStatus,
                                                            aOperationType,
                                                            aId,
                                                            aDetail) {
         let invitationsBox = document.getElementById("calendar-invitations-panel");
         if (Components.isSuccessCode(aStatus)) {
             let value = ltnGetString("lightning", "invitationsLink.label", [this.mCount]);
--- a/calendar/providers/caldav/calDavCalendar.js
+++ b/calendar/providers/caldav/calDavCalendar.js
@@ -254,16 +254,17 @@ calDavCalendar.prototype = {
     /**
      * Ensure that cached items have associated meta data, otherwise server side
      * changes may not be reflected
      */
     ensureMetaData: function caldav_ensureMetaData() {
         let self = this;
         let refreshNeeded = false;
         let getMetaListener = {
+            QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             onGetResult: function meta_onGetResult(aCalendar, aStatus, aItemType, aDetail, aCount, aItems) {
                 for each (let item in aItems) {
                     if (!(item.id in self.mItemInfoCache)) {
                         let path = self.getItemLocationPath(item);
                         cal.LOG("Adding meta-data for cached item " + item.id);
                         self.mItemInfoCache[item.id] = { etag: null,
                                                          isNew: false,
                                                          locationPath: path,
@@ -1324,16 +1325,17 @@ calDavCalendar.prototype = {
             if (this.isCached && aChangeLogListener) {
                 aChangeLogListener.onResult({ status: status }, status);
             }
         };
 
         if (!this.mACLEntry) {
             let thisCalendar = this;
             let opListener = {
+                QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
                 onGetResult: function(calendar, status, itemType, detail, count, items) {
                     ASSERT(false, "unexpected!");
                 },
                 onOperationComplete: function(opCalendar, opStatus, opType, opId, opDetail) {
                     thisCalendar.mACLEntry = opDetail;
                     thisCalendar.fillACLProperties();
                     thisCalendar.safeRefresh(aChangeLogListener);
                 }
@@ -2629,16 +2631,17 @@ calDavCalendar.prototype = {
     //
 
     processItipReply: function caldav_processItipReply(aItem, aPath) {
         // modify partstat for in-calendar item
         // delete item from inbox
         var thisCalendar = this;
 
         var getItemListener = {};
+        getItemListener.QueryInterface = XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
         getItemListener.onOperationComplete = function caldav_gUIs_oOC(aCalendar,
                                                                        aStatus,
                                                                        aOperationType,
                                                                        aId,
                                                                        aDetail) {
         };
         getItemListener.onGetResult = function caldav_pIR_oGR(aCalendar,
                                                               aStatus,
@@ -2661,16 +2664,17 @@ calDavCalendar.prototype = {
                     newItem.addAttendee(att);
                 }
             }
             thisCalendar.doModifyItem(newItem, itemToUpdate.parentItem /* related to bug 396182 */,
                                       modListener, true);
         };
 
         var modListener = {};
+        modListener.QueryInterface = XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
         modListener.onOperationComplete = function caldav_pIR_moOC(aCalendar,
                                                                    aStatus,
                                                                    aOperationType,
                                                                    aItemId,
                                                                    aDetail) {
             cal.LOG("CalDAV: status " + aStatus + " while processing iTIP REPLY " +
                     " for " + thisCalendar.name);
             // don't delete the REPLY item from inbox unless modifying the master
--- a/calendar/providers/gdata/modules/shim/Calendar.jsm
+++ b/calendar/providers/gdata/modules/shim/Calendar.jsm
@@ -2,16 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 var EXPORTED_SYMBOLS = ["calendarShim", "gdataRegisterCalendar", "promisifyCalendar"];
 
 Components.utils.import("resource://gdata-provider/modules/shim/Loader.jsm");
 CuImport("resource://calendar/modules/calUtils.jsm", this);
 CuImport("resource://gre/modules/PromiseUtils.jsm", this);
+CuImport("resource://gre/modules/XPCOMUtils.jsm", this);
 
 const cIOL = Components.interfaces.calIOperationListener;
 const cICL = Components.interfaces.calIChangeLog;
 const cIC = Components.interfaces.calICalendar;
 
 /**
  * Shim functions that can be injected into an object implementing calICalendar
  * to make it compatible with older versions of Lightning
@@ -20,28 +21,30 @@ var calendarShim = {
     addItemOrUseCache: function(aItem, useCache, aListener) {
         let newItem = aItem.clone();
         return this.adoptItemOrUseCache(newItem, useCache, aListener);
     },
 
     adoptItemOrUseCache: function(aItem, useCache, aListener) {
         let self = this;
         let addOfflineListener = {
+            QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             onGetResult: function() {},
             onOperationComplete: function(calendar, status, opType, id, detail) {
                 if (Components.isSuccessCode(status)) {
                     let storage = self.mOfflineStorage.QueryInterface(Components.interfaces.calIOfflineStorage);
                     storage.addOfflineItem(detail, aListener);
                 } else if (aListener) {
                     aListener.onOperationComplete(self, status, opType, id, detail);
                 }
             }
         };
 
         let intermediateListener = {
+            QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             onGetResult: function() {},
             onOperationComplete: function(aCalendar, aStatus, aOp, aId, aInnerItem) {
                 if (useCache) {
                     if (isUnavailableCode(aStatus)) {
                         self.mOfflineStorage.adoptItem(aInnerItem, addOfflineListener);
                     } else {
                         self.mOfflineStorage.addItem(aInnerItem, aListener);
                     }
@@ -53,23 +56,25 @@ var calendarShim = {
 
         return this.adoptItem(aItem, intermediateListener);
     },
 
     modifyItemOrUseCache: function modifyItemOrUseCache(aNewItem, aOldItem, useCache, aListener) {
         let self = this;
         let storage = this.mOfflineStorage.QueryInterface(Components.interfaces.calIOfflineStorage);
         let modifyOfflineListener = {
+            QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             onGetResult: function(calendar, status, itemType, detail, count, items) {},
             onOperationComplete: function(calendar, status, opType, id, detail) {
                 storage.modifyOfflineItem(detail, aListener);
             }
         };
 
         let offlineFlagListener = {
+            QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             onGetResult: function(calendar, status, itemType, detail, count, items) {},
             onOperationComplete: function(calendar, status, opType, id, detail) {
                 let offline_flag = detail;
                 if ((offline_flag == cICL.OFFLINE_FLAG_CREATED_RECORD ||
                      offline_flag == cICL.OFFLINE_FLAG_MODIFIED_RECORD) && useCache) {
                     storage.modifyItem(aNewItem, aOldItem, modifyOfflineListener);
                 } else {
                     self.modifyItem(aNewItem, aOldItem, aListener);
@@ -78,25 +83,27 @@ var calendarShim = {
         };
         storage.getItemOfflineFlag(aOldItem, offlineFlagListener);
     },
 
     deleteItemOrUseCache: function deleteItemOrUseCache(aItem, useCache, aListener) {
         let self = this;
         let storage = this.mOfflineStorage.QueryInterface(Components.interfaces.calIOfflineStorage);
         let deleteOfflineListener = {
+            QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             onGetResult: function(calendar, status, itemType, detail, count, items) {},
             onOperationComplete: function(calendar, status, opType, id, detail) {
                 if (aListener) {
                     aListener.onOperationComplete(calendar, status, opType, aItem.id, aItem);
                 }
             }
         };
 
         let offlineFlagListener = {
+            QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             onGetResult: function(calendar, status, itemType, detail, count, items) {},
             onOperationComplete: function(calendar, status, opType, id, detail) {
                 let offline_flag = detail;
                 if ((offline_flag == cICL.OFFLINE_FLAG_CREATED_RECORD ||
                      offline_flag == cICL.OFFLINE_FLAG_MODIFIED_RECORD) && useCache) {
                     /* We do not delete the item from the cache, but mark it deleted */
                     storage.deleteOfflineItem(aItem, aListener);
                 } else {
@@ -192,16 +199,17 @@ function gdataRegisterCalendar(calendar)
 }
 
 /**
  * Shim for calAsyncUtils' promsifyCalendar for Lightning before 3.5
  */
 function promisifyCalendar(aCalendar) {
     function promiseOperationListener(deferred) {
         return {
+            QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             items: [],
             itemStatus: Components.results.NS_OK,
             onGetResult: function(aCalendar, aStatus, aItemType, aDetail,
                                   aCount, aItems) {
                 this.itemStatus = aStatus;
                 if (Components.isSuccessCode(aStatus)) {
                     this.items = this.items.concat(aItems);
                 } else {
--- a/calendar/providers/ics/calICSCalendar.js
+++ b/calendar/providers/ics/calICSCalendar.js
@@ -315,16 +315,17 @@ calICSCalendar.prototype = {
     },
 
     doWriteICS: function () {
         cal.LOG("[calICSCalendar] Writing ICS File " + this.uri.spec);
         var savedthis = this;
         var listener =
         {
             serializer: null,
+            QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             onOperationComplete: function(aCalendar, aStatus, aOperationType, aId, aDetail)
             {
                 var inLastWindowClosingSurvivalArea = false;
                 try  {
                     // All events are returned. Now set up a channel and a
                     // streamloader to upload.  onStopRequest will be called
                     // once the write has finished
                     var channel = Services.io.newChannelFromURI2(savedthis.mUri,
@@ -506,16 +507,17 @@ calICSCalendar.prototype = {
     {
         if (this.isLocked())
             return;
 
         function modListener(action) {
             this.mAction = action;
         }
         modListener.prototype = {
+            QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             onGetResult: function() {},
             onOperationComplete: function() {
                 this.mAction.opCompleteArgs = arguments;
             }
         };
 
         var a;
         var writeICS = false;
--- a/calendar/providers/storage/calStorageCalendar.js
+++ b/calendar/providers/storage/calStorageCalendar.js
@@ -1008,16 +1008,17 @@ calStorageCalendar.prototype = {
                                      Components.interfaces.calIOperationListener.ADD,
                                      aItem.id,
                                      aItem);
     },
 
     modifyOfflineItem: function(aItem, aListener) {
         let this_ = this;
         let opListener = {
+            QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             onGetResult: function (calendar, status, itemType, detail, count, items) {
             },
             onOperationComplete: function(calendar, status, opType, id, oldOfflineJournalFlag ) {
                 let newOfflineJournalFlag = cICL.OFFLINE_FLAG_MODIFIED_RECORD;
                 if (oldOfflineJournalFlag == cICL.OFFLINE_FLAG_CREATED_RECORD || oldOfflineJournalFlag == cICL.OFFLINE_FLAG_DELETED_RECORD) {
                     // Do nothing since a flag of "created" or "deleted" exists
                 } else {
                     this_.setOfflineJournalFlag(aItem, newOfflineJournalFlag);
@@ -1030,16 +1031,17 @@ calStorageCalendar.prototype = {
             }
         };
         this.getItemOfflineFlag(aItem, opListener);
     },
 
     deleteOfflineItem: function(aItem, aListener) {
         let this_ = this;
         let opListener = {
+            QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             onGetResult: function (calendar, status, itemType, detail, count, items) {
 
             },
             onOperationComplete: function(calendar, status, opType, id, oldOfflineJournalFlag) {
                 var newOfflineJournalFlag = cICL.OFFLINE_FLAG_DELETED_RECORD;
                 if (oldOfflineJournalFlag) {
                     // Delete item if flag is c
                     if (oldOfflineJournalFlag == cICL.OFFLINE_FLAG_CREATED_RECORD) {
--- a/calendar/providers/wcap/calWcapCalendarItems.js
+++ b/calendar/providers/wcap/calWcapCalendarItems.js
@@ -1,12 +1,13 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 Components.utils.import("resource://calendar/modules/calAlarmUtils.jsm");
 Components.utils.import("resource://calendar/modules/calIteratorUtils.jsm");
 
 calWcapCalendar.prototype.encodeAttendee =
 function calWcapCalendar_encodeAttendee(att) {
     if (LOG_LEVEL > 2) {
         log("attendee.icalProperty.icalString=" + att.icalProperty.icalString, this);
     }
@@ -1338,16 +1339,17 @@ function calWcapCalendar_replayChangesOn
                 listener.onResult(request, null);
             }
         },
         log("replayChangesOn():\n\titemFilter=0x" + itemFilter.toString(0x10) +
             "\n\tdtFrom=" + getIcalUTC(dtFrom), this));
 
     try {
         var writeListener = {
+            QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             onGetResult: function() {},
             onOperationComplete: function(aCalendar, status, opType, id, detail) {
                 if (!Components.isSuccessCode(status)) {
                     request.execRespFunc(status); // any error on writing breaks whole operation
                 }
             }
         };
         var request = new calWcapRequest(
--- a/calendar/resources/content/publish.js
+++ b/calendar/resources/content/publish.js
@@ -1,12 +1,14 @@
 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 Components.utils.import("resource://calendar/modules/calUtils.jsm");
 Components.utils.import("resource://gre/modules/Services.jsm");
 
 /**
  * publishCalendarData
  * Show publish dialog, ask for URL and publish all selected items.
  */
 function publishCalendarData()
@@ -88,16 +90,17 @@ function publishEntireCalendar(aCalendar
 function publishEntireCalendarDialogResponse(CalendarPublishObject, aProgressDialog)
 {
     // store the selected remote ics path as a calendar preference
     CalendarPublishObject.calendar.setProperty("remote-ics-path",
                                            CalendarPublishObject.remotePath);
 
     var itemArray = [];
     var getListener = {
+        QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
         onOperationComplete: function(aCalendar, aStatus, aOperationType, aId, aDetail)
         {
             publishItemArray(itemArray, CalendarPublishObject.remotePath, aProgressDialog);
         },
         onGetResult: function(aCalendar, aStatus, aItemType, aDetail, aCount, aItems)
         {
             if (!Components.isSuccessCode(aStatus)) {
                 aborted = true;