Écriture d'une extension qui rajoute un nouveau panneau aux outils de développement.
Cette fonctionnalité a été introduite dans Firefox 34.
Notez qu'il n'est pour le moment pas possible de déboguer les cibles distantes (par exemple Firefox OS, le simulateur Firefox OS ou Firefox pour Android) en utilisant ces APIs. Nous sommes en train de faire en sorte de lever cette limitation.
Cet article explique comment écrire une extension qui ajoute un nouvel outil à la boîte à outils de développement. L'outil que nous allons créer est une boucle minimale de Lecture / Évaluation / Affichage (REPL) pour le protocole de débogage distant qui permet d'envoyer des messages au serveur de débogage et d'afficher la réponse du serveur :
Le code complet de cette extension est disponible sur GitHub : https://github.com/mdn/repl-panel.
Prérequis
Si vous n'avez jamais utilisé le kit de développement d'extensions (Add-on SDK), vous devrez tout d'abord installer le SDK et suivre le tutoriel de mise en route.
Une fois le SDK installé, créez un nouveau répertoire et positionnez-vous dedans à l'aide d'une invite de commandes. Tapez ensuite cfx init
pour créer la structure de base de la nouvelle extension.
Il faudra également une version 34 ou plus récente de Firefox.
Écriture de l'extension
Pour ajouter un nouveau panneau, nous définirons un constructeur REPLPanel
qui étendra la classe Panel
dans dev/panel.
Un Panel
représente un panneau dans la boîte à outils, comme les panneaux standards du Débogueur JavaScript ou de la Console Web. Le contenu du panneau et son comportement sont définis en HTML, CSS et JavaScript. Lorsqu'un panneau est créé, le framework lui passe un objet debuggee
. Le panneau peut ensuite utiliser cet objet debuggee
pour échanger des messages JSON avec le serveur de débogage qui s'exécute dans Firefox.
Notre extension va définir un panneau REPLPanel
qui va passer l'objet debuggee
dans un script s'exécutant dans le document du panneau. Ce document va définir un élement textarea
pour que l'utilisateur puisse écrire des messages JSON à envoyer au serveur et un bloc pre
pour afficher sa réponse. Le script va utiliser l'objet debuggee
pour :
- envoyer le contenu du
textarea
au serveur - écouter les messages venant du serveur, et afficher les résultats dans le bloc
pre
main.js
La commande cfx init
du SDK va créer un fichier "main.js" dans répertoire "lib" sous la racine de l'extension. Ouvrez ce fichier et remplacer son contenu par :
// require the SDK modules const { Panel } = require("dev/panel"); const { Tool } = require("dev/toolbox"); const { Class } = require("sdk/core/heritage"); const self = require("sdk/self"); // define a REPLPanel class // that inherits from dev/panel const REPLPanel = Class({ extends: Panel, label: "REPL", tooltip: "Firefox debugging protocol REPL", icon: self.data.url("plane_64.png"), url: self.data.url("repl-panel.html"), // when the panel is created, // take a reference to the debuggee setup: function(options) { this.debuggee = options.debuggee; }, dispose: function() { this.debuggee = null; }, // when the panel's script is ready, // send it a message containing // the debuggee onReady: function() { this.debuggee.start(); this.postMessage("init", [this.debuggee]); } }); exports.REPLPanel = REPLPanel; // create a new tool, // initialized with the // REPLPanel's constructor const replTool = new Tool({ panels: { repl: REPLPanel } });
Note : si vous avez utilisé jpm l'outil https://www.npmjs.com/package/jpm, les noms des fichiers peuvent être légèrement différents. Par exemple, le fichier à modifier sera "index.js" et non "main.js".
Dans le code ci-dessous, le constructeur REPLPanel
définit :
- quatre propriétés :
icon
,label
,url
, ettooltip
- deux fonctions :
setup()
etdispose()
- une fonction de rappel :
onReady
Les propriétés icon
, label
, et tooltip
sont utilisées pour identifier le panneau dans la Boîte à outils. La propriété icon
est une ressource://URL pointant vers une icône stockée dans le répertoire "data" de l'extension. La propriété url
est également une resource://URL et pointe vers un fichier HTML, ici "repl-panel.html", dans le répertoire "data", dont le but est de définir le rendu du panneau.
La fonction setup()
est appelée lorsque le panneau est créé. Un objet options
avec une propriété unique debuggee
lui est passé en paramètre. L'objet debuggee
est un objet MessagePort
qui peut être utilisé pour échanger des messages avec le serveur de débogage. Dans cette fonction setup
, on se contente de conserver une référence vers l'objet debuggee
. La fonction dispose()
est appelée lorsque le panneau est sur le point d'être détruit. Vous pouvez utiliser cette fonction pour effectuer toutes les opérations de nettoyage nécessaires.
L'événement ready
est émis lorsque le document dans le panel devient interactif, c'est à dire l'équivalent de document.readyState === "interactive"
. À ce stade, vous pouvez envoyer les messages du document du panneau. Dans la fonction de rappel onReady
, nous envoyons l'objet debuggee
au document du panneau. Ce panneau pourra ensuite utiliser l'objet debuggee
pour échanger des messages avec le serveur de débogage.
Enfin, nous créons un nouvel outil en instanciant la classe Tool
et en passant notre nouveau constructeur REPLPanel
.
plane_64.png
Dans cet exemple, nous avons utilisé l'icône "plane_64.png" pour notre nouvel outil. Cette icône a été créée par https://handdrawngoods.com/ et est utilisée avec la licence Creative Commons Attribution 3.0 Unported license (CC BY 3.0): https://creativecommons.org/licenses/by/3.0/. Vous pouvez trouver cette image dans l'entrepôt GitHub de l'extension.
Que vous utilisiez cette icône ou une autre, sauvez-la dans le répertoire "data" de votre extension et assurez-vous qu'elle est correctement référencée dans la propriété icon
du constructeur REPLPanel
.
repl-panel.html
Créez un fichier "repl-panel.html" dans le répertoire "data" de l'extension et insérez-y le contenu suivant :
<html> <head> <meta charset="utf-8"> <link href="./repl-panel.css"rel="stylesheet"></link> </head> <body> <pre id="response"></pre> <textarea name="request" id="request" rows="10" cols="40"></textarea> </body> <script src="./repl-panel.js"></script> </html>
Le code HTML du panneau définit un élément textarea
pour que l'utilisateur puisse entrer une requête JSON à envoyer au serveur, ainsi qu'un bloc pre
pour afficher la réponse du serveur. Il inclut également un fichier CSS et JavaScript.
repl-panel.js
Créez un fichier "repl-panel.js" dans le répertoire "data" de l'extension dont le contenu ressemblera à :
window.addEventListener("message", function(event) { window.port = event.ports[0]; window.port.onmessage = receive; }); var request = document.getElementById("request"); var response = document.getElementById("response"); request.addEventListener("keyup", send, false); function send(event) { if ((event.keyCode == 13) && (event.getModifierState("Control") == true)) { window.port.postMessage(JSON.parse(request.value)); } } function receive(event) { response.textContent = JSON.stringify(event.data, undefined, 2); }
Le script "repl-panel.js" chargé dans le panneau écoute les message de main.js qui contiennent un objet debuggee
. L'objet debuggee
est un canal de communication avec le serveur de débogage. Les messages que nous envoyons au serveur de débogage sont des requêtes respectant le protocole de débogage distant. Les messages que nous recevons sont des réponses à ces requêtes.
Lorsque "repl-panel.js" reçoit l'objet debuggee
, il se met à écouter les messages du serveur de débogage et affiche les résultats dans l'élément "response". Il écoute également les événements keyup
dans l'élément "request" et son contenu est envoyé au serveur de débogage lorsque l'utilisateur tape Control+Enter.
repl-panel.css
Enfin, créez un fichier "repl-panel.css" dans le répertoire "data" de l'extension dont le contenu ressemblera à :
#request { position: fixed; width: 40%; } #response { float: right; width: 50%; color: blue; font-family: monospace; }
Structure finale
La structure de votre répertoire devrait désormais ressembler à :
- repl-panel
- data
- plane_64.png
- repl-panel.css
- repl-planel.html
- repl-panel.js
- lib
- main.js
- package.json
- data
Exécution de l'extension
Dans l'invite de commandes, exécutez :
cfx run
Vous devriez voir Firefox se lancer. Ouvrez les outils de développement et vous devriez voir un nouvel onglet intitulé "REPL". Cliquez sur cette onglet, entrez une requête JSON et tapez Ctrl+Enter pour l'envoyer :
Si vous avez utilisé l'outil jpm plutôt que le SDK python, vous devrez utiliser la commande
jpm post --post-url https://localhost:8888/
pour mettre à jour votre extension.