Calendar:Creating an Extension

From MozillaWiki
Jump to: navigation, search

<< Back to Calendar Home Page

Draft-template-image.png THIS PAGE IS A WORKING DRAFT Pencil-emoji U270F-gray.png
The page may be difficult to navigate, and some information on its subject might be incomplete and/or evolving rapidly.
If you have any questions or ideas, please add them as a new topic on the discussion page.

For more information on creating an extension, please visit This page is dedicated to the specifics of Sunbird and Lightning Extensions.

Extension Dependencies

Introduced in bug 379005, it is now possible to create extensions that explicitly require Sunbird or Lightning. For more information on how extension dependancies work, read the detailed description.

While in Sunbird it is enough to add an <em:targetApplication> tag to your install.rdf to make the extension require the calendaring application, just requiring Thunderbird is not enough to ensure that Lightning is available. Therefore, you must use the <em:requires>> tag. In the past this again was a problem, since this tag is global, which would in theory require Sunbird to have Lightning installed. To work around this, we created a dummy extension that is globally installed and hidden in Sunbird, with the same id as lightning. You can now let your extensions use the <em:requires> tag to require Sunbird or Lightning.

To make clear which combination of <em:targetApplication> and <em:requires> you need, take a look at the following list:

  • Should run in both Sunbird and Lightning
    • Target Application: Sunbird and Thundebird
    • Requires: Lightning extension id
  • Should run only in Sunbird
    • Target Application: Sunbird
    • Requires: Not needed
  • Should run only in Lightning
    • Target Application: Thunderbird
    • Requires: Lightning extension id

Types of Extensions

Provider Extensions

A provider gives the calendar native support for a certain type of calendar. In contrast to an Import/Export extension, changes made to the calendar will be reflected in the target calendar immediately. An example for this type of extension is the Provider for Google Calendar

A provider must implement the calICalendar interface, and have a contract id like;1?type=myprovider, where myprovider is the type returned in the calICalendar implementation. For an example on how to create a provider, see the Provider for Google Calendar.

A summary of the methods and attributes to be filled:

  • Some attribtes are static and usually only return a value: type, sendItipInvitations, canRefresh
  • Some attribute require remembering the local value: id, readOnly, supressAlarms, uri
  • Some attributes should use the Calendar Manager to set preferences: name
  • Use the uri setter to do extra initialization when the calendar is created and registered.
  • The addObserver, removeObserver, startBatch, endBatch methods can use calListenerBag to easily store and forward the needed messages. Be sure to load calUtils using mozIJSSubscriptLoader.
  • The addItem, deleteItem, modifyItem should fire a notifier message in addition to the calIOperationListener calls.
  • Note that returning the calIOperation from the calendar manipulation methods is optional, but recommended for asynchronous providers.

Import-Export Extensions

This type of extension allows importing and exporting calendar data to different formats. The idea is to implement the calIImporter and calIExporter interfaces, creating a custom serialization for the calendar data. Additionally, you will have to register yourself with the cal-importers and cal-exporters categories. For an example how to register for these categories, see calendar/import-export/calImportExportModule.js

Other Extensions

If you are creating a different type of extension and have some information to share, feel free to contact us in #calendar on

Creating Extensions with the Build System

Original Documentation here

If you have a build environment set up (easy steps can be found here), this is quite easily done using the mozilla build system. The advantage of this method, is that you don't have to take care of different chrome.manifests for development and deploying and also don't have to take care of zipping together the .xpi file yourself or via a script.

The first step is to create your extension directory. You will want to create the directory in $MOZILLA/extensions. If you are on an operating system that supports soft links (i.e Linux), you can also create the directory somewhere else, and create a soft link in the directory noted above.

Now you need to tell the build system to build your extension. This can be done in your mozconfig by appending your extension directory name to the ac_add_options --enable-extensions line. If you have already built the application, then you can easily add the extension without doing a full rebuild. To do so, open $MOZILLA/obj-*/config/, find and modify the lines as follows:


# The next line is the important one to change. Just add your extension directory name
# to this line. All other lines can stay as they are.
MOZ_EXTENSIONS  = xmlextras transformiix lightning inspector venkman

MOZ_IMG_DECODERS= png gif jpeg bmp xbm 

Next, you need a to describe your extension. What belongs in here kind of depends on what sort of extension you are creating. The following can be placed in your $MOZILLA/extensions/my_extension/ directory and contains many different setups. Remove anything you don't need.

DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@

include $(DEPTH)/config/

# Your extension module name.
MODULE = my_extension

# Instead of a chrome.manifest file in every directory, use one manifest file like extensions usually do 

# XPI_NAME controls where files are installed to. This should be exported so it is automatically the case 
# for subdirectories.
export XPI_NAME = my_extension

# Files mentioned here will be preprocessed and included in your .xpi
DIST_FILES = install.rdf

# XPI_PKGNAME is the name of the .xpi file that is generated. If you want, you can use the version number
# here or even import the version number from a file.
XPI_PKGNAME = my_extension


# Subdirectories to process. These must contain their own and can be used to organize your
# extension source directory. Remember to increase the DEPTH variable of the subdirectory's when 
# using subdirectories.
DIRS = components

# Extra components. These get put into your extension's components/ directory and must contain a 
# NSGetModule function. This is usually better put in the components subdirectory mentioned
# above.
EXTRA_COMPONENTS = components/myExtensionModule.js

# Extra scripts. This is not a standard variable, so you'll need some special processing I'm not
# going to include here to put these into the directory you want. An example can be found at 
# the end of calendar/providers/gdata/components/
# The main difference between EXTRA_SCRIPTS and EXTRA_COMPONENTS is that the latter will try to be
# registered as a component by the application, while the former should just be loaded from your components.
EXTRA_SCRIPTS = components/myExtensionScript.js

include $(topsrcdir)/config/

Chrome files can easily be registered using a file, which you should place in your $MOZILLA/extensions/my_extension directory. The developer site on JAR Manifests is quite elaborate and should tell you what to put in this file. From this file, your chrome.manifest automatically gets generated. An example can be found here, if you want to add locales you can also take a look at this one.

If you are using any C++ files or similar, please see the original documentation for how to include them in your extension.