Fix bug 439620 - Calendars without proper provider deployment should be marked as "disabled". r=philipp
authorDaniel Boelzle [:dbo] <daniel.boelzle@sun.com>
Thu, 08 Jan 2009 23:22:02 +0100
changeset 1584 1ff3aca86da6dcaac4d50ad86b9bef3bee93bb5e
parent 1583 6cf9e90978b146084075dd9c6a5e3e68a35512df
child 1585 05d7c1308855b243d04372f3449a8ef9e72fbf12
push id1265
push userdaniel.boelzle@sun.com
push dateThu, 08 Jan 2009 22:24:09 +0000
treeherdercomm-central@1ff3aca86da6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersphilipp
bugs439620
Fix bug 439620 - Calendars without proper provider deployment should be marked as "disabled". r=philipp
calendar/base/content/calendar-properties-dialog.js
calendar/base/modules/Makefile.in
calendar/base/modules/calAuthUtils.jsm
calendar/base/modules/calProviderUtils.jsm
calendar/base/public/calICalendar.idl
calendar/base/src/Makefile.in
calendar/base/src/calAuthUtils.js
calendar/base/src/calCalendarManager.js
calendar/base/src/calProviderUtils.js
calendar/installer/removed-files.in
calendar/installer/windows/packages-static
calendar/providers/Makefile.in
calendar/providers/base/Makefile.in
calendar/providers/base/calProviderBase.js
calendar/providers/caldav/calDavCalendar.js
calendar/providers/caldav/calDavCalendarModule.js
calendar/providers/gdata/components/calGoogleCalendar.js
calendar/providers/gdata/components/calGoogleCalendarModule.js
calendar/providers/gdata/components/calGoogleRequest.js
calendar/providers/gdata/components/calGoogleSession.js
calendar/providers/gdata/components/calGoogleUtils.js
calendar/providers/ics/calICSCalendar.js
calendar/providers/ics/calICSCalendarModule.js
calendar/providers/memory/calMemoryCalendar.js
calendar/providers/memory/calMemoryCalendarModule.js
calendar/providers/storage/calStorageCalendar.js
calendar/providers/storage/calStorageCalendarModule.js
calendar/providers/wcap/calWcapCalendar.js
calendar/providers/wcap/calWcapCalendarModule.js
calendar/providers/wcap/calWcapRequest.js
calendar/providers/wcap/calWcapSession.js
--- a/calendar/base/content/calendar-properties-dialog.js
+++ b/calendar/base/content/calendar-properties-dialog.js
@@ -70,18 +70,23 @@ function onLoad() {
     var suppressAlarmsRow = document.getElementById("calendar-suppressAlarms-row");
     var suppressAlarms = gCalendar.getProperty('suppressAlarms');
     document.getElementById("fire-alarms").checked = !suppressAlarms;
 
     suppressAlarmsRow.hidden =
         (gCalendar.getProperty("capabilities.alarms.popup.supported") === false);
 
     // Set up the disabled checkbox
-    var calendarDisabled = gCalendar.getProperty("disabled");
-    document.getElementById("calendar-enabled-checkbox").checked = !calendarDisabled;
+    let calendarDisabled = false;
+    if (gCalendar.getProperty("force-disabled")) {
+        document.getElementById("calendar-enabled-checkbox").disabled = true;
+    } else {
+        calendarDisabled = gCalendar.getProperty("disabled");
+        document.getElementById("calendar-enabled-checkbox").checked = !calendarDisabled;
+    }
     setupEnabledCheckbox();
 
     // start focus on title, unless we are disabled
     if (!calendarDisabled) {
         document.getElementById("calendar-name").focus();
     }
 
     sizeToContent();
@@ -101,19 +106,21 @@ function onAcceptDialog() {
     gCalendar.readOnly = document.getElementById("read-only").checked;
 
     // Save supressAlarms
     gCalendar.setProperty("suppressAlarms", !document.getElementById("fire-alarms").checked);
 
     // Save cache options
     gCalendar.setProperty("cache.enabled", document.getElementById("cache").checked);
 
-    // Save disabled option (should do this last), remove auto-enabled
-    gCalendar.setProperty("disabled", !document.getElementById("calendar-enabled-checkbox").checked);
-    gCalendar.deleteProperty("auto-enabled");
+    if (!gCalendar.getProperty("force-disabled")) {
+        // Save disabled option (should do this last), remove auto-enabled
+        gCalendar.setProperty("disabled", !document.getElementById("calendar-enabled-checkbox").checked);
+        gCalendar.deleteProperty("auto-enabled");
+    }
 
     // tell standard dialog stuff to close the dialog
     return true;
 }
 
 /**
  * When the calendar is disabled, we need to disable a number of other elements
  */
--- a/calendar/base/modules/Makefile.in
+++ b/calendar/base/modules/Makefile.in
@@ -9,17 +9,17 @@
 # Software distributed under the License is distributed on an "AS IS" basis,
 # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 # for the specific language governing rights and limitations under the
 # License.
 #
 # The Original Code is Sun Microsystems code.
 #
 # The Initial Developer of the Original Code is
-# Sun Microsystems, Inc.
+#   Sun Microsystems, Inc.
 # Portions created by the Initial Developer are Copyright (C) 2008
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
 #   Daniel Boelzle <daniel.boelzle@sun.com>
 #
 # Alternatively, the contents of this file may be used under the terms of
 # either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -43,11 +43,13 @@ VPATH     = @srcdir@
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = calbase
 
 EXTRA_JS_MODULES = \
     calUtils.jsm \
     calIteratorUtils.jsm \
     calItipUtils.jsm \
+    calProviderUtils.jsm \
+    calAuthUtils.jsm \
     $(NULL)
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/calendar/base/modules/calAuthUtils.jsm
@@ -0,0 +1,378 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Calendar component utils.
+ *
+ * The Initial Developer of the Original Code is
+ *   Joey Minta <jminta@gmail.com>
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Philipp Kewisch <mozilla@kewis.ch>
+ *   Daniel Boelzle <daniel.boelzle@sun.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+Components.utils.import("resource://calendar/modules/calUtils.jsm");
+
+/*
+ * Authentication helper code
+ */
+
+EXPORTED_SYMBOLS = ["cal"]; // even though it's defined in calUtils.jsm, import needs this
+cal.auth = {
+    /**
+     * Auth prompt implementation - Uses password manager if at all possible.
+     */
+    Prompt: function calPrompt() {
+        // use the window watcher service to get a nsIAuthPrompt impl
+        this.mPrompter = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
+                                   .getService(Components.interfaces.nsIWindowWatcher)
+                                   .getNewAuthPrompter(null);
+        this.mTriedStoredPassword = false;
+    },
+
+    /**
+     * Tries to get the username/password combination of a specific calendar name
+     * from the password manager or asks the user.
+     *
+     * @param   in aTitle           The dialog title.
+     * @param   in aCalendarName    The calendar name or url to look up. Can be null.
+     * @param   inout aUsername     The username that belongs to the calendar.
+     * @param   inout aPassword     The password that belongs to the calendar.
+     * @param   inout aSavePassword Should the password be saved?
+     * @param   in aFixedUsername   Whether the user name is fixed or editable
+     * @return  Could a password be retrieved?
+     */
+    getCredentials: function calGetCredentials(aTitle,
+                                               aCalendarName,
+                                               aUsername,
+                                               aPassword,
+                                               aSavePassword,
+                                               aFixedUsername) {
+
+        if (typeof aUsername != "object" ||
+            typeof aPassword != "object" ||
+            typeof aSavePassword != "object") {
+            throw new Components.Exception("", Components.results.NS_ERROR_XPC_NEED_OUT_OBJECT);
+        }
+
+        let watcher = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
+                                .getService(Components.interfaces.nsIWindowWatcher);
+        let prompter = watcher.getNewPrompter(null);
+
+        // Only show the save password box if we are supposed to.
+        let savepassword = null;
+        if (cal.getPrefSafe("signon.rememberSignons", true)) {
+            savepassword = cal.calGetString("passwordmgr", "rememberPassword", null, "passwordmgr");
+        }
+
+        let aText;
+        if (aFixedUsername) {
+            aText = cal.calGetString("prompts", "EnterPasswordFor", [aUsername.value, aCalendarName], "global");
+            return prompter.promptPassword(aTitle,
+                                           aText,
+                                           aPassword,
+                                           savepassword,
+                                           aSavePassword);
+        } else {
+            aText = cal.calGetString("prompts", "EnterUserPasswordFor", [aCalendarName], "global");
+            return prompter.promptUsernameAndPassword(aTitle,
+                                                      aText,
+                                                      aUsername,
+                                                      aPassword,
+                                                      savepassword,
+                                                      aSavePassword);
+        }
+    },
+
+    /**
+     * Helper to insert/update an entry to the password manager.
+     *
+     * @param aUserName     The username
+     * @param aPassword     The corresponding password
+     * @param aHostName     The corresponding hostname
+     * @param aRealm        The password realm (unused on branch)
+     */
+    passwordManagerSave: function calPasswordManagerSave(aUsername, aPassword, aHostName, aRealm) {
+        cal.ASSERT(aUsername);
+        cal.ASSERT(aPassword);
+
+        try {
+            if (Components.classes["@mozilla.org/passwordmanager;1"]) {
+                cal.auth.passwordManagerRemove(aUsername, aHostName, aRealm);
+                let passwordManager = Components.classes["@mozilla.org/passwordmanager;1"]
+                                                .getService(Components.interfaces.nsIPasswordManager);
+                if (aHostName && aHostName[aHostName.length - 1] == '/') {
+                    // strip trailing slash on branch:
+                    aHostName = aHostName.substr(0, aHostName.length - 1);
+                }
+                passwordManager.addUser(aHostName, aUsername, aPassword);
+            } else if (Components.classes["@mozilla.org/login-manager;1"]) {
+                // Trunk uses LoginManager
+                let loginManager = Components.classes["@mozilla.org/login-manager;1"]
+                                             .getService(Components.interfaces.nsILoginManager);
+                let logins = loginManager.findLogins({}, aHostName, null, aRealm);
+                if (logins.length > 0) {
+                    let loginInfo = logins[0].clone();
+                    loginInfo.password = aPassword;
+                    loginManager.modifyLogin(logins[0], loginInfo);
+                } else {
+                    let loginInfo = Components.classes["@mozilla.org/login-manager/loginInfo;1"]
+                                              .createInstance(Components.interfaces.nsILoginInfo);
+                    loginInfo.init(aHostName,
+                                   null, aRealm,
+                                   aUsername, aPassword,
+                                   null, null);
+                    loginManager.addLogin(loginInfo);
+                }
+            }
+        } catch (exc) {
+            cal.ASSERT(false, exc);
+        }
+    },
+
+    /**
+     * Helper to retrieve an entry from the password manager.
+     *
+     * @param in  aUsername     The username to search
+     * @param out aPassword     The corresponding password
+     * @param aHostName         The corresponding hostname
+     * @param aRealm            The password realm (unused on branch)
+     * @return                  Does an entry exist in the password manager
+     */
+    passwordManagerGet: function calPasswordManagerGet(aUsername, aPassword, aHostName, aRealm) {
+        cal.ASSERT(aUsername);
+
+        if (typeof aPassword != "object") {
+            throw new Components.Exception("", Components.results.NS_ERROR_XPC_NEED_OUT_OBJECT);
+        }
+
+        try {
+            if (Components.classes["@mozilla.org/passwordmanager;1"]) {
+                // Branch uses PasswordManager
+                let passwordManager = Components.classes["@mozilla.org/passwordmanager;1"]
+                                                .getService(Components.interfaces.nsIPasswordManager);
+
+                if (aHostName && aHostName[aHostName.length - 1] == '/') {
+                    // strip trailing slash on branch:
+                    aHostName = aHostName.substr(0, aHostName.length - 1);
+                }
+
+                let enumerator = passwordManager.enumerator;
+                while (enumerator.hasMoreElements()) {
+                    let entry = enumerator.getNext().QueryInterface(Components.interfaces.nsIPassword);
+                    if ((entry.host == aHostName) &&
+                        (entry.user == aUsername)) {
+                        aPassword.value = entry.password;
+                        return true;
+                    }
+                }
+            } else if (Components.classes["@mozilla.org/login-manager;1"]) {
+                // Trunk uses LoginManager
+                let loginManager = Components.classes["@mozilla.org/login-manager;1"]
+                                             .getService(Components.interfaces.nsILoginManager);
+                if (!loginManager.getLoginSavingEnabled(aUsername)) {
+                    return false;
+                }
+
+                let logins = loginManager.findLogins({}, aHostName, null, aRealm);
+                for each (let loginInfo in logins) {
+                    if (loginInfo.username == aUsername) {
+                        aPassword.value = loginInfo.password;
+                        return true;
+                    }
+                }
+            }
+        } catch (exc) {
+            cal.ASSERT(false, exc);
+        }
+        return false;
+    },
+
+    /**
+     * Helper to remove an entry from the password manager
+     *
+     * @param aUsername     The username to remove.
+     * @param aHostName     The corresponding hostname
+     * @param aRealm        The password realm (unused on branch)
+     * @return              Could the user be removed?
+     */
+    passwordManagerRemove: function calPasswordManagerRemove(aUsername, aHostName, aRealm) {
+        cal.ASSERT(aUsername);
+
+        try {
+            if (Components.classes["@mozilla.org/passwordmanager;1"]) {
+                // Branch uses PasswordManager
+                let passwordManager = Components.classes["@mozilla.org/passwordmanager;1"]
+                                                .getService(Components.interfaces.nsIPasswordManager);
+                if (aHostName && aHostName[aHostName.length - 1] == '/') {
+                    // strip trailing slash on branch:
+                    aHostName = aHostName.substr(0, aHostName.length - 1);
+                }
+                passwordManager.removeUser(aHostName, aUsername);
+                return true;
+            } else if (Components.classes["@mozilla.org/login-manager;1"]) {
+                // Trunk uses LoginManager
+                let loginManager = Components.classes["@mozilla.org/login-manager;1"]
+                                             .getService(Components.interfaces.nsILoginManager);
+                let logins = loginManager.findLogins({}, aHostName, null, aRealm);
+                for each (let loginInfo in logins) {
+                    if (loginInfo.username == aUsername) {
+                        loginManager.removeLogin(loginInfo);
+                        return true;
+                    }
+                }
+            }
+        } catch (exc) {
+        }
+        return false;
+    }
+};
+
+cal.auth.Prompt.prototype = {
+    prompt: function capP(aDialogTitle, aText, aPasswordRealm, aSavePassword, aDefaultText, aResult) {
+        return this.mPrompter.prompt(aDialogTitle,
+                                     aText,
+                                     aPasswordRealm,
+                                     aSavePassword,
+                                     aDefaultText,
+                                     aResult);
+    },
+
+    getPasswordInfo: function capGPI(aPasswordRealm) {
+        let username;
+        let password;
+        let found = false;
+
+        if ("@mozilla.org/passwordmanager;1" in Components.classes) {
+            let passwordManager = Components.classes["@mozilla.org/passwordmanager;1"]
+                                            .getService(Components.interfaces.nsIPasswordManager);
+            let passwordRealm = aPasswordRealm.passwordRealm || aPasswordRealm;
+            let pwenum = passwordManager.enumerator;
+            // step through each password in the password manager until we find the one we want:
+            while (pwenum.hasMoreElements()) {
+                try {
+                    let pass = pwenum.getNext().QueryInterface(Components.interfaces.nsIPassword);
+                    if (pass.host == passwordRealm) {
+                         // found it!
+                         username = pass.user;
+                         password = pass.password;
+                         found = true;
+                    }
+                } catch (ex) {
+                    // don't do anything here, ignore the password that could not be read
+                }
+            }
+        } else {
+            let loginManager = Components.classes["@mozilla.org/login-manager;1"]
+                                         .getService(Components.interfaces
+                                         .nsILoginManager);
+            let logins = loginManager.findLogins({}, aPasswordRealm.prePath, null,
+                                                 aPasswordRealm.realm);
+            if (logins.length) {
+                username = logins[0].username;
+                password = logins[0].password;
+                found = true;
+            }
+        }
+        return {found: found, username: username, password: password};
+    },
+
+    promptUsernameAndPassword: function capPUAP(aDialogTitle, aText,
+                                                aPasswordRealm, aSavePassword,
+                                                aUser, aPwd) {
+        let pw;
+        if (!this.mTriedStoredPassword) {
+            pw = this.getPasswordInfo(aPasswordRealm);
+        }
+
+        if (pw && pw.found) {
+            this.mTriedStoredPassword = true;
+            aUser.value = pw.username;
+            aPwd.value = pw.password;
+            return true;
+        } else {
+            return this.mPrompter.promptUsernameAndPassword(aDialogTitle,
+                                                            aText,
+                                                            aPasswordRealm,
+                                                            aSavePassword,
+                                                            aUser,
+                                                            aPwd);
+        }
+    },
+
+    // promptAuth is needed/used on trunk only
+    promptAuth: function capPA(aChannel, aLevel, aAuthInfo) {
+        let hostRealm = {};
+        hostRealm.prePath = aChannel.URI.prePath;
+        hostRealm.realm = aAuthInfo.realm;
+        let port = aChannel.URI.port;
+        if (port == -1) {
+            let handler = cal.getIOService().getProtocolHandler(aChannel.URI.scheme)
+                                            .QueryInterface(Components.interfaces.nsIProtocolHandler);
+            port = handler.defaultPort;
+        }
+        hostRealm.passwordRealm = aChannel.URI.host + ":" + port + " (" + aAuthInfo.realm + ")";
+
+        let pw;
+        if (!this.mTriedStoredPassword) {
+            pw = this.getPasswordInfo(hostRealm);
+        }
+        if (pw && pw.found) {
+            this.mTriedStoredPassword = true;
+            aAuthInfo.username = pw.username;
+            aAuthInfo.password = pw.password;
+            return true;
+        } else {
+            let prompter2 = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
+                                      .getService(Components.interfaces.nsIPromptFactory)
+                                      .getPrompt(null, Components.interfaces.nsIAuthPrompt2);
+            return prompter2.promptAuth(aChannel, aLevel, aAuthInfo);
+        }
+    },
+
+    promptPassword: function capPP(aDialogTitle, aText, aPasswordRealm,
+                             aSavePassword, aPwd) {
+        let found = false;
+        let pw;
+        if (!this.mTriedStoredPassword) {
+            pw = this.getPasswordInfo(aPasswordRealm);
+        }
+
+        if (pw && pw.found) {
+            this.mTriedStoredPassword = true;
+            aPwd.value = pw.password;
+            return true;
+        } else {
+            return this.mPrompter.promptPassword(aDialogTitle,
+                                                 aText,
+                                                 aPasswordRealm,
+                                                 aSavePassword,
+                                                 aPwd);
+        }
+    }
+};
new file mode 100644
--- /dev/null
+++ b/calendar/base/modules/calProviderUtils.jsm
@@ -0,0 +1,601 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Sun Microsystems code.
+ *
+ * The Initial Developer of the Original Code is
+ *   Sun Microsystems, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Daniel Boelzle <daniel.boelzle@sun.com>
+ *   Philipp Kewisch <mozilla@kewis.ch>
+ *   Bruno Browning <browning@uwalumni.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+Components.utils.import("resource://calendar/modules/calUtils.jsm");
+Components.utils.import("resource://calendar/modules/calAuthUtils.jsm");
+
+/*
+ * Provider helper code
+ */
+
+EXPORTED_SYMBOLS = ["cal"]; // even though it's defined in calUtils.jsm, import needs this
+
+/**
+ * Prepare HTTP channel with standard request headers and upload
+ * data/content-type if needed
+ *
+ * @param arUri                      Channel Uri, will only be used for a new
+ *                                     channel.
+ * @param aUploadData                Data to be uploaded, if any. This may be a
+ *                                     nsIInputStream or string data. In the
+ *                                     latter case the string will be converted
+ *                                     to an input stream.
+ * @param aContentType               Value for Content-Type header, if any
+ * @param aNotificationCallbacks     Calendar using channel
+ * @param aExisting                  An existing channel to modify (optional)
+ */
+cal.prepHttpChannel = function calPrepHttpChannel(aUri, aUploadData, aContentType, aNotificationCallbacks, aExisting) {
+    let channel = aExisting || cal.getIOService().newChannelFromURI(aUri);
+    let httpchannel = channel.QueryInterface(Components.interfaces.nsIHttpChannel);
+
+    httpchannel.setRequestHeader("Accept", "text/xml", false);
+    httpchannel.setRequestHeader("Accept-Charset", "utf-8,*;q=0.1", false);
+    httpchannel.loadFlags |= Components.interfaces.nsIRequest.LOAD_BYPASS_CACHE;
+    httpchannel.notificationCallbacks = aNotificationCallbacks;
+
+    if (aUploadData) {
+        httpchannel = httpchannel.QueryInterface(Components.interfaces.nsIUploadChannel);
+        let stream;
+        if (aUploadData instanceof Components.interfaces.nsIInputStream) {
+            // Make sure the stream is reset
+            stream = aUploadData.QueryInterface(Components.interfaces.nsISeekableStream);
+            stream.seek(Components.interfaces.nsISeekableStream.NS_SEEK_SET, 0);
+        } else {
+            // Otherwise its something that should be a string, convert it.
+            let converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
+                                      .createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
+            converter.charset = "UTF-8";
+            stream = converter.convertToInputStream(aUploadData.toString());
+        }
+
+        httpchannel.setUploadStream(stream, aContentType, -1);
+    }
+
+    return httpchannel;
+};
+
+/**
+ * calSendHttpRequest; send prepared HTTP request
+ *
+ * @param aStreamLoader     streamLoader for request
+ * @param aChannel          channel for request
+ * @param aListener         listener for method completion
+ */
+cal.sendHttpRequest = function calSendHttpRequest(aStreamLoader, aChannel, aListener) {
+    aStreamLoader.init(aListener);
+    aChannel.asyncOpen(aStreamLoader, aChannel);
+};
+
+cal.createStreamLoader = function calCreateStreamLoader() {
+    return Components.classes["@mozilla.org/network/stream-loader;1"]
+                     .createInstance(Components.interfaces.nsIStreamLoader);
+};
+
+cal.convertByteArray = function calConvertByteArray(aResult, aResultLength, aCharset, aThrow) {
+    try {
+        let resultConverter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
+                                        .createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
+        resultConverter.charset = aCharset || "UTF-8";
+        return resultConverter.convertFromByteArray(aResult, aResultLength);
+    } catch (e) {
+        if (aThrow) {
+            throw e;
+        }
+    }
+    return null;
+};
+
+cal.safeNewXML = function calSafeNewXML(aStr) {
+    // Strip <?xml and surrounding whitespaces
+    return new XML(aStr.replace(/(^\s*(<\?xml[^>]*>)?\s*|\s+$)/g, ""));
+};
+    
+
+/**
+ * getInterface method for providers. This should be called in the context of
+ * the respective provider, i.e
+ *
+ * return cal.InterfaceRequestor_getInterface.apply(this, arguments);
+ *
+ * or
+ * ...
+ * getInterface: cal.InterfaceRequestor_getInterface,
+ * ...
+ *
+ * @param aIID      The interface ID to return
+ */
+cal.InterfaceRequestor_getInterface = function calInterfaceRequestor_getInterface(aIID) {
+    // Support Auth Prompt Interfaces
+    if (aIID.equals(Components.interfaces.nsIAuthPrompt) ||
+        (Components.interfaces.nsIAuthPrompt2 &&
+         aIID.equals(Components.interfaces.nsIAuthPrompt2))) {
+        return new cal.auth.Prompt();
+    } else if (aIID.equals(Components.interfaces.nsIAuthPromptProvider) ||
+               aIID.equals(Components.interfaces.nsIPrompt)) {
+        return Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
+                         .getService(Components.interfaces.nsIWindowWatcher)
+                         .getNewPrompter(null);
+    }
+
+    try {
+        // Try to query the this object for the requested interface but don't
+        // throw if it fails since that borks the network code.
+        return this.QueryInterface(aIID);
+    } catch (e) {
+        Components.returnCode = e;
+    }
+    return null;
+};
+
+/**
+ * Freebusy interval implementation. All parameters are optional.
+ *
+ * @param aCalId         The calendar id to set up with.
+ * @param aFreeBusyType  The type from calIFreeBusyInterval.
+ * @param aStart         The start of the interval.
+ * @param aEnd           The end of the interval.
+ * @return               The fresh calIFreeBusyInterval.
+ */
+cal.FreeBusyInterval = function calFreeBusyInterval(aCalId, aFreeBusyType, aStart, aEnd) {
+    this.calId = aCalId
+    this.interval = Components.classes["@mozilla.org/calendar/period;1"]
+                              .createInstance(Components.interfaces.calIPeriod);
+    this.interval.start = aStart;
+    this.interval.end = aEnd;
+
+    this.freeBusyType = aFreeBusyType || Components.interfaces.calIFreeBusyInterval.UNKNOWN;
+};
+cal.FreeBusyInterval.prototype = {
+    QueryInterface: function cFBI_QueryInterface(aIID) {
+        return doQueryInterface(this,
+                                cal.FreeBusyInterval.prototype,
+                                aIID,
+                                [Components.interfaces.calIFreeBusyInterval]);
+    },
+
+    calId: null,
+    interval: null,
+    freeBusyType: Components.interfaces.calIFreeBusyInterval.UNKNOWN
+};
+
+/**
+ * Gets the iTIP/iMIP transport if the passed calendar has configured email.
+ */
+cal.getImipTransport = function calGetImipTransport(aCalendar) {
+    // assure an identity is configured for the calendar
+    return (aCalendar.getProperty("imip.identity")
+            ? Components.classes["@mozilla.org/calendar/itip-transport;1?type=email"]
+                        .getService(Components.interfaces.calIItipTransport)
+            : null);
+};
+
+/**
+ * Gets the configured identity and account of a particular calendar instance, or null.
+ *
+ * @param aCalendar     Calendar instance
+ * @param outAccount    Optional out value for account
+ * @return              The configured identity
+ */
+cal.getEmailIdentityOfCalendar = function calGetEmailIdentityOfCalendar(aCalendar, outAccount) {
+    cal.ASSERT(aCalendar, "no calendar!", Components.results.NS_ERROR_INVALID_ARG);
+    if (cal.isSunbird()) {
+        return null;
+    }
+    let key = aCalendar.getProperty("imip.identity.key");
+    if (key !== null) {
+        if (key.length == 0) { // i.e. "None"
+            return null;
+        }
+        let identity = null;
+        cal.calIterateEmailIdentities(
+            function(identity_, account) {
+                if (identity_.key == key) {
+                    identity = identity_;
+                    if (outAccount) {
+                        outAccount.value = account;
+                    }
+                }
+                return (identity_.key != key);
+            });
+        if (!identity) {
+            // dangling identity:
+            cal.WARN("Calendar " + (aCalendar.uri ? aCalendar.uri.spec : aCalendar.id) +
+                     " has a dangling E-Mail identity configured.");
+        }
+        return identity;
+    } else { // take default account/identity:
+
+        let accounts = cal.getAccountManager().accounts;
+        let account = null;
+        let identity = null;
+        try {
+            account = cal.getAccountManager().defaultAccount;
+        } catch (exc) {}
+
+        for (let i = 0; accounts && (i < accounts.Count()) && (!account || !identity); ++i) {
+            if (!account) { // Pick an account only if none was set (i.e there is no default account)
+                account = accounts.GetElementAt(i);
+                try {
+                    account = account.QueryInterface(Components.interfaces.nsIMsgAccount);
+                } catch (exc) {
+                    account = null;
+                }
+            }
+
+            if (account && account.identities.Count()) { // Pick an identity
+                identity = account.defaultIdentity;
+                if (!identity) { // there is no default identity, use the first
+                    identity = account.identities.GetElementAt(0)
+                                                 .QueryInterface(Components.interfaces.nsIMsgIdentity);
+                }
+            } else { // If this account has no identities, continue to the next account.
+                account = null;
+            }
+        }
+
+        if (identity) {
+            // If an identity was set above, set the account out parameter
+            // and return the identity
+            if (outAccount) {
+                outAccount.value = account;
+            }
+            return identity;
+        }
+        return null;
+    }
+};
+
+/**
+ * Base prototype to be used implementing a provider.
+ *
+ * @see e.g. providers/gdata
+ */
+cal.ProviderBase = function calProviderBase() {
+    cal.ASSERT("This prototype should only be inherited!");
+};
+cal.ProviderBase.mTransientProperties = {
+    "cache.uncachedCalendar": true,
+    "currentStatus": true,
+    "itip.transport": true,
+    "imip.identity": true,
+    "imip.account": true,
+    "imip.identity.disabled": true,
+    "organizerId": true,
+    "organizerCN": true
+};
+cal.ProviderBase.prototype = {
+    QueryInterface: function cPB_QueryInterface(aIID) {
+        return cal.doQueryInterface(this, cal.ProviderBase.prototype, aIID,
+                                    [Components.interfaces.nsISupports,
+                                     Components.interfaces.calICalendar,
+                                     Components.interfaces.calISchedulingSupport]);
+    },
+
+    mID: null,
+    mUri: null,
+    mObservers: null,
+    mProperties: null,
+
+    initProviderBase: function cPB_initProviderBase() {
+        this.wrappedJSObject = this;
+        this.mObservers = new cal.calListenerBag(Components.interfaces.calIObserver);
+        this.mProperties = {};
+        this.mProperties.currentStatus = Components.results.NS_OK;
+    },
+
+    get observers cPB_observers_get() {
+        return this.mObservers;
+    },
+
+    // attribute AUTF8String id;
+    get id cPB_id_get() {
+        return this.mID;
+    },
+    set id cPB_id_set(aValue) {
+        if (this.mID) {
+            throw Components.results.NS_ERROR_ALREADY_INITIALIZED;
+        }
+        this.mID = aValue;
+
+//         cal.ASSERT(this.mProperties.toSource() == "({})", "setProperty calls before id has been set!");
+
+        let calMgr = cal.getCalendarManager();
+        let this_ = this;
+        function takeOverIfNotPresent(oldPref, newPref, dontDeleteOldPref) {
+            let val = calMgr.getCalendarPref_(this_, oldPref);
+            if (val !== null) {
+                if (!dontDeleteOldPref) {
+                    calMgr.deleteCalendarPref_(this_, oldPref);
+                }
+                if (calMgr.getCalendarPref_(this_, newPref) === null) {
+                    calMgr.setCalendarPref_(this_, newPref, val);
+                }
+            }
+        }
+        // takeover lightning calendar visibility from 0.5:
+        takeOverIfNotPresent("lightning-main-in-composite", "calendar-main-in-composite");
+        takeOverIfNotPresent("lightning-main-default", "calendar-main-default");
+
+        return aValue;
+    },
+
+    // attribute AUTF8String name;
+    get name cPB_name_get() {
+        return this.getProperty("name");
+    },
+    set name cPB_name_set(aValue) {
+        return this.setProperty("name", aValue);
+    },
+
+    // attribute calICalendar superCalendar;
+    get superCalendar cPB_superCalendar_get() {
+        // If we have a superCalendar, check this calendar for a superCalendar.
+        // This will make sure the topmost calendar is returned
+        return (this.mSuperCalendar ? this.mSuperCalendar.superCalendar : this);
+    },
+    set superCalendar cPB_superCalendar_set(val) {
+        return (this.mSuperCalendar = val);
+    },
+
+    // attribute nsIURI uri;
+    get uri cPB_uri_get() {
+        return this.mUri;
+    },
+    set uri cPB_uri_set(aValue) {
+        return (this.mUri = aValue);
+    },
+
+    // attribute boolean readOnly;
+    get readOnly cPB_readOnly_get() {
+        return this.getProperty("readOnly");
+    },
+    set readOnly cPB_readOnly_set(aValue) {
+        return this.setProperty("readOnly", aValue);
+    },
+
+    // readonly attribute boolean canRefresh;
+    get canRefresh cPB_canRefresh_get() {
+        return false;
+    },
+
+    // void startBatch();
+    mBatchCount: 0,
+    startBatch: function cPB_startBatch() {
+        if (this.mBatchCount++ == 0) {
+            this.mObservers.notify("onStartBatch");
+        }
+    },
+
+    endBatch: function cPB_endBatch() {
+        if (this.mBatchCount > 0) {
+            if (--this.mBatchCount == 0) {
+                this.mObservers.notify("onEndBatch");
+            }
+        } else {
+            cal.ASSERT(this.mBatchCount > 0, "unexepcted endBatch!");
+        }
+    },
+
+    notifyOperationComplete: function cPB_notifyOperationComplete(aListener,
+                                                                  aStatus,
+                                                                  aOperationType,
+                                                                  aId,
+                                                                  aDetail) {
+        if (aListener) {
+            try {
+                aListener.onOperationComplete(this.superCalendar, aStatus, aOperationType, aId, aDetail);
+            } catch (exc) {
+                cal.ERROR(exc);
+            }
+        }
+        if (aStatus == Components.interfaces.calIErrors.OPERATION_CANCELLED) {
+            return; // cancellation doesn't change current status, no notification
+        }
+        if (Components.isSuccessCode(aStatus)) {
+            this.setProperty("currentStatus", aStatus);
+        } else {
+            if (aDetail instanceof Components.interfaces.nsIException) {
+                this.notifyError(aDetail); // will set currentStatus
+            } else {
+                this.notifyError(aStatus, aDetail); // will set currentStatus
+            }
+            this.notifyError(aOperationType == Components.interfaces.calIOperationListener.GET
+                             ? Components.interfaces.calIErrors.READ_FAILED
+                             : Components.interfaces.calIErrors.MODIFICATION_FAILED,
+                             "");
+        }
+    },
+
+    // for convenience also callable with just an exception
+    notifyError: function cPB_notifyError(aErrNo, aMessage) {
+        if (aErrNo == Components.interfaces.calIErrors.OPERATION_CANCELLED) {
+            return; // cancellation doesn't change current status, no notification
+        }
+        if (aErrNo instanceof Components.interfaces.nsIException) {
+            if (!aMessage) {
+                aMessage = aErrNo.message;
+            }
+            aErrNo = aErrNo.result;
+        }
+        this.setProperty("currentStatus", aErrNo);
+        this.observers.notify("onError", [this.superCalendar, aErrNo, aMessage]);
+    },
+
+    mTransientPropertiesMode: false,
+    get transientProperties cPB_transientProperties() {
+        return this.mTransientPropertiesMode;
+    },
+    set transientProperties cPB_transientProperties(value) {
+        return (this.mTransientPropertiesMode = value);
+    },
+
+    // nsIVariant getProperty(in AUTF8String aName);
+    getProperty: function cPB_getProperty(aName) {
+        switch (aName) {
+            case "itip.transport": // iTIP/iMIP default:
+                return cal.getImipTransport(this);
+            case "itip.notify-replies": // iTIP/iMIP default:
+                 return cal.getPrefSafe("calendar.itip.notify-replies", false);
+            // temporary hack to get the uncached calendar instance:
+            case "cache.uncachedCalendar":
+                return this;
+        }
+
+        let ret = this.mProperties[aName];
+        if (ret === undefined) {
+            ret = null;
+            switch (aName) {
+                case "imip.identity": // we want to cache the identity object a little, because
+                                      // it is heavily used by the invitation checks
+                    ret = cal.getEmailIdentityOfCalendar(this);
+                    break;
+                case "imip.account": {
+                    let outAccount = {};
+                    if (cal.getEmailIdentityOfCalendar(this, outAccount)) {
+                        ret = outAccount.value;
+                    }
+                    break;
+                }
+                case "organizerId": { // itip/imip default: derived out of imip.identity
+                    let identity = this.getProperty("imip.identity");
+                    ret = (identity
+                           ? ("mailto:" + identity.QueryInterface(Components.interfaces.nsIMsgIdentity).email)
+                           : null);
+                    break;
+                }
+                case "organizerCN": { // itip/imip default: derived out of imip.identity
+                    let identity = this.getProperty("imip.identity");
+                    ret = (identity
+                           ? identity.QueryInterface(Components.interfaces.nsIMsgIdentity).fullName
+                           : null);
+                    break;
+                }
+            }
+            if ((ret === null) &&
+                !cal.ProviderBase.mTransientProperties[aName] &&
+                !this.transientProperties) {
+                if (this.id) {
+                    ret = cal.getCalendarManager().getCalendarPref_(this, aName);
+                }
+                if (ret !== null) {
+                    switch (aName) {
+                        case "suppressAlarms":
+                            if (this.getProperty("capabilities.alarms.popup.supported") === false) {
+                                // If popup alarms are not supported,
+                                // automatically suppress alarms
+                                ret = true;
+                            }
+                            break;
+                    }
+                }
+            }
+            this.mProperties[aName] = ret;
+        }
+//         cal.LOG("getProperty(\"" + aName + "\"): " + ret);
+        return ret;
+    },
+
+    // void setProperty(in AUTF8String aName, in nsIVariant aValue);
+    setProperty: function cPB_setProperty(aName, aValue) {
+        let oldValue = this.getProperty(aName);
+        if (oldValue != aValue) {
+            this.mProperties[aName] = aValue;
+            switch (aName) {
+                case "imip.identity.key": // invalidate identity and account object if key is set:
+                    delete this.mProperties["imip.identity"];
+                    delete this.mProperties["imip.account"];
+                    delete this.mProperties["organizerId"];
+                    delete this.mProperties["organizerCN"];
+                    break;
+            }
+            if (!this.transientProperties &&
+                !cal.ProviderBase.mTransientProperties[aName] &&
+                this.id) {
+                cal.getCalendarManager().setCalendarPref_(this, aName, aValue);
+            }
+            this.mObservers.notify("onPropertyChanged",
+                                   [this.superCalendar, aName, aValue, oldValue]);
+        }
+        return aValue;
+    },
+
+    // void deleteProperty(in AUTF8String aName);
+    deleteProperty: function cPB_deleteProperty(aName) {
+        this.mObservers.notify("onPropertyDeleting", [this.superCalendar, aName]);
+        delete this.mProperties[aName];
+        cal.getCalendarManager().deleteCalendarPref_(this, aName);
+    },
+
+    // calIOperation refresh
+    refresh: function cPB_refresh() {
+        return null;
+    },
+
+    // void addObserver( in calIObserver observer );
+    addObserver: function cPB_addObserver(aObserver) {
+        this.mObservers.add(aObserver);
+    },
+
+    // void removeObserver( in calIObserver observer );
+    removeObserver: function cPB_removeObserver(aObserver) {
+        this.mObservers.remove(aObserver);
+    },
+
+    // calISchedulingSupport: Implementation corresponding to our iTIP/iMIP support
+    isInvitation: function cPB_isInvitation(aItem) {
+        let id = this.getProperty("organizerId");
+        if (id) {
+            let org = aItem.organizer;
+            if (!org || (org.id.toLowerCase() == id.toLowerCase())) {
+                return false;
+            }
+            return (aItem.getAttendeeById(id) != null);
+        }
+        return false;
+    },
+
+    getInvitedAttendee: function cPB_getInvitedAttendee(aItem) {
+        let id = this.getProperty("organizerId");
+        return (id ? aItem.getAttendeeById(id) : null);
+    },
+
+    canNotify: function cPB_canNotify(aMethod, aItem) {
+        return false; // use outbound iTIP for all
+    }
+};
--- a/calendar/base/public/calICalendar.idl
+++ b/calendar/base/public/calICalendar.idl
@@ -124,16 +124,17 @@ interface calICalendar : nsISupports
    * callers should use a sensible default in that case.
    *
    * It's up to the provider where to store properties,
    * e.g. on the server or in local prefs.
    *
    * Currently known properties are:
    *   [boolean]  disabled
    *   [boolean]  auto-enabled       If true, the calendar will be enabled on next startup.
+   *   [boolean]  force-disabled     If true, the calendar cannot be enabled (transient).
    *   [boolean]  calendar-main-in-composite
    *   [string]   name
    *   [boolean]  readOnly
    *   [boolean]  requiresNetwork    If false, the calendar does not require
    *                                   network access at all. This is mainy used
    *                                   as a UI hint.
    *   [boolean]  suppressAlarms     If true, alarms of this calendar are not minded.
    *   [boolean]  cache.supported    If true, the calendar should to be cached,
--- a/calendar/base/src/Makefile.in
+++ b/calendar/base/src/Makefile.in
@@ -94,18 +94,16 @@ EXTRA_SCRIPTS = \
     calIcsSerializer.js \
     calItemBase.js \
     calItipItem.js \
     calProtocolHandler.js \
     calRecurrenceInfo.js \
     calRelation.js \
     calTodo.js \
     calUtils.js \
-    calAuthUtils.js \
-    calProviderUtils.js \
     calWeekInfoService.js \
     calTransactionManager.js \
     calFreeBusyService.js \
     calCalendarSearchService.js \
     calTimezoneService.js \
     $(NULL)
 
 # Use NSINSTALL to make the directory, as there's no mtime to preserve.
deleted file mode 100644
--- a/calendar/base/src/calAuthUtils.js
+++ /dev/null
@@ -1,373 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Calendar component utils.
- *
- * The Initial Developer of the Original Code is
- *   Joey Minta <jminta@gmail.com>
- * Portions created by the Initial Developer are Copyright (C) 2006
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Philipp Kewisch <mozilla@kewis.ch>
- *   Daniel Boelzle <daniel.boelzle@sun.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-Components.utils.import("resource://calendar/modules/calUtils.jsm");
-
-/**
- * Auth prompt implementation - Uses password manager if at all possible.
- */
-function calAuthPrompt() {
-    // use the window watcher service to get a nsIAuthPrompt impl
-    this.mPrompter = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
-                               .getService(Components.interfaces.nsIWindowWatcher)
-                               .getNewAuthPrompter(null);
-    this.mTriedStoredPassword = false;
-}
-
-calAuthPrompt.prototype = {
-    prompt: function capP(aDialogTitle, aText, aPasswordRealm, aSavePassword,
-                          aDefaultText, aResult) {
-        return this.mPrompter.prompt(aDialogTitle,
-                                     aText,
-                                     aPasswordRealm,
-                                     aSavePassword,
-                                     aDefaultText,
-                                     aResult);
-    },
-
-    getPasswordInfo: function capGPI(aPasswordRealm) {
-        var username;
-        var password;
-        var found = false;
-
-        if ("@mozilla.org/passwordmanager;1" in Components.classes) {
-            var passwordManager = Components.classes["@mozilla.org/passwordmanager;1"]
-                                            .getService(Components.interfaces.nsIPasswordManager);
-            var passwordRealm = aPasswordRealm.passwordRealm || aPasswordRealm;
-            var pwenum = passwordManager.enumerator;
-            // step through each password in the password manager until we find the one we want:
-            while (pwenum.hasMoreElements()) {
-                try {
-                    var pass = pwenum.getNext().QueryInterface(Components.interfaces.nsIPassword);
-                    if (pass.host == passwordRealm) {
-                         // found it!
-                         username = pass.user;
-                         password = pass.password;
-                         found = true;
-                    }
-                } catch (ex) {
-                    // don't do anything here, ignore the password that could not be read
-                }
-            }
-        } else {
-            var loginManager = Components.classes["@mozilla.org/login-manager;1"]
-                                         .getService(Components.interfaces
-                                         .nsILoginManager);
-            var logins = loginManager.findLogins({}, aPasswordRealm.prePath, null,
-                                                 aPasswordRealm.realm);
-            if (logins.length) {
-                username = logins[0].username;
-                password = logins[0].password;
-                found = true;
-            }
-        }
-        return {found: found, username: username, password: password};
-    },
-
-    promptUsernameAndPassword: function capPUAP(aDialogTitle, aText,
-                                                aPasswordRealm, aSavePassword,
-                                                aUser, aPwd) {
-        var pw;
-        if (!this.mTriedStoredPassword) {
-            pw = this.getPasswordInfo(aPasswordRealm);
-        }
-
-        if (pw && pw.found) {
-            this.mTriedStoredPassword = true;
-            aUser.value = pw.username;
-            aPwd.value = pw.password;
-            return true;
-        } else {
-            return this.mPrompter.promptUsernameAndPassword(aDialogTitle,
-                                                            aText,
-                                                            aPasswordRealm,
-                                                            aSavePassword,
-                                                            aUser,
-                                                            aPwd);
-        }
-    },
-
-    // promptAuth is needed/used on trunk only
-    promptAuth: function capPA(aChannel, aLevel, aAuthInfo) {
-        let hostRealm = {};
-        hostRealm.prePath = aChannel.URI.prePath;
-        hostRealm.realm = aAuthInfo.realm;
-        let port = aChannel.URI.port;
-        if (port == -1) {
-            let handler = cal.getIOService().getProtocolHandler(aChannel.URI.scheme)
-                                        .QueryInterface(Components.interfaces.nsIProtocolHandler);
-            port = handler.defaultPort;
-        }
-        hostRealm.passwordRealm = aChannel.URI.host + ":" + port +
-                                  " (" + aAuthInfo.realm + ")";
-
-        let pw;
-        if (!this.mTriedStoredPassword) {
-            pw = this.getPasswordInfo(hostRealm);
-        }
-        if (pw && pw.found) {
-            this.mTriedStoredPassword = true;
-            aAuthInfo.username = pw.username;
-            aAuthInfo.password = pw.password;
-            return true;
-        } else {
-            let prompter2 = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
-                                      .getService(Components.interfaces.nsIPromptFactory)
-                                      .getPrompt(null, Components.interfaces.nsIAuthPrompt2);
-            return prompter2.promptAuth(aChannel, aLevel, aAuthInfo);
-        }
-    },
-
-    promptPassword: function capPP(aDialogTitle, aText, aPasswordRealm,
-                             aSavePassword, aPwd) {
-        var found = false;
-        var pw;
-        if (!this.mTriedStoredPassword) {
-            pw = this.getPasswordInfo(aPasswordRealm);
-        }
-
-        if (pw && pw.found) {
-            this.mTriedStoredPassword = true;
-            aPwd.value = pw.password;
-            return true;
-        } else {
-            return this.mPrompter.promptPassword(aDialogTitle,
-                                                 aText,
-                                                 aPasswordRealm,
-                                                 aSavePassword,
-                                                 aPwd);
-        }
-    }
-};
-
-/**
- * Tries to get the username/password combination of a specific calendar name
- * from the password manager or asks the user.
- *
- * @param   in aTitle           The dialog title.
- * @param   in aCalendarName    The calendar name or url to look up. Can be null.
- * @param   inout aUsername     The username that belongs to the calendar.
- * @param   inout aPassword     The password that belongs to the calendar.
- * @param   inout aSavePassword Should the password be saved?
- * @param   in aFixedUsername   Whether the user name is fixed or editable
- * @return  Could a password be retrieved?
- */
-function calGetCredentials(aTitle,
-                           aCalendarName,
-                           aUsername,
-                           aPassword,
-                           aSavePassword,
-                           aFixedUsername) {
-
-    if (typeof aUsername != "object" ||
-        typeof aPassword != "object" ||
-        typeof aSavePassword != "object") {
-        throw new Components.Exception("", Components.results.NS_ERROR_XPC_NEED_OUT_OBJECT);
-    }
-
-    var watcher = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
-                            .getService(Components.interfaces.nsIWindowWatcher);
-    var prompter = watcher.getNewPrompter(null);
-
-    // Only show the save password box if we are supposed to.
-    var savepassword = null;
-    if (getPrefSafe("signon.rememberSignons", true)) {
-        savepassword = calGetString("passwordmgr", "rememberPassword", null, "passwordmgr");
-    }
-
-    var aText;
-    if (aFixedUsername) {
-        aText = calGetString("prompts", "EnterPasswordFor", [aUsername.value, aCalendarName], "global");
-        return prompter.promptPassword(aTitle,
-                                       aText,
-                                       aPassword,
-                                       savepassword,
-                                       aSavePassword);
-    } else {
-        aText = calGetString("prompts", "EnterUserPasswordFor", [aCalendarName], "global");
-        return prompter.promptUsernameAndPassword(aTitle,
-                                                  aText,
-                                                  aUsername,
-                                                  aPassword,
-                                                  savepassword,
-                                                  aSavePassword);
-    }
-}
-
-/**
- * Helper to insert/update an entry to the password manager.
- *
- * @param aUserName     The username
- * @param aPassword     The corresponding password
- * @param aHostName     The corresponding hostname
- * @param aRealm        The password realm (unused on branch)
- */
-function calPasswordManagerSave(aUsername, aPassword, aHostName, aRealm) {
-    ASSERT(aUsername);
-    ASSERT(aPassword);
-
-    try {
-        if (Components.classes["@mozilla.org/passwordmanager;1"]) {
-            calPasswordManagerRemove(aUsername, aHostName, aRealm);
-            var passwordManager = Components.classes["@mozilla.org/passwordmanager;1"]
-                                            .getService(Components.interfaces.nsIPasswordManager);
-            if (aHostName && aHostName[aHostName.length - 1] == '/') {
-                // strip trailing slash on branch:
-                aHostName = aHostName.substr(0, aHostName.length - 1);
-            }
-            passwordManager.addUser(aHostName, aUsername, aPassword);
-        } else if (Components.classes["@mozilla.org/login-manager;1"]) {
-            // Trunk uses LoginManager
-            var loginManager = Components.classes["@mozilla.org/login-manager;1"]
-                                         .getService(Components.interfaces.nsILoginManager);
-            var logins = loginManager.findLogins({}, aHostName, null, aRealm);
-            if (logins.length > 0) {
-                var loginInfo = logins[0].clone();
-                loginInfo.password = aPassword;
-                loginManager.modifyLogin(logins[0], loginInfo);
-            } else {
-                var loginInfo = Components.classes["@mozilla.org/login-manager/loginInfo;1"]
-                                          .createInstance(Components.interfaces.nsILoginInfo);
-                loginInfo.init(aHostName,
-                               null, aRealm,
-                               aUsername, aPassword,
-                               null, null);
-                loginManager.addLogin(loginInfo);
-            }
-        }
-    } catch (exc) {
-        ASSERT(false, exc);
-    }
-}
-
-/**
- * Helper to retrieve an entry from the password manager.
- *
- * @param in  aUsername     The username to search
- * @param out aPassword     The corresponding password
- * @param aHostName         The corresponding hostname
- * @param aRealm            The password realm (unused on branch)
- * @return                  Does an entry exist in the password manager
- */
-function calPasswordManagerGet(aUsername, aPassword, aHostName, aRealm) {
-    ASSERT(aUsername);
-
-    if (typeof aPassword != "object") {
-        throw new Components.Exception("", Components.results.NS_ERROR_XPC_NEED_OUT_OBJECT);
-    }
-
-    try {
-        if (Components.classes["@mozilla.org/passwordmanager;1"]) {
-            // Branch uses PasswordManager
-            var passwordManager = Components.classes["@mozilla.org/passwordmanager;1"]
-                                            .getService(Components.interfaces.nsIPasswordManager);
-
-            if (aHostName && aHostName[aHostName.length - 1] == '/') {
-                // strip trailing slash on branch:
-                aHostName = aHostName.substr(0, aHostName.length - 1);
-            }
-
-            var enumerator = passwordManager.enumerator;
-            while (enumerator.hasMoreElements()) {
-                var entry = enumerator.getNext().QueryInterface(Components.interfaces.nsIPassword);
-                if ((entry.host == aHostName) &&
-                    (entry.user == aUsername)) {
-                    aPassword.value = entry.password;
-                    return true;
-                }
-            }
-        } else if (Components.classes["@mozilla.org/login-manager;1"]) {
-            // Trunk uses LoginManager
-            var loginManager = Components.classes["@mozilla.org/login-manager;1"]
-                                         .getService(Components.interfaces.nsILoginManager);
-            if (!loginManager.getLoginSavingEnabled(aUsername)) {
-                return false;
-            }
-
-            var logins = loginManager.findLogins({}, aHostName, null, aRealm);
-            for each (var loginInfo in logins) {
-                if (loginInfo.username == aUsername) {
-                    aPassword.value = loginInfo.password;
-                    return true;
-                }
-            }
-        }
-    } catch (exc) {
-        ASSERT(false, exc);
-    }
-    return false;
-}
-
-/**
- * Helper to remove an entry from the password manager
- *
- * @param aUsername     The username to remove.
- * @param aHostName     The corresponding hostname
- * @param aRealm        The password realm (unused on branch)
- * @return              Could the user be removed?
- */
-function calPasswordManagerRemove(aUsername, aHostName, aRealm) {
-    ASSERT(aUsername);
-
-    try {
-        if (Components.classes["@mozilla.org/passwordmanager;1"]) {
-            // Branch uses PasswordManager
-            var passwordManager = Components.classes["@mozilla.org/passwordmanager;1"]
-                                            .getService(Components.interfaces.nsIPasswordManager);
-            if (aHostName && aHostName[aHostName.length - 1] == '/') {
-                // strip trailing slash on branch:
-                aHostName = aHostName.substr(0, aHostName.length - 1);
-            }
-            passwordManager.removeUser(aHostName, aUsername);
-            return true;
-        } else if (Components.classes["@mozilla.org/login-manager;1"]) {
-            // Trunk uses LoginManager
-            var loginManager = Components.classes["@mozilla.org/login-manager;1"]
-                                         .getService(Components.interfaces.nsILoginManager);
-            var logins = loginManager.findLogins({}, aHostName, null, aRealm);
-            for each (var loginInfo in logins) {
-                if (loginInfo.username == aUsername) {
-                    loginManager.removeLogin(loginInfo);
-                    return true;
-                }
-            }
-        }
-    } catch (exc) {
-    }
-    return false;
-}
--- a/calendar/base/src/calCalendarManager.js
+++ b/calendar/base/src/calCalendarManager.js
@@ -35,16 +35,17 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 Components.utils.import("resource://calendar/modules/calUtils.jsm");
+Components.utils.import("resource://calendar/modules/calProviderUtils.jsm");
 
 const REGISTRY_BRANCH = "calendar.registry.";
 const DB_SCHEMA_VERSION = 10;
 
 function getPrefBranchFor(id) {
     return (REGISTRY_BRANCH + id + ".");
 }
 
@@ -515,20 +516,16 @@ calCalendarManager.prototype = {
      */
     createCalendar: function cmgr_createCalendar(type, uri) {
         try {
             var calendar = Components.classes["@mozilla.org/calendar/calendar;1?type=" + type]
                                      .createInstance(Components.interfaces.calICalendar);
             calendar.uri = uri;
             return calendar;
         } catch (ex) {
-            // XXX todo: bug 439620
-            // In general, we might consider to keep calendars disabled in case they couldn't
-            // be created instead of filtering them out. This leaves the chance to clean up
-            // calendar registration, getting rid of error boxes.
             var rc = ex;
             var message = ex;
             if (ex instanceof Components.interfaces.nsIException) {
                 rc = ex.result;
                 message = ex.message;
             }
             switch (rc) {
                 case Components.interfaces.calIErrors.STORAGE_UNKNOWN_SCHEMA_ERROR:
@@ -671,31 +668,40 @@ calCalendarManager.prototype = {
             }
 
             for (let calBranch in allCals) {
                 let id = calBranch.substring(REGISTRY_BRANCH.length);
                 let ctype = cal.getPrefSafe(calBranch + ".type", null);
                 let curi = cal.getPrefSafe(calBranch + ".uri", null);
 
                 try {
-                    let calendar = this.createCalendar(ctype, cal.makeURL(curi));
-                    if (!calendar) {
-                        continue;
-                    }
-                    calendar.id = id;
-
-                    if (calendar.getProperty("auto-enabled") === true) {
-                        calendar.deleteProperty("disabled");
-                        calendar.deleteProperty("auto-enabled");
-                    }
-
-                    if ((calendar.getProperty("cache.supported") !== false) && calendar.getProperty("cache.enabled")) {
-                        calendar = new calCachedCalendar(calendar);
-                    }
-
+                    let uri = cal.makeURL(curi);
+                    let calendar = this.createCalendar(ctype, uri);
+                    if (calendar) {
+                        calendar.id = id;
+                        if (calendar.getProperty("auto-enabled")) {
+                            calendar.deleteProperty("disabled");
+                            calendar.deleteProperty("auto-enabled");
+                        }
+ 
+                        if ((calendar.getProperty("cache.supported") !== false) &&
+                            calendar.getProperty("cache.enabled")) {
+                            calendar = new calCachedCalendar(calendar);
+                        }
+                    } else { // create dummy calendar that stays disabled for this run:
+                        calendar = new calDummyCalendar(ctype);
+                        calendar.id = id;
+                        calendar.uri = uri;
+                        // try to enable on next startup if calendar has been enabled:
+                        if (!calendar.getProperty("disabled")) {
+                            calendar.setProperty("auto-enabled", true);
+                        }
+                        calendar.setProperty("disabled", true);
+                     }
+ 
                     this.setupCalendar(calendar);
                 } catch (exc) {
                     cal.ERROR("Can't create calendar for " + id + " (" + ctype + ", " + curi + "): " + exc);
                 }
             }
 
             // do refreshing in a second step, when *all* calendars are already available
             // via getCalendars():
@@ -931,9 +937,26 @@ calMgrCalendarObserver.prototype = {
                 }
                 // #3 add unload listener (wait for user to close promptWindow)
                 promptWindow.addEventListener("unload", awaitUnload, false);
             }
             // #1 add load listener
             promptWindow.addEventListener("load", awaitLoad, false);
         }
     }
+};
+
+function calDummyCalendar(type) {
+    this.initProviderBase();
+    this.type = type;
 }
+calDummyCalendar.prototype = {
+    __proto__: cal.ProviderBase.prototype,
+
+    getProperty: function calDummyCalendar_getProperty(aName) {
+        switch (aName) {
+            case "force-disabled":
+                return true;
+            default:
+                return this.__proto__.__proto__.getProperty.apply(this, arguments);
+        }
+    }
+};
deleted file mode 100644
--- a/calendar/base/src/calProviderUtils.js
+++ /dev/null
@@ -1,204 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Calendar code.
- *
- * The Initial Developer of the Original Code is
- *   Bruno Browning <browning@uwalumni.com>
- * Portions created by the Initial Developer are Copyright (C) 2008
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Philipp Kewisch <mozilla@kewis.ch>
- *   Daniel Boelzle <daniel.boelzle@sun.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/*
- * Using this file requires calUtils.js to be loaded
- */
-
-/**
- * Prepare HTTP channel with standard request headers and upload
- * data/content-type if needed
- *
- * @param arUri                      Channel Uri, will only be used for a new
- *                                     channel.
- * @param aUploadData                Data to be uploaded, if any. This may be a
- *                                     nsIInputStream or string data. In the
- *                                     latter case the string will be converted
- *                                     to an input stream.
- * @param aContentType               Value for Content-Type header, if any
- * @param aNotificationCallbacks     Calendar using channel
- * @param aExisting                  An existing channel to modify (optional)
- */
-function calPrepHttpChannel(aUri, aUploadData, aContentType, aNotificationCallbacks, aExisting) {
-    let ioService = getIOService();
-    let channel = aExisting || ioService.newChannelFromURI(aUri);
-    let httpchannel = channel.QueryInterface(Components.interfaces.nsIHttpChannel);
-
-    httpchannel.setRequestHeader("Accept", "text/xml", false);
-    httpchannel.setRequestHeader("Accept-Charset", "utf-8,*;q=0.1", false);
-    httpchannel.loadFlags |= Components.interfaces.nsIRequest.LOAD_BYPASS_CACHE;
-    httpchannel.notificationCallbacks = aNotificationCallbacks;
-
-    if (aUploadData) {
-        httpchannel = httpchannel.QueryInterface(Components.interfaces.nsIUploadChannel);
-        let stream;
-        if (aUploadData instanceof Components.interfaces.nsIInputStream) {
-            // Make sure the stream is reset
-            stream = aUploadData.QueryInterface(Components.interfaces.nsISeekableStream);
-            stream.seek(Components.interfaces.nsISeekableStream.NS_SEEK_SET, 0);
-        } else {
-            // Otherwise its something that should be a string, convert it.
-            let converter =
-                Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
-                          .createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
-            converter.charset = "UTF-8";
-            stream = converter.convertToInputStream(aUploadData.toString());
-        }
-
-        httpchannel.setUploadStream(stream, aContentType, -1);
-    }
-
-    return httpchannel;
-}
-
-/**
- * calSendHttpRequest; send prepared HTTP request
- *
- * @param aStreamLoader     streamLoader for request
- * @param aChannel          channel for request
- * @param aListener         listener for method completion
- */
-function calSendHttpRequest(aStreamLoader, aChannel, aListener) {
-    aStreamLoader.init(aListener);
-    aChannel.asyncOpen(aStreamLoader, aChannel);
-}
-
-function createStreamLoader() {
-    return Components.classes["@mozilla.org/network/stream-loader;1"]
-                     .createInstance(Components.interfaces.nsIStreamLoader);
-}
-
-function convertByteArray(aResult, aResultLength, aCharset, aThrow) {
-    try {
-        var resultConverter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
-                                    .createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
-        resultConverter.charset = aCharset || "UTF-8";
-        return resultConverter.convertFromByteArray(aResult, aResultLength);
-    } catch (e) {
-        if (aThrow) {
-            throw e;
-        }
-    }
-    return null;
-}
-
-function safeNewXML(aStr) {
-    // Strip <?xml and surrounding whitespaces
-    return new XML(aStr.replace(/(^\s*(<\?xml[^>]*>)?\s*|\s+$)/g, ""));
-}
-    
-
-/**
- * getInterface method for providers. This should be called in the context of
- * the respective provider, i.e
- *
- * return calInterfaceRequestor_getInterface.apply(this, arguments);
- *
- * or
- * ...
- * getInterface: calInterfaceRequestor_getInterface,
- * ...
- *
- * @param aIID      The interface ID to return
- */
-function calInterfaceRequestor_getInterface(aIID) {
-    // Support Auth Prompt Interfaces
-    if (aIID.equals(Components.interfaces.nsIAuthPrompt) ||
-        (Components.interfaces.nsIAuthPrompt2 &&
-         aIID.equals(Components.interfaces.nsIAuthPrompt2))) {
-        return new calAuthPrompt();
-    } else if (aIID.equals(Components.interfaces.nsIAuthPromptProvider) ||
-               aIID.equals(Components.interfaces.nsIPrompt)) {
-        return Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
-                         .getService(Components.interfaces.nsIWindowWatcher)
-                         .getNewPrompter(null);
-    }
-
-    try {
-        // Try to query the this object for the requested interface but don't
-        // throw if it fails since that borks the network code.
-        return this.QueryInterface(aIID);
-    } catch (e) {
-        Components.returnCode = e;
-    }
-    return null;
-}
-
-/**
- * Freebusy interval implementation. All parameters are optional.
- *
- * @param aCalId         The calendar id to set up with.
- * @param aFreeBusyType  The type from calIFreeBusyInterval.
- * @param aStart         The start of the interval.
- * @param aEnd           The end of the interval.
- * @return               The fresh calIFreeBusyInterval.
- */
-function calFreeBusyInterval(aCalId, aFreeBusyType, aStart, aEnd) {
-    this.calId = aCalId
-    this.interval = Components.classes["@mozilla.org/calendar/period;1"]
-                              .createInstance(Components.interfaces.calIPeriod);
-    this.interval.start = aStart;
-    this.interval.end = aEnd;
-
-    this.freeBusyType = aFreeBusyType ||
-        Components.interfaces.calIFreeBusyInterval.UNKNOWN;
-}
-
-calFreeBusyInterval.prototype = {
-    QueryInterface: function cFBI_QueryInterface(aIID) {
-        return doQueryInterface(this,
-                                calFreeBusyInterval.prototype,
-                                aIID,
-                                [Components.interfaces.calIFreeBusyInterval]);
-    },
-
-    calId: null,
-    interval: null,
-    freeBusyType: Components.interfaces.calIFreeBusyInterval.UNKNOWN
-};
-
-/**
- * Gets the iTIP/iMIP transport if the passed calendar has configured email.
- */
-function calGetImipTransport(aCalendar) {
-    // assure an identity is configured for the calendar
-    return (aCalendar.getProperty("imip.identity")
-            ? Components.classes["@mozilla.org/calendar/itip-transport;1?type=email"]
-                        .getService(Components.interfaces.calIItipTransport)
-            : null);
-}
--- a/calendar/installer/removed-files.in
+++ b/calendar/installer/removed-files.in
@@ -424,8 +424,13 @@ js/calWcapErrors.js
 js/calWcapRequest.js
 js/calWcapSession.js
 js/calWcapUtils.js
 js/calWeekInfoService.js
 js/calWeekPrinter.js
 
 # Bug 462773 drop JSON.jsm
 modules/JSON.jsm
+
+# Bug 439620
+calendar-js/calProviderBase.js
+calendar-js/calProviderUtils.js
+calendar-js/calAuthUtils.js
--- a/calendar/installer/windows/packages-static
+++ b/calendar/installer/windows/packages-static
@@ -217,17 +217,16 @@ bin\components\pluginGlue.js
 bin\components\storage-Legacy.js
 bin\components\storage-mozStorage.js
 bin\components\txEXSLTRegExFunctions.js
 bin\calendar-js\calAlarm.js
 bin\calendar-js\calAlarmMonitor.js
 bin\calendar-js\calAlarmService.js
 bin\calendar-js\calAttachment.js
 bin\calendar-js\calAttendee.js
-bin\calendar-js\calAuthUtils.js
 bin\calendar-js\calCachedCalendar.js
 bin\calendar-js\calCalendarManager.js
 bin\calendar-js\calCalendarSearchService.js
 bin\calendar-js\calDateTimeFormatter.js
 bin\calendar-js\calDavCalendar.js
 bin\calendar-js\calEvent.js
 bin\calendar-js\calFilter.js
 bin\calendar-js\calFreeBusyService.js
@@ -238,18 +237,16 @@ bin\calendar-js\calIcsParser.js
 bin\calendar-js\calIcsSerializer.js
 bin\calendar-js\calItemBase.js
 bin\calendar-js\calItipItem.js
 bin\calendar-js\calListFormatter.js
 bin\calendar-js\calMemoryCalendar.js
 bin\calendar-js\calMonthGridPrinter.js
 bin\calendar-js\calOutlookCSVImportExport.js
 bin\calendar-js\calProtocolHandler.js
-bin\calendar-js\calProviderBase.js
-bin\calendar-js\calProviderUtils.js
 bin\calendar-js\calRecurrenceInfo.js
 bin\calendar-js\calRelation.js
 bin\calendar-js\calStorageCalendar.js
 bin\calendar-js\calTimezoneService.js
 bin\calendar-js\calTodo.js
 bin\calendar-js\calTransactionManager.js
 bin\calendar-js\calUtils.js
 bin\calendar-js\calWcapCalendar.js
--- a/calendar/providers/Makefile.in
+++ b/calendar/providers/Makefile.in
@@ -41,18 +41,17 @@ topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = calprovs
 MODULE_NAME = calProviderModule
 
-DIRS = base \
-       caldav \
+DIRS = caldav \
        composite \
        gdata \
        ics \
        memory \
        storage \
        wcap \
 	   $(NULL)
 
deleted file mode 100644
--- a/calendar/providers/base/Makefile.in
+++ /dev/null
@@ -1,54 +0,0 @@
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is Sun Microsystems code.
-#
-# The Initial Developer of the Original Code is
-#   Philipp Kewisch <mozilla@kewis.ch>
-# Portions created by the Initial Developer are Copyright (C) 2007
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either the GNU General Public License Version 2 or later (the "GPL"), or
-# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-DEPTH		= ../../..
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH		= @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-
-EXTRA_SCRIPTS = calProviderBase.js
-
-libs:: $(EXTRA_SCRIPTS)
-	if test ! -d $(FINAL_TARGET)/calendar-js; then $(NSINSTALL) -D $(FINAL_TARGET)/calendar-js; fi
-	$(INSTALL) $^ $(FINAL_TARGET)/calendar-js
-
-# The install target must use SYSINSTALL, which is NSINSTALL in copy mode.
-install:: $(EXTRA_SCRIPTS)
-	$(SYSINSTALL) $(IFLAGS1) $^ $(DESTDIR)$(mozappdir)/calendar-js
-
-include $(topsrcdir)/config/rules.mk
deleted file mode 100644
--- a/calendar/providers/base/calProviderBase.js
+++ /dev/null
@@ -1,426 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Sun Microsystems code.
- *
- * The Initial Developer of the Original Code is
- *   Philipp Kewisch <mozilla@kewis.ch>
- * Portions created by the Initial Developer are Copyright (C) 2007
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Daniel Boelzle <daniel.boelzle@sun.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/**
- * Gets the configured identity and account of a particular calendar instance, or null.
- *
- * @param aCalendar     Calendar instance
- * @param outAccount    Optional out value for account
- * @return              The configured identity
- */
-function calGetEmailIdentityOfCalendar(aCalendar, outAccount) {
-    ASSERT(aCalendar, "no calendar!", Components.results.NS_ERROR_INVALID_ARG);
-    if (isSunbird()) {
-        return null;
-    }
-    var key = aCalendar.getProperty("imip.identity.key");
-    if (key !== null) {
-        if (key.length == 0) { // i.e. "None"
-            return null;
-        }
-        var identity = null;
-        calIterateEmailIdentities(
-            function(identity_, account) {
-                if (identity_.key == key) {
-                    identity = identity_;
-                    if (outAccount) {
-                        outAccount.value = account;
-                    }
-                }
-                return (identity_.key != key);
-            });
-        if (!identity) {
-            // dangling identity:
-            WARN("Calendar " + (aCalendar.uri ? aCalendar.uri.spec : aCalendar.id) +
-                 " has a dangling E-Mail identity configured.");
-        }
-        return identity;
-    } else { // take default account/identity:
-
-        var accounts = getAccountManager().accounts;
-        var account = null;
-        var identity = null;
-        try {
-            account = getAccountManager().defaultAccount;
-        } catch (exc) {}
-
-        for (var i = 0; accounts && (i < accounts.Count()) && (!account || !identity); ++i) {
-            if (!account) { // Pick an account only if none was set (i.e there is no default account)
-                account = accounts.GetElementAt(i);
-                try {
-                    account = account.QueryInterface(Components.interfaces.nsIMsgAccount);
-                } catch (exc) {
-                    account = null;
-                }
-            }
-
-            if (account && account.identities.Count()) { // Pick an identity
-                identity = account.defaultIdentity;
-                if (!identity) { // there is no default identity, use the first
-                    identity = account.identities.GetElementAt(0)
-                                                 .QueryInterface(Components.interfaces.nsIMsgIdentity);
-                }
-            } else { // If this account has no identities, continue to the next account.
-                account = null;
-            }
-        }
-
-        if (identity) {
-            // If an identity was set above, set the account out parameter
-            // and return the identity
-            if (outAccount) {
-                outAccount.value = account;
-            }
-            return identity;
-        }
-        return null;
-    }
-}
-
-function calProviderBase() {
-    ASSERT("This prototype should only be inherited!");
-}
-calProviderBase.mTransientProperties = {};
-["cache.uncachedCalendar", "currentStatus",
- "itip.transport", "imip.identity", "imip.account",
- "imip.identity.disabled", "organizerId", "organizerCN"].forEach(
-    function(prop) {
-        calProviderBase.mTransientProperties[prop] = true;
-    });
-
-calProviderBase.prototype = {
-    QueryInterface: function cPB_QueryInterface(aIID) {
-        return doQueryInterface(this, calProviderBase.prototype, aIID,
-                                [Components.interfaces.nsISupports,
-                                 Components.interfaces.calICalendar,
-                                 Components.interfaces.calISchedulingSupport]);
-    },
-
-    mID: null,
-    mUri: null,
-    mObservers: null,
-    mProperties: null,
-
-    initProviderBase: function cPB_initProviderBase() {
-        this.wrappedJSObject = this;
-        this.mObservers = new calListenerBag(Components.interfaces.calIObserver);
-        this.mProperties = {};
-        this.mProperties.currentStatus = Components.results.NS_OK;
-    },
-
-    get observers() {
-        return this.mObservers;
-    },
-
-    // attribute AUTF8String id;
-    get id() {
-        return this.mID;
-    },
-    set id(aValue) {
-        if (this.mID) {
-            throw Components.results.NS_ERROR_ALREADY_INITIALIZED;
-        }
-        this.mID = aValue;
-
-//         ASSERT(this.mProperties.toSource() == "({})", "setProperty calls before id has been set!");
-
-        // xxx todo: move this code hack when migrating storage prefs to moz prefs,
-        //           presumably with bug 378754
-        var calMgr = getCalendarManager();
-        var this_ = this;
-        function takeOverIfNotPresent(oldPref, newPref, dontDeleteOldPref) {
-            var val = calMgr.getCalendarPref_(this_, oldPref);
-            if (val !== null) {
-                if (!dontDeleteOldPref) {
-                    calMgr.deleteCalendarPref_(this_, oldPref);
-                }
-                if (calMgr.getCalendarPref_(this_, newPref) === null) {
-                    calMgr.setCalendarPref_(this_, newPref, val);
-                }
-            }
-        }
-        // takeover lightning calendar visibility from 0.5:
-        takeOverIfNotPresent("lightning-main-in-composite", "calendar-main-in-composite");
-        takeOverIfNotPresent("lightning-main-default", "calendar-main-default");
-
-        return aValue;
-    },
-
-    // attribute AUTF8String name;
-    get name() {
-        return this.getProperty("name");
-    },
-    set name(aValue) {
-        return this.setProperty("name", aValue);
-    },
-
-    // attribute calICalendar superCalendar;
-    get superCalendar() {
-        // If we have a superCalendar, check this calendar for a superCalendar.
-        // This will make sure the topmost calendar is returned
-        return (this.mSuperCalendar ? this.mSuperCalendar.superCalendar : this);
-    },
-    set superCalendar(val) {
-        return (this.mSuperCalendar = val);
-    },
-
-    // attribute nsIURI uri;
-    get uri() {
-        return this.mUri;
-    },
-    set uri(aValue) {
-        return (this.mUri = aValue);
-    },
-
-    // attribute boolean readOnly;
-    get readOnly() {
-        return this.getProperty("readOnly");
-    },
-    set readOnly(aValue) {
-        return this.setProperty("readOnly", aValue);
-    },
-
-    // readonly attribute boolean canRefresh;
-    get canRefresh() {
-        return false;
-    },
-
-    // void startBatch();
-    mBatchCount: 0,
-    startBatch: function cPB_startBatch() {
-        if (this.mBatchCount++ == 0) {
-            this.mObservers.notify("onStartBatch");
-        }
-    },
-
-    endBatch: function cPB_endBatch() {
-        if (this.mBatchCount > 0) {
-            if (--this.mBatchCount == 0) {
-                this.mObservers.notify("onEndBatch");
-            }
-        } else {
-            ASSERT(this.mBatchCount > 0, "unexepcted endBatch!");
-        }
-    },
-
-    notifyOperationComplete: function cPB_notifyOperationComplete(aListener,
-                                                                  aStatus,
-                                                                  aOperationType,
-                                                                  aId,
-                                                                  aDetail) {
-        if (aListener) {
-            try {
-                aListener.onOperationComplete(this.superCalendar, aStatus, aOperationType, aId, aDetail);
-            } catch (exc) {
-                ERROR(exc);
-            }
-        }
-        if (aStatus == Components.interfaces.calIErrors.OPERATION_CANCELLED) {
-            return; // cancellation doesn't change current status, no notification
-        }
-        if (Components.isSuccessCode(aStatus)) {
-            this.setProperty("currentStatus", aStatus);
-        } else {
-            if (aDetail instanceof Components.interfaces.nsIException) {
-                this.notifyError(aDetail); // will set currentStatus
-            } else {
-                this.notifyError(aStatus, aDetail); // will set currentStatus
-            }
-            this.notifyError(aOperationType == Components.interfaces.calIOperationListener.GET
-                             ? Components.interfaces.calIErrors.READ_FAILED
-                             : Components.interfaces.calIErrors.MODIFICATION_FAILED,
-                             "");
-        }
-    },
-
-    // for convenience also callable with just an exception
-    notifyError: function cPB_notifyError(aErrNo, aMessage) {
-        if (aErrNo == Components.interfaces.calIErrors.OPERATION_CANCELLED) {
-            return; // cancellation doesn't change current status, no notification
-        }
-        if (aErrNo instanceof Components.interfaces.nsIException) {
-            if (!aMessage) {
-                aMessage = aErrNo.message;
-            }
-            aErrNo = aErrNo.result;
-        }
-        this.setProperty("currentStatus", aErrNo);
-        this.observers.notify("onError", [this.superCalendar, aErrNo, aMessage]);
-    },
-
-    mTransientPropertiesMode: false,
-    get transientProperties cPB_transientProperties() {
-        return this.mTransientPropertiesMode;
-    },
-    set transientProperties cPB_transientProperties(value) {
-        return (this.mTransientPropertiesMode = value);
-    },
-
-    // nsIVariant getProperty(in AUTF8String aName);
-    getProperty: function cPB_getProperty(aName) {
-        switch (aName) {
-            case "itip.transport": // iTIP/iMIP default:
-                return calGetImipTransport(this);
-            case "itip.notify-replies": // iTIP/iMIP default:
-                 return getPrefSafe("calendar.itip.notify-replies", false);
-            // temporary hack to get the uncached calendar instance:
-            case "cache.uncachedCalendar":
-                return this;
-        }
-
-        var ret = this.mProperties[aName];
-        if (ret === undefined) {
-            ret = null;
-            switch (aName) {
-                case "imip.identity": // we want to cache the identity object a little, because
-                                      // it is heavily used by the invitation checks
-                    ret = calGetEmailIdentityOfCalendar(this);
-                    break;
-                case "imip.account": {
-                    var outAccount = {};
-                    if (calGetEmailIdentityOfCalendar(this, outAccount)) {
-                        ret = outAccount.value;
-                    }
-                    break;
-                }
-                case "organizerId": { // itip/imip default: derived out of imip.identity
-                    var identity = this.getProperty("imip.identity");
-                    ret = (identity
-                           ? ("mailto:" + identity.QueryInterface(Components.interfaces.nsIMsgIdentity).email)
-                           : null);
-                    break;
-                }
-                case "organizerCN": { // itip/imip default: derived out of imip.identity
-                    var identity = this.getProperty("imip.identity");
-                    ret = (identity
-                           ? identity.QueryInterface(Components.interfaces.nsIMsgIdentity).fullName
-                           : null);
-                    break;
-                }
-            }
-            if ((ret === null) &&
-                !calProviderBase.mTransientProperties[aName] &&
-                !this.transientProperties) {
-                if (this.id) {
-                    ret = getCalendarManager().getCalendarPref_(this, aName);
-                }
-                if (ret !== null) {
-                    switch (aName) {
-                        case "suppressAlarms":
-                            if (this.getProperty("capabilities.alarms.popup.supported") === false) {
-                                // If popup alarms are not supported,
-                                // automatically suppress alarms
-                                ret = true;
-                            }
-                            break;
-                    }
-                }
-            }
-            this.mProperties[aName] = ret;
-        }
-//         LOG("getProperty(\"" + aName + "\"): " + ret);
-        return ret;
-    },
-
-    // void setProperty(in AUTF8String aName, in nsIVariant aValue);
-    setProperty: function cPB_setProperty(aName, aValue) {
-        var oldValue = this.getProperty(aName);
-        if (oldValue != aValue) {
-            this.mProperties[aName] = aValue;
-            switch (aName) {
-                case "imip.identity.key": // invalidate identity and account object if key is set:
-                    delete this.mProperties["imip.identity"];
-                    delete this.mProperties["imip.account"];
-                    delete this.mProperties["organizerId"];
-                    delete this.mProperties["organizerCN"];
-                    break;
-            }
-            if (!this.transientProperties &&
-                !calProviderBase.mTransientProperties[aName] &&
-                this.id) {
-                getCalendarManager().setCalendarPref_(this, aName, aValue);
-            }
-            this.mObservers.notify("onPropertyChanged",
-                                   [this.superCalendar, aName, aValue, oldValue]);
-        }
-        return aValue;
-    },
-
-    // void deleteProperty(in AUTF8String aName);
-    deleteProperty: function cPB_deleteProperty(aName) {
-        this.mObservers.notify("onPropertyDeleting", [this.superCalendar, aName]);
-        delete this.mProperties[aName];
-        getCalendarManager().deleteCalendarPref_(this, aName);
-    },
-
-    // calIOperation refresh
-    refresh: function cPB_refresh() {
-        return null;
-    },
-
-    // void addObserver( in calIObserver observer );
-    addObserver: function cPB_addObserver(aObserver) {
-        this.mObservers.add(aObserver);
-    },
-
-    // void removeObserver( in calIObserver observer );
-    removeObserver: function cPB_removeObserver(aObserver) {
-        this.mObservers.remove(aObserver);
-    },
-
-    // calISchedulingSupport: Implementation corresponding to our iTIP/iMIP support
-    isInvitation: function cPB_isInvitation(aItem) {
-        var id = this.getProperty("organizerId");
-        if (id) {
-            var org = aItem.organizer;
-            if (!org || (org.id.toLowerCase() == id.toLowerCase())) {
-                return false;
-            }
-            return (aItem.getAttendeeById(id) != null);
-        }
-        return false;
-    },
-
-    getInvitedAttendee: function cPB_getInvitedAttendee(aItem) {
-        var id = this.getProperty("organizerId");
-        return (id ? aItem.getAttendeeById(id) : null);
-    },
-
-    canNotify: function cPB_canNotify(aMethod, aItem) {
-        return false; // use outbound iTIP for all
-    }
-};
--- a/calendar/providers/caldav/calDavCalendar.js
+++ b/calendar/providers/caldav/calDavCalendar.js
@@ -40,16 +40,18 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 Components.utils.import("resource://calendar/modules/calUtils.jsm");
 Components.utils.import("resource://calendar/modules/calIteratorUtils.jsm");
+Components.utils.import("resource://calendar/modules/calProviderUtils.jsm");
+Components.utils.import("resource://calendar/modules/calAuthUtils.jsm");
 
 //
 // calDavCalendar.js
 //
 
 const xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>\n';
 
 function calDavCalendar() {
@@ -89,17 +91,17 @@ const kDavResourceTypeCollection = 1;
 const kDavResourceTypeCalendar = 2;
 
 // used for etag checking
 const CALDAV_ADOPT_ITEM = 1;
 const CALDAV_MODIFY_ITEM = 2;
 const CALDAV_DELETE_ITEM = 3;
 
 calDavCalendar.prototype = {
-    __proto__: calProviderBase.prototype,
+    __proto__: cal.ProviderBase.prototype,
 
     //
     // nsISupports interface
     //
     QueryInterface: function caldav_QueryInterface(aIID) {
         return doQueryInterface(this, calDavCalendar.prototype, aIID,
                                 [Components.interfaces.calICalendarProvider,
                                  Components.interfaces.nsIInterfaceRequestor,
@@ -357,17 +359,17 @@ calDavCalendar.prototype = {
                 break;
             case "organizerCN":
                 return null; // xxx todo
             case "itip.transport":
                 if (this.hasAutoScheduling) {
                     return null;
                 } else if (this.hasScheduling) {
                     return this.QueryInterface(Components.interfaces.calIItipTransport);
-                } // else use outbound email-based iTIP (from calProviderBase.js)
+                } // else use outbound email-based iTIP (from cal.ProviderBase)
                 break;
             case "capabilities.tasks.supported":
                 return (this.supportedItemTypes.indexOf("VTODO") > -1);
             case "capabilities.events.supported":
                 return (this.supportedItemTypes.indexOf("VEVENT") > -1);
         }
         return this.__proto__.__proto__.getProperty.apply(this, arguments);
     },
@@ -472,17 +474,17 @@ calDavCalendar.prototype = {
             let request = aLoader.request;
             let status;
             try {
                 status = request.responseStatus;
             } catch (ex) {
                 status = Components.interfaces.calIErrors.DAV_PUT_ERROR;
             }
             if (thisCalendar.verboseLogging()) {
-                var str = convertByteArray(aResult, aResultLength);
+                let str = cal.convertByteArray(aResult, aResultLength);
                 LOG("CalDAV: recv: " + (str || ""));
             }
             // 201 = HTTP "Created"
             // 204 = HTTP "No Content"
             //
             if (status == 201 || status == 204) {
                 LOG("CalDAV: Item added successfully");
 
@@ -497,28 +499,27 @@ calDavCalendar.prototype = {
                 }
                 LOG("CalDAV: Unexpected status adding item: " + status);
                 thisCalendar.reportDavError(Components.interfaces.calIErrors.DAV_PUT_ERROR);
             }
         };
 
         parentItem.calendar = this.superCalendar;
 
-        var httpchannel = calPrepHttpChannel(itemUri,
-                                             this.getSerializedItem(aItem),
-                                             "text/calendar; charset=utf-8",
-                                             this);
+        let httpchannel = cal.prepHttpChannel(itemUri,
+                                              this.getSerializedItem(aItem),
+                                              "text/calendar; charset=utf-8",
+                                              this);
 
 
         if (!aIgnoreEtag) {
             httpchannel.setRequestHeader("If-None-Match", "*", false);
         }
 
-        var streamLoader = createStreamLoader();
-        calSendHttpRequest(streamLoader, httpchannel, addListener);
+        cal.sendHttpRequest(cal.createStreamLoader(), httpchannel, addListener);
     },
 
     /**
      * modifyItem(); required by calICalendar.idl
      * we actually use doModifyItem()
      *
      * @param aItem       item to check
      * @param aListener   listener for method completion
@@ -602,29 +603,28 @@ calDavCalendar.prototype = {
                 if (status > 999) {
                     status = "0x " + status.toString(16);
                 }
                 LOG("CalDAV: Unexpected status on modifying item: " + status);
                 thisCalendar.reportDavError(Components.interfaces.calIErrors.DAV_PUT_ERROR);
             }
         };
 
-        var httpchannel = calPrepHttpChannel(eventUri,
-                                             modifiedItemICS,
-                                             "text/calendar; charset=utf-8",
-                                             this);
+        let httpchannel = cal.prepHttpChannel(eventUri,
+                                              modifiedItemICS,
+                                              "text/calendar; charset=utf-8",
+                                              this);
 
         if (!aIgnoreEtag) {
             httpchannel.setRequestHeader("If-Match",
                                          this.mItemInfoCache[aNewItem.id].etag,
                                          false);
         }
 
-        var streamLoader = createStreamLoader();
-        calSendHttpRequest(streamLoader, httpchannel, modListener);
+        cal.sendHttpRequest(cal.createStreamLoader(), httpchannel, modListener);
     },
 
     /**
      * deleteItem(); required by calICalendar.idl
      * the actual deletion is done in doDeleteItem()
      *
      * @param aItem       item to delete
      * @param aListener   listener for method completion
@@ -691,23 +691,22 @@ calDavCalendar.prototype = {
                     delete thisCalendar.mHrefIndex[eventUri.path];
                     delete thisCalendar.mItemInfoCache[aItem.id];
                     LOG("CalDAV: Item deleted successfully.");
                 }
             } else if (status == 412) {
                 // item has either been modified or deleted by someone else
                 // check to see which
 
-                var httpchannel2 = calPrepHttpChannel(eventUri,
-                                                      null,
-                                                      null,
-                                                      thisCalendar);
+                let httpchannel2 = cal.prepHttpChannel(eventUri,
+                                                       null,
+                                                       null,
+                                                       thisCalendar);
                 httpchannel2.requestMethod = "HEAD";
-                var streamLoader2 = createStreamLoader();
-                calSendHttpRequest(streamLoader2, httpchannel2, delListener2);
+                cal.sendHttpRequest(cal.createStreamLoader(), httpchannel2, delListener2);
             } else {
                 LOG("CalDAV: Unexpected status deleting item: " + status);
                 thisCalendar.reportDavError(Components.interfaces.calIErrors.DAV_REMOVE_ERROR);
             }
         };
         var delListener2 = {};
         delListener2.onStreamComplete =
         function caldav_dDI_del2_onStreamComplete(aLoader, aContext, aStatus, aResultLength, aResult) {
@@ -717,26 +716,25 @@ calDavCalendar.prototype = {
                 // someone else already deleted it
                 return;
             } else {
                 thisCalendar.promptOverwrite(CALDAV_DELETE_ITEM, aItem,
                                              realListener, null);
             }
         };
 
-        var httpchannel = calPrepHttpChannel(eventUri, null, null, this);
+        let httpchannel = cal.prepHttpChannel(eventUri, null, null, this);
         if (!aIgnoreEtag) {
             httpchannel.setRequestHeader("If-Match",
                                          this.mItemInfoCache[aItem.id].etag,
                                          false);
         }
         httpchannel.requestMethod = "DELETE";
 
-        var streamLoader = createStreamLoader();
-        calSendHttpRequest(streamLoader, httpchannel, delListener);
+        cal.sendHttpRequest(cal.createStreamLoader(), httpchannel, delListener);
     },
 
     /**
      * Retrieves a specific item from the CalDAV store.
      * Use when an outdated copy of the item is in hand.
      *
      * @param aItem       item to fetch
      * @param aListener   listener for method completion
@@ -810,18 +808,17 @@ calDavCalendar.prototype = {
     safeRefresh: function caldav_safeRefresh(aChangeLogListener) {
         this.ensureTargetCalendar();
 
         if (this.mAuthScheme == "Digest") {
             // the auth could have timed out and be in need of renegotiation
             // we can't risk several calendars doing this simultaneously so
             // we'll force the renegotiation in a sync query, using HEAD to keep
             // it quick
-            var headchannel = calPrepHttpChannel(this.calendarUri, null, null,
-                                                 this);
+            let headchannel = cal.prepHttpChannel(this.calendarUri, null, null, this);
             headchannel.requestMethod = "HEAD";
             headchannel.open();
         }
 
         if (!this.mCtag || !this.mFirstRefreshDone) {
             this.getUpdatedItems(this.calendarUri, aChangeLogListener);
             return;
         }
@@ -832,44 +829,44 @@ calDavCalendar.prototype = {
         var queryXml = <D:propfind xmlns:D={D} xmlns:CS={CS}>
                         <D:prop>
                             <CS:getctag/>
                         </D:prop>
                         </D:propfind>;
         if (this.verboseLogging()) {
             LOG("CalDAV: send: " + queryXml);
         }
-        var httpchannel = calPrepHttpChannel(this.calendarUri,
-                                             queryXml,
-                                             "text/xml; charset=utf-8",
-                                             this);
+        let httpchannel = cal.prepHttpChannel(this.calendarUri,
+                                              queryXml,
+                                              "text/xml; charset=utf-8",
+                                              this);
         httpchannel.setRequestHeader("Depth", "0", false);
         httpchannel.requestMethod = "PROPFIND";
 
         var streamListener = {};
         streamListener.onStreamComplete =
             function safeRefresh_safeRefresh_onStreamComplete(aLoader, aContext, aStatus, aResultLength, aResult) {
             let request = aLoader.request;
             try {
                 LOG("CalDAV: Status " + request.responseStatus +
                     " checking ctag for calendar " + thisCalendar.name);
             } catch (ex) {
                 LOG("CalDAV: Error without status on checking ctag for calendar " +
                     thisCalendar.name);
             }
 
-            var str = convertByteArray(aResult, aResultLength);
+            let str = cal.convertByteArray(aResult, aResultLength);
             if (!str) {
                 LOG("CalDAV: Failed to get ctag from server");
             } else if (thisCalendar.verboseLogging()) {
                 LOG("CalDAV: recv: " + str);
             }
 
             try {
-                var multistatus = safeNewXML(str);
+                var multistatus = cal.safeNewXML(str);
             } catch (ex) {
                 LOG("CalDAV: Failed to get ctag from server");
                 return;
             }
 
             var ctag = multistatus..CS::getctag.toString();
             if (!ctag.length || ctag != thisCalendar.mCtag) {
                 // ctag mismatch, need to fetch calendar-data
@@ -886,18 +883,17 @@ calDavCalendar.prototype = {
                         + thisCalendar.name);
                 }
                 // we may still need to poll the inbox
                 if (thisCalendar.firstInRealm()) {
                     thisCalendar.pollInbox();
                 }
             }
         };
-        var streamLoader = createStreamLoader();
-        calSendHttpRequest(streamLoader, httpchannel, streamListener);
+        cal.sendHttpRequest(cal.createStreamLoader(), httpchannel, streamListener);
     },
 
     refresh: function caldav_refresh() {
         if (!this.mCheckedServerInfo) {
             // If we haven't refreshed yet, then we should check the resource
             // type first. This will call refresh() again afterwards.
             this.checkDavResourceType(null);
         } else {
@@ -977,24 +973,24 @@ calDavCalendar.prototype = {
                 LOG("CalDAV: Error without status on getetag for calendar " +
                     thisCalendar.name);
                 responseStatus = "none";
             }
 
             if (responseStatus == 207) {
                 // We only need to parse 207's, anything else is probably a
                 // server error (i.e 50x).
-                var str = convertByteArray(aResult, aResultLength);
+                let str = cal.convertByteArray(aResult, aResultLength);
                 if (!str) {
                     LOG("CAlDAV: Failed to parse getetag PROPFIND");
                 } else if (thisCalendar.verboseLogging()) {
                     LOG("CalDAV: recv: " + str);
                 }
 
-                var multistatus = safeNewXML(str);
+                let multistatus = cal.safeNewXML(str);
                 for each (let response in multistatus.*::response) {
                     var etag = response..D::["getetag"];
                     if (etag.length() == 0) {
                         continue;
                     }
                     var contenttype = null;
                     contenttype = response..D::["getcontenttype"];
                     // workaround for a Scalix bug which causes incorrect
@@ -1117,24 +1113,23 @@ calDavCalendar.prototype = {
                                          null,
                                          aChangeLogListener);
         };
 
         if (this.verboseLogging()) {
             LOG("CalDAV: send(" + aUri.spec + "): " + queryString);
         }
 
-        var httpchannel = calPrepHttpChannel(aUri,
-                                             queryString,
-                                             "text/xml; charset=utf-8",
-                                             this);
+        let httpchannel = cal.prepHttpChannel(aUri,
+                                              queryString,
+                                              "text/xml; charset=utf-8",
+                                              this);
         httpchannel.requestMethod = "PROPFIND";
         httpchannel.setRequestHeader("Depth", "1", false);
-        var streamLoader = createStreamLoader();
-        calSendHttpRequest(streamLoader, httpchannel, etagListener);
+        cal.sendHttpRequest(cal.createStreamLoader(), httpchannel, etagListener);
     },
 
     getCalendarData: function caldav_getCalendarData(aUri, aQuery, aItem, aListener, aChangeLogListener) {
         this.ensureTargetCalendar();
 
         var thisCalendar = this;
         var caldataListener = {};
         var C = new Namespace("C", "urn:ietf:params:xml:ns:caldav");
@@ -1156,32 +1151,32 @@ calDavCalendar.prototype = {
             }
             if (responseStatus != 207) {
                 LOG("error: got status " + responseStatus + " fetching calendar data");
                 if (thisCalendar.isCached && aChangeLogListener)
                     aChangeLogListener.onResult({ status: Components.results.NS_ERROR_FAILURE },
                                                 Components.results.NS_ERROR_FAILURE);
                 return;
             }
-            var str = convertByteArray(aResult, aResultLength);
+            let str = cal.convertByteArray(aResult, aResultLength);
             if (!str) {
                 LOG("CalDAV: Failed to parse getCalendarData REPORT");
                 if (thisCalendar.isCached && aChangeLogListener) {
                     aChangeLogListener.onResult({ status: Components.results.NS_ERROR_FAILURE },
                                                 Components.results.NS_ERROR_FAILURE);
                 }
                 return;
             } else if (thisCalendar.verboseLogging()) {
                 LOG("CalDAV: recv: " + str);
             }
             if (thisCalendar.isCached) {
                 thisCalendar.superCalendar.startBatch();
             }
             try {
-                var multistatus = safeNewXML(str);
+                let multistatus = cal.safeNewXML(str);
                 for each (let response in multistatus.*::response) {
 
                     var hasNon200 = false;
                     var non200Statuses = [];
                     for each (let itemStatus in response..D::["status"]) {
                       var status = itemStatus.toString().split(" ")[1];
                       if (status != 200) {
                           hasNon200 = true;
@@ -1283,31 +1278,30 @@ calDavCalendar.prototype = {
                 thisCalendar.pollInbox();
             }
         };
 
         if (this.verboseLogging()) {
             LOG("CalDAV: send: " + aQuery);
         }
 
-        var httpchannel = calPrepHttpChannel(aUri,
-                                             aQuery,
-                                             "text/xml; charset=utf-8",
-                                             this);
+        let httpchannel = cal.prepHttpChannel(aUri,
+                                              aQuery,
+                                              "text/xml; charset=utf-8",
+                                              this);
         httpchannel.requestMethod = "REPORT";
         httpchannel.setRequestHeader("Depth", "1", false);
-        var streamLoader = createStreamLoader();
-        calSendHttpRequest(streamLoader, httpchannel, caldataListener);
+        cal.sendHttpRequest(cal.createStreamLoader(), httpchannel, caldataListener);
     },
 
     /**
      * @see nsIInterfaceRequestor
-     * @see calProviderUtils.js
+     * @see calProviderUtils.jsm
      */
-    getInterface: calInterfaceRequestor_getInterface,
+    getInterface: cal.InterfaceRequestor_getInterface,
 
     //
     // Helper functions
     //
 
     /**
      * Checks that the calendar URI exists and is a CalDAV calendar. This is the
      * beginning of a chain of asynchronous calls. This function will, when
@@ -1334,20 +1328,20 @@ calDavCalendar.prototype = {
                             <D:resourcetype/>
                             <D:owner/>
                             <CS:getctag/>
                         </D:prop>
                         </D:propfind>;
         if (this.verboseLogging()) {
             LOG("CalDAV: send: " + queryXml);
         }
-        var httpchannel = calPrepHttpChannel(this.calendarUri,
-                                             queryXml,
-                                             "text/xml; charset=utf-8",
-                                             this);
+        let httpchannel = cal.prepHttpChannel(this.calendarUri,
+                                              queryXml,
+                                              "text/xml; charset=utf-8",
+                                              this);
         httpchannel.setRequestHeader("Depth", "0", false);
         httpchannel.requestMethod = "PROPFIND";
 
         var streamListener = {};
 
         streamListener.onStreamComplete =
             function checkDavResourceType_oSC(aLoader, aContext, aStatus, aResultLength, aResult) {
             let request = aLoader.request;
@@ -1374,28 +1368,28 @@ calDavCalendar.prototype = {
             // we only really need the authrealm for Digest auth
             // since only Digest is going to time out on us
             if (thisCalendar.mAuthScheme == "Digest") {
                 var realmChop = wwwauth.split("realm=\"")[1];
                 thisCalendar.mAuthRealm = realmChop.split("\", ")[0];
                 LOG("CalDAV: realm " + thisCalendar.mAuthRealm);
             }
 
-            var str = convertByteArray(aResult, aResultLength);
+            let str = cal.convertByteArray(aResult, aResultLength);
             if (!str) {
                 LOG("CalDAV: Failed to determine resource type");
                 thisCalendar.completeCheckServerInfo(aChangeLogListener,
                                                      Components.interfaces.calIErrors.DAV_NOT_DAV);
                 return;
             } else if (thisCalendar.verboseLogging()) {
                 LOG("CalDAV: recv: " + str);
             }
 
             try {
-                var multistatus = safeNewXML(str);
+                var multistatus = cal.safeNewXML(str);
             } catch (ex) {
                 thisCalendar.completeCheckServerInfo(aChangeLogListener,
                                                      Components.interfaces.calIErrors.DAV_NOT_DAV);
                 return;
             }
 
             // check for server-side ctag support
             var ctag = multistatus..CS::["getctag"].toString();
@@ -1445,34 +1439,33 @@ calDavCalendar.prototype = {
                 thisCalendar.mDisabled) {
                 thisCalendar.mDisabled = false;
                 thisCalendar.mReadOnly = false;
             }
 
             thisCalendar.setCalHomeSet();
             thisCalendar.checkServerCaps(aChangeLogListener);
         };
-        var streamLoader = createStreamLoader();
-        calSendHttpRequest(streamLoader, httpchannel, streamListener);
+        cal.sendHttpRequest(cal.createStreamLoader(), httpchannel, streamListener);
     },
 
     /**
      * Checks server capabilities.
      *
      * checkDavResourceType
      * checkServerCaps                              * You are here
      * findPrincipalNS
      * checkPrincipalsNameSpace
      * completeCheckServerInfo
      */
     checkServerCaps: function caldav_checkServerCaps(aChangeLogListener) {
         var homeSet = this.mCalHomeSet.clone();
         var thisCalendar = this;
 
-        var httpchannel = calPrepHttpChannel(homeSet, null, null, this);
+        let httpchannel = cal.prepHttpChannel(homeSet, null, null, this);
 
         httpchannel.requestMethod = "OPTIONS";
         if (this.verboseLogging()) {
             LOG("CalDAV: send: OPTIONS");
         }
 
         var streamListener = {};
         streamListener.onStreamComplete =
@@ -1482,17 +1475,17 @@ calDavCalendar.prototype = {
             let dav = null;
             try {
                 dav = request.getResponseHeader("DAV");
                 if (thisCalendar.verboseLogging()) {
                     LOG("CalDAV: DAV header: " + dav);
                 }
             } catch (ex) {
                 LOG("CalDAV: Error getting DAV header, status " + request.responseStatus +
-                    ", data: " + convertByteArray(aResult, aResultLength));
+                    ", data: " + cal.convertByteArray(aResult, aResultLength));
             
             }
             // Google does not yet support OPTIONS but does support scheduling
             // so we'll spoof the DAV header until Google gets fixed
             if (thisCalendar.calendarUri.host == "www.google.com") {
                 dav = "calendar-schedule";
                 // Google also reports an inbox URL distinct from the calendar
                 // URL but a) doesn't use it and b) 405s on etag queries to it
@@ -1519,18 +1512,17 @@ calDavCalendar.prototype = {
                 getFreeBusyService().addProvider(thisCalendar);
                 thisCalendar.findPrincipalNS(aChangeLogListener);
             } else {
                 LOG("CalDAV: Server does not support CalDAV scheduling.");
                 thisCalendar.completeCheckServerInfo(aChangeLogListener);
             }
         };
 
-        var streamLoader = createStreamLoader();
-        calSendHttpRequest(streamLoader, httpchannel, streamListener);
+        cal.sendHttpRequest(cal.createStreamLoader(), httpchannel, streamListener);
     },
 
     /**
      * Locates the principal namespace. This function should soely be called
      * from checkServerCaps to find the principal namespace.
      *
      * checkDavResourceType
      * checkServerCaps
@@ -1555,20 +1547,20 @@ calDavCalendar.prototype = {
                 <D:prop>
                     <D:principal-collection-set/>
                 </D:prop>
             </D:propfind>;
 
         if (this.verboseLogging()) {
             LOG("CalDAV: send: " + homeSet.spec + "\n"  + queryXml);
         }
-        var httpchannel = calPrepHttpChannel(homeSet,
-                                             queryXml,
-                                             "text/xml; charset=utf-8",
-                                             this);
+        let httpchannel = cal.prepHttpChannel(homeSet,
+                                              queryXml,
+                                              "text/xml; charset=utf-8",
+                                              this);
 
         httpchannel.setRequestHeader("Depth", "0", false);
         httpchannel.requestMethod = "PROPFIND";
 
         var streamListener = {};
         streamListener.onStreamComplete =
             function findInOutboxes_oSC(aLoader, aContext, aStatus,
                                          aResultLength, aResult) {
@@ -1576,40 +1568,39 @@ calDavCalendar.prototype = {
             if (request.responseStatus != 207) {
                 LOG("CalDAV: Unexpected status " + request.responseStatus +
                     " while querying principal namespace");
                 thisCalendar.completeCheckServerInfo(aChangeLogListener,
                                                      Components.results.NS_ERROR_FAILURE);
                 return;
             }
 
-            var str = convertByteArray(aResult, aResultLength);
+            let str = cal.convertByteArray(aResult, aResultLength);
             if (!str) {
                 LOG("CalDAV: Failed to propstat principal namespace");
                 thisCalendar.completeCheckServerInfo(aChangeLogListener,
                                                      Components.results.NS_ERROR_FAILURE);
                 return;
             } else if (thisCalendar.verboseLogging()) {
                 LOG("CalDAV: recv: " + str);
             }
 
-            var multistatus = safeNewXML(str);
+            let multistatus = cal.safeNewXML(str);
             var pcs = multistatus..D::["principal-collection-set"]..D::href;
             var nsList = [];
             for (var ns in pcs) {
                 var nsString = pcs[ns].toString();
                 var nsPath = thisCalendar.ensurePath(nsString);
                 nsList.push(nsPath);
             }
 
             thisCalendar.checkPrincipalsNameSpace(nsList, aChangeLogListener);
         };
 
-        var streamLoader = createStreamLoader();
-        calSendHttpRequest(streamLoader, httpchannel, streamListener);
+        cal.sendHttpRequest(cal.createStreamLoader(), httpchannel, streamListener);
     },
 
     /**
      * Checks the principals namespace for scheduling info. This function should
      * soely be called from findPrincipalNS
      *
      * checkDavResourceType
      * checkServerCaps
@@ -1681,50 +1672,50 @@ calDavCalendar.prototype = {
         // We want a trailing slash, ensure it.
         var nsUri = this.calendarUri.clone();
         nsUri.path = aNameSpaceList.pop().replace(/([^\/])$/, "$1/");
 
         if (this.verboseLogging()) {
             LOG("CalDAV: send: " + queryMethod + " " + nsUri.spec + "\n" + queryXml);
         }
 
-        var httpchannel = calPrepHttpChannel(nsUri,
-                                             queryXml,
-                                             "text/xml; charset=utf-8",
-                                             this);
+        let httpchannel = cal.prepHttpChannel(nsUri,
+                                              queryXml,
+                                              "text/xml; charset=utf-8",
+                                              this);
 
         httpchannel.requestMethod = queryMethod;
         if (queryDepth == 0) {
             // Set header, doing this for Depth: 1 is not needed since thats the
             // default.
             httpchannel.setRequestHeader("Depth", "0", false);
         }
 
         var streamListener = {};
         streamListener.onStreamComplete =
             function caldav_cPNS_oSC(aLoader, aContext, aStatus,
                                          aResultLength, aResult) {
-            var str = convertByteArray(aResult, aResultLength);
+            let str = cal.convertByteArray(aResult, aResultLength);
             if (!str) {
                 LOG("CalDAV: Failed to report principals namespace");
                 doesntSupportScheduling();
                 return;
             } else if (thisCalendar.verboseLogging()) {
                 LOG("CalDAV: recv: " + str);
             }
 
             if (aLoader.request.responseStatus != 207) {
                 LOG("CalDAV: Bad response to in/outbox query, status " +
                     aLoader.request.responseStatus);
                 doesntSupportScheduling();
                 return;
             }
 
-            var multistatus = safeNewXML(str);
-            var multistatusLength = multistatus.*::response.length();
+            let multistatus = cal.safeNewXML(str);
+            let multistatusLength = multistatus.*::response.length();
 
             for each (let response in multistatus.*::response) {
                 let responseCHS = null;
                 try {
                     responseCHS = response..*::["calendar-home-set"]..*::href[0].toString().replace(/([^/])$/, "$1/");
                 } catch (ex) {}
 
                 if (multistatusLength > 1 &&
@@ -1767,18 +1758,17 @@ calDavCalendar.prototype = {
                     doesntSupportScheduling();
                 }
             } else {
                 // We have everything, complete.
                 thisCalendar.completeCheckServerInfo(aChangeLogListener);
             }
         };
 
-        var streamLoader = createStreamLoader();
-        calSendHttpRequest(streamLoader, httpchannel, streamListener);
+        cal.sendHttpRequest(cal.createStreamLoader(), httpchannel, streamListener);
     },
 
     /**
      * This is called to complete checking the server info. It should be the
      * final call when checking server options. This will either report the
      * error or if it is a success then refresh the calendar.
      *
      * checkDavResourceType
@@ -1911,31 +1901,31 @@ calDavCalendar.prototype = {
         fbComp.addProperty(prop);
         fbQuery.addSubcomponent(fbComp);
         fbQuery = fbQuery.serializeToICS();
         if (this.verboseLogging()) {
             LOG("CalDAV: send (Originator=" + organizer +
                     ",Recipient=" + mailto_aCalId + "): " + fbQuery);
         }
 
-        var httpchannel = calPrepHttpChannel(this.outboxUrl,
-                                             fbQuery,
-                                             "text/calendar; charset=utf-8",
-                                             this);
+        let httpchannel = cal.prepHttpChannel(this.outboxUrl,
+                                              fbQuery,
+                                              "text/calendar; charset=utf-8",
+                                              this);
         httpchannel.requestMethod = "POST";
         httpchannel.setRequestHeader("Originator", organizer, false);
         httpchannel.setRequestHeader("Recipient", mailto_aCalId, false);
 
         var streamListener = {};
 
         streamListener.onStreamComplete =
             function caldav_GFBI_oSC(aLoader, aContext, aStatus,
                                          aResultLength, aResult) {
             let request = aLoader.request;
-            let str = convertByteArray(aResult, aResultLength);
+            let str = cal.convertByteArray(aResult, aResultLength);
             if (!str) {
                 LOG("CalDAV: Failed to parse freebusy response");
             } else if (thisCalendar.verboseLogging()) {
                 LOG("CalDAV: recv: " + str);
             }
 
             if (request.responseStatus == 200) {
                 var periodsToReturn = [];
@@ -1944,18 +1934,18 @@ calDavCalendar.prototype = {
                 var fbTypeMap = {};
                 fbTypeMap["FREE"] = calIFreeBusyInterval.FREE;
                 fbTypeMap["BUSY"] = calIFreeBusyInterval.BUSY;
                 fbTypeMap["BUSY-UNAVAILABLE"] = calIFreeBusyInterval.BUSY_UNAVAILABLE;
                 fbTypeMap["BUSY-TENTATIVE"] = calIFreeBusyInterval.BUSY_TENTATIVE;
                 var C = new Namespace("C", "urn:ietf:params:xml:ns:caldav");
                 var D = new Namespace("D", "DAV:");
 
-                var response = safeNewXML(str);
-                var status = response..C::response..C::["request-status"];
+                let response = cal.safeNewXML(str);
+                let status = response..C::response..C::["request-status"];
                 if (status.substr(0,1) != 2) {
                     LOG("CalDAV: Got status " + status + " in response to freebusy query");
                     aListener.onResult(null, null);
                     return;
                 }
                 if (status.substr(0,3) != "2.0") {
                     LOG("CalDAV: Got status " + status + " in response to freebusy query");
                 }
@@ -1963,28 +1953,28 @@ calDavCalendar.prototype = {
                 var caldata = response..C::response..C::["calendar-data"];
                 try {
                     let calComp = getIcsService().parseICS(caldata, null);
                     for (let fbComp in cal.ical.calendarComponentIterator(calComp)) {
                         let interval;
 
                         let replyRangeStart = fbComp.startTime;
                         if (replyRangeStart && (aRangeStart.compare(replyRangeStart) == -1)) {
-                            interval = new calFreeBusyInterval(aCalId,
-                                                               calIFreeBusyInterval.UNKNOWN,
-                                                               aRangeStart,
-                                                               replyRangeStart);
+                            interval = new cal.FreeBusyInterval(aCalId,
+                                                                calIFreeBusyInterval.UNKNOWN,
+                                                                aRangeStart,
+                                                                replyRangeStart);
                             periodsToReturn.push(interval);
                         }
                         let replyRangeEnd = fbComp.endTime;
                         if (replyRangeEnd && (aRangeEnd.compare(replyRangeEnd) == 1)) {
-                            interval = new calFreeBusyInterval(aCalId,
-                                                               calIFreeBusyInterval.UNKNOWN,
-                                                               replyRangeEnd,
-                                                               aRangeEnd);
+                            interval = new cal.FreeBusyInterval(aCalId,
+                                                                calIFreeBusyInterval.UNKNOWN,
+                                                                replyRangeEnd,
+                                                                aRangeEnd);
                             periodsToReturn.push(interval);
                         }
 
                         for (let fbProp in cal.ical.propertyIterator(fbComp, "FREEBUSY")) {
                             let fbType = fbProp.getParameter("FBTYPE");
                             if (fbType) {
                                 fbType = fbTypeMap[fbType];
                             } else {
@@ -1995,36 +1985,35 @@ calDavCalendar.prototype = {
                             let end;
                             if (parts[1].charAt(0) == "P") { // this is a duration
                                 end = begin.clone();
                                 end.addDuration(cal.createDuration(parts[1]))
                             } else {
                                 // This is a date string
                                 end = cal.createDateTime(parts[1]);
                             }
-                            interval = new calFreeBusyInterval(aCalId,
-                                                               fbType,
-                                                               begin,
-                                                               end);
+                            interval = new cal.FreeBusyInterval(aCalId,
+                                                                fbType,
+                                                                begin,
+                                                                end);
                             periodsToReturn.push(interval);
                         }
                     }
                 } catch (exc) {
                     LOG("Error parsing free-busy info.");
                 }
 
                 aListener.onResult(null, periodsToReturn);
             } else {
                 LOG("CalDAV: Received status " + request.responseStatus + " from freebusy query");
                 aListener.onResult(null, null);
             }
         };
 
-        var streamLoader = createStreamLoader();
-        calSendHttpRequest(streamLoader, httpchannel, streamListener);
+        cal.sendHttpRequest(cal.createStreamLoader(), httpchannel, streamListener);
     },
 
     ensurePath: function caldav_ensurePath(aString) {
         if (aString.charAt(0) != "/") {
             var bogusUri = makeURL(aString);
             return bogusUri.path;
         }
         return aString;
@@ -2046,17 +2035,17 @@ calDavCalendar.prototype = {
         if (!this.hasScheduling || !this.mShouldPollInbox || !this.firstInRealm()) {
             return;
         }
 
         this.getUpdatedItems(this.mInboxUrl, null);
     },
 
     //
-    // take calISchedulingSupport interface base implementation (calProviderBase.js)
+    // take calISchedulingSupport interface base implementation (cal.ProviderBase)
     //
 
     processItipReply: function caldav_processItipReply(aItem, aPath) {
         // modify partstat for in-calendar item
         // delete item from inbox
         var thisCalendar = this;
 
         var getItemListener = {};
@@ -2154,20 +2143,20 @@ calDavCalendar.prototype = {
             var serializer = Components.classes["@mozilla.org/calendar/ics-serializer;1"]
                                        .createInstance(Components.interfaces.calIIcsSerializer);
             serializer.addItems([item], 1);
             var methodProp = getIcsService().createIcalProperty("METHOD");
             methodProp.value = aItipItem.responseMethod;
             serializer.addProperty(methodProp);
             var uploadData = serializer.serializeToString();
 
-            var httpchannel = calPrepHttpChannel(this.outboxUrl,
-                                                 uploadData,
-                                                 "text/calendar; charset=utf-8",
-                                                 this);
+            let httpchannel = cal.prepHttpChannel(this.outboxUrl,
+                                                  uploadData,
+                                                  "text/calendar; charset=utf-8",
+                                                  this);
             httpchannel.requestMethod = "POST";
             httpchannel.setRequestHeader("Originator", this.calendarUserAddress, false);
             for each (var recipient in aRecipients) {
                 httpchannel.setRequestHeader("Recipient", recipient.id, true);
             }
 
             var thisCalendar = this;
             var streamListener = {
@@ -2181,28 +2170,28 @@ calDavCalendar.prototype = {
                         status = Components.interfaces.calIErrors.DAV_POST_ERROR;
                         LOG("CalDAV: no response status when sending iTIP.");
                     }
 
                     if (status != 200) {
                         LOG("Sending iITIP failed with status " + status);
                     }
 
-                    var str = convertByteArray(aResult, aResultLength, "UTF-8", false);
+                    let str = cal.convertByteArray(aResult, aResultLength, "UTF-8", false);
                     if (str) {
                         if (thisCalendar.verboseLogging()) {
                             LOG("CalDAV: recv: " + str);
                         }
                     } else {
                         LOG("CalDAV: Failed to parse iTIP response.");
                     }
 
                     var C = new Namespace("C", "urn:ietf:params:xml:ns:caldav");
                     var D = new Namespace("D", "DAV:");
-                    var responseXML = safeNewXML(str);
+                    let responseXML = cal.safeNewXML(str);
 
                     var remainingAttendees = [];
                     for each (let response in responseXML.*::response) {
                         var recip = response..C::recipient..D::href;
                         var status = response..C::["request-status"];
                         if (status.substr(0, 1) != "2") {
                             if (thisCalendar.verboseLogging()) {
                                 LOG("CalDAV: failed delivery to " + recip);
@@ -2214,34 +2203,33 @@ calDavCalendar.prototype = {
                                 }
                             }
                         }
                     }
 
                     if (remainingAttendees.length) {
                         // try to fall back to email delivery if CalDAV-sched
                         // didn't work
-                        var imipTransport = calGetImipTransport(thisCalendar);
+                        var imipTransport = cal.getImipTransport(thisCalendar);
                         if (imipTransport) {
                             if (thisCalendar.verboseLogging()) {
                                 LOG("CalDAV: sending email to " + remainingAttendees.length + " recipients");
                             }
                             imipTransport.sendItems(remainingAttendees.length, remainingAttendees, aItipItem);
                         } else {
                             LOG("CalDAV: no fallback to iTIP/iMIP transport.");
                         }
                     }
                 }
             };
 
             if (this.verboseLogging()) {
                 LOG("CalDAV: send: " + uploadData);
             }
-            var streamLoader = createStreamLoader();
-            calSendHttpRequest(streamLoader, httpchannel, streamListener);
+            cal.sendHttpRequest(cal.createStreamLoader(), httpchannel, streamListener);
         }
     },
 
     mVerboseLogging: undefined,
     verboseLogging: function caldav_verboseLogging() {
         if (this.mVerboseLogging === undefined) {
             this.mVerboseLogging = getPrefSafe("calendar.debug.log.verbose", false);
         }
@@ -2265,21 +2253,21 @@ calDavCalendar.prototype = {
         let uploadData;
         let uploadContent;
         if (aOldChannel instanceof Components.interfaces.nsIUploadChannel &&
             aOldChannel.uploadStream) {
             uploadData = aOldChannel.uploadStream;
             uploadContent = aOldChannel.getRequestHeader("Content-Type");
         }
 
-        calPrepHttpChannel(null,
-                           uploadData,
-                           uploadContent,
-                           this,
-                           aNewChannel);
+        cal.prepHttpChannel(null,
+                            uploadData,
+                            uploadContent,
+                            this,
+                            aNewChannel);
 
         // Make sure we can get/set headers on both channels.
         aNewChannel.QueryInterface(Components.interfaces.nsIHttpChannel);
         aOldChannel.QueryInterface(Components.interfaces.nsIHttpChannel);
 
 
         function copyHeader(aHdr) {
             try {
--- a/calendar/providers/caldav/calDavCalendarModule.js
+++ b/calendar/providers/caldav/calDavCalendarModule.js
@@ -69,19 +69,17 @@ var calDavCalendarModule = {
 
     mUtilsLoaded: false,
     loadUtils: function cDCM_loadUtils() {
         if (this.mUtilsLoaded) {
             return;
         }
 
         Components.utils.import("resource://calendar/modules/calUtils.jsm");
-        cal.loadScripts(["calUtils.js", "calAuthUtils.js", "calProviderBase.js",
-                         "calProviderUtils.js", "calDavCalendar.js" ],
-                        this.__parent__);
+        cal.loadScripts(["calUtils.js", "calDavCalendar.js" ], this.__parent__);
 
         this.mUtilsLoaded = true;
     },
 
     registerSelf: function (compMgr, fileSpec, location, type) {
         compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
         compMgr.registerFactoryLocation(this.mCID,
                                         "Calendar CalDAV back-end",
--- a/calendar/providers/gdata/components/calGoogleCalendar.js
+++ b/calendar/providers/gdata/components/calGoogleCalendar.js
@@ -44,17 +44,17 @@
  * @class
  * @constructor
  */
 function calGoogleCalendar() {
     this.initProviderBase();
 }
 
 calGoogleCalendar.prototype = {
-    __proto__: calProviderBase.prototype,
+    __proto__: cal.ProviderBase.prototype,
 
     QueryInterface: function cGS_QueryInterface(aIID) {
         return doQueryInterface(this,
                                 calGoogleCalendar.prototype,
                                 aIID,
                                 null,
                                 g_classInfo["calGoogleCalendar"]);
     },
--- a/calendar/providers/gdata/components/calGoogleCalendarModule.js
+++ b/calendar/providers/gdata/components/calGoogleCalendarModule.js
@@ -142,19 +142,19 @@ var calGoogleCalendarModule = {
 
     mUtilsLoaded: false,
 
     loadUtils: function cGCM_loadUtils() {
         if (this.mUtilsLoaded)
             return;
 
         Components.utils.import("resource://calendar/modules/calUtils.jsm");
-        cal.loadScripts(["calUtils.js", "calAuthUtils.js",
-                         "calProviderBase.js", "calProviderUtils.js"],
-                        this.__parent__);
+        Components.utils.import("resource://calendar/modules/calProviderUtils.jsm");
+        Components.utils.import("resource://calendar/modules/calAuthUtils.jsm");
+        cal.loadScripts(["calUtils.js"], this.__parent__);
 
         // Now load gdata extension scripts. Note that unintuitively,
         // __LOCATION__.parent == . We expect to find the subscripts in ./../js
         let thisDir = __LOCATION__.parent.parent.clone();
         thisDir.append("js");
         cal.loadScripts(["calGoogleCalendar.js", "calGoogleSession.js",
                          "calGoogleRequest.js", "calGoogleUtils.js"],
                         this.__parent__,
--- a/calendar/providers/gdata/components/calGoogleRequest.js
+++ b/calendar/providers/gdata/components/calGoogleRequest.js
@@ -213,24 +213,24 @@ calGoogleRequest.prototype = {
             var uri = ioService.newURI(uristring, null, null);
             var channel = ioService.newChannelFromURI(uri);
 
             this.prepareChannel(channel);
 
             channel = channel.QueryInterface(Components.interfaces.nsIHttpChannel);
             channel.redirectionLimit = 3;
 
-            this.mLoader = createStreamLoader();
+            this.mLoader = cal.createStreamLoader();
 
             LOG("calGoogleRequest: Requesting " + this.method + " " +
                 channel.URI.spec);
 
             channel.notificationCallbacks = this;
 
-            calSendHttpRequest(this.mLoader, channel, this);
+            cal.sendHttpRequest(this.mLoader, channel, this);
         } catch (e) {
             // Let the response function handle the error that happens here
             this.fail(e.result, e.message);
         }
     },
 
     /**
      * fail
@@ -309,19 +309,19 @@ calGoogleRequest.prototype = {
                                       "GoogleLogin auth="
                                       +  this.mSession.authToken,
                                       false);
         }
     },
 
     /**
      * @see nsIInterfaceRequestor
-     * @see calProviderUtils.js
+     * @see calProviderUtils.jsm
      */
-    getInterface: calInterfaceRequestor_getInterface,
+    getInterface: cal.InterfaceRequestor_getInterface,
 
     /**
      * @see nsIChannelEventSink
      */
     onChannelRedirect: function cGR_onChannelRedirect(aOldChannel,
                                                       aNewChannel,
                                                       aFlags) {
         // all we need to do to the new channel is the basic preparation
@@ -339,17 +339,17 @@ calGoogleRequest.prototype = {
         if (!aResult || !Components.isSuccessCode(aStatus)) {
             this.fail(aStatus, aResult);
             return;
         }
 
         var httpChannel = aLoader.request.QueryInterface(Components.interfaces.nsIHttpChannel);
 
         // Convert the stream, falling back to utf-8 in case its not given.
-        var result = convertByteArray(aResult, aResultLength, httpChannel.contentCharset);
+        let result = cal.convertByteArray(aResult, aResultLength, httpChannel.contentCharset);
         if (result === null) {
             this.fail(Components.results.NS_ERROR_FAILURE,
                       "Could not convert bytestream to Unicode: " + e);
             return;
         }
 
         // Calculate Google Clock Skew
         var serverDate = new Date(httpChannel.getResponseHeader("Date"));
--- a/calendar/providers/gdata/components/calGoogleSession.js
+++ b/calendar/providers/gdata/components/calGoogleSession.js
@@ -585,18 +585,18 @@ calGoogleSession.prototype = {
         // This line is needed, otherwise the for each () block will never
         // be entered. It may seem strange, but if you don't believe me, try
         // it!
         xml.link.(@rel);
 
         var intervals = [];
         const fbtypes = Components.interfaces.calIFreeBusyInterval;
         for each (var entry in xml.entry) {
-            var start =  fromRFC3339(entry.gd::when.@startTime.toString(), timezone);
-            var end = fromRFC3339(entry.gd::when.@endTime.toString(), timezone);
-            var interval = new calFreeBusyInterval(aCalId, fbtypes.BUSY, start, end);
+            let start =  fromRFC3339(entry.gd::when.@startTime.toString(), timezone);
+            let end = fromRFC3339(entry.gd::when.@endTime.toString(), timezone);
+            let interval = new cal.FreeBusyInterval(aCalId, fbtypes.BUSY, start, end);
             LOGinterval(interval);
             intervals.push(interval);
         }
 
         aOperation.operationListener.onResult(aOperation, intervals);
     }
 };
--- a/calendar/providers/gdata/components/calGoogleUtils.js
+++ b/calendar/providers/gdata/components/calGoogleUtils.js
@@ -118,21 +118,21 @@ function getFormattedString(aBundleName,
  * @param   out aPassword       The password that belongs to the calendar.
  * @param   out aSavePassword   Should the password be saved?
  * @return  Could a password be retrieved?
  */
 function getCalendarCredentials(aCalendarName,
                                 aUsername,
                                 aPassword,
                                 aSavePassword) {
-    return calGetCredentials(getFormattedString("gdata", "loginDialogTitle"),
-                             aCalendarName,
-                             aUsername,
-                             aPassword,
-                             aSavePassword);
+    return cal.auth.getCredentials(getFormattedString("gdata", "loginDialogTitle"),
+                                   aCalendarName,
+                                   aUsername,
+                                   aPassword,
+                                   aSavePassword);
 }
 
 /**
  * Gets the date and time that Google's http server last sent us. Note the
  * passed argument is modified. This might not be the exact server time (i.e it
  * may be off by network latency), but it does give a good guess when syncing.
  *
  * @param aDate     The date to modify
@@ -319,40 +319,40 @@ function toRFC3339(aDateTime) {
 /**
  * passwordManagerSave
  * Helper to insert an entry to the password manager.
  *
  * @param aUserName     The username to search
  * @param aPassword     The corresponding password
  */
 function passwordManagerSave(aUsername, aPassword) {
-    calPasswordManagerSave(aUsername, aPassword, aUsername, "Google Calendar");
+    cal.auth.passwordManagerSave(aUsername, aPassword, aUsername, "Google Calendar");
 }
 
 /**
  * passwordManagerGet
  * Helper to retrieve an entry from the password manager
  *
  * @param in  aUsername     The username to search
  * @param out aPassword     The corresponding password
  * @return                  Does an entry exist in the password manager
  */
 function passwordManagerGet(aUsername, aPassword) {
-    return calPasswordManagerGet(aUsername, aPassword, aUsername, "Google Calendar");
+    return cal.auth.passwordManagerGet(aUsername, aPassword, aUsername, "Google Calendar");
 }
 
 /**
  * passwordManagerRemove
  * Helper to remove an entry from the password manager
  *
  * @param aUsername     The username to remove.
  * @return              Could the user be removed?
  */
 function passwordManagerRemove(aUsername) {
-    return calPasswordManagerRemove(aUsername, aUsername, "Google Calendar");
+    return cal.auth.passwordManagerRemove(aUsername, aUsername, "Google Calendar");
 }
 
 /**
  * ItemToXMLEntry
  * Converts a calIEvent to a string of xml data.
  *
  * @param aItem         The item to convert
  * @param aAuthorEmail  The email of the author of the event
--- a/calendar/providers/ics/calICSCalendar.js
+++ b/calendar/providers/ics/calICSCalendar.js
@@ -34,16 +34,18 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+Components.utils.import("resource://calendar/modules/calProviderUtils.jsm");
+
 //
 // calICSCalendar.js
 //
 // This is a non-sync ics file. It reads the file pointer to by uri when set,
 // then writes it on updates. External changes to the file will be
 // ignored and overwritten.
 //
 // XXX Should do locks, so that external changes are not overwritten.
@@ -59,17 +61,17 @@ function calICSCalendar() {
 
     this.unmappedComponents = [];
     this.unmappedProperties = [];
     this.queue = new Array();
     this.mModificationActions = [];
 }
 
 calICSCalendar.prototype = {
-    __proto__: calProviderBase.prototype,
+    __proto__: cal.ProviderBase.prototype,
 
     mObserver: null,
     locked: false,
 
     QueryInterface: function (aIID) {
         return doQueryInterface(this, calICSCalendar.prototype, aIID,
                                 [Components.interfaces.calICalendarProvider,
                                  Components.interfaces.nsIStreamListener,
@@ -540,19 +542,19 @@ calICSCalendar.prototype = {
     },
     endBatch: function ()
     {
         this.mObserver.onEndBatch();
     },
 
     /**
      * @see nsIInterfaceRequestor
-     * @see calProviderUtils.js
+     * @see calProviderUtils.jsm
      */
-    getInterface: calInterfaceRequestor_getInterface,
+    getInterface: cal.InterfaceRequestor_getInterface,
 
     /**
      * Make a backup of the (remote) calendar
      *
      * This will download the remote file into the profile dir.
      * It should be called before every upload, so every change can be
      * restored. By default, it will keep 3 backups. It also keeps one
      * file each day, for 3 days. That way, even if the user doesn't notice
@@ -932,26 +934,26 @@ httpHooks.prototype = {
             var D = new Namespace("D", "DAV:");
             default xml namespace = D;
             var queryXml = <D:propfind xmlns:D="DAV:">
                     <D:prop>
                       <D:getetag/>
                     </D:prop>
                   </D:propfind>;
 
-            var etagChannel = calPrepHttpChannel(aChannel.URI, queryXml,
-                                                 "text/xml; charset=utf-8",
-                                                 this);
+            let etagChannel = cal.prepHttpChannel(aChannel.URI, queryXml,
+                                                  "text/xml; charset=utf-8",
+                                                  this);
             etagChannel.setRequestHeader("Depth", "0", false);
             etagChannel.requestMethod = "PROPFIND";
             var streamLoader = Components.classes["@mozilla.org/network/stream-loader;1"]
                                          .createInstance(Components.interfaces
                                          .nsIStreamLoader);
 
-            calSendHttpRequest(streamLoader, etagChannel, etagListener);
+            cal.sendHttpRequest(streamLoader, etagChannel, etagListener);
         }
         return true;
     },
 
     // nsIProgressEventSink
     onProgress: function onProgress(aRequest, aContext, aProgress, aProgressMax) {},
     onStatus: function onStatus(aRequest, aContext, aStatus, aStatusArg) {},
 
--- a/calendar/providers/ics/calICSCalendarModule.js
+++ b/calendar/providers/ics/calICSCalendarModule.js
@@ -66,19 +66,17 @@ var calICSCalendarModule = {
 
     mUtilsLoaded: false,
     loadUtils: function cICM_loadUtils() {
         if (this.mUtilsLoaded) {
             return;
         }
 
         Components.utils.import("resource://calendar/modules/calUtils.jsm");
-        cal.loadScripts(["calUtils.js", "calAuthUtils.js", "calProviderBase.js",
-                         "calProviderUtils.js", "calICSCalendar.js"],
-                        this.__parent__);
+        cal.loadScripts(["calUtils.js", "calICSCalendar.js"], this.__parent__);
 
         this.mUtilsLoaded = true;
     },
 
     registerSelf: function (compMgr, fileSpec, location, type) {
         compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
         compMgr.registerFactoryLocation(this.mCID,
                                         "Calendar ICS provider",
--- a/calendar/providers/memory/calMemoryCalendar.js
+++ b/calendar/providers/memory/calMemoryCalendar.js
@@ -32,30 +32,32 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+Components.utils.import("resource://calendar/modules/calProviderUtils.jsm");
+
 //
 // calMemoryCalendar.js
 //
 
 const calCalendarManagerContractID = "@mozilla.org/calendar/manager;1";
 const calICalendarManager = Components.interfaces.calICalendarManager;
 
 function calMemoryCalendar() {
     this.initProviderBase();
     this.initMemoryCalendar();
 }
 
 calMemoryCalendar.prototype = {
-    __proto__: calProviderBase.prototype,
+    __proto__: cal.ProviderBase.prototype,
 
     //
     // nsISupports interface
     // 
     QueryInterface: function (aIID) {
         return doQueryInterface(this, calMemoryCalendar.prototype, aIID,
                                 [Components.interfaces.calISyncCalendar,
                                  Components.interfaces.calICalendarProvider]);
--- a/calendar/providers/memory/calMemoryCalendarModule.js
+++ b/calendar/providers/memory/calMemoryCalendarModule.js
@@ -63,18 +63,17 @@ var calMemoryCalendarModule = {
 
     mUtilsLoaded: false,
     loadUtils: function cMCM_loadUtils() {
         if (this.mUtilsLoaded) {
             return;
         }
 
         Components.utils.import("resource://calendar/modules/calUtils.jsm");
-        cal.loadScripts(["calUtils.js", "calProviderBase.js", "calProviderUtils.js",
-                         "calMemoryCalendar.js"],
+        cal.loadScripts(["calUtils.js", "calMemoryCalendar.js"],
                         this.__parent__);
 
         this.mUtilsLoaded = true;
     },
 
     registerSelf: function (compMgr, fileSpec, location, type) {
         compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
         compMgr.registerFactoryLocation(this.mCID,
--- a/calendar/providers/storage/calStorageCalendar.js
+++ b/calendar/providers/storage/calStorageCalendar.js
@@ -38,16 +38,18 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+Components.utils.import("resource://calendar/modules/calProviderUtils.jsm");
+
 const kStorageServiceContractID = "@mozilla.org/storage/service;1";
 const kStorageServiceIID = Components.interfaces.mozIStorageService;
 
 const kCalICalendar = Components.interfaces.calICalendar;
 
 const kCalAttendeeContractID = "@mozilla.org/calendar/attendee;1";
 const kCalIAttendee = Components.interfaces.calIAttendee;
 var CalAttendee;
@@ -255,17 +257,17 @@ function newDateTime(aNativeTime, aTimez
 function calStorageCalendar() {
     this.initProviderBase();
     this.mItemCache = {};
     this.mRecEventCache = {};
     this.mRecTodoCache = {};
 }
 
 calStorageCalendar.prototype = {
-    __proto__: calProviderBase.prototype,
+    __proto__: cal.ProviderBase.prototype,
     //
     // private members
     //
     mDB: null,
     mCalId: 0,
     mItemCache: null,
     mRecItemCacheInited: false,
     mRecEventCache: null,
--- a/calendar/providers/storage/calStorageCalendarModule.js
+++ b/calendar/providers/storage/calStorageCalendarModule.js
@@ -66,18 +66,17 @@ var calStorageCalendarModule = {
     mContractID: "@mozilla.org/calendar/calendar;1?type=storage",
 
     mUtilsLoaded: false,
     loadUtils: function storageLoadUtils() {
         if (this.mUtilsLoaded)
             return;
 
         Components.utils.import("resource://calendar/modules/calUtils.jsm");
-        cal.loadScripts(["calUtils.js", "calProviderBase.js", "calProviderUtils.js",
-                         "calStorageCalendar.js"],
+        cal.loadScripts(["calUtils.js", "calStorageCalendar.js"],
                         this.__parent__);
 
         initCalStorageCalendarComponent();
         this.mUtilsLoaded = true;
     },
 
     registerSelf: function (compMgr, fileSpec, location, type) {
         compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
--- a/calendar/providers/wcap/calWcapCalendar.js
+++ b/calendar/providers/wcap/calWcapCalendar.js
@@ -37,17 +37,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 function calWcapCalendar(/*optional*/session, /*optional*/calProps) {
     this.initProviderBase();
     this.m_session = session;
     this.m_calProps = calProps;
 }
 calWcapCalendar.prototype = {
-    __proto__: calProviderBase.prototype,
+    __proto__: cal.ProviderBase.prototype,
 
     // nsISupports:
     QueryInterface: function calWcapCalendar_QueryInterface(iid) {
         return doQueryInterface(this, calWcapCalendar.prototype, iid, null, g_classInfo.wcapCalendar);
     },
 
     toString: function calWcapCalendar_toString() {
         var str = this.session.toString();
--- a/calendar/providers/wcap/calWcapCalendarModule.js
+++ b/calendar/providers/wcap/calWcapCalendarModule.js
@@ -203,18 +203,19 @@ var calWcapCalendarModule = { // nsIModu
         compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
         compMgr.unregisterFactoryLocation(g_classInfo.wcapCalendar.classID, fileSpec);
     },
 
     m_scriptsLoaded: false,
     getClassObject: function calWcapCalendarModule_getClassObject(compMgr, cid, iid) {
         if (!this.m_scriptsLoaded) {
             Components.utils.import("resource://calendar/modules/calUtils.jsm");
-            cal.loadScripts(["calUtils.js", "calAuthUtils.js",
-                             "calProviderUtils.js", "calProviderBase.js", "calProviderUtils.js",
+            Components.utils.import("resource://calendar/modules/calProviderUtils.jsm");
+            Components.utils.import("resource://calendar/modules/calAuthUtils.jsm");
+            cal.loadScripts(["calUtils.js",
                              "calWcapUtils.js", "calWcapErrors.js",
                              "calWcapRequest.js", "calWcapSession.js",
                              "calWcapCalendar.js", "calWcapCalendarItems.js"],
                             this.__parent__);
             initWcapProvider();
             this.m_scriptsLoaded = true;
         }
 
--- a/calendar/providers/wcap/calWcapRequest.js
+++ b/calendar/providers/wcap/calWcapRequest.js
@@ -231,19 +231,19 @@ calWcapNetworkRequest.prototype = {
     m_bLogging: false,
 
     QueryInterface: function calWcapNetworkRequest_QueryInterface(iid) {
         return doQueryInterface(this, calWcapNetworkRequest.prototype, iid, null, g_classInfo.wcapNetworkRequest);
     },
 
     /**
      * @see nsIInterfaceRequestor
-     * @see calProviderUtils.js
+     * @see calProviderUtils.jsm
      */
-    getInterface: calInterfaceRequestor_getInterface,
+    getInterface: cal.InterfaceRequestor_getInterface,
 
     /**
      * prepareChannel
      * Prepares the passed channel to match this objects properties
      *
      * @param aChannel    The Channel to be prepared
      */
     prepareChannel: function calWcapNetworkRequest_prepareChannel(aChannel) {
--- a/calendar/providers/wcap/calWcapSession.js
+++ b/calendar/providers/wcap/calWcapSession.js
@@ -268,43 +268,43 @@ calWcapSession.prototype = {
                 }
 
                 var outUser = { value: this_.credentials.userId };
                 var outPW = { value: this_.credentials.pw };
                 var outSavePW = { value: false };
 
                 if (outUser.value && !outPW.value) { // lookup pw manager
                     log("looking in pw db for: " + this_.uri.spec, this_);
-                    calPasswordManagerGet(outUser.value, outPW, this_.uri.spec, "wcap login");
+                    cal.auth.passwordManagerGet(outUser.value, outPW, this_.uri.spec, "wcap login");
                 }
 
                 function promptAndLoginLoop_resp(err, sessionId) {
                     if (checkErrorCode(err, calIWcapErrors.WCAP_LOGIN_FAILED)) {
                         log("prompting for [user/]pw...", this_);
-                        if (calGetCredentials(calGetString("wcap", "loginDialog.label"),
-                                              this_.sessionUri.hostPort,
-                                              outUser,
-                                              outPW,
-                                              outSavePW,
-                                              this_.credentials.userId != null)) {
+                        if (cal.auth.getCredentials(calGetString("wcap", "loginDialog.label"),
+                                                    this_.sessionUri.hostPort,
+                                                    outUser,
+                                                    outPW,
+                                                    outSavePW,
+                                                    this_.credentials.userId != null)) {
                             this_.login(request, promptAndLoginLoop_resp,
                                         outUser.value, outPW.value);
                         } else {
                             log("login prompt cancelled.", this_);
                             this_.defaultCalendar.setProperty("disabled", true);
                             this_.defaultCalendar.setProperty("auto-enabled", true);
                             respFunc(new Components.Exception(errorToString(calIWcapErrors.WCAP_LOGIN_FAILED),
                                                               calIWcapErrors.WCAP_LOGIN_FAILED));
                         }
                     } else if (err) {
                         respFunc(err);
                     } else {
                         if (outSavePW.value) {
                             // so try to remove old pw from db first:
-                            calPasswordManagerSave(outUser.value, outPW.value, this_.uri.spec, "wcap login");
+                            cal.auth.passwordManagerSave(outUser.value, outPW.value, this_.uri.spec, "wcap login");
                         }
                         this_.credentials.userId = outUser.value;
                         this_.credentials.pw = outPW.value;
                         this_.setupSession(sessionId,
                                            request,
                                            function setupSession_resp(err) {
                                                respFunc(err, sessionId);
                                            });
@@ -1008,22 +1008,22 @@ calWcapSession.prototype = {
 
                         for (var i = 0; i < nodeList.length; ++i) {
                             var node = nodeList.item(i);
                             var fbType = fbTypeMap[node.attributes.getNamedItem("FBTYPE").nodeValue];
                             if (!fbType || (fbType & busyTypes)) {
                                 if (!fbType) {
                                     fbType = calIFreeBusyInterval.UNKNOWN;
                                 }
-                                var str = node.textContent;
-                                var slash = str.indexOf('/');
-                                var start =  getDatetimeFromIcalString(str.substr(0, slash));
-                                var end =  getDatetimeFromIcalString(str.substr(slash + 1));
+                                let str = node.textContent;
+                                let slash = str.indexOf('/');
+                                let start = getDatetimeFromIcalString(str.substr(0, slash));
+                                let end = getDatetimeFromIcalString(str.substr(slash + 1));
 
-                                ret.push(new calFreeBusyInterval(calId, fbType, start, end));
+                                ret.push(new cal.FreeBusyInterval(calId, fbType, start, end));
                             }
                         }
                         request.execRespFunc(null, ret);
                     }
                 },
                 stringToXml_, "get_freebusy", params);
 
         } catch (exc) {