Saturday, October 25, 2008

Synchronization

Since my original plan for mailing list sanity was upset by an underestimation of the insanity, I looked into fixing it in the various components. One place where this happened was in palm sync code. This code is so perilous I wouldn't be surprised to find that it broke somewhere along the line. As happens a lot, though, I got a little sidetracked. I tried to sit down and actually figure out what the heck goes on in there.

Like every other time I forayed into this code, I started thinking about how to improve it. What this code most needs is to be generic; there are bugs for adding support for SyncML, ActiveSync, OpenSync, BlackBerries, and even N-Gage devices. There are a few more bugs not citing a specific protocol or device; surprisingly, though, there are no bugs on supporting Microsoft's or Apple's synchronization APIs, as well as iSync. One might also consider something like Google Contacts to be a synchronization architecture.

In short, for Thunderbird and SeaMonkey to support most devices, they need to bridge at least six different APIs. So how can this be done? Fortunately, there are basic steps that need to be done that are common between them: registration, getting the data from the handheld and locally, resolving conflicts, and pushing between them. The primary differences I could find (aside from exact API semantics) were that some APIs requested changes from the applications (calling back when there were conflicts) while others just dumped handles to everything on the application and let the application figure it out.

How could these functions be abstracted from an API point of view? Here's a rough interface:

interface mozIExternalSynchronizer : nsISupports {
   /** The name that one would see in a dialog to enable/disable. */
   readonly attribute nsAUTF8String displayName;
   /** True if the OS sync manager will grab the changes. */
   readonly attribute boolean wantsChanges;
   /** Register this with the appropriate OS sync manager. */
   void enable();
   /** Unregister this with the appropriate OS sync manager. */
   void disable();
   /** Push a set of changes. (Called only if wantsChanges is true) */
   void pushChanges(in nsISimpleEnumerator changes);
   /** Get the records from the other end. (Called only if wantsChanges is false) */
   nsISimpleEnumerator getOtherRecords();
}

Hmm... if we can mostly abstract away the main sync manager stuff, why not abstract the other part? After all, if we're already doing work to synchronize the address book, it's not a large jump to synchronize calendars as well. And who knows what extension developers may be interested in synchronizing? The managers already abstract over various types; we would only need to provide a common glue over this.

Such a feature would need interfaces for defining what could be synchronized (and UI for doing those separately). I don't have these planned out (I need to look more at the APIs, an endeavor I do not have sufficient time for yet). One thing is certain, though: with these changes, Mozilla could add "cross-platform synchronization manager" to its list of features. Indeed, though my main impetus comes from mailnews's current palm sync feature, it does not need to be specific to Thunderbird and SeaMonkey.

1 comment:

Anonymous said...

Such a capability is, now that Calendar support is right over the corner with Lightning, Sunbird and Thunderbird 3 (and likely soon in Seamonkey too) the number one of the missing features of MailNews.

With such a feature (and several backends implemented directly or through extension) it would allow all Gecko-based application to have a large advantage on other application, especially proprietary ones.

And syncing your mobile phone with your desktop data is something people really want. Apps that doesn't allow this are left aside.