Ajouter un nouveau panneau dans les outils de développement

É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, et tooltip
  • deux fonctions : setup() et dispose()
  • 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 http://handdrawngoods.com/ et est utilisée avec la licence Creative Commons Attribution 3.0 Unported license (CC BY 3.0): http://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

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 http://localhost:8888/

pour mettre à jour votre extension.

Étiquettes et contributeurs liés au document

 Contributeurs à cette page : Hell_Carlito, KrySoar, maybe, adim
 Dernière mise à jour par : Hell_Carlito,