Paul Féry

Pièce 04 · En attente de validation chez Mozilla

Thème sombre du portail De Vinci

Sur la page de connexion du portail, mon extension remplissait bien mon adresse mail. Elle s'affichait dans le champ. Mais le bouton « Continuer » restait grisé, comme si le champ était vide.

Le portail de l'école, myDeVinci, sert à tout : emploi du temps, notes, absences, documents. Je l'ouvre plusieurs fois par jour, souvent le soir, et il n'existe qu'en clair. Les extensions qui inversent les couleurs donnent des photos en négatif et des alertes illisibles. J'ai écrit la mienne, sans aucun accès au code du site.

Rôle
Projet perso : conception, code, publication
Quand
Septembre 2026
État
Envoyée sur addons.mozilla.org, en attente de validation
Code
github.com/mincho95/devinci-dark-firefox
Outils
JavaScript, CSS, WebExtensions (Manifest V3), Python

Le bouton grisé

La page de connexion est rendue côté client. Le framework de la page intercepte l'écriture de input.value : la valeur s'affiche, mais lui n'est pas prévenu, donc pour lui le champ est toujours vide.

J'ai dû passer par le setter natif de HTMLInputElement, envoyer moi-même les événements input et change, puis attendre que le bouton se réactive avant de cliquer. Au bout de 15 secondes sans réaction, le script abandonne.

Comment c'est construit

Une extension Manifest V3 sans script d'arrière-plan : deux scripts injectés à deux moments du chargement, un troisième sur la page de connexion, et une popup de réglages qui écrit dans le stockage synchronisé de Firefox.

Architecture de l'extension La popup écrit les préférences dans le stockage synchronisé. Au chargement de la page, un premier script lit une copie synchrone et pose des attributs sur l'élément racine, ce qui active les feuilles de style. Un second script corrige les styles écrits en dur et suit le contenu chargé ensuite. Sur la page de connexion, un troisième script pré-remplit l'adresse mail. Popup réglages storage.sync préférences PAGE DU PORTAIL early.js document_start <html data-dvx> active 3 feuilles CSS content.js document_end inline-fix.js luminance WCAG MutationObserver contenu AJAX auth-autofill.js page de connexion copie lit lit l'adresse écrit
Les feuilles de style ne font rien tant que la racine ne porte pas l'attribut data-dvx.

Les choix

Recolorer au lieu d'inverser

Écarté : inverser toute la page

Le portail contient environ 270 attributs style="" avec des couleurs claires écrites en dur, qu'aucune feuille de style ne peut surcharger proprement. Un script les relit, calcule leur luminance relative avec la formule du WCAG, et ne réécrit que les couleurs trop claires, en gardant leur teinte : une alerte rouge pâle devient une alerte rouge foncé, pas un gris.

Le style d'origine est gardé dans une WeakMap. Désactiver l'option remet la page exactement comme avant, sans fuite de mémoire quand des éléments disparaissent.

Pas de flash blanc au chargement

Écarté : attendre le stockage de l'extension

Le stockage de l'extension répond de façon asynchrone. L'attendre, c'est laisser la page s'afficher en blanc une fraction de seconde. Le premier script lit donc une copie des réglages dans le localStorage de la page, pose les attributs sur <html> avant le premier affichage, et le second remet la copie à jour ensuite.

Un CSS qui ne fait rien tout seul

Écarté : injecter et retirer les feuilles

Aucune règle ne s'applique sans l'attribut data-dvx="on" sur <html>. Couper l'extension retire l'attribut : les trois feuilles restent chargées mais n'ont plus d'effet, sans recharger la page.

Côté permissions, deux domaines et le stockage, rien d'autre. Aucune requête réseau, aucune télémétrie : rien ne sort du navigateur.

Ce qui a coincé

Du contenu qui arrive après coup

L'agenda et les tableaux du portail se remplissent en AJAX, après le passage du script. Un MutationObserver traite les nouveaux éléments au fil de l'eau, en ne regardant que ce qui vient d'être ajouté. Relire toute la page à chaque fois ralentirait un agenda de plusieurs centaines de cases.

Mon adresse mail dans le code

Le premier prototype avait mon adresse mail écrite en dur. Pour moi seul, ça allait. Publiée, elle se serait retrouvée dans chaque copie installée. C'est devenu un réglage de la popup, vide par défaut, et le dépôt exclut la page d'aperçu, qui reproduit mon tableau de bord.

La publication

≈ 270 styles écrits en dur dans le portail, recolorés un par un

Firefox n'installe durablement que les extensions signées par Mozilla. J'ai écrit un script Python qui emballe l'extension, l'envoie à l'API d'addons.mozilla.org, attend la validation automatique et récupère le fichier signé. Il n'utilise que la bibliothèque standard : le jeton JWT est signé à la main en HMAC-SHA256, et la requête multipart est construite sans bibliothèque HTTP.

Le même script publie sur deux canaux : non listé, signé en quelques minutes pour mon usage, et listé, qui passe par la revue de Mozilla pour apparaître dans le catalogue. Elle en est là en ce moment : en attente de validation.

À reprendre

Aucun test automatique. Si l'école change son site, je le découvrirai en l'utilisant. Des tests sur une copie figée des pages du portail me préviendraient avant.