About this Documentation

This document tries to cover all aspects of how to create a provider add-on for TbSync to extends its sync capabilities.

Note

All TbSync provider add-ons are currently designed as bootrapped extensions, for which support is probably going to be dropped from Thunderbird at some time. We are working on migrating the TbSync API into a WebExtension API, so - hopefully - all provider add-ons can be converted into future proof WebExtensions without much effort.

Introduction
This section gives a short introduction to TbSync and its provider concept.
Getting Started
As promised by the name, this section gets you started by explainig how to create your own basic provider add-on in just a couple of minutes and gives instructions to get it running in Thunderbird.
Implementing the Provider Classes
Learn how to interact with TbSync.

Introduction

What is TbSync ?

TbSync is a central user interface to manage cloud accounts and to synchronize their contact, task and calendar information with Thunderbird. Its main objective is to simplify the setup process for such accounts and to improve the user experience by creating a common place to manage them.

https://raw.githubusercontent.com/jobisoft/TbSync/master/screenshots/TbSync_005.png

Further details can be found in the wiki of the TbSync project.

What is a TbSync Provider Add-on ?

TbSync itself is just the manager UI and does not provide any sync capabilities on its own. But it provides an API for other add-ons to hook into TbSync. Such add-ons, which use this API and add sync capabilities are called TbSync provider add-ons. The following provider add-ons are currently available:

Getting Started

Generating a Basic TbSync Provider Add-on

Head over to

https://github.com/jobisoft/Provider-4-TbSync

and clone the provider add-on template repository. If you have a GitHub account yourself, you can simply add a copy of the provider add-on template to your own account.

After you have all the files on disc, run

./setup.py

which will ask you a couple of questions to setup the provider add-on for you. After that is done, you can install your own provider add-on in Thunderbird 68. Just zip the project folder and install the file using the gear menu in the Thunderbird add-on manager:

https://raw.githubusercontent.com/jobisoft/TbSync/master/screenshots/install-from-file.PNG

To see your own provider add-on in action, you need to install the latest version of TbSync from the so called beta release channel for Thunderbird 68.

https://github.com/jobisoft/TbSync/wiki/Get-the-latest-TbSync-version#beta-release-channel

Please make sure, that you uninstall any other TbSync provider add-on or switch to their version from the beta release channel as well. Your own provider add-on should then show up in the “Add new account” menu of TbSync:

https://raw.githubusercontent.com/jobisoft/TbSync/master/screenshots/custom_provider.PNG

Once your TbSync provider add-on is stable and released to addons.thunderbird.net, it can be added as a standard entry to the “Add new account” menu of TbSync, so all TbSync users will learn about it and get directed to its add-on page. For example this is what users see, when they try to create an ActiveSync account, but the provider add-on for ActiveSync is not yet installed:

https://raw.githubusercontent.com/jobisoft/TbSync/master/screenshots/missing_provider.PNG

Directory Structure of the Generated Provider Add-on

These are the important files and folders of the generated provider add-on:

Project
├── bootstrap.js
├── chrome.manifest
├── manifest.json
├── _locales
│   └── en-US
│       ├── messages.json
│       ├── provider.dtd
│       └── provider.strings
├── skin
│   ├── logo16.png
│   └── logo32.png
│   └── logo48.png
└── content
    ├── provider.js
    └── manager
        ├── createAccount.js
        ├── createAccount.xul
        ├── editAccountOverlay.js
        └── editAccountOverlay.xul

The author suggests to not rename files or folders, to not break the add-on. The following list provides an overview:

bootstrap.js
This file is registering your provider add-on with TbSync. The generated file should work out of the box.
manifest.json
The main configuration file for your add-on. Further details about this file can be found in the MDN documentation. The generated file should work out of the box.
chrome.manifest
An additional configuration file for your add-on. You probably only have to change it, when adding further translations (locales).
_locales

Folder containing files to translate your add-on into different languages. Add a subfolder for each language and register them in chrome.manifest. The name of the folder must not be changed.

en-US/messages.json
Localization for entries in manifest.json. Check the MDN documentation for more details. The name of the file must not be changed.
en-US/provider.strings
Localization for your add-on, which can be accessed from JavaScript. The name of the file may be anything you like, but it must be announced via Base.getStringBundleUrl() as TbSync needs to access some of your localized strings. In paticular error messages and synchronization states your add-on is using.
en-US/provider.dtd
Deprecated localization for XUL files of your add-on. Try to avoid its usage and instead set the localized labels of XUL/HTML elements via JavaScript. The generated provider add-on is using this in createAccount.xul and editAccountOverlay.xul.
skin
Folder containing all your additional resources like images and CSS files. It exists for historical reasons and the author is used to that approach. The generated provider add-on also stores its logo files there. If you change their names, please also update your manifest.json and your implementation of Base.getProviderIcon().
content

Folder containing your add-ons source files.

provider.js
File containing your implementation of the Base() class and a few other classes, depending on what your add-on is supposed to do. See Implementing the Provider Classes for more details.
manager
Folder containing resources used be the manager UI. In paticular the XUL file for the Create new account dialog of your provider add-on (see Base.getCreateAccountWindowUrl()) and the XUL file containing your tabs for the Edit account dialog (see Base.getEditAccountOverlayUrl()).

Implementing the Provider Classes

The content of file provider.js will be loaded into the provider namespace and is the central starting point to implement the TbSync provider classes. The provider namespace is build using the short provider identifier selected during the initial setup of the provider add-on:

TbSync.providers.<short provider identifier>
Base Class
Implementing the Base() class defines, where TbSync can find certain things, like icons, XUL files for different dialogs or localized string definitions. It also defines, what properties the provider needs in the account and folder database and what should happen, if an account is being synchronized.
FolderList Classes

A central part of the TbSync manager UI is the folder list, which displays available resources discovered by the provider and their synchronization status. It even allows interaction via additional buttons or context menus.

Either the FolderList() class or the StandardFolderList() class has to be implemented. The first one allows to fully control how the list items should look like, the second one is a lot simpler but does not give full control over the layout.

Target Classes
Implementing one or more TargetData() classes defines, how TbSync can access the local elements like address books, calendars or whatever is used to store the elements received from the server.

Base Class

class Base()

Base class for the TbSync provider interface.

Base.abAutoComplete(accountData, query)

Implement this method, if this provider should add additional entries to the autocomplete list while typing something into the address field of the message composer.

The return value is an Array of Objects and each Object needs the following attributes:

  • value : An email address written like DisplayName <EmailAddress>.
  • comment : Optional A comment displayed to the right of the value in the autocomplete list.
  • icon : Optional A chrome uri to a 16x16 icon.
  • style : Optional A CSS class name.

When creating directories, you can set:

directory.setBoolValue("enable_autocomplete", false);

to disable the default autocomplete for this directory and have full control over the autocomplete.

Arguments:
  • accountData (AccountData) – The AccountData instance of the account being queried.
  • query (string) – The search query.
Returns:

Array of Objects.

Base.getApiVersion()

Returns the version identifier of the TbSync API this provider is using. If it is not matching the version identifier of the TbSync add-on the user has currently installed, this provider add-on is not loaded.

Returns:string – The API version identifier.
Base.getConnectionTimeout(accountData)

Returns the connection timeout for an active server request, so TbSync can append a countdown to the connection timeout, while waiting for an answer from the server. Only syncstates which start with send. will trigger this, see SyncData.setSyncState().

Arguments:
  • accountData (AccountData) – The AccountData instance for the account for which the timeout is being requested.
Returns:

integer – The timeout in milliseconds.

Base.getCreateAccountWindowUrl()

Returns URL of the new account window.

The URL will be opened via openDialog(), when the user wants to create a new account of this provider.

Returns:string – Chrome uri to file to be used in create account dialog.
Base.getDefaultAccountEntries()

Returns an Object which contains all possible account properties of accounts of this provider, with its default value if not yet stored in the database.

The returned Object uses the properties names as key and its default values as their value:

return {
 "username" : "",
 "host" : "",
 "https" : true,
 "someOtherOption" : false,
}

Please also check the standard account properties added by TbSync.

    defaults.provider = provider;
    defaults.accountID = "";
    defaults.lastsynctime = 0;
    defaults.status = "disabled";
    defaults.autosync = 0;
    defaults.accountname = "";
Returns:Object – List of properties with default values.
Base.getDefaultFolderEntries()

Returns an Object which contains all possible folder properties of folders of this provider, with its default value if not yet stored in the database.

The returned Object uses the properties names as key and its default values as their value:

return {
  "someSetting" : "none",
}

Please also check the standard folder properties added by TbSync:

    defaults.accountID = accountID;
    defaults.targetType = "";
    defaults.cached = false;
    defaults.selected = false;
    defaults.lastsynctime = 0;
    defaults.status = "";
    defaults.foldername = "";
    defaults.downloadonly = false;
Returns:Object – List of properties with default values.
Base.getEditAccountOverlayUrl()

Returns uri to the overlay for the edit account dialog (chrome://tbsync/content/manager/editAccount.xul)

The overlay must (!) implement:

tbSyncEditAccountOverlay.onload(window, accountData)

which is called each time an account of this provider is viewed/selected in the manager and gets passed the AccountData of the corresponding account.

Returns:string – Chrome uri to overlay for edit account dialog.
Base.getMaintainerEmail()

Returns the email address of the maintainer (used for bug reports).

Returns:string – An email address.
Base.getProviderIcon(size, accountData=null)

Returns location of a provider icon.

Arguments:
  • size (integer) – Size of the requested icon.
  • accountData (AccountData) – The AccountData instance of the account, which is requesting the icon. Optional.
Base.getProviderName()

Returns name of this provider for the Add account menu of tbe TbSync account manager.

Returns:string – A name.
Base.getSortedFolders(accountData)

Returns all folders of the account, sorted in the desired order.

The order will be used in the folder list and also as the order to sync the resources of the account identified by the passed AccountData.

Arguments:
  • accountData (AccountData) – The AccountData instance for the account for which the sorted list of folders should be returned.
Returns:

Array of FolderData() instances in the desired order.

Base.getSponsors()

Returns a list of sponsors, they will be sorted by sortIndex.

return {
  "sortIndex" : {name       : "Name",
                 description: "Something",
                 icon: chrome://path/or/empty,
                 link: "url://or/empty"
                },
}
Returns:Object – List of sponsors.
Base.getStringBundleUrl()

Returns the URL of the string bundle file of this provider, it can be accessed by getString().

Returns:string – Chrome uri to the string bundle file.
Base.load()

Called during load of this provider add-on.

Base.onDisableAccount(accountData)

Is called everytime an account of this provider is disabled in the manager UI.

Arguments:
  • accountData (AccountData) – The AccountData instance of the account being disabled.
Base.onEnableAccount(accountData)

Is called everytime an account of this provider is enabled in the manager UI.

Arguments:
  • accountData (AccountData) – The AccountData instance of the account being enabled.
Base.syncFolder(syncData, syncJob, syncRunNr)

Is called to synchronize a folder.

Never call this method directly, but use AccountData.sync() or FolderData.sync().

Arguments:
  • syncData (SyncData) – The SyncData instance with information regarding the requested sync
  • syncJob (string) – A specific sync job, defaults to “sync”, but can be set via the syncDescription. (see AccountData.sync or FolderData.sync).
  • syncRunNr (integer) – Indicates the n-th number the account is being (re-)synced due to enforced retries. It starts with 1 and is limited by syncDescription.maxAccountReruns.
Returns:

A StatusData() instance with information of the sync (failed/success).

Base.syncFolderList(syncData, syncJob, syncRunNr)

Is called to synchronize the folder list.

Never call this method directly, but use AccountData.sync().

Arguments:
  • syncData (SyncData) – The SyncData instance with information regarding the requested sync
  • syncJob (string) – A specific sync job, defaults to “sync”, but can be set via the syncDescription. (see AccountData.sync or FolderData.sync).
  • syncRunNr (integer) – Indicates the n-th number the account is being (re-)synced due to enforced retries. It starts with 1 and is limited by syncDescription.maxAccountReruns.
Returns:

A StatusData() instance with information of the sync (failed/success).

Base.unload()

Called during unload of this provider add-on.

FolderList Classes

The DOM of the folderlist can be accessed by its ID and the FolderData of each entry is attached to its row. To get the FolderData of the selected row can be accessed like so:

let folderlist = document.getElementById("tbsync.accountsettings.folderlist");
let folderData = folderList.selectedItem.folderData;
class StandardFolderList()

StandardFolderList class.

StandardFolderList.getAttributesRoAcl(folderData)

Returns the attributes for the readonly menuitem element of the ACL selector for a folder to be shown in the folderlist. You can define any available attribute (label, disabled, hidden, style, …) by returning an Object which uses the attribute names as key and its values as their value. For example:

return {
  label: "Readonly access",
  disabled: false
}

If both (RO+RW) do not return any attributes, the ACL menu is not displayed at all.

Arguments:
  • folderData (FolderData) – The FolderData instance of the folder for which the attributes for the ACL RO XUL element are requested.
Returns:

Object – A list of attributes and their values for the ACL RO XUL element.

StandardFolderList.getAttributesRwAcl(folderData)

Returns the attributes for the read/write menuitem element of the ACL selector for a folder to be shown in the folderlist. You can define any available attribute (label, disabled, hidden, style, …) by returning an Object which uses the attribute names as key and its values as their value. For example:

return {
   label: "Read/Write access",
   disabled: true
}

If both (RO+RW) do not return any attributes, the ACL menu is not displayed at all.

Arguments:
  • folderData (FolderData) – The FolderData instance of the folder for which the attributes for the ACL RW XUL element are requested.
Returns:

Object – A list of attributes and their values for the ACL RW XUL element.

StandardFolderList.getFolderDisplayName(folderData)

Returns the display name for a folder to be shown in the folderlist.

Arguments:
  • folderData (FolderData) – The FolderData instance of the folder for which the display name is requested.
Returns:

string – Display name of the folder.

StandardFolderList.getTypeImage(folderData)

Returns the icon for a folder to be shown in the folderlist.

Arguments:
  • folderData (FolderData) – The FolderData instance of the folder for which the icon is requested.
Returns:

string – Chrome URL of icon.

StandardFolderList.onContextMenuShowing(window, folderData)

Is called before the context menu of the folderlist is shown, allows to show/hide custom menu options based on the selected folder. During an active synchronisation, folderData will be null and the folder list will be disabled.

Arguments:
  • window (nsIDOMWindow) – Object of the account settings window.
  • folderData (FolderData) – The FolderData instance of the selected folder.
class FolderList(provider)

Functions used by the folderlist in the main account settings tab

Arguments:
  • provider (string) – Identifier for the provider this FolderListView is created for.
FolderList.getHeader()

Returns an array of attribute objects, which define the number of columns and the look of the header

FolderList.getRow(document, folderData)

Is called to add a row to the folderlist. After this call, updateRow is called as well.

Arguments:
  • document – [in] document object of the account settings window
  • folderData – [in] FolderData of the folder in the row
FolderList.onContextMenuShowing(document, folderData)

Is called before the context menu of the folderlist is shown, allows to show/hide custom menu options based on selected folder

Arguments:
  • document – [in] document object of the account settings window - element.ownerDocument - menuentry?
  • folderData – [in] FolderData of the selected folder
FolderList.toggleFolder(event)

ToggleFolder event

FolderList.updateReadOnly(event)

updateReadOnly event

FolderList.updateRow(document, listItem, folderData)

Is called to update a row of the folderlist (the first cell is a select checkbox inserted by TbSync)

Arguments:
  • document – [in] document object of the account settings window
  • listItem – [in] the listitem of the row, which needs to be updated
  • folderData – [in] FolderData for that row

Target Classes

TbSync can manage different types of storage targets (calendars, address books, whatever) for each folder / resource found on the server. The provider only has to set a value for the targetType folder property when creating new folders. For each possible value, the provider must implememt a matching class of type TargetData in his provider namespace.

Example:

If one of the possible values of the targetType property is MyCalendar, the provider must implement a TargetData class inside his provider.js with a name of TargetData_MyCalendar.

When interacting with TbSync, for example when syncing a specific folder / resource, you will usually have access to a FolderData() instance, which will return the associated TargetData via FolderData.targetData().

class TargetData(folderData)

TargetData constrcutor.

Arguments:
  • folderData (FolderData) – The FolderData instance of the folder for which this TargetData instance is being created.
TargetData.disconnectTarget()

Disconnects the target in the local storage from this TargetData, but does not delete it, so it becomes a stale “left over”. A call to TargetData.hasTarget() should return false, after this has been executed.

TargetData.getTarget()

Returns the actual target object (for example a nsIAbDirectory). If the target does not exist, it should be created.

Note

The thrown error message will be used as a status and TbSync will use status.<Error.message> from your string bundle (see Base.getStringBundleUrl()) for the actual error/status message.

Throws:Error – Reason, why the target could not be created.
Returns:Object – Whatever you want to use as target object for this TargetData.
TargetData.hasTarget()

Check, if the target object of this TargetData exists in the local storage.

Returns:boolean – True, if target exists.
TargetData.removeTarget()

Removes the target from the local storage. If it does not exist, return silently. A call to TargetData.hasTarget() should return false, after this has been executed.

TargetData.setReadOnly(value)

The readonly property of the associated folder has been changed via the TbSync UI.

Note

This might be changed to a general FolderProperty observer.

Arguments:
  • value (boolean) – The current value of the downloadonly folder property.
TargetData.targetName

Getter/Setter for the target name.

TbSync Class Reference

daskjd akdj askldja sdjka dasljd aldja dlja sdasldj adljkas dlasjkd alsd asldja sdlasjd aldj

AccountData

class AccountData(accountID)

AccountData

AccountData.eventLogInfo

Getter for an EventLogInfo() instance with all the information regarding this AccountData instance.

AccountData.sync(syncDescription)

Initiate a sync of this entire account by calling Base.syncFolderList(). If that succeeded, Base.syncFolder() will be called for each available folder / resource found on the server.

Arguments:
  • syncDescription (Object) – Optional

EventLogInfo

class EventLogInfo(provider, accountname, accountID, foldername)

An EventLogInfo instance is used when adding entries to the TbSync Event Log. The information given here will be added as a header to the actual event.

Arguments:
  • provider (string) – Optional A provider ID (also used as provider namespace).
  • accountname (string) – Optional An account name. Can be arbitrary but should match the accountID (if provided).
  • accountID (string) – Optional An account ID. Used to filter events for a given account.
  • foldername (string) – Optional A folder name.
EventLogInfo.accountID

Getter/Setter for the account name of this EventLogInfo.

EventLogInfo.accountname

Getter/Setter for the account ID of this EventLogInfo.

EventLogInfo.foldername

Getter/Setter for the folder name of this EventLogInfo.

EventLogInfo.provider

Getter/Setter for the provider ID of this EventLogInfo.

FolderData

class FolderData(accountData, folderID)

FolderData

FolderData.eventLogInfo

Getter for an EventLogInfo() instance with all the information regarding this FolderData instance.

FolderData.sync(syncDescription)

Initiate a sync of this folder only by calling Base.syncFolderList() and than Base.syncFolder() for this folder / resource only.

Arguments:
  • syncDescription (Object) – Optional
FolderData.targetData

Getter for the TargetData() instance associated with this FolderData. See Target Classes for more details.

ProgressData

class ProgressData()

ProgressData to manage a done and a todo counter.

Each SyncData() instance has an associated ProgressData instance. See SyncData.progressData(). The information of that ProgressData instance is used, when the current syncstate is prefixed by send., eval. or prepare.. See SyncData.setSyncState().

ProgressData.done

Getter for the done counter.

ProgressData.inc(value=1)

Increment the done counter.

Arguments:
  • value (integer) – Optional Set incrementation value.
ProgressData.reset(done=0, todo=0)

Reset done and todo counter.

Arguments:
  • done (integer) – Optional Set a value for the done counter.
  • todo (integer) – Optional Set a value for the todo counter.
ProgressData.todo

Getter for the todo counter.

ProviderData

class ProviderData(folderData)

ProviderData

Constructor

Arguments:
  • folderData (FolderData) – FolderData of the folder for which the display name is requested.
ProviderData.eventLogInfo

Getter for an EventLogInfo() instance with all the information regarding this ProviderData instance.

StatusData

class StatusData(type=success, message, details)

A StatusData instance must be used as return value by Base.syncFolderList() and Base.syncFolder().

StatusData also defines the possible StatusDataTypes used by the TbSync Event Log.

Arguments:
  • type (StatusDataType) – Status type (see const definitions below)
  • message (string) – Optional A message, which will be used as sync status. If this is not a success, it will be used also in the TbSync Event Log as well.
  • details (string) – Optional If this is not a success, it will be used as description in the TbSync Event Log.
StatusData.ACCOUNT_RERUN

Sync of the entire account will be aborted and restarted completely.

StatusData.ERROR

Sync of the entire account will be aborted.

StatusData.FOLDER_RERUN

Sync of the current folder/resource will be restarted.

StatusData.INFO

Successfull sync, but message and details provided will be added to the event log.

StatusData.SUCCESS

Successfull sync.

StatusData.WARNING

Sync of this resource will be aborted and continued with next resource.

Example usage:

let status = TbSync.StatusData.INFO;
return new TbSync.StatusData(status, "Have a nice day!", "Everything is fine.");

SyncData

class SyncData(accountID)

There is only one SyncData instance per account which contains all relevant information regarding an ongoing sync.

SyncData.accountData

Getter for the AccountData() instance of the account being currently synced.

SyncData.currentFolderData

Getter for the FolderData() instance of the folder being currently synced. Can be null if no folder is being synced.

SyncData.eventLogInfo

Getter for an EventLogInfo() instance with all the information regarding this SyncData instance.

SyncData.getSyncState()

Gets the current syncstate and its timestamp of the ongoing sync. The returned Object has the following attributes:

  • state : the current syncstate
  • timestamp : its timestamp
Returns:Object – The syncstate and its timestamp.
SyncData.progressData

Getter for the ProgressData() instance of the ongoing sync.

SyncData.setSyncState(state)

Sets the syncstate of the ongoing sync, to provide feedback to the user. The selected state can trigger special UI features, if it starts with one of the following prefixes:

  • send., eval., prepare. : The status message in the UI will be appended with the current progress stored in the ProgressData() associated with this SyncData instance. See SyncData.progressData().
  • send. : The status message in the UI will be appended by a timeout countdown with the timeout being defined by Base.getConnectionTimeout().
Arguments:
  • state (string) – A short syncstate identifier. The actual message to be displayed in the UI will be looked up in the string bundle of the provider associated with this SyncData instance (Base.getStringBundleUrl()) by looking for syncstate.<state>. The lookup is done via getString(), so the same fallback rules apply.

TbSync Methods Reference

daskjd akdj askldja sdjka dasljd aldja dlja sdasldj adljkas dlasjkd alsd asldja sdlasjd aldj

getString()

getString(key, provider)

Get a localized string from a string bundle.

TODO: Explain placeholder and :: notation.

Arguments:
  • key (string) – The key to look up in the string bundle
  • provider (string) – Optional The provider whose string bundle should be used to lookup the key. See Base.getStringBundleUrl().
Returns:

string – The entry in the string bundle of the specified provider matching the provided key. If that key is not found in the string bundle of the specified provider or if no provider has been specified, the string bundle of TbSync itself we be used as fallback. If the key could not be found there as well, the key itself is returned.

TbSync Event Log

The TbSync event log can be used by any provider to log messages which could be important for the user.

eventlog.add(type, eventInfo, message, details)

Adds an entry to the TbSync event log

Arguments:
  • type (StatusDataType) – One of the types defined in StatusData()
  • eventInfo (EventLogInfo) – EventLogInfo for this event.
  • message (string) – The event message.
  • details (string) – Optional The event details.

Example usage:

let eventInfo = new TbSync.EventLogInfo();
TbSync.eventlog.add(TbSync.StatusData.WARNING, eventInfo, "Something bad happend!");

Instead of creating a custom EventLogInfo() instance, you can also get one with prefilled information via