Scopri come l'API Local Font Access ti consente di accedere ai caratteri installati localmente dell'utente e ottenere dettagli di basso livello su questi caratteri
Caratteri sicuri per il web
Se hai lavorato abbastanza a lungo lo sviluppo web, potresti ricordare i cosiddetti caratteri sicuri per il web.
Questi caratteri sono noti per essere disponibili in quasi tutte le istanze dei sistemi operativi più utilizzati (ovvero Windows, macOS, le distribuzioni Linux più comuni, Android e iOS). Nei primi anni 2000, Microsoft ha anche lanciato un'iniziativa chiamata fonti di base TrueType per il web che fornivano questi caratteri senza costi con l'obiettivo che "ogni volta che visiti un sito web in cui le specifichi, vengono visualizzate pagine esattamente come le intendevano il design del sito". Sì, questi siti includevano siti impostati in Comic Sans MS. Ecco un classico stack di caratteri sicuri per il web (con l'ultimo tipo di carattere sans-serif
di riserva) simile al seguente:
body {
font-family: Helvetica, Arial, sans-serif;
}
Caratteri web
Sono finiti i tempi in cui i caratteri sicuri per il web contavano davvero. Oggi disponiamo di caratteri web, alcuni dei quali sono anche caratteri variabili che possiamo modificare ulteriormente modificando i valori per i vari assi esposti. Puoi utilizzare i caratteri web dichiarando un blocco @font-face
all'inizio del CSS, che specifica i file dei caratteri da scaricare:
@font-face {
font-family: 'FlamboyantSansSerif';
src: url('flamboyant.woff2');
}
Successivamente, puoi utilizzare il carattere web personalizzato specificando font-family
, come di consueto:
body {
font-family: 'FlamboyantSansSerif';
}
Caratteri locali come vettore di impronte digitali
La maggior parte dei caratteri web proviene dal web. Un fatto interessante, tuttavia, è che la proprietà src
nella dichiarazione @font-face
, oltre alla funzione url()
, accetta anche una funzione local()
. Ciò consente di caricare caratteri personalizzati (sorpresa!) localmente. Se l'utente ha installato
FlamboyantSansSerif sul proprio sistema operativo, verrà utilizzata la copia locale anziché
scaricarla:
@font-face {
font-family: 'FlamboyantSansSerif';
src: local('FlamboyantSansSerif'), url('flamboyant.woff2');
}
Questo approccio fornisce un utile meccanismo di riserva che può farti risparmiare larghezza di banda. Su internet,
purtroppo non possiamo avere cose carine. Il problema della funzione local()
è che potrebbe essere
utilizzata in modo illecito per il fingerprinting del browser. Ho scoperto che l'elenco di caratteri installati
da un utente può essere facilmente identificabile. Molte aziende dispongono dei propri caratteri aziendali installati sui laptop dei dipendenti. Ad esempio, Google ha un carattere aziendale chiamato Google Sans.
![L'app Font Book di macOS che mostra un'anteprima del carattere Google Sans.](https://developer.chrome.google.cn/static/docs/capabilities/web-apis/local-fonts/image/the-macos-font-book-app-s-28dfca88ee8bd.png?authuser=5&hl=it)
Un utente malintenzionato può tentare di determinare per quale azienda lavora qualcuno testando l'esistenza di un gran numero di caratteri aziendali noti, come Google Sans. L'autore dell'attacco provava a eseguire il rendering del testo impostato in questi caratteri su una tela e a misurare i glifi. Se i glifi corrispondono alla forma nota del carattere aziendale, l'utente malintenzionato ha un hit. Se i glifi non corrispondono, l'utente malintenzionato sa che è stato utilizzato un carattere sostitutivo predefinito poiché il carattere aziendale non era installato. Per informazioni dettagliate su questo e altri attacchi di fingerprinting dei browser, leggi il sondaggio di Laperdix et al.
A parte i caratteri aziendali, è possibile identificare anche solo l'elenco dei caratteri installati. La situazione con questo vettore di attacco è diventata così negativa che di recente il team di WebKit ha deciso di "includere solo caratteri web e caratteri [nell'elenco dei caratteri disponibili] integrati nel sistema operativo, ma non i caratteri installati dall'utente localmente". Ed ecco un articolo sulla concessione dell'accesso ai caratteri locali.
API Local Font Access
L'inizio di questo articolo potrebbe averti messo di umore sfavorevole. Non possiamo avere cose belle? Non tasti. Crediamo che possiamo e forse tutto non è senza speranza. Per prima cosa, però, vorrei rispondere a una domanda che potreste porvi.
Perché è necessaria l'API Local Font Access quando sono disponibili caratteri web?
Da sempre è difficile offrire strumenti di progettazione e grafica di qualità professionale sul web. Uno ostacolo è stato l'impossibilità di accedere e utilizzare la varietà di caratteri suggeriti e creati in modo professionale che i designer hanno installato localmente. I caratteri web consentono alcuni casi d'uso di pubblicazione, ma non consentono l'accesso programmatico alle forme dei glifi vettoriali e alle tabelle di caratteri utilizzate dai rasterizzatori per eseguire il rendering dei contorni dei glifi. Analogamente, non c'è modo di accedere ai dati binari di un carattere web.
- Gli strumenti di progettazione devono accedere ai byte dei caratteri per implementare il layout OpenType e consentire agli strumenti di progettazione di agganciarsi a livelli inferiori per azioni come l'esecuzione di filtri vettoriali o trasformazioni sulle forme degli glifi.
- Gli sviluppatori potrebbero avere stack di caratteri legacy per le loro applicazioni che stanno portando sul web. L'utilizzo di questi stack richiede in genere l'accesso diretto ai dati dei caratteri, a differenza dei caratteri web.
- Alcuni caratteri potrebbero non essere concessi in licenza per la pubblicazione sul web. Ad esempio, Linotype ha una licenza per alcuni caratteri che includono solo l'uso su computer.
L'API Local Font Access è un tentativo di risolvere questi problemi. Si compone di due parti:
- Un'API di enumerazione dei caratteri, che consente agli utenti di concedere l'accesso all'insieme completo di caratteri di sistema disponibili.
- Da ogni risultato dell'enumerazione, la possibilità di richiedere l'accesso al container SFNT di basso livello (orientato ai byte) che include i dati completi del carattere.
Supporto del browser
Come utilizzare l'API Local Font Access
Rilevamento delle funzionalità
Per verificare se l'API Local Font Access è supportata, utilizza:
if ('queryLocalFonts' in window) {
// The Local Font Access API is supported
}
enumerazione dei caratteri locali
Per ottenere un elenco dei caratteri installati localmente, devi chiamare window.queryLocalFonts()
. La prima volta viene attivata una richiesta di autorizzazione, che l'utente può approvare o negare. Se l'utente approva i caratteri locali per la query, il browser restituisce un array con dati sui caratteri su cui puoi eseguire il loop. Ogni carattere è rappresentato come un oggetto FontData
con le proprietà family
(ad esempio "Comic Sans MS"
), fullName
(ad esempio "Comic Sans MS"
), postscriptName
(ad esempio "ComicSansMS"
) e style
(ad esempio "Regular"
).
// Query for all available fonts and log metadata.
try {
const availableFonts = await window.queryLocalFonts();
for (const fontData of availableFonts) {
console.log(fontData.postscriptName);
console.log(fontData.fullName);
console.log(fontData.family);
console.log(fontData.style);
}
} catch (err) {
console.error(err.name, err.message);
}
Se ti interessa solo un sottoinsieme di caratteri, puoi anche filtrarli in base ai nomi PostScript aggiungendo un parametro postscriptNames
.
const availableFonts = await window.queryLocalFonts({
postscriptNames: ['Verdana', 'Verdana-Bold', 'Verdana-Italic'],
});
Accesso ai dati SFNT
L'accesso SFNT completo è disponibile tramite il metodo blob()
dell'oggetto FontData
. SFNT è un formato di file che può contenere altri tipi di carattere, come PostScript, TrueType, OpenType e WOFF (Web Open Font Format).
try {
const availableFonts = await window.queryLocalFonts({
postscriptNames: ['ComicSansMS'],
});
for (const fontData of availableFonts) {
// `blob()` returns a Blob containing valid and complete
// SFNT-wrapped font data.
const sfnt = await fontData.blob();
// Slice out only the bytes we need: the first 4 bytes are the SFNT
// version info.
// Spec: https://docs.microsoft.com/en-us/typography/opentype/spec/otff#organization-of-an-opentype-font
const sfntVersion = await sfnt.slice(0, 4).text();
let outlineFormat = 'UNKNOWN';
switch (sfntVersion) {
case '\x00\x01\x00\x00':
case 'true':
case 'typ1':
outlineFormat = 'truetype';
break;
case 'OTTO':
outlineFormat = 'cff';
break;
}
console.log('Outline format:', outlineFormat);
}
} catch (err) {
console.error(err.name, err.message);
}
Demo
Puoi vedere l'API Local Font Access in azione nella demo di seguito. Assicurati di controllare anche il
codice sorgente. La demo mostra un elemento personalizzato chiamato <font-select>
che implementa un selettore di caratteri locale.
Considerazioni sulla privacy
Sembra che l'autorizzazione "local-fonts"
offra una piattaforma in cui è possibile acquisire facilmente le impronte. Tuttavia, i browser sono liberi di restituire tutto ciò che desiderano. Ad esempio, i browser incentrati sull'anonimato potrebbero scegliere di
fornire solo un insieme di caratteri predefiniti integrati nel browser. Analogamente, i browser non sono tenuti a fornire i dati delle tabelle esattamente come appaiono su disco.
Dove possibile, l'API Local Font Access è progettata per mostrare solo esattamente le informazioni necessarie per abilitare i casi d'uso menzionati. Le API di sistema potrebbero produrre un elenco dei caratteri installati non in ordine casuale o ordinato, ma nell'ordine di installazione dei caratteri. Restituire esattamente l'elenco dei caratteri installati fornito da questa API di sistema può esporre dati aggiuntivi che possono essere utilizzati per il fingerprinting, mentre i casi d'uso che vogliamo attivare non sono assistiti conservando questo ordine. Di conseguenza, questa API richiede che i dati restituiti vengano ordinati prima di essere restituiti.
Sicurezza e autorizzazioni
Il team di Chrome ha progettato e implementato l'API Local Font Access utilizzando i principi fondamentali definiti nella sezione Controllo dell'accesso alle funzionalità avanzate della piattaforma web, tra cui controllo degli utenti, trasparenza ed ergonomia.
Controllo utente
L'accesso ai caratteri dell'utente è completamente sotto il suo controllo e non verrà consentito, a meno che non venga concessa l'autorizzazione
"local-fonts"
, indicata nel
registro delle autorizzazioni.
Trasparenza
Se a un sito è stato concesso l'accesso ai caratteri locali dell'utente sarà visibile nel foglio informativo del sito.
Persistenza delle autorizzazioni
L'autorizzazione "local-fonts"
verrà mantenuta tra i ricaricamenti della pagina. Può essere revocato tramite il foglio delle informazioni sul sito.
Feedback
Il team di Chrome vuole conoscere la tua esperienza con l'API Local Font Access.
Parlaci della progettazione dell'API
C'è qualcosa nell'API che non funziona come previsto? Oppure mancano metodi o proprietà di cui hai bisogno per implementare la tua idea? Hai domande o commenti sul modello di sicurezza? Segnala un problema relativo alle specifiche nel repository GitHub corrispondente o aggiungi le tue opinioni su un problema esistente.
Segnala un problema con l'implementazione
Hai trovato un bug nell'implementazione di Chrome? Oppure l'implementazione è diversa dalle specifiche?
Segnala un bug all'indirizzo new.crbug.com. Assicurati di includere il maggior numero di dettagli possibile e di istruzioni semplici per la riproduzione e inserisci Blink>Storage>FontAccess
nella casella Componenti.
Glitch funziona benissimo per condividere riproduzioni rapide e semplici.
Mostra il supporto dell'API
Intendi utilizzare l'API Local Font Access? Il supporto pubblico aiuta il team di Chrome a dare la priorità alle funzionalità e mostra ad altri fornitori di browser quanto sia fondamentale supportarle.
Invia un tweet a @ChromiumDev usando l'hashtag
#LocalFontAccess
e facci sapere dove e come lo stai usando.
Link utili
- Spiegazione
- Bozza delle specifiche
- Bug di Chromium per l'enumerazione dei caratteri
- Bug di Chromium per l'accesso alla tabella dei caratteri
- Voce ChromeStatus
- Repository GitHub
- Revisione TAG
- Posizione degli standard Mozilla
Ringraziamenti
La specifica dell'API Local Font Access è stata modificata da Emil A. Eklund, Alex Russell, Joshua Bell e Olivier Yiptong. Questo articolo è stato esaminato da Joe Medley, Dominik Röttsches e Olivier Yiptong. Immagine hero di Brett Jordan su Unsplash.