Reveal URLs — Arhitektuur

See dokument kirjeldab, kuidas Reveal URLs-i laiendus on üles ehitatud ja kuidas selle põhiloogika töötab, tehnilistele lugejatele ja kaasaaitajatele. See viitab järjepidevalt päris failidele ja sümbolitele kujul path symbol, et iga väide oleks kontrollitav lähtekoodis. Kasutajale suunatud kirjelduse jaoks vaadake manual. Käsitsi kontrollimise sammude jaoks vaadake manual test plan.

Ülevaade

Reveal URLs on üks MV3 WebExtension, mis ehitatakse Chrome'i, Edge'i, Opera, Firefoxi ja Thunderbirdi jaoks ühest jagatud puhtast koodituumast. Safari on edasi lükatud: tal on manifest ja ta on nimeliselt build-itav, kuid ta on vaikebuild-ist ja CI-st välja jäetud. Laiendus kuvab iga lingi siht-URL-i renderdatud e-kirjas lingi kõrval ning märgib lingi ära siis, kui nähtav tekst nimetab teist registrable domeeni kui see, mis asub selle href-is.

Hoidla on pnpm-i ja TypeScripti monorepo, mida kirjeldavad pnpm-workspace.yaml ja package.json, ning "private": true hoiab selle paketina avaldamisest eemal. Bundlingut juhib tooling/build.mjs, mis kompileerib jagatud paketid ja õhukesed entry points kõigi engine'ite jaoks laaditavasse dist/<target>/ kataloogi. webextension-polyfill pakitakse iga script bundle'i sisse, selle asemel et eeldada runtime global-it.

Kaks native e-posti lisandit laiendavad sama tuvastusloogikat pindadele, kuhu WebExtension ei ulatu: Outlook Add-in Office.js-il ja Gmail Add-on Apps Script CardService'il. Mõlemad kasutavad uuesti ainult PURE analüüsi failist packages/core/src/findings.ts, koos analyseAnchors, analyseHtml, neutraalse mudeliga Finding[], loogikaga hostMismatch ja registrable domeeni tuletamisega tldts kaudu. Erinevaks jäävad ainult host-adapter ja esitlus. Outlook kasutab DOMParser-it ja töötab client-side. Gmail kasutab node-html-parser-it ja töötab server-side Google'i Apps Script V8 infrastruktuuris. Kuna kumbki raamistik ei luba loetud sõnumi DOM-i muuta, näitavad mõlemad paneeli või kaarti tulemustega, mitte inline annotation-it. linkProcessor.ts DOM-mutation rada ja REVEAL_URLS_CSS ei kasutata seal uuesti. Suhteline href lahendatakse ainult usaldusväärse <base href> suhtes e-kirja sees ja muul juhul jäetakse see vahele.

Koodibaas jaotab vastutused selgelt:

Hoidla paigutus

packages/core — puhas tuum

Ükski siin olev moodul ei impordi extension API-t nagu browser.*, chrome.* või messenger.*, ning ükski ei kasuta string-to-markup DOM sinks'e nagu innerHTML või insertAdjacentHTML. Seda lepingut jõustab mehaaniliselt packages/core/test/purity.test.ts, mis kogub src/**/*.ts, eemaldab kommentaaride kehad stripComments abil ning kontrollib, et EXTENSION_API_PATTERN ega UNSAFE_DOM_PATTERN ei vastaks ühelegi moodulile. Avalik pind eksporditakse uuesti failist packages/core/src/index.ts, ning ainus runtime sõltuvus on tldts.

Põhimoodulid on:

packages/webext — browser API ümbrised

Need moodulid VÕIVAD kasutada browser.* ning see on ainus koht, kus WebExtension APIs-e puudutatakse. Avalik pind eksporditakse uuesti failist packages/webext/src/index.ts. Siin asuvad content.ts, contentRegistration.ts, storage.ts, background.ts, toolbarAction.ts, messageDisplay.ts, messageDisplayBackground.ts ja options/options.ts.

extensions/<engine> — õhukesed sisenemispunktid ja manifestid

Iga engine kannab oma manifest.json-i ja icons/ kataloogi. Chrome, Firefox ja Thunderbird kannavad lisaks src/ kataloogi entry points'idega. Edge, Opera ja Safari kannavad ainult manifesti ja ikoone ning kasutavad uuesti Chrome'i src/-i. Näiteks extensions/chrome/src/content.ts sisaldab ainult void createContentController().bootstrap();, samal ajal kui extensions/chrome/src/background.ts kutsub registerBackground, registerContentReconciliation ja registerToolbarToggle. extensions/thunderbird/src/background.ts kutsub registerBackground ja registerMessageDisplay. extensions/_template on scaffold, mitte build target.

tooling, features ja smoke testid

tooling sisaldab faile build.mjs, version.mjs ja icons.mjs. features sisaldab Gherkini stsenaariume, step definitions'e ja usaldusväärseid doubles'e failides features/support/webext.ts ja features/support/world.ts. Igal engine'il on ka extensions/<engine>/test/manifest.smoke.test.mjs, samal ajal kui _template kasutab template.smoke.test.mjs.

Paljastamise voog

Content'i tee algab engine'i entry point'ist, näiteks extensions/chrome/src/content.ts, mis kutsub createContentController().bootstrap() failist packages/webext/src/content.ts.

Bootstrap

createContentController bootstrap käivitub kord iga frame'i kohta. See võtab frame'i enda kontrolli alla enne iga await-i läbi claimBootstrap, laeb config'i läbi loadConfigWithRetry, injekteerib stylesheet'i läbi injectStyles alles pärast edukat lugemist ning taastab marker-i läbi releaseBootstrap, kui laadimine täielikult ebaõnnestub. Kui config.enabled on tõene, kutsub see start, ning alati registreerib ka listener'i onConfigChanged.

Aktiivse saidi reegli lahendamine

start ja applyConfig kasutavad resolveSiteRule-i, et otsustada, kas ja kus annotation tehakse. Kõigepealt proovitakse dokumendi enda asukohta resolveForHref kaudu, mis filtreerib config.sites lubatud reeglitele ja jätab valiku selectMostSpecific hoolde. Kui dokument ei sobi ning selle päritolu on opaque või inherited, nagu kontrollib hasOpaqueOrigin, järgnevad fallback-id readTopHref, readOpenerHref ja readReferrer kaudu, kaitstult cross-origin lugemise eest.

Sisujuure piiramine ja muudatuste jälgimine

start salvestab contentRoot-i, loob annotator'i createAnnotator(config) abil ning töötleb iga sobiva juure failist selectRoots(doc, contentRoot), mis mähib querySelectorAll-i try/catch-i, nii et vigane selector kukub ohutult väärtusele []. Seejärel jälgib see doc.body-d OBSERVER_OPTIONS-iga. processMutations filtreerib iga muutuse root'i järgi ning processAddedNode katab juure sees olevad sõlmed, juure enda ja seda sisaldavad sõlmed. applyConfig teeb teardown'i, restart'i või reflow'd olenevalt aktiivsest reeglist ja contentRoot-i muutumisest.

Üksiku lingi märgistamine

Annotator elab failis packages/core/src/linkProcessor.ts. createAnnotator tagastab Annotator-i koos Map-iga, data-ru token'iga failist generateToken ja aktiivse config'iga. process(root) puhastab lahtiühendatud kirjed, kogub a[href] elemendid läbi collectAnchors, lahendab URL-id läbi resolveAnnotatableUrl, kasutab fast path'i isAnnotationIntact, kui render on puutumata, ning arvutab mismatch'i läbi hostMismatch-i enne annotateAnchor-i kutsumist.

annotateAnchor renderdab ainult SAFE-DOM-i. Režiimis "inline" lisab see <span class="reveal-urls-url"> koos textContent-iga ja <br>-i. Režiimis "title" salvestab see olemasoleva title-i, asendab selle URL-iga ja lisab rõhutatud mismatch'i korral <span class="reveal-urls-warn"> elemendi väärtusega REVEAL_URLS_WARN_LABEL. Loodud sõlmed saavad data-ru="<token>", ning configFingerprint käivitab vajadusel reflow. truncateUrl töötab üle [...displayHref] ja kasutab URL_ELLIPSIS-t.

Host-i ebakõla

packages/core/src/hostMismatch.ts hostMismatch võrdleb lingi nähtavat teksti selle href-iga registrable domeeni tasemel, mitte toor-hostname'i põhjal. extractHostCandidates jagab teksti token'iteks ja taandab need läbi hostCandidate, mis nõuab punkti ja tldts-i poolt tunnustatud public suffix'it. Href-i host ja kandidaadid taandatakse tldts.getDomain abil. Iga kandidaat erineva domeeniga tekitab mismatch'i.

Stiilid ja kontrast

packages/core/src/styles.ts hoiab REVEAL_URLS_CSS-i ja helper'eid applyColour, applyFontOverrides ning applyContrastBackdrop. applyContrastBackdrop loeb elemendi arvutatud värvi ja esimese opaque tausta getComputedStyle kaudu, seejärel kasutab needsWhiteBackdrop-i failist packages/core/src/contrast.ts, et otsustada, kas määrata style.backgroundColor = "white". contrast.ts annab parseColour, relativeLuminance ja contrastRatio.

Seadistatavad host-id ja sisu piiramine

Üks SiteRule failis packages/core/src/config.ts määrab, KUS annotation töötab läbi match ja allFrames, ning MILLINE container seda piirab läbi contentRoot, koos enabled-i ja märgiga builtin. DEFAULT_SITES katavad Gmaili, Protoni koos allFrames-iga ja mõlemad Outlooki host-id. Config ühendab globaalsed toggles, colours, font overrides ja loendi sites.

Match pattern'i mehhanism

packages/core/src/matchPattern.ts hoiab restrictive grammatikat MATCH_PATTERN: ainult http ja https, valikuline *. wildcard host, glob path, ilma port'ita, ilma * scheme'ita ja ilma <all_urls>-ita. matchesPattern võrdleb URL-i valideeritud mustriga ja delegeerib path'i pathGlobMatches-ile. parsePatternParts jagab mustri host-iks, path-iks, scheme-iks ja wildcardHost-iks.

Reeglite kattumisel kehtib põhimõte "most specific wins". compareSiteSpecificity järjestab exact host'i wildcard host'ist ettepoole, seejärel pikema literal host'i, seejärel sõnasõnalisema path'i läbi literalPathLength-i ja lõpuks ASCII tiebreak'i. selectMostSpecific tagastab kõige spetsiifilisema lubatud reegli, mis URL-iga sobib.

permissions.getAll() võib raporteerida grants'e täielikus WebExtensioni grammatikas (<all_urls>, *://*/*, https://*/*, *://*.host/*, https://host/*), mille MATCH_PATTERN tagasi lükkaks. parseGrantedOrigin teeb neist GrantedOriginParts, originCovers kontrollib katvust üle match-i ja matchAllowsOriginFallback ütleb, kas path on täpselt ORIGIN_FALLBACK_PATH, st /*.

Dünaamiline registreerimine

packages/webext/src/contentRegistration.ts registreerib iga kasutaja lisatud reegli jaoks ühe dynamic content script'i. Built-ins teenindatakse läbi static content_scripts entries'e ega registreerita kunagi dünaamiliselt. desiredContentScripts filtreerib config.sites-i, kasutab isOriginGranted, originCovers ja contentScriptId ning paneb matchOriginAsFallback: true ainult siis, kui seda lubab matchAllowsOriginFallback(rule.match).

reconcileContentScriptsOnce loeb grantitud originid, salvestatud config'i ja live registrations'e ning viib need kokku property-aware diff'iga. sameRegistration normaliseerib nii soovitud descriptor'i kui ka live read-back'i. Kuna updateContentScripts puudub, eemaldatakse muudetud script ja registreeritakse uuesti. reconcileContentScripts kasutab promise'i inFlight, et järjestada trigger'id, mis võivad juhtuda lähestikku.

Selgesõnalise loa voog

Static manifest'id deklareerivad optional_host_permissions (http://*/*, https://*/*), et kasutaja saaks runtime'i ajal anda loa lisahost-ile. packages/webext/src/options/options.ts addSite valideerib kogu kandidaatreegli läbi normaliseSiteRule, tuletab origin'i läbi matchOrigin ja kutsub browser.permissions.request-i Add nupu click gesture'i seest. Alles pärast kinnitamist lisab see rea builtin:false.

Config, storage ja kanooniline muster

Üks valideerimisfunnel

normaliseConfig failis packages/core/src/config.ts on ainus kanooniline lugemistee. See teisendab ja piirab iga välja, langeb vigase sisendi korral vaikeväärtusele tagasi ega viska kunagi exception'it. See on ehitatud validatoritest nagu normaliseBoolean, normaliseRenderMode, normaliseMaxLength, normaliseIgnoreHosts, normaliseMatchColour, normaliseMismatchColour, normaliseCssSize, normaliseFontWeight, normaliseContentRoot, normaliseMatchPattern ja normaliseSites. normaliseSites eemaldab vigased entries'ed, eemaldab duplikaadid võtme match järgi, sunnib builtin: true-d kattuvatel built-in reeglitel ja taastab puuduvad built-ins.

Salvestamine

packages/webext/src/storage.ts mähib WebExtension storage API ümber. configArea kasutab browser.storage.sync-i, kui see on olemas, ja teeb fallback'i browser.storage.local-ile, näiteks Thunderbirdis. getConfig, setConfig ja onConfigChanged lasevad väärtused alati läbi normaliseConfig-i, nii et katkine store ei saa kunagi tagastada vigast Config-i. Mõlemad add-on vormid kasutavad sama funnel'it omaenda host-storage'ite kohal.

Kanooniline config-muster ja sihitud uuendused

Kolm write path'i loevad kanoonilist config'it, muudavad täpselt üht asja ja kirjutavad selle tagasi, salvestamata pooleliolevaid form edits'e:

toggleEnabled failis packages/webext/src/toolbarAction.ts järgib sama mustrit ka background'i poolel.

Build engine'i järgi ja manifesti leping

tooling/build.mjs juhib ühtset esbuild build'i iga WebExtension target'i jaoks. Descriptor TARGETS määrab SOURCE TARGET-i igale target'ile. Chrome'il, Firefoxil ja Thunderbirdil on oma src/. Edge, Opera ja Safari kasutavad chrome-i allikana. Outlook add-in'il on oma allikas. ACTIVE_TARGETS, st Chrome, Edge, Firefox, Opera ja Thunderbird, on need, mida build'itakse --all ja --package kaudu. Safari ja Outlook build'itakse ainult siis, kui need on nimeliselt küsitud, ning Gmail kasutab make build-gmail.

Gmaili bundle sihib Apps Script V8 runtime'i, millel puuduvad ES modules ja native URL. Seepärast ehitatakse see ESM-ina ja seejärel eemaldatakse export {…}, et trigger funktsioonid jääksid globaalseks. Väike URL polyfill lisatakse ainult vajadusel. buildTarget puhastab dist/<target>/, kopeerib manifest.json-i ja icons/, pakib scripts'id IIFE-na ning options lehe ESM-ina ja kopeerib options.html ning options.css.

tooling/version.mjs stamp-ib versioonid. See võtab MAJOR.MINOR väärtuse root package.json-ist, leiab kõrgeima BUILD number'i ja lisab selle igale target manifestile. Outlook add-in kannab nii manifest.json-i kui ka manifest.xml-i. tooling/icons.mjs, mis töötab käsuga make icons, rasterises assets/icon.svg failiks icon48.png ja icon128.png.

Manifesti leping on määratletud failides extensions/<engine>/test/manifest.smoke.test.mjs, kus kontrollitakse iga manifesti täpset kuju ja iga referenced file'i olemasolu.

Rahvusvahelistamine (i18n)

Reveal URLs on lokaliseeritud paljudesse keeltesse peale inglise keele. Ainsaks allikaks sellele komplektile on packages/core/src/locales.json, mis sisaldab SUPPORTED_LOCALES, emakeelseid nimesid ja vaikekeelt. Iga mitteingliskeelne string on machine-translated ja ootab inimülevaatust. Provenientsi marker erineb vormiti: _locales kannavad seda description-is, site catalogues märgivad seda failis site/i18n/README.md ning tõlgitud docs kannavad esimesel real HTML kommentaari.

Lokaliseerimisvahendeid on kolm sõltumatut:

“Aktiivsete saitide” peitmine meilikliendis (AD-3)

Mail client target nagu Thunderbird näeb juba kõiki rendered messages'e, seega on host-põhine “Active sites” editor seal üleliigne. Otsus kandub läbi mailClient: true välja failis tooling/build.mjs.

Turvalisuse ja privaatsuse hoiak

Testimine