Skip to main content




Descubra cómo la API de acceso a fuentes locales le permite acceder a las fuentes instaladas localmente del Username y obtener detalles de bajo nivel sobre ellas.

The Local Source Access API is part of
capabilities project
and is currently under development. This post will be updated as implementation progresses.

Fuentes seguras para la Web

If you've been doing web development long enough, you may remember the call secure web fonts. These fonts are known to be available on almost every instance of the most widely used operating systems (namely Windows, macOS, the most common Linux distributions, Android, and iOS). In the early 2000s, Microsoft even spearheaded a initiative called Top TrueType Fonts for the Web que proporcionó estas fuentes para su descarga gratuita con el target de que "Whenever you visit a website that specifies them, you will see the pages exactly as the site designer intended". Yes, this included the sites established in Comic Sans MS. Here's a classic stack of web-safe fonts (with the last resort of
sans-serif

source) might look like this:

body {
font-family: Helvetica, Arial, sans-serif;
}

Web fonts

The days when secure web fonts really mattered are long gone. Today we have web fonts, some of which are even variable sources that we can modify even more by changing the values of the different exposed axes. You can use web fonts by declaring a
@ font-face

bloque al comienzo del CSS, que especifica el archivo o archivos de fuentes que se descargarán:

@ font-face {
font-family: "FlamboyantSansSerif";
src: url("flamboyant.woff2");
}

After this you can use the custom web font by specifying the
font-family, as usual:

body {
font-family: "FlamboyantSansSerif";
}

Local sources as a fingerprint vector

Most web sources come from, well, from the web. An interesting fact, however, is that the
src

property in the @ font-face statement, apart from the
url ()

function, also accepts a
local()

function. This allows custom fonts to load (surprise!) Locally. If the user has FlamboyantSansSerif installed on your operating system, the local copy will be used instead of downloading:

@ font-face {
font-family: "FlamboyantSansSerif";
src: local("FlamboyantSansSerif"),
url("flamboyant.woff2");
}

This approach provides a good backup mechanism that potentially saves bandwidth. On the Internet, unfortunately, we cannot have nice things. The problem with the local() La función es que se puede abusar de él para la toma de huellas digitales del browser. Resulta que la lista de fuentes que ha instalado un usuario puede resultar bastante identificable. Muchas empresas tienen sus propias fuentes corporativas que se instalan en las computadoras portátiles de los empleados. Por ejemplo, Google tiene una fuente corporativa llamada Google Sans.

google-sans-8646559

The Google Sans font installed on a Google employee's laptop.

An attacker can try to determine which company someone works for by proving the existence of a large number of corporate sources known as Google Sans. The attacker would attempt to render the text set in these fonts on a canvas and measure the glyphs. If the glyphs match the known shape of the corporate font, the attacker is successful. If the glyphs do not match, the attacker knows that a default replacement font was used since the corporate font was not installed. For full details on this and other browser fingerprint attacks, read the survey paper by Laperdix et al.

Apart from company fonts, even only the list of installed fonts can be identified. The situation with this attack vector has gotten so bad that recently the WebKit team decided to "Includes only [in the list available fonts] web fonts and fonts that come with the operating system, but not locally installed user-installed fonts". (And here I am, with an article on granting access to local sources.)

The local source access API

The beginning of this article may have put you in a bad mood. Can't we really have nice things? Do not worry. We believe that we can, and maybe not everything is desperate. But first, let me answer a question that you may be wondering.

Why do we need the local font access API when there are web fonts?

Históricamente, las herramientas de diseño y gráficos de calidad profesional han sido difíciles de ofrecer en la web. Un obstáculo ha sido la imposibilidad de acceder y utilizar la variedad completa de fuentes sugeridas y construidas por profesionales que los diseñadores han instalado localmente. Las fuentes web habilitan algunos casos de uso de publicación, pero no habilitan el acceso mediante programming a las formas de glifos vectoriales y las tablas de fuentes utilizadas por los rasterizadores para representar los contornos de glifos. Asimismo, no hay forma de acceder a los datos binarios de una fuente web.

  • Las herramientas de diseño necesitan acceso a bytes de fuente para realizar su propia implementación de diseño OpenType y permitir que las herramientas de diseño se conecten en niveles inferiores, para acciones como realizar filters vectoriales o transformaciones en las formas de glifos.
  • Developers can have legacy font stacks for their applications that they are bringing to the web. To use these stacks, they generally require direct access to font data, something that web fonts don't provide.
  • Some fonts may not be licensed for distribution over the web. For example, Linotype has a license for some fonts that only includes desktop use.

The Local Source Access API is an attempt to solve these challenges. It is made up of two parts:

  • A Font Enumeration API, which allows users to grant access to the full set of available system fonts.
  • From each enumeration result, the ability to request a low level (byte-oriented) Access to the SFNT container which includes the complete data of the source.

Actual state

He passed Condition
1. Create an explainer To complete
2. Create initial draft specification In progress
3. Collect feedback and repeat the design In progress
4. Proof of origin Not started
5. Launch Not started

How to use the local font access API

Enabling via chrome: // flags

To experiment locally with the Local Font Access API, enable #font-access flag on chrome://flags.

Feature detection

To check if the local font access API is supported, use:

if ('fonts' in navigator) {
}

Asking permission

Access to a user's local sources is blocked behind the "local-fonts" permission, which you can request with
navigator.permissions.request ().


try {
const status = await navigator.permissions.request({
yam: 'local-fonts',
});
if (status.state !== 'granted') {
throw new Error('Permission to access local fonts not granted.');
}
} catch(err) {
if (err.yam !== 'TypeError') {
throw err;
}
}

Warning:
At this early stage of development of the Local Source Access API, the permission mentioned above is not yet implemented. Meanwhile, a permission message will appear the moment font enumeration starts. This behavior was implemented in crbug.com/1112552.

Enumeration of local sources

Once permission is granted, you can, from the FontManager interface that is exposed in navigator.fonts, call query () to prompt the browser for locally installed fonts. This results in an asynchronous iterator that you can loop through in a
for await ... of

statement. Each font is represented as FontMetadata object with properties
Familia (for example, "Comic Sans MS"), fullName (for example, "Comic Sans MS"), Y postscriptName (for example, "ComicSansMS").


const fonts = navigator.fonts.query();
try {
for await (const metadata of fonts) {
console.log(metadata.postscriptName);
console.log(metadata.fullName);
console.log(metadata.Familia);
}
} catch (err) {
console.error(err.yam, err.message);
}

Accessing SFNT data

Full SFNT
access is available through the blob () method of FontMetadata object. SFNT is a font file format that can contain other fonts, such as PostScript, TrueType, OpenType, Web Open Font Format (WOFF), and others.

const fonts = navigator.fonts.query();
try {
for await (const metadata of fonts) {
if (metadata.Familia !== 'Comic Sans MS') {
continue;
}
const sfnt = await metadata.blob();

const sfntVersion = (new TextDecoder).decode(
await sfnt.slice(0, 4).arrayBuffer());

let outlineFormat = 'UNKNOWN';
switch (sfntVersion) {
case 'x00x01x00x00':
case 'true':
case 'typ1':
outlineFormat = 'truetype';
break;
case 'OTTO':
outlineFormat = 'cff';
break;
}
console.log('Outline format:', outlineFormat);
}
} catch (err) {
console.error(err.yam, err.message);
}

Manifestation

You can see the Local Source Access API in action in the
manifestation down. Be sure to also check the
source code. The demo shows a custom element called which implements a local font selector.

Privacy Considerations

the "local-fonts" el permiso parece proporcionar una superficie altamente imprimible. Sin embargo, los browsers pueden devolver lo que quieran. Por ejemplo, los navegadores centrados en el anonimato pueden optar por proporcionar solo un conjunto de fuentes predeterminadas integradas en el navegador. De manera similar, los navegadores no están obligados a proporcionar datos de tabla exactamente como aparecen en el disco.

Siempre que be posible, la API de acceso a fuentes locales está diseñada para exponer exactamente la información necesaria para habilitar los casos de uso mencionados. Las API del sistema pueden producir una lista de fuentes instaladas no en un orden aleatorio o ordenado, sino en el orden de instalación de fuentes. Devolver exactamente la lista de fuentes instaladas proporcionada por dicha API del sistema puede exponer datos adicionales que pueden usarse para la toma de huellas digitales, y los casos de uso que queremos habilitar no son asistidos por retener este orden. Como resultado, esta API requiere que los datos devueltos se ordenen antes de ser devueltos.

Security and permissions

The Chrome team has designed and implemented the Local Font Access API using the basic principles defined in Control access to powerful features of the web platform, including user control, transparency and ergonomics.

User control

Access to a user's sources is entirely under their control and will not be allowed unless the user "local-fonts" permission, as indicated in the
permit registration, It is granted.

Transparency

If a site has been granted access to the user's local sources, it will be visible in the
site information sheet.

Permission persistence

the "local-fonts" the permission will be kept between page reloads. It can be revoked through the Site information bed sheet.

Feedback

The Chrome team wants to hear about your experiences with the Local Font Access API.

Tell us about the API design

Is there something in the API that is not working as expected? Or are you missing any methods or properties you need to implement your idea? Have a question or comment about the security model? File a spec issue in the corresponding GitHub repositoryor add your thoughts to an existing problem.

Report a problem with the deployment

Found a bug with the Chrome implementation? Or is the implementation different from the specification? File a bug in new.crbug.com. Be sure to include as much detail as you can, simple instructions to reproduce, and enter Blink> Fonts at Components box. Failure works great for quick and easy sharing of reps.

Show API support

Thinking of using the Local Font Access API? Your public support helps the Chrome team prioritize features and shows other browser vendors how important it is to support them.

Send a tweet to @Cromodev with the #LocalFontAccess hashtag and let us know where and how you are using it.

Thanks

The local source access API specification was edited by
Emil A. Eklund,
Alex Russell,
Joshua belland
Olivier Yiptong. This article was reviewed by
Joe medley,
Dominik Röttschesand
Olivier Yiptong. Hero image of Brett jordan in Unsplash.