From 682e6811836d5e8401a1d009f45d70b4afd44c50 Mon Sep 17 00:00:00 2001 From: Vincent Vatelot Date: Tue, 7 Apr 2026 14:38:04 +0000 Subject: [PATCH] refactor: streamline extension build process and update permissions - Removed background script files and adjusted the build process for browser extensions. - Updated manifest files to restrict host permissions to the official Ecoindex API endpoint. - Enhanced privacy policy documentation to clarify data handling practices. - Added functionality for integrating Ecoindex badges in the popup, including a preview feature. --- bin/build-extension.mjs | 4 -- doc/PRIVACY-POLICY-FR.md | 10 ++--- doc/PRIVACY-POLICY.md | 10 ++--- src/background/background.html | 13 ------- src/background/background.js | 68 ---------------------------------- src/manifest-chrome.json | 7 +--- src/manifest-firefox.json | 6 +-- src/options/options.html | 8 ++-- src/popup/popup.css | 9 +++++ src/popup/popup.html | 22 ++++++++++- src/popup/popup.js | 50 +++++++++++++++++++++---- 11 files changed, 86 insertions(+), 121 deletions(-) delete mode 100644 src/background/background.html delete mode 100644 src/background/background.js diff --git a/bin/build-extension.mjs b/bin/build-extension.mjs index 934b4b4..9a9378d 100644 --- a/bin/build-extension.mjs +++ b/bin/build-extension.mjs @@ -29,10 +29,6 @@ async function buildForBrowser(browser) { `${dirname}/../src/images`, `${dirname}/../dist/${browser}/images`, ); - fs.copySync( - `${dirname}/../src/background`, - `${dirname}/../dist/${browser}/background`, - ); fs.copySync( `${dirname}/../src/common.js`, `${dirname}/../dist/${browser}/common.js`, diff --git a/doc/PRIVACY-POLICY-FR.md b/doc/PRIVACY-POLICY-FR.md index d2ca78e..1e47f17 100644 --- a/doc/PRIVACY-POLICY-FR.md +++ b/doc/PRIVACY-POLICY-FR.md @@ -38,17 +38,15 @@ Le fichier manifeste de l’Extension peut contenir les déclarations suivantes, ```json { "permissions": ["activeTab", "storage"], - "host_permissions": [""] + "host_permissions": ["https://bff.ecoindex.fr/*"] } ``` -- **`activeTab`** — Accorde un accès **temporaire** à l’onglet actif lorsque vous utilisez l’Extension (par exemple à l’ouverture de la popup). Elle sert à lire **l’URL de la page affichée** afin d’interroger le backend Ecoindex pour le résultat correspondant. Elle **ne** permet pas de lire en continu tous les onglets en arrière-plan. +- **`activeTab`** — Accorde un accès **temporaire** à l’onglet actif lorsque vous ouvrez la popup de l’Extension. Elle sert à lire **l’URL de la page affichée** afin d’interroger le backend Ecoindex pour le résultat correspondant. Elle **ne** permet pas de lire en continu tous les onglets en arrière-plan. -- **`storage`** — Sert à conserver **localement sur votre appareil** des données d’Extension : préférences et état d’interface de courte durée (par exemple le badge de la barre d’outils lié à l’onglet courant). Ce stockage n’est pas utilisé pour constituer un historique de navigation exploité par des tiers. +- **`storage`** — Sert à conserver **localement sur votre appareil** les préférences de l’Extension. Ce stockage n’est pas utilisé pour constituer un historique de navigation exploité par des tiers. -- **`host_permissions` : ``** — Indique que l’Extension peut **s’exécuter dans le contexte des pages web sur les sites que vous visitez**. Ce schéma est en particulier nécessaire lorsque l’Extension injecte des **scripts de contenu** sur toutes les pages (par exemple pour partager du code avec la popup) ou lorsque le navigateur associe ce type d’injection à des autorisations d’hôtes larges. **Il ne s’agit pas d’un dispositif de suivi comportemental** : l’objectif reste d’obtenir l’URL de la page pour la requête Ecoindex décrite ci-dessus. Lorsque les politiques des magasins d’extensions le permettent, l’**accès réseau** au backend est limité à l’API officielle Ecoindex (`https://bff.ecoindex.fr/`) plutôt qu’à des sites arbitraires. - -Certaines versions peuvent aussi demander la permission **`tabs`** pour que la partie « arrière-plan » réagisse aux changements d’onglet ou de chargement de page, toujours dans le même objectif (par exemple mettre à jour le badge pour l’onglet actif). +- **`host_permissions` : `https://bff.ecoindex.fr/*`** — Autorise uniquement les appels réseau vers l’API officielle Ecoindex BFF. Aucun accès hôte large de type `` n’est demandé. --- diff --git a/doc/PRIVACY-POLICY.md b/doc/PRIVACY-POLICY.md index 2723880..599e328 100644 --- a/doc/PRIVACY-POLICY.md +++ b/doc/PRIVACY-POLICY.md @@ -38,17 +38,15 @@ The extension manifest may include the following declarations and use them only ```json { "permissions": ["activeTab", "storage"], - "host_permissions": [""] + "host_permissions": ["https://bff.ecoindex.fr/*"] } ``` -- **`activeTab`** — Grants **temporary** access to the active tab when you interact with the extension (for example when you open the toolbar popup). The extension uses this to read the **URL of the page you are viewing** so it can request the corresponding Ecoindex result from the backend. It does **not** give ongoing read access to all tabs in the background. +- **`activeTab`** — Grants **temporary** access to the active tab when you open the extension popup. The extension uses this to read the **URL of the page you are viewing** so it can request the corresponding Ecoindex result from the backend. It does **not** give ongoing read access to all tabs in the background. -- **`storage`** — Used to keep **local data on your device**: extension preferences and short-lived UI state (for example toolbar badge information tied to the current tab). This storage is not used to build a browsing history for third parties. +- **`storage`** — Used to keep **local data on your device**: extension preferences. This storage is not used to build a browsing history for third parties. -- **`host_permissions`: ``** — Declares that the extension may **run in the context of web pages on any site** you visit. This pattern is required when the extension uses **content scripts** injected on all pages (for example to share helpers with the popup) or when the browser ties injection to broad host permissions. **This is not used for behavioural tracking**: the goal remains to obtain the current page URL for the Ecoindex query described above. Where store policies allow, **network** access to the backend is kept to the official Ecoindex API host (`https://bff.ecoindex.fr/`) rather than arbitrary sites. - -Some builds may also request **`tabs`** so the background logic can react when you switch tabs or load a page, still in line with the same purpose (updating the badge for the active tab). +- **`host_permissions`: `https://bff.ecoindex.fr/*`** — Allows network requests only to the official Ecoindex BFF API. No broad host access such as `` is requested. --- diff --git a/src/background/background.html b/src/background/background.html deleted file mode 100644 index 7dbefb9..0000000 --- a/src/background/background.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/background/background.js b/src/background/background.js deleted file mode 100644 index 167671b..0000000 --- a/src/background/background.js +++ /dev/null @@ -1,68 +0,0 @@ -import { - DEFAULT_BADGE_TEXT, - DEFAULT_COLOR, - FETCH_RESULT_URL, - getBrowserPolyfill, - setBadge, - setBadgeLocalStorage, -} from "../common.js"; - -let tabUrl = ""; -const currentBrowser = getBrowserPolyfill(); - -async function updateBadge(ecoindexData) { - if (!ecoindexData["latest-result"].id) { - await setBadge(DEFAULT_COLOR, DEFAULT_BADGE_TEXT); - await setBadgeLocalStorage(tabUrl, DEFAULT_COLOR, DEFAULT_BADGE_TEXT); - } else { - const { color, grade: text } = ecoindexData["latest-result"]; - setBadgeLocalStorage(tabUrl, color, text) - .then() - .catch(async () => { - await setBadge(DEFAULT_COLOR, DEFAULT_BADGE_TEXT); - }); - await setBadge(color, text); - } -} - -async function getBadgeInfo() { - currentBrowser.storage.local.get([tabUrl]).then(async (result) => { - if (tabUrl === "about:newtab") { - await setBadge("transparent", ""); - return; - } - - if (!result[tabUrl] || result[tabUrl]?.expirationTimestamp < Date.now()) { - await setBadge(DEFAULT_COLOR, DEFAULT_BADGE_TEXT); - fetch(FETCH_RESULT_URL(tabUrl)) - .then((r) => r.json()) - .then(updateBadge) - .catch(async () => { - await setBadge(DEFAULT_COLOR, DEFAULT_BADGE_TEXT); - await setBadgeLocalStorage(tabUrl, DEFAULT_COLOR, DEFAULT_BADGE_TEXT); - }); - } else { - const { text, color } = result[tabUrl]; - await setBadge(color, text); - } - }); -} - -currentBrowser.tabs.onUpdated.addListener(async (_tabId, changeInfo) => { - if (changeInfo.url !== undefined && changeInfo.url !== "") { - tabUrl = changeInfo.url; - } - - if (changeInfo.status === "loading") { - await getBadgeInfo(); - } -}); - -currentBrowser.tabs.onActivated.addListener(async () => { - const [tab] = await currentBrowser.tabs.query({ - active: true, - currentWindow: true, - }); - tabUrl = tab.url; - await getBadgeInfo(); -}); diff --git a/src/manifest-chrome.json b/src/manifest-chrome.json index 8774a59..7bd3c93 100644 --- a/src/manifest-chrome.json +++ b/src/manifest-chrome.json @@ -12,14 +12,9 @@ "default_title": "Ecoindex", "default_popup": "popup/popup.html" }, - "background": { - "service_worker": "background/background.js", - "type": "module" - }, "permissions": [ "activeTab", - "storage", - "tabs" + "storage" ], "host_permissions": [ "https://bff.ecoindex.fr/*" diff --git a/src/manifest-firefox.json b/src/manifest-firefox.json index a85e7b7..8d4a6b3 100644 --- a/src/manifest-firefox.json +++ b/src/manifest-firefox.json @@ -12,14 +12,10 @@ "default_title": "Ecoindex", "default_popup": "popup/popup.html" }, - "background": { - "page": "background/background.html" - }, "permissions": [ "activeTab", "https://bff.ecoindex.fr/*", - "storage", - "tabs" + "storage" ], "options_ui": { "page": "options/options.html", diff --git a/src/options/options.html b/src/options/options.html index 4f641bf..838701f 100644 --- a/src/options/options.html +++ b/src/options/options.html @@ -28,12 +28,12 @@

Données et permissions

L’Extension peut déclarer dans son manifeste :

{
   "permissions": ["activeTab", "storage"],
-  "host_permissions": ["<all_urls>"]
+  "host_permissions": ["https://bff.ecoindex.fr/*"]
 }
    -
  • activeTab — Accès temporaire à l’onglet actif quand vous ouvrez la popup (ou utilisez l’Extension), pour lire l’URL de la page et interroger le service Ecoindex. Pas de lecture continue de tous les onglets.
  • -
  • storage — Stockage local des préférences et d’un état d’affichage de courte durée (par ex. badge), sur votre appareil.
  • -
  • host_permissions <all_urls> — Autorise l’Extension à s’exécuter sur les pages que vous visitez (notamment si des scripts de contenu sont injectés partout). Ce n’est pas utilisé pour du pistage publicitaire ; l’URL sert à demander le score Ecoindex. L’accès réseau vers le backend peut être limité à https://bff.ecoindex.fr/ selon la version du manifeste.
  • +
  • activeTab — Accès temporaire à l’onglet actif lorsque vous ouvrez la popup pour récupérer l’URL affichée et demander le score Ecoindex correspondant.
  • +
  • storage — Stockage local des préférences de l’extension sur votre appareil.
  • +
  • host_permissions https://bff.ecoindex.fr/* — Autorise uniquement les appels réseau vers l’API officielle Ecoindex BFF. Aucun accès hôte large de type <all_urls> n’est demandé.

Détail : voir la politique de confidentialité du projet (doc/PRIVACY-POLICY-FR.md ou doc/PRIVACY-POLICY.md).

diff --git a/src/popup/popup.css b/src/popup/popup.css index 67cbb68..c74135f 100644 --- a/src/popup/popup.css +++ b/src/popup/popup.css @@ -739,6 +739,8 @@ code { background: #f5f5f5; font-family: monospace; font-size: 12px; + white-space: pre-wrap; + word-break: break-all; } .shadow { @@ -768,4 +770,11 @@ code { summary { cursor: pointer; +} + +#badge-preview-img { + display: block; + margin: 0.5rem 0; + max-width: 100%; + height: auto; } \ No newline at end of file diff --git a/src/popup/popup.html b/src/popup/popup.html index 6299bf9..99c0dae 100644 --- a/src/popup/popup.html +++ b/src/popup/popup.html @@ -63,7 +63,9 @@

Ecoindex

@@ -98,9 +100,25 @@

Derniers résultats

+
+
+ Intégrer le badge Ecoindex + Ecoindex Badge + +

Vous pouvez intégrer un badge Ecoindex pour la page analysée avec le snippet suivant :

+ + + +

En savoir plus : cnumr/ecoindex_badge sur jsDelivr

+
diff --git a/src/popup/popup.js b/src/popup/popup.js index a4e429a..8c1dd9f 100644 --- a/src/popup/popup.js +++ b/src/popup/popup.js @@ -5,7 +5,6 @@ import { FETCH_SCREENSHOT_URL, FETCH_TASK_URL, getBrowserPolyfill, - setBadgeLocalStorage, } from "../common.js"; let tabUrl; @@ -13,6 +12,12 @@ let tabUrl; let options = { showScreenshot: true }; const domTitle = document.getElementById("title"); const currentBrowser = getBrowserPolyfill(); +const badgeIntegrationElement = document.getElementById("badge-integration"); +const badgeSnippetElement = document.getElementById("badge-snippet"); +const badgeThemeElement = document.getElementById("badge-theme"); +const badgePreviewLinkElement = document.getElementById("badge-preview-link"); +const badgePreviewImgElement = document.getElementById("badge-preview-img"); +let shouldRefreshBadgePreview = false; async function loadOptions() { const stored = await currentBrowser.storage.local.get({ @@ -168,10 +173,6 @@ function setOtherResults(ecoindexData, tag) { section.style.display = "block"; } -async function updateLocalStorage(value) { - await setBadgeLocalStorage(tabUrl, value.color, value.grade); -} - /** * Display the result of the analysis using data from the API * @param any ecoindexData results from the BFF API @@ -197,10 +198,12 @@ function displayResult(ecoindexData) { resultLink.setAttribute("href", FETCH_RESULT_ECOINDEX_URL(latestResult.id)); document.getElementById("result").style.display = "block"; + badgeIntegrationElement.style.display = "block"; + updateBadgeSnippet(tabUrl, getBadgeTheme(), shouldRefreshBadgePreview); + shouldRefreshBadgePreview = false; if (options.showScreenshot) { displayImage(latestResult.id); } - updateLocalStorage(latestResult); } if ( @@ -230,6 +233,29 @@ function updatePopup(ecoindexData) { displayResult(ecoindexData); } +/** + * Build and display a reusable Ecoindex badge snippet for the current URL. + * @param {string} url + * @param {"light" | "dark"} theme + * @param {boolean} refreshPreview + */ +function updateBadgeSnippet(url, theme = "light", refreshPreview = false) { + const redirectUrl = `https://bff.ecoindex.fr/redirect/?url=${url}`; + const badgeUrl = `https://bff.ecoindex.fr/badge/?theme=${theme}&url=${url}`; + const previewUrl = refreshPreview + ? `${badgeUrl}&refresh=true&_ts=${Date.now()}` + : badgeUrl; + badgeSnippetElement.textContent = ` + Ecoindex Badge +`; + badgePreviewLinkElement.setAttribute("href", redirectUrl); + badgePreviewImgElement.setAttribute("src", previewUrl); +} + +function getBadgeTheme() { + return badgeThemeElement.value === "dark" ? "dark" : "light"; +} + /** * Get data from the API and update the popup * @param string url @@ -304,6 +330,7 @@ function resetDisplay() { document.getElementById("older-results").style.display = "none"; document.getElementById("host-results").style.display = "none"; document.getElementById("error").style.display = "none"; + badgeIntegrationElement.style.display = "none"; } /** @@ -312,6 +339,7 @@ function resetDisplay() { async function runAnalysis() { resetDisplay(); document.getElementById("loader").style.display = "block"; + shouldRefreshBadgePreview = true; fetch(FETCH_TASK_URL, { method: "POST", @@ -319,7 +347,11 @@ async function runAnalysis() { "Content-Type": "application/json", }, body: JSON.stringify({ - url: tabUrl, + web_page: { + width: 1920, + height: 1080, + url: tabUrl, + }, }), }) .then((r) => r.json()) @@ -341,6 +373,9 @@ loadOptions() .querySelector("#no-analysis button") .addEventListener("click", runAnalysis); document.getElementById("retest").addEventListener("click", runAnalysis); + badgeThemeElement.addEventListener("change", () => { + updateBadgeSnippet(tabUrl, getBadgeTheme()); + }); currentBrowser.tabs.query( { @@ -349,6 +384,7 @@ loadOptions() }, (tabs) => { tabUrl = tabs[0].url; + updateBadgeSnippet(tabUrl, getBadgeTheme()); getAndUpdateEcoindexData(tabUrl); },