Google Summer of Code 2008

I recently submitted a proposal to Mozilla outlining plans to create an extension for Thunderbird that would synchronize and modify Gmail's contacts from Thunderbird as part of Google's annual Summer of Code. My abstract:

"Google released an API for programmers to use in order to import one’s Gmail contact list, synchronize contact lists, or export another contact list to Gmail. Using this API, it is possible to add, edit, and delete contacts with Google’s Data Protocol. Before the release of this API, users were required to enter their username and password to allow an application or service to access their contact list. Now, using this API, releasing one’s username and password is unnecessary.

The number of extensions for Thunderbird is most impressive, and I would like to create an extension to work with Google’s contact API and import, export, sync, add, remove, and edit contacts. This extension will help people maintain and synchronize contact lists on several computers through Google’s contacts."

Screenshots

screenshot1

screenshot 2

Timeline

Lines with bold text have been completed. I started coding early expecting some difficulties and a learning curve, but found it easier than expected, so this timeline will be updated a lot...

April 21: Find out whether or not my proposal was accepted
April 21-May 26: Read documentation and forums, get to know my mentor and some of the Thunderbird team, and view code along with extensions to get a firm understanding of how Thunderbird handles contacts and extensions.
April 23: Add a page to my website about my project and plans with a contact form for suggestions
April 26: Have a basic extension GUI in Thunderbird
April 27: Have an improved script with methods with HTTP requests for GET, POST, PUT and DELETE (or POST w/ DELETE and POST w/ PUT override for some firewalls that block DELETE and/or PUT) and able to use the ClientLogin authentication method to get contacts
April 29: Read contacts using JavaScript and parse the results
May 3: Create a basic GUI for displaying a contact (ex. name, email address(es), phone number(s)...) and add a context menu to the Google Contacts tree
May 4: Add or remove a hard-coded contact in Gmail using JavaScript
May 8: Create an extension that can add or remove a contact in Thunderbird’s address book.
May 12: Add an Address Book to Thunderbird for Google Contacts and syn
May 13: Synchronize two contacts' fields, without handling the case where both fields changed
May 14: Find new contacts in Thunderbird's Google Address Book not yet in Google.
May 14: Handle both fields changing. See notes for May 14.
May 16: Import a csv into the Address Book with JavaScript (to prepare for testing, not for the extension)
May 23: Start using preferences in the program and have a preferences dialog
May 30: Have some basic testing done for Thunderbird 3's Address Book import functionality
June 15: Sync 500 contacts without any problems
June 25: Use locales for script alerts and errors
July 14: Submit midterm evaluation
July 31: Update the initial extension and publish on my website
Aug 1-?: Work on getting a page on addons.mozilla.org (AMO) for my extension
Aug 10: Fix major bugs, refactor code if necessary
Aug 14: Fix other bugs and continue documentation, revise and refactor code.
Aug 25: Update website with screenshots and downloads.
Sept 1: Submit final evaluation, prepare code for submission
Sept 3: Submit code samples to Google

Progress/Notes

Note: From now on (May 25), I will be keeping track of my progress on my blog.

April 23 - I have created this website a little earlier than originally planned.

April 24 - I introduced myself to my mentor on IRC and started reading documentation. I used Google's Java Documentation and libraries to list, add, and remove (a) contact(s) to a hard-coded username/password. A GUI for this program to allow more control over editing contacts could be added easily, but it probably wouldn't help me much, as I plan to do this in JavaScript.

April 25 - I read more about Google's Contacts API and XUL. I have created a quick and basic login GUI to experiment with the language:

April 26 - I created a basic extension with support for localization (only en-US for now) with the install script, the RDFs, preferences, an overlay, a preferences window and an options window. I read about XMLHttpRequest (JavaScript) which should help me use Google's ClientLogin method for authentication, but had some problems when I tried it in a local script and in a script on my website due to security restrictions. Mook on IRC told me that it could probably be done in an extension, so I added the script to my extension and was able to GET my website's homepage.

April 27 - I created a JavaScript that has methods for POST and GET and another script that authenticates using Google's ClientLogin method. I also am able to obtain the authentication token. Finally, it is able to send a GET request for the contacts and display them (not parsed).

April 28 - I put a wrote a new version of my script that sends http requests and returns the object. Took some time off to study for (and ace) my two finals today, then started making a new GUI to display contacts obtained from Google.

April 29 - Continued working on the new GUI and tree. I now can parse the XML returned from Google for whatever information I want. Here's the current GUI that displays some of that information

April 30-May 4 - I'm changed the GUI and added a tree for Thunderbird's contacts. It can display and has a context menu for both, but it cannot do much with the TB address book yet. It can remove the selected Google contact or add it to TB's address book.

May 4-11 - I can transfer contacts between Google and TB and tell if there already is an "identical" card, although I am trying to define "identical" better. I am working on detecting if the card is different between the two and updating the other.

May 12-13 - Following the suggestion of my mentor, I changed my extension to make a new Address Book for Google Contacts. I am working on synchronizing them and refactoring my code.

May 13 - I was able to compare two contacts with the same name and update Google and/or Thunderbird. I also started refactoring, commenting, and JSDoc'ing my code and started adding code to several methods to throw exceptions for invalid arguments (the values passed into the methods)

May 14 - I can synchronize both ways (including adding cards that are in one and not the other), but need to find a way to find deleted cards and found out that lastModifiedDate isn't working for Thunderbird 3 yet, so for now it is impossible to delete a contact since it will be added right back unless it is deleted between syncs on every host (Google and every TB client). It can also refresh after a set interval.

May 15 - I was busy most of the day, but checked out bugzilla (Bug Day today), continued refactoring code, and added a listener to the address book so I know when a card is added/deleted/modified in the Google Contacts address book within Thunderbird, possibly helping solve the delete problem

May 16 - I now have an intial, but rough, method of deleting contacts. I wanted to make it work on multiple clients, so right now it marks the contact on Google with a certain tag so my program knows not to add it, but to delete it if it is the Address Book. It works well when I tested it and I also wrote some code to "clean" Google of all these marked contacts. After reading several hundred lines of code relating to importing, I was able to import a csv into the Address Book as a start for writing tests for Thunderbird's Import function.

May 17-18 - I worked on testing import code and accidentally crashed Thunderbird at first, so I worked on a fix that would prevent that. I will probably write a bug report for it soon.

May 19 - I changed how the code synchronizes (adds/modifies/deletes) to make it more simple. lastModifiedDate doesn't work for TB 3 address book cards yet, so it uses the last modified date on the Google Contact and the last sync date/time to figure out what needs to be updated/added/deleted. In my somewhat casual tests it worked well with two computers using Thunderbird and using Google Contacts online.

May 20-22 - I made some slight modifications and improvements

May 23 - Added a preferences dialog and starting using preferences

May 24 - Removed most occurences of setTimeout and now pass commands to methods that send HTTP requests which are run upon a successful request (status 200 or 201 usually) instead of using timeouts. Removed all timeout values except for "shortDelay" which was decreased to a default of 100 ms. This should make the program work more quickly and hopefully eliminate most, if not all, timing issues.

Suggestions

At this early stage, I would really appreciate any input as to what features you would like to see in this extension. I will not have a copy available to try for a while. If you have any suggestions, please use the form here.