Mailbox state machine (Mailnews Exchange support)
May 10, 2010 – 1:41 pmPreviously I have described interfaces that allowed me to display Exchange Web Server objects in Thunderbird’s folder tree and account manager. My goal lately has been to display lists of messages in the thread pane. To do that, I have to acquire, store and interface message metadata (the message summary database) to the Mozilla mailnews interfaces.
Unfortunately an issue has loomed too large to ignore: the need to sequence a number of SOAP requests when I need to send multiple requests to meet a single goal. Previously I had simply kludged around this, but I needed to make some decisions to be able to move forward in an orderly manner.
I’m also having enormous problems deciding what to name things. So before I can even talk about what I decided to do, I need to give a little lesson on the naming that surrounds my architecture.
Overall Architecture
Since my last diagram, I have clarified things a little, so the structure now looks like this:
The architectural layers are:
Mailnews: the existing Mozilla Mailnews code and objects.
Colonial: the Colonial layer provides the glue between objects represented in Mozilla mailnews format, and Exchange server format. The “colonial” analogy is an extension of the “native” layer analogy presented earlier. That is, if we picture Mozilla mailnews as the mother country, trying to make sense of some aboriginal “native” tribe, then there exists a colonial administration that pretends to have the same laws as the mother country, but has to translate all of those laws into some sort of actions involving native people. So the objects that pretend to be following the laws of the mother country (Mozilla mailnews), but in fact really exist in some other culture, are Colonial objects.
In my architecture, the Colonial objects are subclasses of base Mailnews objects like nsMsgDatabase, nsMsgDBFolder, nsMsgIncomingServer, etc.
Native: This layer’s objects exist as XPCOM objects on the Mozilla platform, but are represented in the native “Exchange” format rather than in Mailnews format. So for example they are identified primarily by string object ids (and not integer keys like Mailnews objects), and they are located in the Exchange tree. For example, folders containing contacts, the inbox, and tasks are all subfolders of a root mailbox folder, as in Exchange Server.
EWS: This layer provides translation of methods to perform operations on native-layer objects (like get subfolders, or sync message metadata) with objects that can be directly translated into SOAP web calls. (I actually use an intermediate representation, called a “property list”, that is very similar to an nsIPropertyBag, but supports ordered, multiple-valued lists such as are present in the SOAP protocols. But these property list objects can be translated directly into the SOAP protocol using the schema provided by Exchange Web Services).
SOAP: As discussed earlier, this is an updated version of Mozilla’s abandoned webservices package.
Exchange: The Exchange Messaging Server itself, implementing a SOAP interface.
State Machine to implement Mailnews Object methods
Let me now describe the problem, and what I decided to do. This is the msqEwsMachine class in the diagram.
The interface to Mozilla mailnews frequently consists of methods that are executed on mailnews interfaces, for example nsIMsgFolder.getNewMessages(). Such methods will get translated into a sequence of requests to a web server, which leave the SOAP layer as a sequence of nsXMLHttpRequests.
Which object is responsible for taking the method call, managing the series of requests to the web server, and generating appropriate events and callbacks when the method has been completed? That has been the issue of the last two weeks.
Originally, I had it done by the colonial-layer representation of nsIMsgIncomingServer, msqEwsIncomingServer. But I did not like how that forced the incoming server object to know way too much about the details of the SOAP calls, when at that layer all it really needed to know was the data results. I also tested using the service layer objects, either the colonial layer object that implements nsIMsgMessageService, or its Native-layer counterpart. But I found that everything that I did needed access to the root of the Native layer data representation, which is the native mailbox object.
So that is where the management ended up: methods on an object, msqEwsMachine, which is fully owned by the the native-layer mailbox object (The mailbox is the native-layer analog of nsIMsgIncomingServer).
A simple request to the mailbox layer would be “discover subfolders”, which requests that the Exchange server provide a list of all defined folders, their parent/child relationship, and some basic folder properties such as the display name. That requires two SOAP requests: 1) a first to translate the so-called “DistinguishedFolderId” such as “inbox” into the guid equivalent for the limited number of distinguished folders, and 2) a second call where the root folder is asked for all of its children recursively. At the end of the whole process, an “onStop” event is generated, which will ultimately be translated into the appropriate mailnews notifications.
Next step: message metadata and nsIMsgDBHdr
Yes this has been a rather boring post, but I didn’t want anyone to think nothing was happening! As the next step, I am now ready to start generating a list of messages per folder, and their corresponding nsIMsgDBHdr objects. Then I can show messages in the thread pane.






