Aprender cómo la API de Local Font Access te permite acceder a las fuentes instaladas localmente por el usuario y obtener detalles de bajo nivel sobre ellas
Fuentes seguras para la Web
Si llevas suficiente tiempo haciendo desarrollo web, quizás recuerdes los llamados
fuentes seguras para la Web.
Se sabe que estas fuentes están disponibles en casi todas las instancias de los sistemas operativos más usados.
(es decir, Windows, macOS, las distribuciones más comunes de Linux, iOS y Android). A principios de los 2000,
Microsoft incluso encabezó una
iniciativa
llamadas fuentes principales TrueType para la Web, que ofrecían la descarga gratuita de estas fuentes con el
objetivo de que "cada vez que visites un sitio web que las especifique, verás páginas exactamente como las
del diseñador del sitio". Sí, esto incluyó sitios configurados en
Comic Sans MS. Este es un
la pila de fuentes seguras clásicas para la Web (con el resguardo definitivo de lo que sea
sans-serif
fuente) podría verse así:
body {
font-family: Helvetica, Arial, sans-serif;
}
Fuentes web
Los días en que las fuentes seguras para la Web eran realmente importantes han quedado en el pasado. Hoy tenemos
fuentes web, algunas de las cuales son
incluso fuentes variables que podemos modificar aún más cambiando los valores de la
varios ejes expuestos. Puedes usar fuentes web si declaras un
el bloque @font-face
al comienzo del CSS
que especifica los archivos de fuente que se descargarán:
@font-face {
font-family: 'FlamboyantSansSerif';
src: url('flamboyant.woff2');
}
Luego, puedes usar la fuente web personalizada especificando la
font-family
, como de costumbre:
body {
font-family: 'FlamboyantSansSerif';
}
Fuentes locales como vector de huellas digitales
La mayoría de las fuentes web provienen, bueno, de la Web. Sin embargo, un hecho interesante es que la
Propiedad src
en @font-face
de la declaración de clientes, además del
url()
esta función también acepta un
local()
. Esto permite que las fuentes personalizadas se carguen (sorpresa) de forma local. Si el usuario tiene
FlamboyantSansSerif instalado en su sistema operativo, se usará la copia local en lugar de
que se descarga:
@font-face {
font-family: 'FlamboyantSansSerif';
src: local('FlamboyantSansSerif'), url('flamboyant.woff2');
}
Este enfoque proporciona un buen mecanismo de resguardo que potencialmente ahorra ancho de banda. En Internet,
lamentablemente, no podemos tener cosas buenas. El problema con la función local()
es que puede
las huellas digitales del navegador. Resulta que la lista de fuentes que instaló un usuario
la identificación. Muchas empresas tienen sus propias fuentes corporativas que se instalan en las computadoras de los empleados.
laptops. Por ejemplo, Google tiene una fuente corporativa llamada Google Sans.
![La app de Font Book para macOS que muestra una vista previa de la fuente Google Sans.](https://developer.chrome.com/static/docs/capabilities/web-apis/local-fonts/image/the-macos-font-book-app-s-28dfca88ee8bd.png?authuser=19&hl=es)
Un atacante puede intentar determinar para qué empresa trabaja alguien probando la existencia de una una gran cantidad de fuentes corporativas conocidas, como Google Sans. El atacante intentaría renderizar texto colocar estas fuentes en un lienzo y medir los glifos. Si los glifos coinciden con la forma conocida de la fuente corporativa, el atacante tiene un golpe. Si los glifos no coinciden, el atacante sabrá que hay se usó la fuente de reemplazo predeterminada porque la fuente corporativa no estaba instalada. Para obtener todos los detalles este y otros ataques de huella digital del navegador, lee el informe de encuesta de Laperdix et al.
Se pueden separar fuentes empresariales, incluso solo la lista de fuentes instaladas. La situación con este vector de ataque se volvió tan malo que recientemente el equipo de WebKit decidido para "incluir solo [en la lista de fuentes disponibles] las fuentes web y las fuentes que vienen con el sistema del sistema, pero no de las fuentes instaladas por el usuario de forma local. (Y aquí estoy, con un artículo sobre cómo otorgar acceso a fuentes locales).
La API de Local Font Access
Es posible que el comienzo de este artículo te haya puesto de ánimo. ¿Es posible realmente no tener cosas? No te preocupes. Creemos que sí podemos, y quizás no todo es desesperado. Pero primero, permítanme responder una pregunta que podrían estar haciendo.
¿Por qué necesitamos la API de Local Font Access cuando hay fuentes web?
Las herramientas gráficas y de diseño de calidad profesional siempre han sido difíciles de entregar web. Un obstáculo fue la imposibilidad de acceder y utilizar toda la variedad de herramientas fuentes construidas y optimizadas que los diseñadores instalaron de forma local. Las fuentes web permiten algunas publicaciones casos de uso, pero que no permita el acceso programático a las tablas de fuentes y formas de glifos vectoriales que utiliza rasterizadores para renderizar los contornos del glifo. Tampoco hay forma de acceder al objeto binario de una fuente web de datos no estructurados.
- Las herramientas de diseño necesitan acceso a bytes de fuente para realizar su propia implementación de diseño de OpenType y permitir herramientas de diseño para conectarse en los niveles inferiores, para acciones como realizar filtros vectoriales o se transforman en las formas del glifo.
- Es posible que los desarrolladores tengan pilas de fuentes heredadas para sus aplicaciones que llevan a la Web. Para usar estas pilas, suelen requerir acceso directo a los datos de fuente, algo que las fuentes web no necesitan proporcionan.
- Es posible que algunas fuentes no tengan una licencia para su entrega a través de la Web. Por ejemplo, Linotype tiene una licencia para algunas fuentes que solo incluyen uso de escritorio
La API de Local Font Access sirve para resolver estos desafíos. Está compuesto por dos partes:
- Una API de enumeración de fuentes, que permite a los usuarios otorgar acceso al conjunto completo de sistemas disponibles fuentes.
- A partir de cada resultado de enumeración, la capacidad de solicitar un contenedor SFNT de bajo nivel (orientado a bytes) de las fuentes que incluya todos los datos de la fuente.
Navegadores compatibles
Cómo utilizar la API de Local Font Access
Detección de funciones
Para comprobar si la API de Local Font Access es compatible, utiliza lo siguiente:
if ('queryLocalFonts' in window) {
// The Local Font Access API is supported
}
Enumera las fuentes locales
Para obtener una lista de las fuentes instaladas de forma local, debes llamar a window.queryLocalFonts()
. El
primera vez, se activará una solicitud de permiso que el usuario puede aprobar o rechazar. Si el usuario
aprueba las fuentes locales que se consultarán, el navegador devolverá una matriz con los datos de las fuentes.
que puedes usar en bucle. Cada fuente se representa como un objeto FontData
con las propiedades family
.
(por ejemplo, "Comic Sans MS"
), fullName
(por ejemplo, "Comic Sans MS"
), postscriptName
(por ejemplo,
por ejemplo, "ComicSansMS"
) y style
(por ejemplo, "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);
}
Si solo te interesa un subconjunto de fuentes, también puedes filtrarlas en función del PostScript
nombres mediante la adición de un parámetro postscriptNames
.
const availableFonts = await window.queryLocalFonts({
postscriptNames: ['Verdana', 'Verdana-Bold', 'Verdana-Italic'],
});
Acceso a datos de SFNT
El acceso completo a SFNT está disponible a través del método blob()
de la
FontData
. SFNT es un formato de archivo de fuente que puede contener otras fuentes, como PostScript,
Fuentes: TrueType, OpenType, Web Open Font Format (WOFF), etcétera
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);
}
Demostración
Puedes ver la API de Local Font Access en acción en la
demo a continuación. Asegúrate de consultar también
código fuente. La demostración
muestra un elemento personalizado llamado <font-select>
que
implementa un selector de fuentes local.
Consideraciones de privacidad
El permiso "local-fonts"
parece proporcionar una superficie en la que se pueden extraer las huellas digitales. Sin embargo,
los navegadores tienen la libertad de mostrar lo que quieran. Por ejemplo, los navegadores centrados en el anonimato pueden elegir
para proporcionar solo un conjunto de fuentes predeterminadas integradas en el navegador. Del mismo modo, los navegadores no son obligatorios
para proporcionar los datos de la tabla exactamente como aparecen en el disco.
Siempre que sea posible, la API de Local Font Access se diseñó para mostrar solo la información con exactitud. necesarios para habilitar los casos de uso mencionados. Las APIs del sistema pueden generar una lista de fuentes instaladas que no están en una aleatorio o en un orden ordenado, pero en el orden de instalación de la fuente. Mostrar exactamente la lista de Las fuentes instaladas que brinda una API del sistema pueden exponer datos adicionales que pueden usarse para la creación de huellas digitales y los casos de uso que queremos habilitar no cuentan con la asistencia de retener este orden. Como como resultado, esta API requiere que los datos devueltos se ordenen antes de mostrarse.
Seguridad y permisos
El equipo de Chrome diseñó e implementó la API de Local Font Access con los principios fundamentales. se definen en Controla el acceso a las funciones potentes de la plataforma web, incluida la información la transparencia y la ergonomía.
Control de usuarios
El acceso a las fuentes de un usuario está completamente bajo su control y no se permitirá a menos que
"local-fonts"
, como se indica en la
permiso de registro.
Transparencia
Si un sitio tiene acceso a las fuentes locales del usuario, aparecerá en la sección hoja de información del sitio.
Persistencia de permisos
Se conservará el permiso "local-fonts"
entre las recargas de páginas. Se puede revocar mediante
información del sitio.
Comentarios
El equipo de Chrome quiere conocer tu experiencia con la API de Local Font Access.
Cuéntanos sobre el diseño de la API
¿Algo en la API no funciona como esperabas? ¿O faltan métodos o propiedades que necesitas para implementar tu idea? Haz una pregunta o comentario sobre la seguridad modelo? Informa un problema de especificaciones en el repositorio de GitHub correspondiente o agrega lo que piensas a un problema existente.
Informar un problema con la implementación
¿Encontraste un error en la implementación de Chrome? ¿O la implementación es diferente de la especificación?
Informa un error en new.crbug.com. Asegúrate de incluir tantos detalles como puedas
instrucciones simples de reproducción y, luego, ingresa Blink>Storage>FontAccess
en el cuadro Componentes.
Glitch funciona muy bien para compartir repros rápidos y fáciles.
Demuestra compatibilidad con la API
¿Piensas utilizar la API de Local Font Access? Tu asistencia pública ayuda al equipo de Chrome a prioriza funciones y muestra a otros proveedores de navegadores la importancia de admitirlas.
Envía un tweet a @ChromiumDev con el hashtag
#LocalFontAccess
y deja
para saber dónde y cómo lo utilizas.
Vínculos útiles
- Explicación
- Borrador de especificaciones
- Error de Chromium para la enumeración de fuentes
- Error de Chromium para acceder a la tabla de fuentes
- Entrada de ChromeStatus
- Repositorio de GitHub
- Revisión de TAG
- Posición de los estándares de Mozilla
Agradecimientos
La especificación de la API de Local Font Access fue editada por Emil A. Eklund, Alex Russell Joshua Bell y Olivier Yiptong. Este artículo fue revisado por Joe Medley: Dominik Röttsches y Olivier Yiptong. Hero image de Brett Jordan en Retiro: