Pelajari cara Local Font Access API memungkinkan Anda mengakses font yang diinstal secara lokal milik pengguna dan mendapatkan detail tingkat rendah tentang font tersebut
Font yang aman untuk web
Jika Anda telah melakukan pengembangan web cukup lama, Anda mungkin ingat apa yang disebut
font yang aman untuk web.
{i>Font<i} ini diketahui tersedia di hampir semua {i>instance<i} pada sistem operasi yang paling sering digunakan
(yaitu Windows, macOS, distribusi Linux yang paling umum, Android, dan iOS). Pada awal 2000-an,
Microsoft bahkan memelopori
inisiatif
yang disebut font inti TrueType untuk Web yang menyediakan font ini secara gratis dengan
tujuan yang "setiap kali Anda mengunjungi situs Web yang menetapkannya, Anda akan melihat laman persis dengan
yang ditujukan oleh desainer situs". Ya, ini termasuk situs yang disetel di
Comic Sans MS. Berikut adalah
tumpukan font klasik yang aman untuk web (dengan penggantian akhir dari
sans-serif
) mungkin terlihat seperti ini:
body {
font-family: Helvetica, Arial, sans-serif;
}
Font web
Hari-hari di mana {i>font<i} yang aman untuk web menjadi sangat penting sudah lama berlalu. Hari ini, tersedia
font web, beberapa di antaranya adalah
bahkan font variabel yang dapat kita ubah lebih lanjut dengan mengubah nilai untuk
berbagai sumbu yang terbuka. Anda dapat menggunakan {i>font<i} web dengan mendeklarasikan
Blok @font-face
di awal CSS,
yang menentukan file font yang akan didownload:
@font-face {
font-family: 'FlamboyantSansSerif';
src: url('flamboyant.woff2');
}
Setelah ini, Anda kemudian dapat menggunakan {i>font<i} web khusus dengan menentukan
font-family
, seperti biasa:
body {
font-family: 'FlamboyantSansSerif';
}
Font lokal sebagai vektor sidik jari
Kebanyakan {i>font<i} web berasal dari web. Namun, fakta yang menarik adalah
Properti src
di @font-face
deklarasi, selain
url()
, juga menerima
local()
. Hal ini memungkinkan font kustom dimuat (secara tiba-tiba) secara lokal. Jika pengguna memiliki
FlamboyantSansSerif yang diinstal di sistem operasi mereka, salinan lokal akan digunakan, bukan
yang sedang diunduh:
@font-face {
font-family: 'FlamboyantSansSerif';
src: local('FlamboyantSansSerif'), url('flamboyant.woff2');
}
Pendekatan ini memberikan mekanisme fallback yang bagus yang berpotensi menghemat bandwidth. Di Internet,
sayangnya, kita tidak bisa memiliki
hal-hal baik. Masalah dengan fungsi local()
adalah
disalahgunakan untuk pelacakan sidik jari browser. Ternyata, daftar {i>font<i} yang telah
diinstal oleh pengguna bisa
identitas. Banyak perusahaan memiliki {i>font<i} perusahaan mereka sendiri yang dipasang pada
laptop. Misalnya, Google memiliki font perusahaan yang disebut Google Sans.
Penyerang dapat mencoba menentukan perusahaan tempat seseorang bekerja dengan menguji keberadaan sejumlah besar font perusahaan yang dikenal, seperti Google Sans. Penyerang akan mencoba merender teks menetapkan font ini pada kanvas dan mengukur glyph. Jika glyph sesuai dengan bentuk elemen {i>font<i} perusahaan, penyerang telah mendapatkan serangan. Jika glyph tidak cocok, penyerang tahu bahwa {i>font<i} pengganti {i>default<i} digunakan karena {i>font<i} perusahaan tidak diinstal. Untuk detail selengkapnya tentang serangan ini dan serangan sidik jari browser lainnya, baca makalah survei oleh Laperdix dk.
Font perusahaan terpisah, bahkan hanya daftar font yang terinstal dapat mengidentifikasi. Situasi dengan vektor serangan ini telah menjadi begitu buruk sehingga baru-baru ini tim WebKit memutuskan menjadi "hanya sertakan [dalam daftar font yang tersedia] font dan font web yang disertakan dengan sistem, tetapi bukan font yang diinstal pengguna secara lokal". (Inilah artikel tentang cara memberikan akses ke font lokal.)
Local Font Access API
Bagian awal artikel ini mungkin membuat Anda dalam suasana hati negatif. Dapatkah kita benar-benar tidak memiliki banyak hal? Jangan khawatir. Kita pikir kita bisa, dan mungkin tidak ada harapan. Tapi sebelumnya, saya akan menjawab pertanyaan yang mungkin Anda tanyakan pada diri sendiri.
Mengapa kita memerlukan Local Font Access API padahal ada font web?
Alat desain dan grafis berkualitas profesional secara historis sulit untuk diberikan web. Salah satu hambatan adalah ketidakmampuan untuk mengakses dan menggunakan beragam keterampilan yang dibuat dan diberi petunjuk yang telah diinstal secara lokal oleh desainer. Dengan font web, publikasi mungkin dilakukan kasus penggunaan, tetapi gagal mengaktifkan akses terprogram ke bentuk glyph vektor dan tabel font yang digunakan oleh rasterizer untuk merender garis batas glyph. Demikian juga tidak ada cara untuk mengakses biner {i>font<i} web layanan otomatis dan data skalabel.
- Alat desain membutuhkan akses ke byte font untuk melakukan implementasi tata letak OpenType mereka sendiri dan memungkinkan alat desain untuk memikat pada tingkat yang lebih rendah, untuk tindakan seperti melakukan filter vektor atau bertransformasi pada bentuk glyph.
- Developer mungkin memiliki stack font lama untuk aplikasi yang mereka bawa ke web. Untuk menggunakan tumpukan ini, mereka biasanya memerlukan akses langsung ke data {i>font<i}, sesuatu yang tidak sediakan.
- Beberapa font mungkin tidak dilisensikan untuk dikirim melalui web. Misalnya, Linotype memiliki lisensi untuk beberapa font yang hanya mencakup penggunaan di desktop.
Local Font Access API merupakan upaya untuk memecahkan masalah ini. Ini terdiri dari dua bagian:
- API enumerasi font, yang memungkinkan pengguna memberikan akses ke kumpulan lengkap sistem yang tersedia font.
- Dari setiap hasil enumerasi, kemampuan untuk meminta container SFNT level rendah (berorientasi byte) akses yang mencakup data font lengkap.
Dukungan browser
Cara menggunakan Local Font Access API
Deteksi fitur
Untuk memeriksa apakah Local Font Access API didukung, gunakan:
if ('queryLocalFonts' in window) {
// The Local Font Access API is supported
}
Menghitung font lokal
Untuk mendapatkan daftar font yang diinstal secara lokal, Anda perlu memanggil window.queryLocalFonts()
. Tujuan
pertama kali, hal ini akan memicu dialog izin, yang dapat disetujui atau ditolak oleh pengguna. Jika pengguna
menyetujui {i>font<i} lokal yang akan dikueri, browser akan mengembalikan larik dengan data {i>font<i}
yang dapat Anda ulangi. Setiap font direpresentasikan sebagai objek FontData
dengan properti family
(misalnya, "Comic Sans MS"
), fullName
(misalnya, "Comic Sans MS"
), postscriptName
(untuk
misalnya, "ComicSansMS"
), dan style
(misalnya, "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);
}
Jika Anda hanya tertarik pada sebagian font, Anda juga dapat memfilternya berdasarkan PostScript
dengan menambahkan parameter postscriptNames
.
const availableFonts = await window.queryLocalFonts({
postscriptNames: ['Verdana', 'Verdana-Bold', 'Verdana-Italic'],
});
Mengakses data SFNT
Akses SFNT penuh tersedia melalui metode blob()
Objek FontData
. SFNT adalah format file {i>font<i} yang dapat
berisi {i>font<i} lain, seperti PostScript,
Font TrueType, OpenType, Web Open Font Format (WOFF), dan lainnya.
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
Anda dapat melihat Local Font Access API beraksi di
demo di bawah. Pastikan juga untuk memeriksa
kode sumber. Demo
menampilkan elemen kustom bernama <font-select>
yang
mengimplementasikan pemilih font lokal.
Pertimbangan privasi
Izin "local-fonts"
tampaknya memberikan platform yang sangat mudah digunakan dengan sidik jari. Namun,
browser bebas untuk mengembalikan apa pun yang mereka inginkan. Misalnya, {i>browser<i} yang berfokus
pada anonimitas dapat memilih
hanya menyediakan serangkaian {i>font<i} {i>default<i} yang terpasang pada browser. Demikian pula, browser tidak diperlukan
untuk memberikan data tabel persis
seperti yang muncul di {i>disk<i}.
Jika memungkinkan, Local Font Access API dirancang untuk hanya mengekspos informasi yang diperlukan untuk memungkinkan kasus penggunaan yang disebutkan. API Sistem dapat menghasilkan daftar font terinstal yang tidak ada dalam acak atau dengan urutan yang diurutkan, tetapi dalam urutan instalasi {i>font<i}. Mengembalikan dengan tepat daftar font terinstal yang diberikan oleh API sistem semacam itu dapat mengekspos data tambahan yang dapat digunakan untuk pelacakan sidik jari, dan kasus penggunaan yang ingin kita aktifkan tidak dibantu dengan mempertahankan pengurutan ini. Sebagai seorang , API ini mengharuskan data yang ditampilkan diurutkan sebelum ditampilkan.
Keamanan dan izin
Tim Chrome telah merancang dan menerapkan Local Font Access API menggunakan prinsip inti didefinisikan dalam Mengontrol Akses ke Fitur Platform Web yang Canggih, termasuk informasi kontrol, transparansi, dan ergonomi.
Kontrol pengguna
Akses ke font pengguna sepenuhnya di bawah kendali mereka dan tidak akan diizinkan kecuali jika
"local-fonts"
, seperti yang tercantum dalam
registry izin, diberikan.
Transparansi
Apakah situs telah diberi akses ke {i>font<i} lokal pengguna akan terlihat di lembar informasi situs.
Persistensi izin
Izin "local-fonts"
akan dipertahankan di antara pemuatan ulang halaman. Lisensi dapat dicabut melalui
site information.
Masukan
Tim Chrome ingin mengetahui pengalaman Anda saat menggunakan Local Font Access API.
Beri tahu kami tentang desain API
Apakah ada sesuatu terkait API yang tidak berfungsi seperti yang Anda harapkan? Atau apakah ada metode yang hilang yang dibutuhkan untuk menerapkan ide Anda? Memiliki pertanyaan atau komentar tentang keamanan model? Ajukan masalah spesifikasi di repo GitHub yang sesuai, atau tambahkan pendapat Anda ke masalah yang ada.
Laporkan masalah terkait penerapan
Apakah Anda menemukan bug pada implementasi Chrome? Atau apakah implementasinya berbeda dengan spesifikasi?
Laporkan bug di new.crbug.com. Pastikan untuk menyertakan detail sebanyak mungkin,
instruksi sederhana untuk mereproduksi, dan masukkan Blink>Storage>FontAccess
dalam kotak Components.
Glitch sangat cocok untuk membagikan repro dengan cepat dan mudah.
Menunjukkan dukungan untuk API
Anda berencana menggunakan Local Font Access API? Dukungan publik Anda membantu tim Chrome untuk memprioritaskan fitur dan menunjukkan kepada vendor browser lain betapa pentingnya mendukung mereka.
Kirim tweet ke @ChromiumDev menggunakan hashtag
#LocalFontAccess
dan biarkan
kami tahu di mana dan bagaimana
Anda menggunakannya.
Link bermanfaat
- Penjelasan
- Draf spesifikasi
- Bug Chromium untuk enumerasi font
- Bug Chromium untuk akses tabel font
- Entri ChromeStatus
- Repositori GitHub
- Peninjauan TAG
- Posisi standar Mozilla
Ucapan terima kasih
Spesifikasi Local Font Access API diedit oleh Emil A. Eklund, Alex Russell Joshua Bell, dan Olivier Yiptong. Artikel ini telah ditinjau oleh Joe Medley, Dominik Röttsches, dan Olivier Yiptong. Banner besar oleh Brett Jordan di Buka pembuka.