Leer hoe de Local Font Access API u toegang geeft tot de lokaal geïnstalleerde lettertypen van de gebruiker en gedetailleerde informatie daarover kunt verkrijgen.
Gepubliceerd: 24 augustus 2020
Webveilige lettertypen
Als je al langer bezig bent met webdevelopment, herinner je je misschien nog de zogenaamde webveilige lettertypen . Deze lettertypen zijn beschikbaar op vrijwel alle gangbare besturingssystemen (zoals Windows, macOS, de meest voorkomende Linux-distributies, Android en iOS). Begin jaren 2000 nam Microsoft zelfs het voortouw met een initiatief genaamd TrueType Core Fonts for the Web, waarbij deze lettertypen gratis te downloaden waren met als doel dat "wanneer je een website bezoekt die deze lettertypen gebruikt, je pagina's precies zo ziet als de websiteontwerper bedoeld heeft" . Ja, dit gold ook voor websites die waren ingesteld op Comic Sans MS . Een klassieke webveilige lettertypecombinatie (met als ultieme fallback een willekeurig sans-serif lettertype) zou er als volgt uit kunnen zien:
body {
font-family: Helvetica, Arial, sans-serif;
}
Weblettertypen
De tijd dat webveilige lettertypen er echt toe deden, is allang voorbij. Tegenwoordig hebben we webfonts , waarvan sommige zelfs variabele lettertypen zijn die we verder kunnen aanpassen door de waarden voor de verschillende zichtbare assen te wijzigen. Je kunt webfonts gebruiken door een @font-face blok aan het begin van de CSS te plaatsen, waarmee je de te downloaden lettertypebestanden specificeert:
@font-face {
font-family: 'FlamboyantSansSerif';
src: url('flamboyant.woff2');
}
Hierna kunt u het aangepaste weblettertype gebruiken door de font-family op te geven, zoals gebruikelijk:
body {
font-family: 'FlamboyantSansSerif';
}
Lokale lettertypen als vingerafdrukvector
De meeste webfonts komen, zoals de naam al doet vermoeden, van het web. Een interessant feit is echter dat de src eigenschap in de @font-face -declaratie, naast de url() `-functie, ook een local() `-functie accepteert. Dit maakt het mogelijk om aangepaste lettertypen (verrassing!) lokaal te laden. Als de gebruiker toevallig FlamboyantSansSerif op zijn besturingssysteem heeft geïnstalleerd, wordt de lokale kopie gebruikt in plaats van dat deze wordt gedownload.
@font-face {
font-family: 'FlamboyantSansSerif';
src: local('FlamboyantSansSerif'), url('flamboyant.woff2');
}
Deze aanpak biedt een handig terugvalmechanisme dat mogelijk bandbreedte bespaart. Helaas kunnen we op internet niet alles hebben. Het probleem met de local() -functie is dat deze misbruikt kan worden voor browserfingerprinting. Het blijkt dat de lijst met lettertypen die een gebruiker heeft geïnstalleerd, behoorlijk veel informatie kan geven. Veel bedrijven hebben hun eigen bedrijfslettertypen die op de laptops van werknemers zijn geïnstalleerd. Google heeft bijvoorbeeld een bedrijfslettertype genaamd Google Sans .

Een aanvaller kan proberen te achterhalen voor welk bedrijf iemand werkt door te controleren of een groot aantal bekende bedrijfslettertypen, zoals Google Sans, aanwezig is. De aanvaller zou tekst in deze lettertypen op een canvas weergeven en de tekens (glyphs) meten. Als de tekens overeenkomen met de bekende vorm van het bedrijfslettertype, heeft de aanvaller een match. Als de tekens niet overeenkomen, weet de aanvaller dat er een standaard vervangend lettertype is gebruikt, omdat het bedrijfslettertype niet was geïnstalleerd. Lees voor meer informatie over deze en andere browserfingerprinting-aanvallen het overzichtsartikel van Laperdix et al.
Los van de bedrijfslettertypen, kan zelfs de lijst met geïnstalleerde lettertypen al een aanwijzing zijn. De situatie met deze aanvalsvector is zo ernstig geworden dat het WebKit-team onlangs heeft besloten om "alleen weblettertypen en lettertypen die bij het besturingssysteem worden geleverd op te nemen in de lijst met beschikbare lettertypen, maar niet lokaal door de gebruiker geïnstalleerde lettertypen" . (En hier ben ik dan, met een artikel over het verlenen van toegang tot lokale lettertypen.)
De Local Font Access API
Het begin van dit artikel heeft je misschien in een negatieve stemming gebracht. Kunnen we echt geen leuke dingen hebben? Maak je geen zorgen. We denken van wel, en misschien is alles toch niet hopeloos . Maar laat me eerst een vraag beantwoorden die je jezelf misschien stelt.
Waarom hebben we de Local Font Access API nodig als er webfonts beschikbaar zijn?
Professionele ontwerp- en grafische tools zijn historisch gezien lastig te leveren op het web. Een struikelblok is het gebrek aan toegang tot en gebruik van de volledige verscheidenheid aan professioneel ontworpen en gehintte lettertypen die ontwerpers lokaal hebben geïnstalleerd. Webfonts maken bepaalde publicatietoepassingen mogelijk, maar bieden geen programmatische toegang tot de vectorvormen van de glyphs en de lettertypetabellen die door rasterizers worden gebruikt om de contouren van de glyphs weer te geven. Evenmin is er een manier om toegang te krijgen tot de binaire gegevens van een webfont.
- Ontwerptools hebben toegang nodig tot de lettertypebytes om hun eigen OpenType-lay-outimplementatie uit te voeren en om op lagere niveaus in te grijpen voor acties zoals het uitvoeren van vectorfilters of transformaties op de glyphvormen.
- Ontwikkelaars gebruiken mogelijk bestaande lettertypen voor hun applicaties die ze naar het web migreren. Om deze lettertypen te gebruiken, hebben ze meestal directe toegang tot de lettertypegegevens nodig, iets wat webfonts niet bieden.
- Sommige lettertypen zijn mogelijk niet gelicentieerd voor gebruik via het web. Linotype heeft bijvoorbeeld voor sommige lettertypen een licentie die alleen gebruik op desktops toestaat.
De Local Font Access API is een poging om deze uitdagingen op te lossen. Deze bestaat uit twee delen:
- Een API voor het opsommen van lettertypen , waarmee gebruikers toegang kunnen verlenen tot alle beschikbare systeemlettertypen.
- Vanuit elk enumeratieresultaat is het mogelijk om toegang tot de SFNT-container op laag niveau (byte-georiënteerd) aan te vragen, inclusief de volledige lettertypegegevens.
Browserondersteuning
Hoe gebruik je de Local Font Access API?
Kenmerkdetectie
Om te controleren of de Local Font Access API wordt ondersteund, gebruikt u:
if ('queryLocalFonts' in window) {
// The Local Font Access API is supported
}
Lokale lettertypen opsommen
Om een lijst van de lokaal geïnstalleerde lettertypen te verkrijgen, moet u window.queryLocalFonts() aanroepen. De eerste keer dat u dit doet, verschijnt er een toestemmingsprompt, die de gebruiker kan goedkeuren of weigeren. Als de gebruiker toestemming geeft om de lokale lettertypen op te vragen, retourneert de browser een array met lettertypegegevens waar u doorheen kunt itereren. Elk lettertype wordt weergegeven als een FontData object met de eigenschappen family (bijvoorbeeld "Comic Sans MS" ), fullName (bijvoorbeeld "Comic Sans MS" ), postscriptName (bijvoorbeeld "ComicSansMS" ) en style (bijvoorbeeld "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);
}
Als u alleen geïnteresseerd bent in een subset van lettertypen, kunt u deze ook filteren op basis van de PostScript-namen door een parameter postscriptNames toe te voegen.
const availableFonts = await window.queryLocalFonts({
postscriptNames: ['Verdana', 'Verdana-Bold', 'Verdana-Italic'],
});
Toegang tot SFNT-gegevens
Volledige toegang tot SFNT is beschikbaar via de blob() methode van het FontData object. SFNT is een lettertypebestandsformaat dat andere lettertypen kan bevatten, zoals PostScript, TrueType, OpenType, Web Open Font Format (WOFF)-lettertypen en andere.
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
In de demo kunt u de Local Font Access API in actie zien. Bekijk ook zeker de broncode . De demo toont een aangepast element genaamd <font-select> dat een lokale lettertypekiezer implementeert.
Privacyoverwegingen
De toestemming voor "local-fonts" lijkt een zeer herkenbare interface te bieden. Browsers zijn echter vrij om alles terug te geven wat ze willen. Browsers die zich richten op anonimiteit kunnen er bijvoorbeeld voor kiezen om alleen een set standaardlettertypen te gebruiken die in de browser zijn ingebouwd. Evenzo zijn browsers niet verplicht om tabelgegevens exact weer te geven zoals ze op de schijf staan.
De Local Font Access API is zo ontworpen dat, waar mogelijk, alleen de informatie wordt weergegeven die nodig is voor de genoemde gebruiksscenario's. Systeem-API's kunnen een lijst met geïnstalleerde lettertypen produceren die niet willekeurig of gesorteerd is, maar in de volgorde van installatie. Het exact retourneren van de lijst met geïnstalleerde lettertypen zoals die door een dergelijke systeem-API wordt gegeven, kan extra gegevens blootleggen die gebruikt kunnen worden voor fingerprinting. Gebruiksscenario's die we willen ondersteunen, worden niet ondersteund door deze sortering. Daarom vereist deze API dat de geretourneerde gegevens gesorteerd zijn voordat ze worden teruggestuurd.
Beveiliging en machtigingen
Het Chrome-team heeft de Local Font Access API ontworpen en geïmplementeerd op basis van de kernprincipes die zijn vastgelegd in Controlling Access to Powerful Web Platform Features , waaronder gebruikerscontrole, transparantie en ergonomie.
Gebruikersbesturing
De gebruiker heeft volledige controle over zijn of haar lettertypen en krijgt alleen toegang als de machtiging "local-fonts" , zoals vermeld in het machtigingenregister , is verleend.
Transparantie
Of een site toegang heeft gekregen tot de lokale lettertypen van de gebruiker, is te zien in het site-informatieblad .
Persistentie van toestemming
De "local-fonts" -toestemming blijft behouden tussen paginaverversingen. Deze kan worden ingetrokken via het informatieblad van de site .
Feedback
Het Chrome-team wil graag meer horen over uw ervaringen met de Local Font Access API.
Vertel ons iets over het API-ontwerp.
Werkt er iets aan de API niet zoals je had verwacht? Of ontbreken er methoden of eigenschappen die je nodig hebt om je idee te implementeren? Heb je een vraag of opmerking over het beveiligingsmodel? Dien een specificatieprobleem in op de bijbehorende GitHub-repository , of voeg je gedachten toe aan een bestaand probleem.
Meld een probleem met de implementatie.
Heb je een bug gevonden in de implementatie van Chrome? Of wijkt de implementatie af van de specificatie? Meld een bug op new.crbug.com . Vermeld zoveel mogelijk details, eenvoudige instructies voor het reproduceren van het probleem en voer Blink>Storage>FontAccess in bij het veld Components .
Toon je steun voor de API
Ben je van plan de Local Font Access API te gebruiken? Jouw publieke steun helpt het Chrome-team bij het prioriteren van functies en laat andere browserleveranciers zien hoe belangrijk het is om deze te ondersteunen.
Stuur een tweet naar @ChromiumDev met de hashtag #LocalFontAccess en laat ons weten waar en hoe je het gebruikt.
Handige links
- Uitleg
- Conceptversie
- Chromium-bug met betrekking tot lettertype-enumeratie
- Chromium-bug voor toegang tot de lettertypetabel
- ChromeStatus-item
- GitHub-repository
- TAG-recensie
- Mozilla-standaardpositie
Dankbetuigingen
De specificatie van de Local Font Access API is bewerkt door Emil A. Eklund , Alex Russell , Joshua Bell en Olivier Yiptong . Dit artikel is beoordeeld door Joe Medley , Dominik Röttsches en Olivier Yiptong .