// background.js — Service worker (Manifest V3) — v4 // // Rôles : // 1. Au clic sur l'icône : ouvrir le viewer // 2. Répondre aux messages du viewer : // - getSession : trouve l'onglet EasyVista ouvert, renvoie {phpsessid, origin} // - fetchPlanning : fetch le XML du planning pour une date (1 requête = tout) // - fetchXhr2 : fetch un texte d'action détaillé (utilisé en lazy-load au survol) // - fetchFiche : fetch une fiche individuelle (HTML) pour statut + commentaire tech // 3. Nettoyer les vieux caches (>7 jours) // (v4.2 : l'auto-refresh 12h/15h a été retiré) // // v4 : suppression de fetchTimeline (pu utilisé). Le calendar_block contient // directement ref/contact/lieu/catégorie dans ses attributs attr1/attr2/attr3, // donc on n'a plus besoin ni de xhr2 en masse, ni de l'API timeline. // Domaines EasyVista reconnus (interne d'abord, externe en fallback) const EV_ORIGINS = [ "https://itsma.etat-de-vaud.ch", "https://itsma.vd.ch" ]; // ============================================================================ // Clic sur l'icône → ouvrir le viewer // ============================================================================ chrome.action.onClicked.addListener(async () => { const viewerUrl = chrome.runtime.getURL("viewer.html"); // Si le viewer est déjà ouvert, on focus cet onglet plutôt que d'en ouvrir un autre const existing = await chrome.tabs.query({ url: viewerUrl + "*" }); if (existing.length > 0) { await chrome.tabs.update(existing[0].id, { active: true }); await chrome.windows.update(existing[0].windowId, { focused: true }); } else { await chrome.tabs.create({ url: viewerUrl }); } }); // ============================================================================ // Trouver l'onglet EasyVista actif et en extraire le PHPSESSID // ============================================================================ async function findEasyVistaSession() { // Chercher tous les onglets sur un domaine EasyVista for (const origin of EV_ORIGINS) { const tabs = await chrome.tabs.query({ url: origin + "/*" }); for (const tab of tabs) { const m = (tab.url || "").match(/[?&]PHPSESSID=([a-zA-Z0-9]+)/); if (m) { return { phpsessid: m[1], origin: origin, tabId: tab.id }; } } } return null; } // ============================================================================ // Fetch helpers (s'exécutent dans le contexte du service worker, // les cookies du domaine sont automatiquement inclus via credentials: include) // ============================================================================ /** * Fetch du XML retourné par planning_xhr.php?div=calendar_block. * Contient les interventions de nos 8 techs pour la date donnée (~40 ko). * * Ce n'est PAS le HTML de la page Planning — le serveur ne rend pas les données * dans le HTML, elles arrivent via cet endpoint AJAX. */ async function fetchPlanningXml(origin, phpsessid, unixDate) { const techIds = "76272,83725,66635,92235,90070,40944,72485,86874"; const groupId = "191"; const url = `${origin}/planning_xhr.php` + `?PHPSESSID=${encodeURIComponent(phpsessid)}` + `&div=calendar_block` + `&mode=day` + `&group_id=${groupId}` + `&event_name=HelpDesk_PlanningItem` + `&sql_param=${techIds}` + `&unix_date=${unixDate}` + `&start_date_label=Date` + `&end_date_label=Date` + `&click_here_label=Ici` + `&mail_title=mail` + `&day_start_hour=8` + `&day_end_hour=19`; console.log("[bg] fetchPlanningXml →", url.substring(0, 140)); const r = await fetch(url, { credentials: "include" }); console.log("[bg] status =", r.status); if (!r.ok) { // v4.2 : classifier l'erreur HTTP pour que le viewer affiche le bon // écran (session expirée vs EV inaccessible). const err = new Error("HTTP " + r.status); err.kind = classifyHttpStatus(r.status); err.status = r.status; throw err; } const xml = await r.text(); console.log("[bg] taille XML =", xml.length); return xml; } /** * v4.2 : classifie un statut HTTP comme "session_expired" ou "ev_unreachable". * - 401, 403, 404 → session_expired (EV renvoie souvent 404 au lieu de rediriger * vers la page de login quand PHPSESSID n'est plus valide) * - 5xx, autres → ev_unreachable (service down, surcharge, etc.) */ function classifyHttpStatus(status) { if (status === 401 || status === 403 || status === 404) return "session_expired"; return "ev_unreachable"; } /** * Fetch planning_xhr_2.php?id=ACTIONID pour UNE intervention. * Retourne ~400 octets au format custom : * @@DESCRIPTION_S@@...@@DESCRIPTION_E@@@@LABEL_S@@... */ async function fetchXhr2(origin, phpsessid, actionId) { const url = `${origin}/planning_xhr_2.php?PHPSESSID=${encodeURIComponent(phpsessid)}&id=${encodeURIComponent(actionId)}`; const r = await fetch(url, { credentials: "include" }); if (!r.ok) { const err = new Error("HTTP " + r.status); err.kind = classifyHttpStatus(r.status); err.status = r.status; throw err; } return await r.text(); } async function fetchFicheHtml(origin, phpsessid, formLink) { const url = `${origin}/index.php?${formLink}&PHPSESSID=${encodeURIComponent(phpsessid)}`; console.log("[bg] fetchFicheHtml →", url.substring(0, 120)); // v5.0.8 : EasyVista retourne maintenant un