Architecture d'une Extension : Manifest et Fichiers Clés
Dans le cadre de notre cours "Maîtriser le Développement d'Extensions de Navigateur : De l'Idée à la Publication", cette leçon fondamentale vous plongera au cœur de l'anatomie d'une extension. Comprendre comment une extension est structurée, et en particulier le rôle crucial du fichier manifest.json ainsi que des différents types de scripts, est la première étape indispensable pour bâtir des outils robustes et performants.
Introduction : Les Fondations d'une Extension
Une extension de navigateur, bien qu'elle puisse sembler complexe, est en réalité une collection organisée de fichiers : des fichiers HTML, CSS, JavaScript, ainsi que des images et autres ressources. La clé de cette organisation et de son fonctionnement réside dans son architecture. Une architecture bien pensée garantit la sécurité, la performance et la maintenabilité de votre extension.
Au centre de cette architecture se trouve un fichier très spécial : le manifest.json. Ce fichier est la carte d'identité de votre extension, dictant au navigateur comment la charger, quelles permissions elle nécessite et quels composants elle contient.
Nous allons explorer en détail :
- Le rôle et la structure du
manifest.json. - Les différents types de fichiers JavaScript (scripts de fond, scripts de contenu, pop-ups) et leur interaction.
- Comment ces éléments collaborent pour donner vie à votre extension.
Le Fichier Manifest (manifest.json) : Le Cœur de l'Extension
Le fichier manifest.json est le fichier le plus important de votre extension. C'est un fichier JSON qui fournit des métadonnées essentielles sur votre extension au navigateur. Il informe le navigateur sur le nom de l'extension, sa version, ses permissions, les fichiers qu'elle doit exécuter, et bien plus encore.
Depuis la fin de 2022, la version Manifest V3 est la norme obligatoire pour toutes les nouvelles extensions et les mises à jour sur le Chrome Web Store. Elle apporte des changements significatifs en matière de sécurité, de performance et de confidentialité par rapport à Manifest V2. Nous nous concentrerons sur Manifest V3 dans cette leçon.
Structure Générale du manifest.json
Voici les champs les plus courants et les plus importants que vous trouverez dans un fichier manifest.json (V3) :
manifest_version: Spécifie la version du format de manifeste que votre extension utilise. Pour Manifest V3, sa valeur est3.name: Le nom de votre extension tel qu'il apparaît à l'utilisateur.version: Le numéro de version de votre extension. Il est utilisé pour les mises à jour.description: Une brève description de votre extension.icons: Spécifie les icônes à utiliser pour représenter votre extension (dans le navigateur, les magasins d'extensions, etc.). Différentes tailles sont généralement fournies.action: (Nouveau en V3, remplacebrowser_actionetpage_actionde V2) Définit l'interface utilisateur de votre extension qui apparaît lorsque l'utilisateur clique sur l'icône de l'extension dans la barre d'outils du navigateur. Il peut pointer vers un fichier HTML pour un pop-up.permissions: Un tableau de chaînes spécifiant les API Chrome que votre extension est autorisée à utiliser (ex:storage,activeTab,scripting).host_permissions: Un tableau de chaînes spécifiant les URL ou les motifs d'URL sur lesquels votre extension est autorisée à interagir (ex:"*://*.google.com/*").background: (Service Worker en V3) Définit un script JavaScript qui s'exécute en arrière-plan, gérant les événements du navigateur et les tâches de longue durée. Il doit être un service worker en V3.content_scripts: Un tableau d'objets définissant des scripts JavaScript et/ou CSS qui seront injectés dans des pages web spécifiques. Ils interagissent directement avec le DOM des pages web.web_accessible_resources: (Nouveau en V3) Spécifie les ressources (images, HTML, JavaScript) qui sont accessibles par les pages web normales. Cela est plus strict en V3 pour des raisons de sécurité.options_pageouoptions_ui: Spécifie un fichier HTML qui fournit une page de configuration pour votre extension.
Exemple de manifest.json (Manifest V3)
Voici un exemple commenté d'un fichier manifest.json pour une extension simple qui affiche un pop-up et injecte un script de contenu sur google.com :
{
"manifest_version": 3,
"name": "Ma Super Extension V3",
"version": "1.0",
"description": "Une extension basique pour illustrer l'architecture Manifest V3.",
"icons": {
"16": "images/icon-16.png",
"48": "images/icon-48.png",
"128": "images/icon-128.png"
},
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "images/icon-16.png",
"24": "images/icon-24.png",
"32": "images/icon-32.png"
},
"default_title": "Cliquez-moi !"
},
"permissions": [
"storage",
"activeTab",
"scripting"
],
"host_permissions": [
"*://*.google.com/*"
],
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": ["*://*.google.com/*"],
"js": ["content-script.js"],
"css": ["content-style.css"]
}
],
"options_page": "options.html",
"web_accessible_resources": [
{
"resources": ["images/logo.png", "injected-script.js"],
"matches": ["<all_urls>"]
}
]
}
Explication du code :
manifest_version: 3est obligatoire pour les nouvelles extensions.name,version,description,iconssont des métadonnées standards.actionconfigure le bouton de l'extension dans la barre d'outils.default_popupindique le fichier HTML à charger lorsque l'utilisateur clique sur l'icône.permissionsdemande l'accès à l'APIstorage(pour stocker des données),activeTab(pour interagir avec l'onglet actif temporairement), etscripting(pour injecter des scripts).host_permissionsdemande l'accès aux sites se terminant pargoogle.com(tous les sous-domaines et protocoles).backgroundpointe versbackground.jsqui sera exécuté comme un service worker.content_scriptsspécifie quecontent-script.jsetcontent-style.cssdoivent être injectés sur toutes les pages degoogle.com.options_pageindique queoptions.htmlest la page de configuration de l'extension.web_accessible_resourcespermet aux pages web d'accéder àlogo.pngetinjected-script.jsdepuis l'extension.<all_urls>signifie qu'ils sont accessibles depuis n'importe quelle URL.
Les Fichiers Clés de l'Architecture
Au-delà du manifest.json, plusieurs types de fichiers JavaScript (et HTML/CSS) jouent des rôles distincts mais complémentaires dans le fonctionnement d'une extension.
Le Service Worker (Background Script - V3) : Le Cerveau Invisible
Le service worker (précédemment appelé background script en V2) est un script JavaScript qui s'exécute en arrière-plan et gère les événements du navigateur. C'est le cerveau de votre extension.
Caractéristiques clés du Service Worker :
- Événementiel : Il ne s'exécute que lorsqu'un événement spécifique se produit (clic sur l'icône, réception d'un message, navigation vers une URL spécifique, etc.). Il peut se "mettre en veille" ou être désactivé lorsqu'il n'y a pas d'événement pour économiser des ressources.
- Global : Il a accès à toutes les API Chrome déclarées dans le
manifest.json(sous réserve des permissions demandées). - Communication : C'est le point central pour la communication avec d'autres parties de l'extension (pop-ups, scripts de contenu).
- Pas d'accès direct au DOM : Il ne peut pas interagir directement avec le contenu des pages web.
Exemple de background.js (Service Worker)
Ce script écoute l'installation de l'extension et enregistre un message dans la console du service worker.
// background.js
chrome.runtime.onInstalled.addListener(() => {
console.log('Extension installée ou mise à jour !');
// Vous pourriez initialiser des valeurs par défaut ici
chrome.storage.sync.set({ couleurFavorite: '#3aa757' }, () => {
console.log('Couleur favorite définie par défaut.');
});
});
// Exemple d'écouteur pour un message venant d'un script de contenu ou d'un pop-up
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.greeting === "hello") {
console.log("Message reçu du script de contenu ou du pop-up :", request.greeting);
sendResponse({ farewell: "goodbye from background" });
}
});
// Exemple de gestion d'un clic sur l'icône si action.default_popup n'est pas défini
// ou si vous voulez effectuer une action avant l'ouverture du popup.
// Attention : avec default_popup, le clic ouvre le popup,
// ce listener serait pour un cas où default_popup n'est pas utilisé ou pour des actions spécifiques.
/*
chrome.action.onClicked.addListener((tab) => {
console.log("Icône de l'extension cliquée !");
// Par exemple, ouvrir une page spécifique
chrome.tabs.create({ url: 'https://developer.chrome.com/docs/extensions/' });
});
*/
Explication du code :
chrome.runtime.onInstalled.addListener(): un écouteur d'événements qui se déclenche lorsque l'extension est installée pour la première fois ou mise à jour.chrome.storage.sync.set(): un exemple d'utilisation d'une API Chrome pour stocker des données utilisateur synchronisées entre les appareils.chrome.runtime.onMessage.addListener(): un écouteur crucial pour la communication. Il reçoit des messages d'autres parties de l'extension et peut y répondre.
Le Script de Contenu (Content Script) : Interagir avec les Pages Web
Les scripts de contenu sont des fichiers JavaScript qui s'exécutent dans le contexte d'une page web spécifique. Ils sont le bras et les jambes de votre extension, permettant d'interagir directement avec le contenu DOM de la page.
Caractéristiques clés des Scripts de Contenu :
- Injection : Ils sont injectés dans des pages web selon les
matchesspécifiés dans lemanifest.json. - Accès au DOM : Ils peuvent lire et modifier le DOM de la page, intercepter les événements JavaScript, et injecter des CSS.
- Environnement isolé : Bien qu'ils s'exécutent dans le contexte de la page, leur environnement JavaScript est isolé de celui de la page elle-même. Cela signifie qu'ils ne peuvent pas accéder directement aux variables ou fonctions JavaScript définies par la page et vice versa, mais ils peuvent interagir avec le DOM partagé.
- Communication avec le Service Worker : Ils doivent communiquer avec le service worker pour accéder aux API Chrome ou stocker des données, car ils n'ont pas accès directement aux API Chrome (sauf un sous-ensemble très limité).
Exemple de content-script.js
Ce script de contenu simple, injecté sur google.com, ajoute un message et change la couleur de fond du corps de la page.
// content-script.js
console.log("Script de contenu chargé sur la page !");
// Ajouter un message à la page
const messageDiv = document.createElement('div');
messageDiv.style.cssText = `
position: fixed;
top: 10px;
right: 10px;
background-color: lightblue;
border: 1px solid blue;
padding: 5px;
z-index: 10000;
`;
messageDiv.textContent = "Bonjour depuis mon extension !";
document.body.appendChild(messageDiv);
// Changer la couleur de fond du corps de la page
document.body.style.backgroundColor = "lightyellow";
// Exemple de communication avec le service worker
chrome.runtime.sendMessage({ greeting: "hello from content script" }, (response) => {
console.log("Réponse du service worker :", response.farewell);
});
Explication du code :
- Le script accède directement à
document.bodypour ajouter un élément et modifier son style. chrome.runtime.sendMessage(): C'est la méthode standard pour envoyer un message au service worker (ou à d'autres parties de l'extension). Le service worker peut alors répondre via la fonction de rappel.
Le Pop-up (Popup HTML & JavaScript) : L'Interface Utilisateur Directe
Le pop-up est une petite fenêtre qui apparaît lorsque l'utilisateur clique sur l'icône de votre extension dans la barre d'outils du navigateur. C'est l'une des interfaces utilisateurs les plus courantes pour les extensions.
Caractéristiques clés du Pop-up :
- Éphémère : Il apparaît lors d'un clic et se ferme automatiquement lorsque l'utilisateur clique en dehors de la fenêtre du pop-up ou bascule vers une autre fenêtre.
- Interface Utilisateur : Il est idéal pour des interactions rapides, des options simples ou l'affichage d'informations pertinentes pour l'onglet actif.
- Accès aux API Chrome : Contrairement aux scripts de contenu, le JavaScript du pop-up a un accès direct aux API Chrome (selon les permissions du manifeste).
- Communication avec le Service Worker et les Scripts de Contenu : Il peut envoyer des messages au service worker et aux scripts de contenu, et vice versa.
Exemple de popup.html et popup.js
popup.html
<!DOCTYPE html>
<html>
<head>
<title>Ma Super Extension Pop-up</title>
<link rel="stylesheet" href="popup.css">
</head>
<body>
<h1>Bienvenue !</h1>
<p>Ceci est l'interface de mon extension.</p>
<button id="changeColorBtn">Changer la couleur de fond</button>
<script src="popup.js"></script>
</body>
</html>
popup.js
// popup.js
document.addEventListener('DOMContentLoaded', () => {
const changeColorBtn = document.getElementById('changeColorBtn');
changeColorBtn.addEventListener('click', () => {
// Récupérer la couleur favorite stockée
chrome.storage.sync.get('couleurFavorite', (data) => {
const color = data.couleurFavorite || '#ff0000'; // Rouge par défaut si non définie
// Envoyer un message au script de contenu de l'onglet actif pour changer la couleur
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
chrome.tabs.sendMessage(tabs[0].id, { action: "change_page_color", color: color }, (response) => {
if (response && response.status === "color_changed") {
console.log("Couleur de la page changée !");
}
});
});
});
});
});
// Le service worker pourrait aussi envoyer un message ici
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.greeting === "hello from background") {
console.log("Message reçu du service worker dans le pop-up :", request.greeting);
// Mettre à jour l'UI du popup si nécessaire
document.querySelector('h1').textContent = "Message du background reçu !";
sendResponse({ farewell: "goodbye from popup" });
}
});
Explication du code :
popup.htmlest un simple fichier HTML qui inclut un bouton.popup.jsécoute le clic sur le bouton.chrome.storage.sync.get(): utilise l'API storage pour récupérer une préférence utilisateur.chrome.tabs.query()etchrome.tabs.sendMessage(): permettent au pop-up d'identifier l'onglet actif et d'envoyer un message spécifique à son script de contenu.- Le pop-up peut également recevoir des messages du service worker via
chrome.runtime.onMessage.addListener.
La Page d'Options (Options Page) : La Configuration Détaillée
La page d'options est une interface utilisateur plus persistante et généralement plus complexe, utilisée pour permettre aux utilisateurs de configurer les paramètres de l'extension. Elle est accessible via le menu des extensions du navigateur.
Caractéristiques clés de la Page d'Options :
- Persistante : Contrairement au pop-up, elle ne se ferme pas automatiquement et peut rester ouverte aussi longtemps que l'utilisateur le souhaite.
- Interface Riche : Idéale pour des formulaires, des paramètres avancés, et des interfaces de configuration.
- Accès aux API Chrome : Le JavaScript de la page d'options a un accès direct aux API Chrome, tout comme le pop-up.
- Communication : Elle communique généralement avec le service worker pour sauvegarder et charger les paramètres via l'API
chrome.storage.
Une page d'options est un simple fichier HTML (ex: options.html) qui inclut son propre fichier JavaScript (ex: options.js) pour gérer la logique.
Communication entre les Composants
L'un des aspects les plus importants d'une architecture d'extension est la capacité de ses différents composants à communiquer entre eux. Les extensions de navigateur fournissent des mécanismes robustes pour cela, principalement via l'API chrome.runtime.sendMessage et chrome.tabs.sendMessage.
-
chrome.runtime.sendMessage(message, [options,] [callback]): Utilisé pour envoyer des messages unidirectionnels ou bidirectionnels entre :- Un script de contenu et le service worker.
- Un pop-up et le service worker.
- La page d'options et le service worker.
- Et même entre différentes extensions (avec permissions spécifiques).
-
chrome.tabs.sendMessage(tabId, message, [options,] [callback]): Spécifiquement utilisé par le service worker ou le pop-up pour envoyer un message à un script de contenu s'exécutant dans un onglet particulier. -
chrome.runtime.onMessage.addListener(callback): C'est l'écouteur universel. Tous les composants qui souhaitent recevoir des messages doivent enregistrer un tel écouteur.
Cette communication est essentielle pour des scénarios où, par exemple :
- Un utilisateur clique sur un bouton dans le pop-up pour déclencher une action sur la page web courante (pop-up -> service worker -> script de contenu).
- Un script de contenu détecte quelque chose d'intéressant sur une page et informe le service worker de le stocker ou de le traiter.
- La page d'options met à jour un paramètre, et le service worker doit réagir à ce changement.
Conclusion et Résumé
Félicitations ! Vous avez maintenant une vue d'ensemble solide de l'architecture fondamentale d'une extension de navigateur. Pour récapituler les points clés :
- Le
manifest.jsonest le blueprint de votre extension, décrivant ses métadonnées, ses permissions, et ses composants. La Manifest V3 est la norme actuelle, mettant l'accent sur la sécurité et la performance avec l'introduction des service workers. - Le Service Worker (
background.js) est le cerveau invisible, gérant les événements en arrière-plan et orchestrant la logique globale de l'extension. - Les Scripts de Contenu (
content-script.js) sont les acteurs sur scène, interagissant directement avec le contenu des pages web pour manipuler le DOM et collecter des informations. - Le Pop-up (
popup.html+popup.js) est une interface utilisateur éphémère pour des interactions rapides et des actions spécifiques à l'onglet actif. - La Page d'Options (
options.html+options.js) offre une interface utilisateur plus riche et persistante pour configurer les paramètres de l'extension. - La communication entre ces composants est cruciale, utilisant
chrome.runtime.sendMessageetchrome.tabs.sendMessagepour échanger des données et déclencher des actions.
Comprendre ces rôles et comment ils s'imbriquent est la première étape pour concevoir des extensions efficaces, sécurisées et intuitives. Dans les leçons suivantes, nous approfondirons chacun de ces composants et explorerons des cas d'usage plus avancés.