Comparaison avec le SDK Add-on

Cet article est une comparaison technique entre les add-ons construits avec le SDK et ceux construits avec la technologie WebExtensions. Il est destiné à aider les personnes maintenant un add-on SDK à le porter vers une WebExtension.

Si vous souhaitez porter une extension de surcouche ou une extension bootstrappée, consultez la page de comparaison des extensions XUL/XPCOM.

Les WebExtensions et add-ons SDK partagent les mêmes concepts et structures de base. Ces deux technologies utilisent :

Au-delà de ces ressemblances, il existe de nombreuses différences énumérées ci-après.

Les fichiers de manifeste

Pour ces deux technologies, on dispose d'un fichier manifeste en JSON situé dans le répertoire racine de l'extension. Dans le SDK, ce fichier est appelé package.json ; pour les WebExtensions, ce fichier s'intitule manifest.json. Les deux fichiers contiennent des métadonnées de base telles que le nom, la description et les icônes de l'extension.

Cependant, manifest.json contient de nombreuses clés qui définissent certaines capacités et certains comportements de l'extension. Pour le SDK, certaines sont définies dans le code :

Fonctionnalité SDK WebExtensions
Scripts de contenu correspondant aux modèles d'URL API page-mod Clé de manifeste content_scripts
Boutons de la barre d'outils API ui/button/action Clé de manifeste browser_action
Accéder aux API privilégiées Fonction require() Clé de manifeste permissions

Les WebExtensions sont donc plus déclaratives et moins programmables que les add-ons construits avec le SDK.

Pour le  SDK, on utilisera généralement jpm init afin de créer un nouveau package.json. La technologie WebExtensions n'a pas d'équivalent de jpm init, le fichier de manifeste sera probablement écrit à partir de zéro ou adapté d'un fichier existant.

En savoir plus

Scripts persistants

Les deux technologies utilisent des scripts persistants qui restent chargés pendant que l'extension est active. Ces scripts accèdent à des API privilégiées et peuvent communiquer avec d'autres parties de l'extension telles que les scripts de contenu.

Dans le SDK, par défaut, ce script est appelé index.js et il peut charger d'autres scripts à l'aide du chargeur de module.

Avec les WebExtensions, ces scripts sont appelés scripts d'arrière-plan. Vous pouvez définir un ensemble de scripts listés via la clé de manifeste background et tous seront chargés dans le même document (une page HTML vierge cachée et générée automatiquement). Vous pouvez également définir votre propre document personnalisé à l'aide de la clé background.

Une différence importante est que les scripts d'arrière-plan ont accès à la variable globale  window globale qui permet d'utiliser l'ensemble des objets DOM habituellement présents dans une fenêtre. De cette façon, l'écriture des extensions se rapproche de l'écriture de pages web avec un accès direct à l'ensemble des API Web classiques (par exemple XMLHttpRequest ou IndexedDB).

On notera également que, par défaut, les extensions ont une politique de sécurité de contenu (CSP) qui leur est appliquée. Vous pouvez spécifier votre propre politique, mais la politique par défaut, entre autres, interdit les pratiques potentiellement dangereuses telles que l'utilisation d'eval().

En savoir plus

Scripts de contenus

Pour les extensions SDK et les WebExtensions, les scripts persistants ne peuvent pas accéder directement au contenu des pages web. Au lieu de cela, les extensions peuvent ajouter des scripts de contenu aux pages web. Ces scripts :

  • accèdent directement au contenu web
  • n'accèdent pas aux API privilégiées
  • peuvent communiquer avec les scripts persistants avec une API de messagerie.

Pour  les deux technologies, on dispose de deux façons pour ajouter des scripts de contenu : on peut rattacher un ensemble de scripts aux pages dont l'URL contient un motif donné ou on peut, via le code, ajouter un script à une page d'un onglet donné. Si ces mécanismes existent dans les deux technologies, ils sont exécutés différemment :

Opération SDK WebExtensions
Attacher des scripts à des pages dont l'URL correspond à un motif API page-mod Clé de manifeste content_scripts
Attacher des scripts à des pages hébergées dans un onglet tab.attach() tabs.executeScript()

Les motifs de correspondance utilisés pour les URL sont différentes :

Dans les deux technologies, on peut passer des options pour contrôler lorsque le script s'exécute et s'il sera attaché aux sous-trames. Les  WebExtensions n'ont pas d'équivalent pour contentScriptOptions et, si on veut transmettre les options de configuration à un script de contenu, il faudra les envoyer via un message ou les stocker dans storage.local.

Dans les deux technologies, les scripts de contenu peuvent communiquer avec des scripts persistants grâce à une API de communication asynchrone :

Opération SDK WebExtensions
Envoi de  message port.emit() runtime.sendMessage() / tabs.sendMessage()
Réception de  message port.on() runtime.onMessage

Dans les deux cas, les scripts de contenus peuvent communiquer avec les scripts chargés par la page à l'aide de window.postMessage et window.addEventListener.

Dans les deux cas, les scripts accèdent à une vue « propre » du DOM : cela signifie qu'ils ne voient pas les modifications apportées au DOM par les scripts chargés par la page.

Dans le SDK, les scripts de contenu peuvent partager des objets avec des scripts de page, en utilisant des techniques comme unsafeWindow et createObjectIn. Avec les WebExtensions, la unsafeWindow est disponible par l'intermédiaire de wrappedJSObject. Toutes les fonctions d'aide à l'exportation sont également disponibles.

En savoir plus

Les éléments d'interface utilisateur (UI)

Les deux technologies fournissent des API pour créer une interface utilisateur pour l'extension. Les options d'interface utilisateur pour les WebExtensions sont plus limitées.

Elément d'interface SDK WebExtensions
Bouton ui/button/action browser_action / page_action
Interrupteur / Bouton à bascule ui/button/toggle browser_action / page_action
Barre d'outils ui/toolbar Aucun
Barre latérale ui/sidebar sidebar_action
Panneau panel browser_action / page_action popup
Menu contextuel context-menu contextMenus

Panneaux et fenêtres contextuelles

Les panneaux et les fenêtres contextuelles sont des boites de dialogue transitoires définies à l'aide de HTML, CSS et JavaScript.

Contrairement aux panneaux, les fenêtres contextuelles sont toujours attachées à un bouton (une action de navigateur ou une action de page) et ne peuvent pas être affichés par programmation : ils ne s'affichent que lorsque l'utilisateur clique sur le bouton.

Aussi, contrairement aux panneaux, les scripts des fenêtres contextuelles ont accès aux mêmes API que les scripts d'arrière-plan. Ils peuvent même accéder directement à la page d'arrière-plan, via  runtime.getBackgroundPage().

Paramètres

Les extensions SDK et les WebExtensions permettent toutes les deux de gérer des paramètres (aussi appelées options ou préférences).

Avec le fichier SDK, il est possible d'indiquer des paramètres via la clé preferences dans le fichier package.json. L'utilisateur peut voir et modifier ces préférences via l'entrée du Gestionnaire de modules de l'extension. À l'inverse, l'extension peut écouter les changements de paramètres à l'aide de l'API simple-prefs.

Dans les WebExtensions, vous devrez implémenter votre propre interface utilisateur afin de présenter les paramètres et votre propre code pour les garder en mémoire pour votre extension. Pour cela, on écrira un fichier HTML qui présente les paramètres et qui peut inclure un script permettant de les sauvegarder. Le script a accès à toutes les API des WebExtensions et on utilisera généralement l'API storage pour la mémorisation.

L'URL du fichier HTML pour l'écran des paramètres doit être indiqué avec la clé options_ui du fichier manifest.json. La page de paramètres apparaît alors dans l'entrée de l'extension sous le Gestionnaire de modules des extensions. La page d'options peut également être ouverte via le code grâce à un appel à browser.runtime.openOptionsPage.

On notera que les WebExtensions ne permettent pas d'accéder aux préférences du navigateur (c'est-à-dire les préférences exposées dans le SDK par preferences/service). Toutefois, il est possible de modifier certains paramètres du navigateur grâce aux API privacy et browserSettings.

En apprendre plus

Internationalisation

Le SDK et les WebExtensions contiennent tous les deux des outils de localisation pour traduire le texte qui sera visible par l'utilisateur. Ces deux outils offrent des fonctionnalités similaires :

Fonctionnalités SDK WebExtensions
Chaînes dans les scripts d'arrière-plan Oui Oui
Chaînes dans les scripts de contenu Non Oui
Chaînes dans les fichiers HTML Oui Non
Chaînes dans les fichiers CSS Non Oui
Titre et descriptions Oui Oui
Gestion des formes plurielles Oui Non
Textes de substitution (placeholders) Oui Oui

Dans les deux systèmes, les chaînes traduites sont fournies via un ensemble de fichier : un pour chaque locale.

Pour récupérer les chaînes localisées dans le code de l'extension, on peut utiliser l'API JavaScript l10n dans le SDK et l'API i18n pour les WebExtensions.

Les WebExtensions ne gèrent pas nativement la localisation des chaînes présentes dans les fichiers HTML : il faut le faire soi-même en utilisant JavaScript pour récupérer des chaînes localisées et pour remplacer dynamiquement le contenu HTML par la version localisée.

En savoir plus

Outil en ligne de commande

Le SDK livré avec un outil en ligne de commande : jpm qu'on peut utiliser pour tester et empaqueter les extensions. Il existe un outil équivalent pour les WebExtensions : web-ext. Web-ext ne prend pas en charge les mêmes commandes que jpm, mais gère run, build et sign.

Il est maintenant possible d'installer (et de recharger) des extensions SDK et les extensions construites avec les API WebExtension dans Firefox à partir de leur répertoire source, sans avoir besoin de les empaqueter dans un fichier XPI. Voir l'installation temporaire dans Firefox.

En savoir plus

Les API JavaScript

Que ce soit pour le SDK et les WebExtensions, la puissance des extensions provient d'un ensemble d'API JavaScript dédiées. Pour la plupart des API SDK de haut niveau, il existe un équivalent WebExtensions.

Une grande limitation de WebExtensions par rapport au SDK est que les modules complémentaires SDK peuvent utiliser require("chrome") pour accéder à la gamme complète des API XPCOM dans Firefox. Ceci n'est pas possible avec WebExtensions.

Pour accéder aux API privilégiées dans le SDK, on utilise require() :

var tabs = require("sdk/tabs");
tabs.open("https://developer.mozilla.org/");

Avec WebExtensions, la plupart des API sont déjà disponibles, sans avoir besoin de les importer :

browser.tabs.create({
  "url": "/"
});

Pour certaines API WebExtension, vous devez d'abord demander la permission, en utilisant la clé des permissions de manifest.json. Dans l'exemple ci-dessous, l'extension doit demander l'autorisation "tabs" si elle souhaite accéder à l'URL de l'onglet :

manifest.json

...

"permissions": [
    "tabs"
  ]

...

Script d'arrière-plan

function logUrl(tabs) {
  console.log(tabs[0].url);
}

var querying = browser.tabs.query(
  {active: true, currentWindow: true}
);

querying.then(logUrl);

Comparaison des API SDK / WebExtension

Les tableaux de cette section répertorient chaque API du SDK et indiquent l'API WebExtension équivalente si elle existe.

Le premier tableau couvre les API SDK de haut niveau, le second couvre les API bas niveau.

API haut niveau

SDK WebExtensions
addon-page tabs.create() peut être utilisé pour charger des pages packagées avec l'add-on dans des onglets de navigateur.
base64 window.atob() et btoa()
clipboard document.execCommand sans select() sur la page d'arrière-plan.
context-menu contextMenus
hotkeys commands
indexed-db window.indexedDB
l10n i18n
notifications notifications
page-mod content_scripts
page-worker

Le portage n'est pas terminé et est décrit dans le bug 1318532

Les méthodes de contournement (qui peuvent avoir besoin de webrequestBlocking pour accéder à l'ensemble des  pages [exemple]) :

  • Utiliser la page d'arrière-plan
  • Charger des iframes distantes dans la page d'arrière-plan
  • Effectuer un appel XHR pour obtenir les informations statiques de la page.
panel Voir la section sur les interfaces utilisateur.
passwords L'API expérimentale logins
private-browsing Tab.incognito et Window.incognito.
querystring window.URLSearchParams
request window.fetch ou window.XMLHttpRequest
selection Utiliser un script de contenu qui envoie la donnée sélectionnée l'add-on. Sinon, si on peut utiliser un menu contextuel sur une sélection, celle-ci sera contenue dans selectionText (contextMenus.OnClickData).
self runtime.getManifest() et extension.getURL() pour data.url()
simple-prefs storage et options_ui
simple-storage storage
system Partiellement couvert par runtime.
tabs tabs
timers alarms
ui Voir la section sur les éléments d'interface.
url window.URL
widget Aucun
windows windows

API bas niveau

SDK WebExtensions
loader Aucun
chrome Aucun
console/plain-text Aucun
console/traceback Aucun
content/content Aucun
content/loader Aucun
content/mod Aucun
content/symbiont Aucun
content/worker Aucun
core/heritage Aucun
core/namespace Aucun
core/promise Promise
dev/panel devtools.panels
event/core Aucun
event/target Aucun
frame/hidden-frame Aucun
frame/utils Aucun
fs/path Aucun
io/byte-streams Aucun
io/file Aucun
io/text-streams Aucun
lang/functional Aucun
lang/type Aucun
loader/cuddlefish Aucun
loader/sandbox Aucun
net/url Aucun
net/xhr window.fetch ou window.XMLHttpRequest
places/bookmarks bookmarks
places/favicon Aucun
places/history history
platform/xpcom Aucun
preferences/event-target Aucun
preferences/service Prise en charge partielle via les API privacy et browserSettings
remote/child Aucun
remote/parent Aucun
stylesheet/style Aucun
stylesheet/utils Aucun
system/child_process runtime.connectNative
system/environment Aucun
system/events Aucun
system/runtime Prise en charge partielle via runtime.getPlatformInfo
system/xul-app Prise en charge partielle via runtime.getBrowserInfo
tabs/utils Aucun
ui/button/action browser_action / page_action
ui/button/toggle browser_action / page_action
ui/frame Aucun
ui/id Aucun
ui/sidebar sidebarAction
ui/toolbar Aucun
util/array Aucun
util/collection Aucun
util/deprecate Aucun
util/list Aucun
util/match-pattern Aucun
util/object Aucun
util/uuid Aucun
window/utils Aucun

Étiquettes et contributeurs liés au document

Étiquettes : 
Contributeurs à cette page : SphinxKnight, hellosct1
Dernière mise à jour par : SphinxKnight,