Skip to main content

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

La API de acceso a fuentes locales es parte de
proyecto de capacidades
y actualmente está en desarrollo. Esta publicación se actualizará a medida que avance la implementación.

Fuentes seguras para la web

Si ha estado haciendo desarrollo web el tiempo suficiente, puede recordar el llamado fuentes web seguras. Se sabe que estas fuentes están disponibles en casi todas las instancias de los sistemas operativos más utilizados (a saber, Windows, macOS, las distribuciones de Linux más comunes, Android e iOS). A principios de la década de 2000, Microsoft incluso encabezó un iniciativa llamado Fuentes principales TrueType para la Web que proporcionó estas fuentes para su descarga gratuita con el objetivo de que «siempre que visite un sitio web que los especifique, verá las páginas exactamente como las concibió el diseñador del sitio». Sí, esto incluyó los sitios establecidos en Comic Sans MS. Aquí hay una pila clásica de fuentes seguras para la web (con el último recurso de
sans-serif

fuente) podría verse así:

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

Fuentes web

Los días en los que las fuentes web seguras realmente importaban han quedado atrás. Hoy tenemos fuentes web, algunas de las cuales son incluso fuentes variables que podemos modificar aún más cambiando los valores de los distintos ejes expuestos. Puede utilizar fuentes web declarando un
@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");
}

Después de esto, puede usar la fuente web personalizada especificando el
font-family, como normal:

body {
font-family: "FlamboyantSansSerif";
}

Fuentes locales como vector de huella digital

La mayoría de las fuentes web provienen, bueno, de la web. Un hecho interesante, sin embargo, es que el
src

propiedad en el @font-face declaración, aparte de la
url()

función, también acepta una
local()

función. Esto permite que las fuentes personalizadas se carguen (¡sorpresa!) Localmente. Si el usuario tiene FlamboyantSansSerif instalado en su sistema operativo, se utilizará la copia local en lugar de descargarla:

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

Este enfoque proporciona un buen mecanismo de respaldo que potencialmente ahorra ancho de banda. En Internet, lamentablemente, no podemos tener cosas bonitas. El problema con el local() La función es que se puede abusar de él para la toma de huellas digitales del navegador. 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

La fuente Google Sans instalada en la computadora portátil de un empleado de Google.

Un atacante puede intentar determinar para qué empresa trabaja alguien probando la existencia de una gran cantidad de fuentes corporativas conocidas como Google Sans. El atacante intentaría representar el texto establecido en estas fuentes en un lienzo y medir los glifos. Si los glifos coinciden con la forma conocida de la fuente corporativa, el atacante tiene éxito. Si los glifos no coinciden, el atacante sabe que se utilizó una fuente de reemplazo predeterminada ya que la fuente corporativa no se instaló. Para obtener detalles completos sobre este y otros ataques de huellas dactilares del navegador, lea el papel de encuesta por Laperdix et al.

Aparte de las fuentes de la empresa, incluso solo la lista de fuentes instaladas puede identificarse. La situación con este vector de ataque se ha vuelto tan mala que recientemente el equipo de WebKit decidido a «solo incluye [in the list available fonts] fuentes web y fuentes que vienen con el sistema operativo, pero no fuentes instaladas por el usuario localmente «. (Y aquí estoy, con un artículo sobre cómo otorgar acceso a fuentes locales).

La API de acceso a fuentes locales

Es posible que el comienzo de este artículo te haya puesto de mal humor. ¿Realmente no podemos tener cosas bonitas? No temas. Creemos que podemos, y tal vez no todo es desesperado. Pero primero, déjame responder una pregunta que quizás te estés preguntando.

¿Por qué necesitamos la API de acceso a fuentes locales cuando hay fuentes web?

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 programación 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 filtros vectoriales o transformaciones en las formas de glifos.
  • Los desarrolladores pueden tener pilas de fuentes heredadas para sus aplicaciones que están trayendo a la web. Para usar estas pilas, generalmente requieren acceso directo a los datos de fuentes, algo que las fuentes web no proporcionan.
  • Es posible que algunas fuentes no tengan licencia para su distribución a través de la web. Por ejemplo, Linotype tiene una licencia para algunas fuentes que solo incluye uso de escritorio.

La API de acceso a fuentes locales es un intento de resolver estos desafíos. Está formado por dos partes:

  • UNA API de enumeración de fuentes, que permite a los usuarios otorgar acceso al conjunto completo de fuentes del sistema disponibles.
  • A partir de cada resultado de enumeración, la capacidad de solicitar un nivel bajo (orientado a bytes) Acceso al contenedor SFNT que incluye los datos completos de la fuente.

Estado actual

Paso Estado
1. Crea un explicador Completar
2. Crear borrador inicial de especificación En progreso
3. Recopile comentarios y repita el diseño En progreso
4. Prueba de origen No empezado
5. Lanzamiento No empezado

Cómo utilizar la API de acceso a fuentes locales

Habilitación a través de chrome: // flags

Para experimentar localmente con la API de acceso a fuentes locales, habilite #font-access bandera en chrome://flags.

Detección de características

Para comprobar si la API de acceso a fuentes locales es compatible, utilice:

if ('fonts' in navigator) {
}

Pidiendo permiso

El acceso a las fuentes locales de un usuario se bloquea detrás del "local-fonts" permiso, que puede solicitar con
navigator.permissions.request().


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

Advertencia:
En esta fase inicial de desarrollo de la API de acceso a fuentes locales, el permiso mencionado anteriormente aún no está implementado. Mientras tanto, aparecerá un mensaje de permiso en el momento en que comience la enumeración de fuentes. Este comportamiento se implementó en crbug.com/1112552.

Enumeración de fuentes locales

Una vez concedido el permiso, puede, desde el FontManager interfaz que se expone en navigator.fonts, llamada query() para solicitar al navegador las fuentes instaladas localmente. Esto da como resultado un iterador asincrónico que puede recorrer en un
for await...of

declaración. Cada fuente se representa como FontMetadata objeto con las propiedades
family (por ejemplo, "Comic Sans MS"), fullName (por ejemplo, "Comic Sans MS"), y postscriptName (por ejemplo, "ComicSansMS").


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

Accediendo a datos SFNT

Completo SFNT
el acceso está disponible a través del blob() método del FontMetadata objeto. SFNT es un formato de archivo de fuente que puede contener otras fuentes, como fuentes PostScript, TrueType, OpenType, Web Open Font Format (WOFF) y otras.

const fonts = navigator.fonts.query();
try {
for await (const metadata of fonts) {
if (metadata.family !== '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.name, err.message);
}

Manifestación

Puede ver la API de acceso a fuentes locales en acción en el
manifestación abajo. Asegúrese de consultar también el
código fuente. La demostración muestra un elemento personalizado llamado <font-select> que implementa un selector de fuentes local.

Consideraciones de privacidad

los "local-fonts" el permiso parece proporcionar una superficie altamente imprimible. Sin embargo, los navegadores 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 sea 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.

Seguridad y permisos

El equipo de Chrome ha diseñado e implementado la API de acceso a fuentes locales utilizando los principios básicos definidos en Controlar el acceso a las potentes funciones de la plataforma web, incluido el control del usuario, la transparencia y la ergonomía.

Control de usuario

El acceso a las fuentes de un usuario está totalmente bajo su control y no se permitirá a menos que el "local-fonts" permiso, como se indica en el
registro de permisos, se concede.

Transparencia

Si a un sitio se le ha otorgado acceso a las fuentes locales del usuario, será visible en el
hoja de información del sitio.

Persistencia de permisos

los "local-fonts" el permiso se mantendrá entre recargas de página. Se puede revocar a través del Información del sitio sábana.

Realimentación

El equipo de Chrome desea conocer sus experiencias con la API de acceso a fuentes locales.

Cuéntanos sobre el diseño de la API

¿Hay algo en la API que no funciona como esperaba? ¿O faltan métodos o propiedades que necesita para implementar su idea? ¿Tiene alguna pregunta o comentario sobre el modelo de seguridad? Presentar un problema de especificaciones en el correspondiente Repositorio de GitHubo agregue sus pensamientos a un problema existente.

Informar un problema con la implementación

¿Encontraste un error con la implementación de Chrome? ¿O la implementación es diferente de la especificación? Presentar un error en new.crbug.com. Asegúrese de incluir todos los detalles que pueda, instrucciones simples para reproducir e ingrese Blink>Fonts en el Componentes caja. Falla funciona muy bien para compartir repros rápidos y fáciles.

Mostrar apoyo a la API

¿Está pensando en utilizar la API de acceso a fuentes locales? Su soporte público ayuda al equipo de Chrome a priorizar funciones y muestra a otros proveedores de navegadores lo importante que es brindarles soporte.

Enviar un tweet a @Cromodev con el #LocalFontAccess hashtag y háganos saber dónde y cómo lo está usando.

Agradecimientos

La especificación de la API de acceso a fuentes locales fue editada por
Emil A. Eklund,
Alex Russell,
Joshua Belly
Olivier Yiptong. Este artículo fue revisado por
Joe Medley,
Dominik Röttschesy
Olivier Yiptong. Imagen de héroe de Brett Jordan en Unsplash.