User:Jcranmer/Writing an Importer

From MozillaWiki
Jump to: navigation, search

There are two components to an extension that imports data into Thunderbird:

  • the import service
  • the import modules (or "importers")

The import process works like this:

  1. The user opens the import dialog and selects something to import (such as an address book, messages, etc).
  2. The import service queries all importers to see which can import the given object.
  3. If necessary, the user is prompted to specify the file containing the data to be imported.
  4. The import runs in a new thread.

Building an importer

The first step to writing an importer is to implement the basic interface: nsIImportModule. The name and description properties are the strings that the user sees. (The name is displayed in the list box, the description displays beneath the box). The supports property is a comma-delineated list of import types that the module supports (for example, the address book or mail filters). The supportsUpgrade property is, as far as I can tell, not used.

The final piece of nsIImportModule is the GetImportInterface function, which will return the object that actually does the import. The caller passes in the type. For mail and address book imports, the caller returns an instance of nsIImportGeneric, wrapping the actual import implementation. For imports of other types of data, the regular import implementation is returned.

To inform the import service of your module, register it with the category manager. The category is "mailnewsimport" and the value should be the same as the supports string. If you are writing C++ code, there is example code in the import module: [1].

An important thing to note about the importer is that the actual import operates on a separate thread. The pre-import steps are performed on the UI thread. For this reason, the importer implementation needs to have thread-safe addref. Also, make sure that the code properly synchronizes across threads. For this reason, we recommend that you implement importers in C++ and not JavaScript. Running on a debug build while building an importer would be very helpful.

Importing an address book

The address book supports string is NS_IMPORT_ADDRESS_STR, "addressbook". The importer needs to implement the nsIImportAddressBooks interface, although the GetImportInterface must return it wrapped in an nsIImportGeneric instance.

The first step in importing an address book is to get the file to import. If GetAutoFind returns false, the user will be presented a dialog with a file to import. If it is true, the user is sent to the import step. (The description is not important in either case - it doesn't seem to be used anymore.)

If GetAutoFind returned false, the next step is to select the file. GetDefaultLocation is then queried to get the default file (if it has been found, and if the user can set the location). If the default file is not null, it is treated as the selected file; if it is null, a file picker is opened. If the address book supports multiple, a directory is selectable; if it does not, a single file is selectable. If the user cannot set the location, it is treated as an error. The found status is not used.

The next step is to build the field map, if necessary. This is determined via GetNeedsFieldMap. The location parameter is the address book (file or directory) that we will be importing, determined in the past step. If GetAutoFind returned true, this function will not be called.

Information on the the field map is still under construction

After building the field map, the import begins. FindAddressBooks is called with the location parameter as selected (it is null if GetAutoFind returned true). The return value here is an nsISupportsArray of nsIImportABDescriptors, an array of information to coalesce into address books. You can choose to use the default implementation by calling nsIImportService::CreateNewABDescriptor or provide your own. The important parameters are import (whether or not the representative address book is imported), size (representing the total amount to process) and preferredName (the name of the new address book).

At this point, ImportAddressBook is called. The parameters here are the descriptor (unmolested), the database to import to (which is already a proxy object), the field map, a copy of the (proxied) nsIAbLDIFService, and a parameter that indicates whether or not an address location is the home (true for Netscape 4.x import; false otherwise). The outputs are strings for the error and success logs, as well as whether or not there were fatal errors. The log strings will be shown to the users. Fatal errors will stop the import immediately.

Importing mail

This section is not yet finished.

Importing filters

This section is not yet finished.

Importing settings

This section is not yet finished.