Address Book accounts

By | March 8, 2011

New account types in Javascript for Thunderbird (Part 4)

Now that I am essentially feature complete in adding Address Book features to my Exchange Web Services implementation ExQuilla, I’d like to discuss how SkinkGlue was used to allow this to mostly be done in JavaScript.

As review, SkinkGlue is my attempt to add an interface layer to Thunderbird to allow new account types to be added using javascript. SkinkGlue provides the necessary C++ interfaces to allow standard Thunderbird objects to be created without writing C++ code. SkinkGlue is licensed inder the standard Mozilla licenses, so it could be used by other extensions, or implemented as a Thunderbird standard feature. The current source is available here.

Adding Exchange Server contacts to the address book

While ExQuilla itself is mostly written in C++, I thought I would try to do the interface to the address book mostly in javascript.

At first I thought that would be straightforward, as the address book interfaces are much simpler than the mail interfaces, and there was supposed to be an existing extension that already did this. But I could not make this work reliably by trying to create a full javascript implementation of the nsIAbDirectory interface.

The main culprit is that the address book implementation seems to require that directory objects also derive from nsRDFResource. The underlying interface nsIRdfResource has the non-scriptable method GetValueConst, which is used by core Mozilla code in accessing RDF items. Perhaps I could have figured out how to work around this, but given the work I had already done in SkinkGlue, it seemed easier to just add a SkinkGlue type that allowed me to create an nsIAbDirectory object.  Another advantage of this is that I could take advantage of the existing full  generic C++ implementations, and then only override methods that I needed to change.

So in the end, I created a SkinkGlue object to be used for address book directories that can be extended using javascript. The C++ implementation of this derives from both nsRDFResource as well as nsAbDirProperty, and provides the minimum needed interfaces. This is actually quite parallel to the mailnews SkinkGlue objects, as the address book object nsAbDirProperty is similar in role to the mail object nsMsgDBFolder. Both provide a generic C++ implementation of key interfaces, and are used in standard mailnews C++ objects as a parent class. By adding this to SkinkGlue, I am simply allowing javascript users to follow the same methods that C++ users employ.

For address book cards, this was not necessary. There is an existing object “@mozilla.org/addressbook/cardproperty;1” which works just fine.

The result is that the standard Exchange Server “Contacts” folder and subfolders appear in the Thunderbird address book:

Note this is a Mork-free implementation, unlike the mailnews SkinkGlue objects.

Since the address book interface does not support a tree of directories, I had to implement the subfolder “Test subfolder” as a top-level address book with an extended name.

I hope to demonstrate this publically soon by adding “address book” support to my TweeQuilla Twitter extension, where an address directory would be interpreted as a list of followers.

Changes needed to Address Book to make this easier

The address book interfaces are much cleaner on average than the mail interfaces, but unfortunately not completely there yet. What would make this easier to do?

1. Remove address book dependencies on RDF

The use of RDF is ultimately what forces me to create a C++ object to backup my javascript implementation.

2. Add async access capability to key interfaces

Most new address book accounts that might be supported would be remote sources. While the existing LDAP implementation manages to work around that, it is not at all clear from the interfaces how this is done. Really async access needs to be thought through and applied consistently. In my implementation, I essentially end up loading all of the contacts into memory, which will not scale well to large implementations.