summaryrefslogtreecommitdiffstats
path: root/mailnews/base/src/folderLookupService.js
diff options
context:
space:
mode:
Diffstat (limited to 'mailnews/base/src/folderLookupService.js')
-rw-r--r--mailnews/base/src/folderLookupService.js99
1 files changed, 99 insertions, 0 deletions
diff --git a/mailnews/base/src/folderLookupService.js b/mailnews/base/src/folderLookupService.js
new file mode 100644
index 000000000..9c64b5ef0
--- /dev/null
+++ b/mailnews/base/src/folderLookupService.js
@@ -0,0 +1,99 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * This module implements the folder lookup service. Presently, this uses RDF as
+ * the backing store, but the intent is that this will eventually become the
+ * authoritative map.
+ */
+
+"use strict";
+
+var Cc = Components.classes;
+var Ci = Components.interfaces;
+var Cr = Components.results;
+
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+function isValidFolder(folder) {
+ // RDF is liable to return folders that don't exist, and we may be working
+ // with a deleted folder but we're still holding on to the reference. For
+ // valid folders, one of two scenarios is true: either the folder has a parent
+ // (the deletion code clears the parent to indicate its nonvalidity), or the
+ // folder is a root folder of some server. Getting the root folder may throw
+ // an exception if we attempted to create a server that doesn't exist, so we
+ // need to guard for that error.
+ try {
+ return folder.parent != null || folder.rootFolder == folder;
+ } catch (e) {
+ return false;
+ }
+}
+
+// This insures that the service is only created once
+var gCreated = false;
+
+function folderLookupService() {
+ if (gCreated)
+ throw Cr.NS_ERROR_ALREADY_INITIALIZED;
+ this._map = new Map();
+ gCreated = true;
+}
+folderLookupService.prototype = {
+ // XPCOM registration stuff
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIFolderLookupService]),
+ classID: Components.ID("{a30be08c-afc8-4fed-9af7-79778a23db23}"),
+
+ // nsIFolderLookupService impl
+ getFolderForURL: function (aUrl) {
+ let folder = null;
+ // First, see if the folder is in our cache.
+ if (this._map.has(aUrl)) {
+ let valid = false;
+ try {
+ folder = this._map.get(aUrl).QueryReferent(Ci.nsIMsgFolder);
+ valid = isValidFolder(folder);
+ } catch (e) {
+ // The object was deleted, so it's not valid
+ }
+
+ if (valid)
+ return folder;
+
+ // Don't keep around invalid folders.
+ this._map.delete(aUrl);
+ folder = null;
+ }
+
+ // If we get here, then the folder was not in our map. It could be that the
+ // folder was created by somebody else, so try to find that folder.
+ // For now, we use the RDF service, since it results in minimal changes. But
+ // RDF has a tendency to create objects without checking to see if they
+ // really exist---use the parent property to see if the folder is a real
+ // folder.
+ if (folder == null) {
+ let rdf = Cc["@mozilla.org/rdf/rdf-service;1"]
+ .getService(Ci.nsIRDFService);
+ try {
+ folder = rdf.GetResource(aUrl)
+ .QueryInterface(Ci.nsIMsgFolder);
+ } catch (e) {
+ // If the QI fails, then we somehow picked up an RDF resource that isn't
+ // a folder. Return null in this case.
+ return null;
+ }
+ }
+ if (!isValidFolder(folder))
+ return null;
+
+ // Add the new folder to our map. Store a weak reference instead, so that
+ // the folder can be closed when necessary.
+ let weakRef = folder.QueryInterface(Ci.nsISupportsWeakReference)
+ .GetWeakReference();
+ this._map.set(aUrl, weakRef);
+ return folder;
+ },
+};
+
+var NSGetFactory = XPCOMUtils.generateNSGetFactory([folderLookupService]);