 places:
- the very first run defaults. This is provided by the microformats team.
- the i18n contributors. The most likely useful address finders in one country may be different to the next.
- the partnership engineering team.
The browser only needs to glue the pieces together.
### Concepts. Words.
In the eclipse world, the unit of distibution Firefox calls an addon is a 'plugin'.
In OSGi, it is a 'bundle'.
The other eclipse words would be 'extension' and 'extension point'. How the extensions were joined to the extension points was the job of the registry.
OSGi bundles have 'service provider' and 'service'. There was no explict Service Registry, but it described itself in terms of a 'whiteboad' pattern.
Analogues with Android intents are noted, and differs mainly in granularity and lifecycle control.
I prefer the Eclipse nomenclature simply because its more descriptive.
However, I am aware that other browsers already use 'extension'. Thus, I will now consistently use extender and extension point (or EP).
### Back to business
For the rest of this post I'll assume a set of addons:
- `microformat-core`
- `microformat-i18n-xx`
- `microformat-commercial-xx`
How these addons get there we can talk about later on.
The microformat-core addon advertises an extension point for microformat linkifiers. Linkifiers are templates for a given detected object that the core addon can use to send the user to a new tab.
Declaratively, we could define an address resolver like so:
```
{
"name": "Open Street Map",
"template": "http://www.openstreetmap.org/search?query={line1}%2C{line2}%2C{zipcode}%2C{country}"
}
```
Linkifiers are extenders provided by the `i18n-xx` and `commercial-xx` addons, as well as any other addon that the user could install. Importantly `microformat-core` addon can provide one, as a fallback when all other addons have been uninstalled.
The linkifier extension point is not part of the manifest spec, but for addon review purposes we'd like to be able to declare it in the manifest. But the syntax to declare extension-points and extenders _should be_ in the spec, so more developers can add to the Firefox ecosystem without stepping on each others toes.
For similar review purposes, and convenience for small addon creators, the extenders should be declared in or near the manifest.json file.
```
{
"name": "Microformatter"
…
"extension-points": {
"mf-linkifier-address": {
"selector": "pref"
},
},
"permissions": [
"extenders"
]
```
Somewhere, in a manifest not far away.
```
"extenders": {
"mf-linkifier-address": {
"name": "Open Street Map",
"template": "http://www.openstreetmap.org/search?query={line1}%2C{line2}%2C{zipcode}%2C{country}"
},
}
// no explicit permission is needed to declare extenders in the manifest.
}
```
The extension point collects all the extenders up from different addons and presents them as a list.
In the microformats-core addon, the extension point is consumed in an event based manner:
```
function findAddress(detectedObject) {
var ep = chrome.extenders.get('mf-linkifier-address');
var linkifiers = ep.all();
var linkifier = linkifiers[0]; // naïve
var url = makeURL(linkifier.template, detectedObject);
return url;
}
//
```
It is possible to limit the access to extension points via the manifest.
Thus, we have parts of other addon manifests squirted into an addon that invites it, and the many-to-many relationship is mediated by an addon 'registry'.
## Further work
.
It starts to become magical when extension points are notified when extenders appear and disappear.
```
var ep = chrome.extenders.get('firefox.addon-manifests');
ep.onAdd(function (addonManifest) {
var allExtenders = addonManifest.extenders || {};
…
for (extensionPointID in allExtenders) {
// …
for (var extender in allExtenders[extensionPointID]) {
var extender = … // iterating through the manifest
chrome.extenders.add(extensionPointID, extender);
// …
}
}
});
ep.onRemove(function (manifest) {
…
chrome.extenders.remove(extensionPointID, extender);
…
});
```
Thus, we have restart-less install.
### Developer tools to ease extender
The mf-linkifier-address extension point above declares a "selector".
```
var linkifier = ep.choose(); // select based upon a preference page choice.
```
### Swift consumers of extension points
```
let ep = registry.get("browserAction")
let buttonMetadata = ep.choose(); // select based upon a preference page choice.
```
The integration between javascript and Swift is just nice enough to get things done, but pretty ugly syntax wise.
However, the registry can be kept in Swift or Javascript, and be shared relatively painlessly between Swift consumers of extension points.
Going further, Swift knows enough about the extension point and the contributed extenders that it can generate a preference page for the extension point.
Extenders with js functions
---------------------------
JSContexts can share functions quite comfortably executing functions in the context they were declared in. JSContexts seem to behave almost exactly like a module-pattern module would.
Thus, programatic access to add functions as or part of an extender would be really interesting.
The extender registry provides a simple API to add and remove extenders – simple enough for a manifest parser to do it in an automated way. Providing access through JS may not be advisable for addon-review purposes, so some manifest driven access
### Concerns with JS adding extenders
- Content-scripts access to the registry is needed (WebExtensions needs getManifest()) anyway, but sharing functions across this boundary may be unneccessary or difficult.
- Contributing addons may expose user-data to other addons.
- A good fences rule will be needed to ensure one addon doesn't crash another.
Security
--------
- Addons can only consume the extension-points they declare in their manifest.
- Addons contribute only the data they want to – extenders do not have access to the extension-points.
- Extension points starting with 'firefox.' are not accessible from any addon.
- A policy where multiple addons consume the same extension-point.
![Ghetto Gecko](https://
Back to our example
-------------------
So we have an microformats-core addon and a microformats-i18n, microformats-commercial addons.
Now we also have API for home tiles. This would also be a likely candidate for the same pattern.
However, the units of extension are extenders, which are can be distributed as a group in single addon.
- feature-a
- feature-b
- feature-c
- i18n-xx
- commercial-xx
The feature addons are shipped with the app.
The locale specific configuration for feature addons can either be distributed from a remote server – and appropriately signed, or distributed with the app and chosen at runtime.
Additional conifg for a, b and c can of course come from other addons the user installs.
This, plus an addon update mechanism gives us great scope to ship code faster, prototype new additions to the spec.
## Summary
I've described an extender registry: a fairly simple data structure which can be the enabling technology for addon management and implementation, but also enables a secure and stable extension mechanism for third party addons.