URL: https://linuxfr.org/news/histoire-des-systemes-d-extensions-de-firefox Title: Histoire des systèmes d'extensions de Firefox Authors: Collectif Lawless, Yoric, Adrien Dorsaz, ZeroHeure, Yves Bourguignon, Benoît Sibaud, FreeFLOSS, theojouedubanjo, bobble bubble, lolowan et olivierweb Date: 2020-08-23T16:07:35+02:00 Tags: firefox Score: 7 Un des points forts de Firefox face à Internet Explorer était sa multitude d'extensions disponibles pour le personnaliser. David Teller nous [explique](https://yoric.github.io/post/why-did-mozilla-remove-xul-addons/) pourquoi Mozilla a dû modifier à deux reprises le système d'extensions pour pouvoir faire évoluer Firefox. Nous vous en proposons une traduction dans la suite de cette dépêche. Cette dépêche est sous licence CC-BY-NC 4.0 (la licence originale de l'entrée de blog). ---- [Why Did Mozilla Remove XUL Add-ons? par David Teller (license CC-BY-NC 4.0)](https://yoric.github.io/post/why-did-mozilla-remove-xul-addons/) ---- # Pourquoi Mozilla a supprimé les extensions XUL ? En résumé : Firefox avait un excellent mécanisme d’extension fondé sur [XUL](https://fr.wikipedia.org/wiki/XML-based_User_interface_Language) et [XPCOM](https://fr.wikipedia.org/wiki/XPCOM). Ce mécanisme nous a longtemps bien servi. Malheureusement, en termes de maintenance, ce mécanisme s’est accompagné d’un coût toujours croissant, aussi bien pour les développeurs de Firefox que pour ceux des extensions. D’un côté, ce coût croissant a progressivement tué tout effort pour rendre Firefox sécurisé, rapide ou pour essayer de nouvelles choses. À la longue, ce coût toujours croissant a progressivement tué la communauté des développeurs d’extensions. Finalement, après des années perdues en essayant de protéger ce vieux mécanisme d’extension, Mozilla a pris la décision difficile de supprimer ce mécanisme et de le remplacer par les [API WebExtensions](https://wiki.mozilla.org/WebExtensions) qui sont moins puissantes, mais beaucoup plus maintenables. Grâce à ce choix, les développeurs de Firefox peuvent à nouveau faire les changements nécessaires pour améliorer la sécurité, la stabilité ou la vitesse. Ces derniers jours, j’ai eu des discussions avec les utilisateurs de Firefox, en essayant de séparer les faits des rumeurs à propos des conséquences des licenciements d’août 2020 par Mozilla. Un des sujets qui est revenu plusieurs fois a été la suppression des extensions XUL lors du passage à Firefox Quantum. J’étais très surpris de voir que, des années après, plusieurs membres de la communauté se sentent encore blessés par ce choix. Et puis, comme quelqu’un l’a indiqué sur Reddit, j’ai réalisé que nous n’avions toujours pas pris le temps d’expliquer en détail pourquoi nous _n'avions pas eu d’autre choix_ que de supprimer les extensions XUL. Donc, si vous êtes prêts pour plonger dans les entrailles des extensions et de Gecko, j’aimerais prendre cette opportunité d’essayer et de vous donner un peu plus de détails. ## À propos des extensions laxistes, JetPack et des WebExtensions Depuis très longtemps, Firefox était composé d’un très petit noyau au-dessus duquel toutes les fonctionnalités étaient développées sous la forme d’extensions. Beaucoup de celles-ci étaient écrites en C++, d’autres en JavaScript et beaucoup utilisaient le langage d’interface XUL et le langage de binding XBL. Les codes C++ et JavaScript étaient connectés grâce à une technologie nommée XPCOM. Dès qu’un développeur d’extension souhaitait personnaliser Firefox, c’était simple et extrêmement puissant, puisque les outils utilisés pour personnaliser Firefox étaient exactement les mêmes outils que ceux utilisés pour construire Firefox. C’est ainsi que la restauration de session (la technologie qui vous permet de reprendre Firefox où vous en étiez la dernière fois, même en cas de plantage) ou la barre de recherche ont été originellement ajoutés dans Firefox, ainsi que d’autres fonctionnalités. C’est cette technologie qui fait fonctionner Firefox et [Thunderbird](https://www.thunderbird.net/). C’est comme ça que des outils comme [Songbird](https://fr.wikipedia.org/wiki/Songbird) (une alternative open source d’iTunes) ou [Instantbird](https://fr.wikipedia.org/wiki/Instantbird) (un client de messagerie instantanée) ont été développés. C’est aussi comme ça que j’ai personnalisé Firefox pour le transformer en lecteur eBook il y a longtemps. Et c’est ainsi que des milliers d’extensions pour Firefox ont été développées. Beaucoup de monde appelle ce mécanisme d’extension les « extensions XUL », ou parfois « extensions XPCOM », et j’utiliserai ces deux termes dans la suite de ce billet, mais j’ai tendance à le décrire comme le « mécanisme d’extension laxiste », pour plusieurs raisons : * très rapidement, les développeurs de modules complémentaires ont réalisé qu’ils pouvaient casser n’importe quoi dans le système, y compris d’autres modules complémentaires et Firefox lui-même, et que, souvent, il n’y avait aucun moyen de le prévenir ; * de même, n’importe quel développement de Firefox pouvait casser des modules complémentaires, et souvent il n’y avait aucun moyen de l’empêcher  ; * de plus, certains des changements que Firefox nécessitait pour être aussi rapide, stable et sécurisé que possible allaient casser la plupart des modules complémentaires rapidement et probablement tous les modules complémentaires à long terme ; * ah, et bien sûr, comme les modules complémentaires pouvaient tout faire, ils pouvaient très facilement accéder au système d’exploitation, voler des mots de passe ou encore prétendre être votre banque. Note : Après avoir lu dans les commentaires que certains utilisateurs ne se soucient apparemment pas de la sécurité, laissez-moi ajouter qu’être sécurisé est un point très très important pour Mozilla et que ça l’a été dès le début. Indépendamment des extensions, _ne pas_ avoir de sécurité signifie que, un jour ou l’autre, une technique sera développée pour voler les mots de passe utilisateurs et les utiliser pour détourner leurs comptes bancaires – et que cette technique sera vendue à gauche et à droite et finira par être utilisée partout sur le web. Les développeurs de Firefox se battent contre cette menace quotidiennement avec toutes sortes de moyens comme les revues de code, la programmation défensive, les investigations de scénarios de plantage, plusieurs types de sandboxing, l’analyse statique, des langages protégeant la mémoire… Par conséquent, pour Mozilla, si une fonctionnalité nous empêche d’obtenir une meilleure sécurité, nous choisissons _toujours_ la sécurité à la place des fonctionnalités. Je reviendrai en détail sur ces points plus tard. Pour le moment, il suffit de dire qu’il était clair depuis longtemps pour les développeurs de Firefox (au moins depuis 2010) que cette situation était intenable. Ainsi Mozilla a présenté un plan de secours appelé _Firefox Jetpack_. Firefox Jetpack était une manière très différente d’étendre Firefox. C’était bien plus propre. Il y avait enfin un mécanisme de permissions (un point qui a été suggéré avant même que Firefox ne s’appelle Firefox et qui était considéré généralement comme trop difficile à implémenter). Dès le départ, les extensions ne pouvaient plus endommager les autres extensions ou Firefox (si je me souviens bien, c’était encore parfois possible en utilisant le service _Observer_, mais il fallait faire exprès de le faire), ça utilisait intensivement la programmation asynchrone (ce qui est très bien pour obtenir la sensation de performances élevées), et, grâce au fait que c’était une API délimitée, ça pouvait être testé, ce qui signifiait que, quand les développeurs de Firefox cassaient les extensions, ils pouvaient s’en rendre compte immédiatement et réparer les problèmes ! Jetpack représentait plusieurs énormes pas en avant. La contrepartie était une API bien plus limitée, mais dans la plupart des cas, le jeu semblait en valoir la chandelle. Malheureusement, il y a eu des incompatibilités inattendues entre la conception de Jetpack et certains des changements majeurs nécessaires dans Firefox. Je ne sais pas exactement ce qu’était cette incompatibilité, mais nous avons été obligés d’abandonner Jetpack. À la place, nous avons introduit les WebExtensions. Dans l’ensemble, les WebExtensions avaient un objectif similaire aux extensions Jetpack, avec également une API restreinte et l’avantage supplémentaire qu’elles pourraient fonctionner sur les navigateurs basés sur Chromium et sur Firefox. Si vous aviez besoin d’API très avancées, passer du mécanisme d’extension laxiste à Jetpack ou aux WebExtensions n’était pas toujours possible, mais pour la plupart des extensions la transition était simple — dans mon expérience personnelle, ça a même été agréable. Firefox a introduit les WebExtensions à temps pour Firefox Quantum parce que c’était le moment où le modèle laxiste d’extensions allait de toute manière arrêter de fonctionner. À ce stade, nous avons terminé avec le rappel historique. J’espère que vous êtes prêts pour un peu plus de technique, parce que c’est ainsi que je vais vous expliquer exactement quels problèmes ont été résolus lorsque nous sommes passés du modèle laxiste d’extensions aux WebExtensions. ## Parlons d’XPCOM ! ### Comment ça a commencé _XPCOM_, _Cross-Platform Component Object Model_, est peut être la fonctionnalité de Firefox qui peut être mieux décrite comme _le noyau_ (pour ceux qui connaissent Gecko en profondeur, je considère _XPConnect_ et le _Cycle Collector_ comme des parties d’XPCOM), aux côtés de _SpiderMonkey_, notre machine virtuelle JavaScript. XPCOM est une technologie qui permet d’écrire du code en deux langages pouvant s’appeler mutuellement. Le code de Firefox est plein de C++ appelant du JavaScript, de JavaScript appelant du C++ et il y a longtemps, nous avons eu des projets qui ont ajouté Python et .Net dans le mélange. Ce mécanisme est extrêmement compliqué, car les langages ne partagent pas les mêmes définitions (qu’est-ce qu’un entier 64 bits en JavaScript ? Qu’est-ce qu’une exception JavaScript en C++ ?) ou le même modèle mémoire (comment gérer un objet JavaScript contenant une référence sur un objet C++ que C++ pourrait vouloir supprimer de la mémoire ?) ou le même modèle de concurrence (les workers JavaScript ne partagent rien alors que les threads C++ partagent tout). Gecko lui-même a été conçu à l’origine comme des milliers de composants XPCOM pouvant chacun être implémenté en C++ ou en JavaScript, testé individuellement, branché, débranché ou remplacé dynamiquement et _cela fonctionnait_. De plus, l’architecture XPCOM permettait une programmation C++ beaucoup plus propre que celle disponible à l’époque, fonctionnait sur des dizaines de plates-formes et permettait de combiner le confort de pouvoir écrire du code en JavaScript et la vitesse brute permise par le C++. Pour écrire un composant XPCOM, il faut généralement définir une [interface](https://searchfox.org/mozilla-central/rev/6cc48251bb97600fdf11a5b4c5f621bfc8606d55/dom/interfaces/base/nsIFocusManager.idl), puis écrire l’implémentation en C++ ou JavaScript (ou en Rust, de nos jours, et peut-être bientôt en Wasm). Il faut encore ajouter à cela un peu de code d’intégration, mais bon, ça marche. Lorsque les premiers développeurs de Firefox ont décidé d’ouvrir la plate-forme aux extensions, XPCOM a immédiatement été choisi comme technologie de base pour les modules complémentaires. Firefox avait juste à laisser les auteurs de modules complémentaires se brancher n’importe où dans le code et ils auraient un pouvoir extraordinaire à leur disposition. Et les développeurs de modules complémentaires (dont je fais partie) l’ont certainement fait et se sont beaucoup amusés avec ! ### … l’ère du XPCOM immuable Malheureusement, les problèmes ont commencé à s’accumuler progressivement. Lorsque vous développez une grosse application, vous avez besoin de changer les choses, soit pour corriger des bogues ou ajouter de nouvelles fonctionnalités, soit pour améliorer les performances. Dans le monde XPCOM, cela signifie changer les composants XPCOM. Parfois pour ajouter de nouvelles fonctionnalités à un composant. Parfois pour en supprimer entièrement un parce qu’une meilleure conception le rendait inutile. Durant la première ère des extensions XPCOM, tout ceci était généralement interdit. Si un composant XPCOM était utilisé par des extensions, les développeurs de Firefox **n’avaient pas le droit** de le modifier de manière incompatible. Ce système fonctionnait très bien pour les développeurs d’extensions mais est rapidement devenu un cauchemar pour les développeurs de Firefox – comme chaque changement devait être fait en maintenant la compatibilité à la fois externe (pour les développeurs web) et interne (pour les développeurs d’extensions). Par conséquent, chaque composant XPCOM `nsITruc` se retrouva rapidement accompagné par un `nsITruc2`, qui représentait le *meilleur* composant – et chacun des deux composants devait bien entendu rester compatible avec l’autre, ce qui doublait la quantité de travail. Un cas était même encore plus compliqué pour les développeurs Firefox : une extension XPCOM pouvait remplacer *n’importe quel composant XPCOM*. Est-il nécessaire de mentionner qu’un tel remplacement constituait une très bonne manière de casser Firefox d’une manière incompréhensible pour les enquêteurs qui travaillaient sur les plantages ? Cela signifiait que le développement est devenu de plus en plus lent, car nous devions vérifier chaque nouvelle fonctionnalité ou chaque amélioration par rapport non seulement aux fonctionnalités actuelles, mais aussi aux fonctionnalités passées/obsolètes ou simplement aux anciennes méthodes de travail qui étaient obsolètes depuis des années. Pendant un certain temps, cette _taxe de développement_ était acceptable. Après tout, le principal concurrent de Firefox était Internet Explorer, qui présentait des problèmes architecturaux encore plus graves, et un nombre apparemment illimité de contributeurs de logiciels libres apportaient leur aide. En outre, l’ensemble des fonctionnalités du web étaient beaucoup plus réduites, donc c’était toujours possible. ### … l’ère des développeurs d’extensions sur tous les chemins critiques Cependant, à mesure que le web se développait, il est devenu évident que ces choix rendaient tout simplement impossible la résolution de certains problèmes, en particulier les problèmes de performance. Par exemple, vers 2008, les développeurs de Firefox ont réalisé que la plateforme comportait tout simplement trop de composants XPCOM et que cela nuisait considérablement aux performances, car les composants XPCOM empêchaient à la fois le compilateur JIT et C++ d’optimiser le code et nécessitaient trop de conversions de données. C’est ainsi qu’a commencé la déCOMtamination, qui consistait à réécrire les sections du code dont les performances étaient critiques sans les composants XPCOM. Ce qui signifiait qu’il fallait casser des modules complémentaires. Durant cette deuxième ère des extensions XPCOM, les développeurs de Firefox avaient l’autorisation d’enlever ou de modifier les composants XPCOM, à condition d’avoir d’abord contacté les développeurs d’extensions et d’avoir trouvé avec eux une méthode qui allait permettre de réparer leurs extensions. Ce changement de méthode permit de débloquer le développement mais, l’un dans l’autre, la _taxe de développement_ avait encore augmenté. En effet, chaque changement de Firefox, même trivial, pouvait être bloqué pendant des semaines, le temps de concevoir des solutions de secours avec les développeurs d’extensions. C’est ainsi que les développeurs d’extensions se retrouvèrent à devoir payer une _taxe de maintenance_, puisqu’ils devaient dorénavant réparer leurs extensions à chaque version de Firefox. Dans certains cas, les développeurs de Firefox et les développeurs d’extensions entretenaient de très bons rapports, avec même certains développeurs d’extensions qui se retrouvèrent à concevoir les API utilisées à l’intérieur de Firefox. Dans d’autres cas, les développeurs d’extensions se lassèrent de cette surcharge de travail et abandonnèrent leurs extensions, parfois pour l’écosystème Chrome naissant. ### … l’ère de Snappy À cette époque, Mozilla a commencé à s’intéresser sérieusement à Chrome. Chrome avait été conçu à partir de principes très différents de Firefox : - à l’époque, Chrome ne se souciait pas de consommer trop de mémoire ou de ressources système ; - Chrome utilisait de nombreux processus, ce qui améliorait immédiatement la sécurité et la réactivité du navigateur ; - initialement, Chrome n’avait pas de mécanisme d’extension, ce qui permettait aux développeurs de Chrome de refactoriser tout ce qui était nécessaire, sans cette _taxe de développement_ ; - lorsque Chrome a introduit son mécanisme d’extension, il l’a fait avec une API appropriée, qui pouvait généralement être maintenue indépendamment des changements apportés au back-end ; - de plus, bien que Chrome était initialement plus _lent_ que Firefox sur presque tous les benchmarks, il s’appuyait sur de nombreuses astuces de conception qui donnaient _l'impression_ que le produit était plus _rapide_ — et les utilisateurs ont adoré cela. Il était clair pour Mozilla depuis des années que Firefox devait passer à une conception multi-processus. En fait, des démonstrations de Firefox multi-processus circulaient déjà à l’époque où Chrome 1.0 a été dévoilé. Le projet s’appelait [Electrolysis](https://wiki.mozilla.org/Electrolysis), ou e10s en abrégé. Nous y reviendrons. À l’époque, Mozilla a décidé de mettre en pause e10s, dont nous savions qu’il utiliserait beaucoup plus de mémoire que ce qui était acceptable pour beaucoup de nos utilisateurs, et de se concentrer sur un nouveau projet appelé [Snappy](https://wiki.mozilla.org/Performance/Snappy) (note : j’étais l’un des développeurs du projet Snappy). Snappy consistait à utiliser les mêmes astuces de conception que Chrome pour donner la même impression de vitesse à Firefox, en espérant ne pas avoir à tout remanier. La raison pour laquelle Firefox paraissait plus lent que Chrome est que nous faisions à peu près tout dans un seul thread. Lorsque Firefox écrivait un fichier sur le disque, cela bloquait les rafraîchissements visuels, ce qui faisait chuter le nombre d’images par seconde. Lorsque Firefox collectait la liste des onglets pour les sauvegarder en cas de plantage, cela bloquait les rafraîchissements, avec le même résultat. Lorsque Firefox nettoyait les cookies, cela bloquait les rafraîchissements, etc. Il y avait deux solutions à cela, que nous avons toutes deux utilisées : - chaque fois que cela a été possible, au lieu d’exécuter le code sur le thread principal, nous l’avons déplacé vers un autre thread ; - chaque fois que cela était impossible, nous devions diviser le traitement en petits morceaux dont nous pouvions garantir l’exécution en quelques millisecondes, puis intercaler manuellement ces morceaux dans le reste de l’exécution du thread principal. Ces deux solutions nous permettaient de nous assurer que nous n’introduisions pas de saccades et que nous pouvions répondre immédiatement lorsque l’utilisateur cliquait. Cela signifiait que l’interface utilisateur était réactive. La première technique avait l’avantage de bénéficier de l’aide du système d’exploitation, tandis que la seconde nécessitait un nombre considérable de mesures et de réglages. Les deux solutions étaient difficiles à mettre en œuvre, car nous étions soudainement confrontés à des problèmes de concurrence, qui sont notoirement difficiles à déboguer. Les deux solutions ont également été difficiles pour les développeurs d’extensions, car elles nécessitent de changer des fonctionnalités entières de synchrone à asynchrone, ce qui signifie souvent que l’extension devait être réécrite à partir de zéro. Pour moi, c’est le temps des souvenirs, car c’est à ce moment qu’[Irakli](https://www.linkedin.com/in/gozala/), [Paolo](http://www.amadzone.org/) et [moi-même](https://yoric.xyz/) (est-ce que j’oublie quelqu’un ?) avons introduit Promise et ce qui est maintenant connu comme les `async function` dans le code source de Firefox. Ces expériences (qui n’étaient en aucun cas les seules expériences autour du sujet) ont servi de champ d’expérimentation pour introduire ultérieurement ces fonctionnalités sur le Web. De manière plus immédiate, elles ont rendu l’écriture de code asynchrone beaucoup plus facile, tant pour les développeurs de Firefox que pour les développeurs d’extensions. Malgré ces améliorations (et d’autres qui n’ont pas tout à fait été approuvées comme standard), l’écriture et le débogage de code asynchrone restaient très compliqués. Donc, une fois de plus, il y a eu une _taxe de maintenance_ pour les développeurs de modules complémentaires, qui est rapidement devenue très compliquée. En termes de puissance d’extension, la situation était encore pire lorsque nous avons retiré du code du thread principal, car ils étaient généralement déplacés vers des threads C++, qui sont entièrement séparés des threads JavaScript. Les composants XPCOM disparaissaient ici et là, perdant leur puissance d’extension pour les développeurs de modules complémentaires. Je crois que c’est à ce stade que de nombreux développeurs de modules complémentaires ont commencé à se plaindre sérieusement de cette taxe de maintenance — ou plus souvent ont simplement cessé de mettre à jour leurs modules complémentaires. Et ils avaient raison. En tant que développeur de modules complémentaires, j’avais depuis longtemps renoncé à la maintenance de mes modules complémentaires, cela prenait trop de temps. La taxe de maintenance épuisait notre communauté de développeurs de modules complémentaires. Et Mozilla a pris au sérieux la recherche d’une nouvelle façon d’écrire des modules complémentaires qui réduirait considérablement la taxe à la fois pour les développeurs de Firefox et pour les développeurs de modules complémentaires. À l’époque, la solution était Jetpack et c’était plutôt génial ! Pendant un certain temps, deux mécanismes d’extension ont coexisté : Jetpack, plus propre, et le modèle laxiste, plus ancien. ### … l’ère d’Electrolysis/Quantum Snappy nous a mené assez loin, mais il n’a jamais pu résoudre tous les problèmes de Firefox. Comme mentionné ci-dessus, les développeurs de Firefox savaient depuis longtemps que nous aurions éventuellement besoin de passer à un modèle multi-processus. C’était mieux pour la sûreté et la sécurité, cela permettait de s’assurer que les images seraient rafraîchies de façon fluide et cela semblait naturel. À ce moment-là, les développeurs de Mozilla expérimentaient depuis un certain temps le multi-processus sous Firefox, mais deux choses avaient empêché Mozilla d’aller de l’avant avec le multi-processus sous Firefox (alias Electrolysis ou e10s) : - le fait que plusieurs processus nécessitent une quantité considérable de mémoire vive ; - le fait qu’avoir plusieurs processus nécessitait de réécrire à peu près tous les modules complémentaires — et que certains d’entre eux ne pourraient jamais être portés. Au fur et à mesure que la mémoire vive devenait moins chère et que nous optimisions l’utilisation de la mémoire (le projet MemShrink), le premier problème a progressivement cessé d’être bloquant. Le deuxième problème, en revanche, n’a pas pu être résolu. Considérons le cas simple d’un module complémentaire qui doit d’une manière ou d’une autre interagir avec le contenu d’une page. Par exemple, un module complémentaire conçu pour augmenter le contraste. Avant e10s, il s’agissait d’un code JavaScript qui existait dans la fenêtre principale de Firefox et qui pouvait manipuler directement le DOM des pages individuelles. C’était assez simple à écrire. Avec e10s, ce module complémentaire devait être réécrit pour fonctionner sur plusieurs processus. Le processus parent ne pouvait communiquer avec les processus enfants qu’en échangeant des messages et les processus enfants pouvaient être arrêtés à tout moment, y compris pendant le traitement d’un message, soit par le système d’exploitation (en cas de plantage), soit par l’utilisateur final (en fermant un onglet). Ce module complémentaire pourrait être porté sur e10s parce que les processus qui traitaient le contenu des pages web exécutaient également JavaScript et parce que l’équipe e10s avait exposé des API permettant aux modules complémentaires d’envoyer et de recevoir des messages et de se charger dans ces processus de contenu. Cependant, tous les processus ne pouvaient pas fonctionner aussi bien avec les modules complémentaires. Par exemple, les processus dédiés à la protection de Firefox contre les plantages notoires du plug-in Flash ne disposaient pas de machine virtuelle JavaScript. Les processus dédiés à l’interaction avec le GPU n’avaient pas de machine virtuelle JavaScript. Tout cela pour de (bonnes) raisons de performance et de sécurité — et le fait d’ajouter une machine virtuelle JavaScript à ces processus les aurait rendus beaucoup plus complexes. Et pourtant, Mozilla n’a pas eu le choix. Chaque jour où Mozilla n’a pas livré Electrolysis était un jour où Chrome était tout simplement meilleur en termes d’architecture, de sûreté et de sécurité. Malheureusement, Mozilla a retardé Electrolysis de plusieurs années, en partie à cause de l’illusion que les benchmarks de Firefox étaient assez bons pour que cela n’ait pas d’importance sur le long terme, en partie parce que nous avons décidé de tester Electrolysis avec FirefoxOS avant Firefox lui-même, mais surtout _parce que nous ne voulions pas perdre tous ces modules complémentaires_. Lorsque Mozilla s’est finalement engagé dans la transition vers Electrolysis, certains développeurs de modules complémentaires ont porté leurs modules complémentaires — consacrant un temps considérable à cette tâche — mais beaucoup ne l’ont pas fait, soit parce que c’était impossible pour leur module complémentaire, soit, plus souvent, parce que nous les avions perdus à cause de la _taxe de maintenance des modules complémentaires_. Et malheureusement, même les modules complémentaires qui avaient été portés sur Electrolysis se sont mis à ne plus fonctionner, un par un, pour toutes les autres raisons mentionnées dans cet article. Finalement, Mozilla a décidé d’introduire les WebExtensions et de faire enfin le saut vers e10s dans le cadre du projet Quantum. Nous avions perdu des années de développement que nous ne récupérerions jamais. Les performances s’amélioraient. Les modules complémentaires devaient être réécrits. La puissance des modules complémentaires avait irrémédiablement diminué. Le mécanisme d’extension basé sur XPCOM a été en grande partie abandonné (nous l’utilisons toujours en interne). ### … le futur est Rust, Wasm, Fission… Nous vivons aujourd’hui dans une ère post-Quantum. Chaque fois que cela est possible, de nouvelles fonctionnalités sont implémentées en Rust. Je ne me souviens pas si nous avons déjà livré des fonctionnalités implémentées en Wasm, mais cela fait partie de la feuille de route. De base, Rust ne fonctionne pas bien avec XPCOM. Rust a un mécanisme différent pour interagir avec d’autres langages, qui fonctionne très bien, mais il ne discute pas XPCOM nativement. Écrire ou utiliser du code XPCOM dans Rust est possible et atteint progressivement le stade où il fonctionne sans trop d’efforts, mais pour la plus grande partie de l’existence du code Rust dans Firefox, c’était simplement trop compliqué à faire. Par conséquent, même si nous avions laissé le mécanisme d’extension basé sur XPCOM disponible, la plupart des fonctionnalités implémentées en Rust n’auraient tout simplement pas été accessibles aux modules complémentaires, à moins que nous n’ayons explicitement publié une API pour eux — éventuellement sous la forme d’une API WebExtension. Bien que je n’aie pas été étroitement impliqué dans Wasm-in-Gecko, je pense que l’histoire se déroulera de la même manière. Pas de XPCOM au début. Plus tard, progressivement, une sorte de support XPCOM, mais seulement sur décision explicite de le faire. Peut-être exposé comme une API d’extension Web, plus tard. De plus, après le projet Electrolysis vient le projet Fission. Il s’agit d’une autre refactorisation majeure de Firefox qui va beaucoup plus loin dans la direction prise initialement par Electrolysis en divisant davantage Firefox en processus pour renforcer la sécurité et la sûreté et, espérons-le, les performances ultérieures. Bien que cela n’affecte pas directement XPCOM, cela signifie que tout module complémentaire utilisant le mécanisme basé sur XPCOM qui a été porté sur le projet Electrolysis devra être entièrement réécrit une fois de plus. Toutes ces raisons confirment que le choix de se débarrasser des modules complémentaires basés sur XPCOM aurait pu, au mieux, être ajusté pour prolonger l’agonie de la technologie, mais que l’issue était courue d’avance. # Les problèmes avec XUL Mais attendez, ce n’est pas tout ! Jusqu’à présent, nous n’avons mentionné que XPCOM, mais XPCOM ne représentait que la moitié de la technologie des modules complémentaires de Firefox. ### Comment cela a commencé XUL, le XML User interface Language, a été comme l’une des révolutions initiées par Firefox. Pour la première fois, un langage déclaratif pour les interfaces utilisateurs fonctionnait. Imaginez placer des boutons, appliquer un style avec des CSS, les connecter avec un peu de JavaScript, ajouter un peu de métadonnées pour atteindre l’accessibilité, la localisation, les préférences de stockage… En plus un excellent mécanisme appelé XUL overlays qui permet de brancher facilement des composants dans des interfaces existantes, par exemple pour étendre un menu ou ajouter un nouveau bouton, etc. sans avoir à changer l’autre document. Pendant la plus grande partie de l’existence de Mozilla, c’est ainsi que l’interface utilisateur de Firefox a été écrite – et bien sûr l’interface utilisateur des modules complémentaires a été écrite. Et cela fonctionnait extrêmement bien. En tant que développeur de modules complémentaires qui en avait assez d’écrire des interfaces utilisateur en Gtk, Win32 et Swing, pour la première fois j’ai pu développer une expérience utilisateur qui était bien meilleure que tout ce que j’avais pu réaliser avec ces boîtes à outils ; de plus, cela ne m’a pris que quelques secondes au lieu de plusieurs heures, je pouvais simplement recharger pour voir à quoi cela ressemblait au lieu d’avoir besoin de reconstruire l’application et, contrairement à Gtk et Win32, je n’avais pas à craindre de plantages, car mon code était écrit dans un langage sans danger pour la mémoire. Si vous pensez que cela ressemble beaucoup à HTML5 (et peut-être Electron) avec les bonnes bibliothèques/frameworks, vous avez tout à fait raison. XUL a été développé à l’époque du HTML4, lorsque les spécifications du web étaient coincées dans les limbes, et a été conçu en grande partie comme le successeur du HTML dédié aux applications plutôt qu’aux documents. Il y a presque vingt ans, Mozilla a publié une première version de XULRunner, qui était essentiellement une version antérieure d’Electron utilisant XUL au lieu de HTML (HTML pouvait également être inséré dans XUL). ### … quelques problèmes de XUL Si vous écriviez des modules complémentaires basés sur XUL, vous vous êtes vite rendu compte qu’il était… compliqué de l’empêcher de casser des choses. Plusieurs modules complémentaires pouvaient modifier la même partie de l’interface utilisateur, entraînant des résultats étranges. Plusieurs modules complémentaires pouvaient accidentellement injecter des fonctions JavaScript avec le même nom, ou avec le même nom qu’une fonction existante, provoquant toutes sortes de dommages. De même, il était très simple d’écrire une extension malveillante. Vous pouviez facilement enregistrer toutes les touches pressées par l’utilisateur, en récupérant tous ses mots de passe, mais pourquoi vous donner la peine de le faire alors que vous pouviez simplement patcher le gestionnaire de mots de passe pour envoyer toutes les informations à un site web distant ? Et, pour être clair, ce n’est pas de la science-fiction. Bien que je ne connaisse aucune extension qui soit allée aussi loin, je connais des installateurs de produits sans rapport avec le sujet (au moins deux d’entre eux sont des leaders du marché dont le nom ne sera pas mentionné dans ce billet) qui ont installé silencieusement des modules complémentaires invisibles de Firefox qui ont pris le contrôle de fonctionnalités clés et ont compromis la vie privée des utilisateurs. Des propositions avaient été faites pour améliorer la sécurité, mais il était très clair que, tant que nous conserverions XUL (et XPCOM), nous ne pouvions rien faire pour empêcher un module complémentaire malveillant de faire tout ce qu’il voulait. ### … l’ère du HTML5 Une fois le travail sur HTML5 commencé, Mozilla a apporté avec enthousiasme les fonctionnalités de XUL. Progressivement, HTML5 a obtenu le stockage, le contenu éditable, le glisser-déposer, les composants (qui étaient connus sous le nom de XBL dans XUL), la manipulation de l’historique, l’audio, la cryptographie… ainsi qu’un support suffisant pour permettre aux bibliothèques clientes de mettre en œuvre l’accessibilité et l’internationalisation. Bien que HTML5 ne dispose toujours pas de toutes les fonctionnalités de XUL, il a finalement atteint un stade où de nombreuses fonctionnalités qui avaient été implémentées dans Gecko pour supporter XUL devaient également être implémentées dans Gecko pour supporter HTML5. Comme c’était le cas avec XPCOM, cela s’est traduit par une _taxe de développement_, car chaque nouvelle fonctionnalité de HTML5 devait être implémentée de manière à ne casser aucune des fonctionnalités de XUL, même si les développeurs de modules complémentaires essayaient d’une manière ou d’une autre de les combiner. Cela a considérablement ralenti le développement de Gecko et a augmenté le nombre de bogues qui ont accidentellement tué les modules complémentaires basés sur XUL, augmentant ainsi la taxe de maintenance des développeurs de modules complémentaires. À ce moment-là, Mozilla avait depuis longtemps décidé d’arrêter d’améliorer XUL et de se concentrer plutôt sur HTML5. Comme les performances de HTML5 devenaient meilleures que celles de XUL pour de nombreuses tâches, les développeurs de Firefox ont commencé à porter des composants de XUL vers HTML5. Le résultat était plus agréable (parce que le design était nouveau), plus rapide (parce que Gecko était optimisé pour HTML5) et créer des modules complémentaires basés sur XUL devenait plus compliqué. De plus, il est devenu plus facile d’engager et de former les développeurs sur l’interface de Firefox car, soudainement, ils pouvaient utiliser leurs connaissances en HTML5 et leurs frameworks HTML5 dans Firefox. C’est à peu près à ce moment que le Jetpack est entré en scène pour la première fois. Jetpack a permis aux auteurs de modules complémentaires d’écrire leurs extensions avec HTML5 au lieu de XUL. C’était mieux pour la plupart des auteurs de modules complémentaires expérimentés et outillés en HTML5. Bien sûr, comme il manquait à HTML5 certaines fonctionnalités de XUL, cela ne fonctionnait pas pour tout le monde. ### … la poussée vers Servo En parallèle, les travaux avaient commencé chez Mozilla sur le moteur de restitution Servo. Bien que le moteur ne soit pas complet (et ne l’est toujours pas à ce jour), des démonstrations extrêmement intéressantes ont montré comment Servo (ou au moins des morceaux de Servo) pourrait un jour remplacer Gecko (ou au moins des morceaux de Gecko) par un code à la fois plus facile à lire et à modifier, plus sûr et beaucoup plus rapide. Il y avait un hic, bien sûr : l’équipe Servo n’avait pas les ressources pour réimplémenter également XUL, d’autant plus que Mozilla avait décidé depuis longtemps d’arrêter de travailler sur cette technologie. Afin de pouvoir éventuellement remplacer Gecko (ou des parties de celui-ci) par Servo, Mozilla devait d’abord migrer l’interface utilisateur de Firefox vers HTML5. Dans Firefox, cela a permis de poursuivre le cercle vertueux : en diminuant la quantité de XUL, on a pu simplifier Gecko, ce qui a réduit la taxe de développement de Gecko et a permis aux développeurs de Gecko d’améliorer la vitesse de tout HTML5. Cela signifiait également que l’interface utilisateur et les développeurs de modules complémentaires pouvaient utiliser des technologies mieux optimisées et les bibliothèques/frameworks web existants. Là encore, cela signifiait que l’utilisation de XUL pour les interfaces utilisateur avait de moins en moins de sens et que cela réduisait le nombre de choses que les modules complémentaires basés sur XUL pouvaient espérer réaliser. ### … l’ère d’Electrolysis/Quantum/Fission Et puis vint le projet Quantum. Comme nous l’avons vu plus haut, chaque jour que Mozilla passait sans livrer Electrolysis était un jour que Firefox passait à être pire que Chrome en termes de sécurité et de plantages. Lorsque XUL a été conçu, le multithreading était encore considéré comme un sujet de recherche, Linux et System 7 (l’ancêtre de macOS) n’avaient même pas de multithreading approprié et peu de personnes en dehors du monde universitaire considéraient sérieusement que toute application destinée aux utilisateurs aurait besoin d’une quelconque concurrence. XUL a donc été conçu pour un seul processus et un seul thread. Lorsque le moment est venu d’implémenter Electrolysis pour Firefox, de nombreuses fonctionnalités de XUL se sont révélées inutilisables. Peut-être qu’une nouvelle version de XUL aurait pu être conçue pour mieux supporter ce paradigme multi-processus, mais cela aurait augmenté une fois de plus la taxe de développement sans diminuer la tâche de maintenance des développeurs de modules complémentaires qui auraient eu besoin, malgré tout, de porter leurs modules complémentaires sur un nouveau XUL. Le choix a donc été fait de réécrire en HTML5 les fonctionnalités qui avaient besoin d’être réécrites pendant la période de lancement d’Electrolysis. Après le projet Electrolysis vient le projet Fission. Si l’on considère la façon dont nous devons re-factoriser le code de Firefox pour Fission, il semble très probable que le projet Fission aurait nécessité un XUL3 ou aurait, au minimum, encore une fois cassé tous les modules complémentaires. Bien que XUL ne serait pas entièrement supprimé de Firefox ou de Gecko avant plusieurs années, l’ère de XUL était officiellement terminée. Encore une fois, le choix de prolonger le mécanisme d’extension basé sur XUL aurait pu être modifié pour prolonger l’agonie, mais la fin était attendue depuis longtemps. ## Et maintenant ? Eh bien, pour les développeurs de modules complémentaires Firefox, le présent et l’avenir prévisible s’appellent WebExtensions. De par sa conception, les WebExtensions sont plus limitées que le mécanisme d’extension laxiste. De par sa conception, cela fonctionne également mieux. La majeure partie de la taxe de développement de Firefox a disparu, car seule l’API WebExtensions a besoin d’être protégée, et non l’ensemble du code de Firefox. La majeure partie de la taxe de maintenance a disparu, car l’API WebExtensions est stable (il y a malheureusement eu quelques exceptions). Elle est également beaucoup plus simple à utiliser, permettant aux développeurs de modules complémentaires de partager du code entre les modules complémentaires de Firefox et Chromium et devrait à terme faciliter l’écriture d’extensions fonctionnant parfaitement sur les ordinateurs de bureau et mobiles. Le principal inconvénient est, bien sûr, que les WebExtensions ne donnent pas aux développeurs de modules complémentaires autant de pouvoir que le mécanisme d’extension laxiste. J’espère que toute la puissance dont les développeurs de modules complémentaires ont besoin pourra éventuellement être ajoutée à l’API des WebExtensions, mais c’est quelque chose qui demande une force d’ingénierie, une ressource précieuse qui nous fait cruellement défaut. Bien que je réalise que toutes les actions décrites ci-dessus ont eu un coût pour les développeurs et les utilisateurs de modules complémentaires, j’espère vous avoir convaincu que ces choix faits par Mozilla étaient nécessaires pour préserver Firefox et le maintenir dans la course contre Chrome.