Pelajari cara Local Font Access API memungkinkan Anda mengakses font yang diinstal secara lokal milik pengguna dan mendapatkan detail mendetail 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.
Font ini diketahui tersedia di hampir semua instance sistem operasi yang paling banyak digunakan
(yaitu Windows, macOS, distribusi Linux yang paling umum, Android, dan iOS). Pada awal 2000-an, Microsoft bahkan memelopori inisiatif yang disebut TrueType core font for the Web yang menyediakan font ini untuk didownload gratis dengan tujuan "setiap kali Anda mengunjungi situs Web yang menentukannya, Anda akan melihat halaman persis seperti yang diinginkan desainer situs". Ya, situs yang disertakan ini ditetapkan dalam
Comic Sans MS. Berikut adalah
tumpukan font klasik yang aman untuk web (dengan penggantian akhir font
sans-serif
apa pun) mungkin terlihat seperti ini:
body {
font-family: Helvetica, Arial, sans-serif;
}
Font web
Masa-masa ketika font yang aman di web kini menjadi sangat penting, sudah tidak ada lagi. Saat ini, kita memiliki
font web, beberapa di antaranya
bahkan merupakan font variabel yang dapat kita sesuaikan lebih lanjut dengan mengubah nilai
berbagai sumbu yang diekspos. Anda dapat menggunakan font 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');
}
Setelahnya, Anda kemudian dapat menggunakan font web kustom dengan menentukan
font-family
, seperti biasa:
body {
font-family: 'FlamboyantSansSerif';
}
Font lokal sebagai vektor sidik jari
Sebagian besar {i>font<i} web berasal dari web. Namun, fakta yang menarik adalah bahwa properti
src
di deklarasi @font-face
,
selain fungsi
url()
,
juga menerima fungsi
local()
. Hal ini memungkinkan font kustom dimuat (mengejutkan!) secara lokal. Jika pengguna menginstal
FlamboyantSansSerif pada sistem operasinya, salinan lokal yang akan digunakan, bukan
didownload:
@font-face {
font-family: 'FlamboyantSansSerif';
src: local('FlamboyantSansSerif'), url('flamboyant.woff2');
}
Pendekatan ini memberikan mekanisme penggantian yang baik yang berpotensi menghemat bandwidth. Di Internet, sayangnya, kita tidak dapat memperoleh hal-hal yang menyenangkan. Masalah pada fungsi local()
adalah fungsi tersebut dapat disalahgunakan untuk pelacakan sidik jari browser. Ternyata, daftar {i>font<i} yang telah dipasang pengguna
bisa sangat mudah diidentifikasi. Banyak perusahaan memiliki font perusahaan sendiri yang diinstal di laptop
karyawan. Misalnya, Google memiliki font perusahaan yang disebut Google Sans.
![Aplikasi Font Book macOS menampilkan pratinjau font Google Sans.](https://developer.chrome.google.cn/static/docs/capabilities/web-apis/local-fonts/image/the-macos-font-book-app-s-28dfca88ee8bd.png?authuser=19&hl=id)
Penyerang dapat mencoba menentukan perusahaan tempat seseorang bekerja dengan menguji keberadaan font perusahaan dalam jumlah besar seperti Google Sans. Penyerang akan mencoba merender teks yang ditetapkan dalam font ini di kanvas dan mengukur glyph. Jika glyph cocok dengan bentuk font perusahaan yang diketahui, penyerang akan mendapatkan hit. Jika glyph tidak cocok, penyerang akan tahu bahwa font pengganti default digunakan karena font perusahaan tidak diinstal. Untuk detail selengkapnya tentang serangan ini dan serangan sidik jari browser lainnya, baca makalah survei oleh Laperdix et al.
Font perusahaan terpisah, bahkan hanya daftar font yang terinstal yang dapat diidentifikasi. Situasi dengan vektor serangan ini menjadi sangat buruk sehingga baru-baru ini tim WebKit memutuskan untuk "hanya menyertakan [dalam daftar font yang tersedia] font dan font web yang disertakan dalam sistem operasi, tetapi bukan font yang diinstal pengguna secara lokal". (Di sinilah saya, dengan artikel tentang pemberian akses ke {i>font<i} lokal.)
Local Font Access API
Bagian awal artikel ini mungkin pernah membuat Anda dalam suasana hati negatif. Bisakah kita benar-benar tidak memiliki hal-hal yang baik? Jangan khawatir. Kami pikir kami bisa, dan mungkin segala sesuatu tidak akan ada harapan. Tapi pertama-tama, izinkan saya menjawab pertanyaan yang mungkin Anda tanyakan kepada diri sendiri.
Mengapa kita memerlukan Local Font Access API jika ada font web?
Alat desain dan grafis berkualitas profesional secara historis sulit untuk disajikan di web. Salah satu hambatannya adalah ketidakmampuan untuk mengakses dan menggunakan berbagai font yang dibuat secara profesional dan petunjuk yang telah diinstal desainer secara lokal. Font web memungkinkan beberapa kasus penggunaan publikasi, tetapi gagal mengaktifkan akses terprogram ke bentuk glyph vektor dan tabel font yang digunakan oleh rasterizer untuk merender garis glyph. Selain itu, tidak ada cara untuk mengakses data biner font web.
- Alat desain memerlukan akses ke byte font untuk melakukan implementasi tata letak OpenType-nya sendiri dan memungkinkan alat desain terhubung pada tingkat yang lebih rendah, untuk tindakan seperti menjalankan filter vektor atau transformasi pada bentuk glyph.
- Developer mungkin memiliki stack font lama untuk aplikasi mereka yang mereka bawa ke web. Untuk menggunakan stack ini, stack biasanya memerlukan akses langsung ke data font, yang tidak disediakan oleh font web.
- Beberapa font mungkin tidak dilisensikan untuk dikirimkan melalui web. Misalnya, Linotype memiliki lisensi untuk beberapa font yang hanya menyertakan penggunaan desktop.
Local Font Access API adalah upaya untuk mengatasi tantangan ini. Terdiri dari dua bagian:
- API enumerasi font, yang memungkinkan pengguna memberikan akses ke kumpulan lengkap font sistem yang tersedia.
- Dari setiap hasil enumerasi, kemampuan untuk meminta akses penampung SFNT tingkat rendah (berorientasi byte) yang menyertakan 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 harus memanggil window.queryLocalFonts()
. Pertama kali, tindakan ini akan memicu dialog izin, yang dapat disetujui atau ditolak pengguna. Jika pengguna
menyetujui font lokal untuk dikueri, browser akan menampilkan array dengan data font
yang dapat Anda loop. Setiap font direpresentasikan sebagai objek FontData
dengan properti family
(misalnya, "Comic Sans MS"
), fullName
(misalnya, "Comic Sans MS"
), postscriptName
(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 hanya ingin melihat sebagian font, Anda juga dapat memfilternya berdasarkan nama 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()
dari objek FontData
. SFNT adalah format file font yang dapat berisi font lain, seperti font PostScript,
TrueType, OpenType, font 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 cara kerja Local Font Access API dalam demo di bawah. Pastikan Anda juga melihat
kode sumber. Demo ini menampilkan elemen kustom yang disebut <font-select>
yang menerapkan pemilih font lokal.
Pertimbangan privasi
Izin "local-fonts"
tampaknya memberikan permukaan yang sangat mudah digunakan dengan sidik jari. Namun,
browser bebas menampilkan apa pun yang mereka inginkan. Misalnya, browser yang berfokus pada anonimitas dapat memilih
untuk hanya menyediakan kumpulan font default yang disertakan dalam browser. Demikian pula, browser tidak perlu memberikan
data tabel persis seperti yang muncul di disk.
Jika memungkinkan, Local Font Access API dirancang untuk hanya menampilkan informasi yang diperlukan untuk mengaktifkan kasus penggunaan yang disebutkan. API sistem dapat menghasilkan daftar font yang diinstal, bukan dalam urutan acak atau diurutkan, tetapi dalam urutan penginstalan font. Menampilkan daftar font terinstal yang diberikan oleh API sistem tersebut dapat mengekspos data tambahan yang dapat digunakan untuk sidik jari, dan kasus penggunaan yang ingin kita aktifkan tidak akan dibantu dengan mempertahankan urutan ini. Akibatnya, 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 yang ditetapkan dalam Mengontrol Akses ke Fitur Platform Web yang Canggih, termasuk kontrol pengguna, transparansi, dan ergonomi.
Kontrol pengguna
Akses ke font pengguna sepenuhnya berada di bawah kendalinya dan tidak akan diizinkan kecuali jika
izin "local-fonts"
, seperti yang tercantum dalam
registry izin, diberikan.
Transparansi
Apakah situs telah diberi akses ke font lokal pengguna akan terlihat di sheet informasi situs.
Persistensi izin
Izin "local-fonts"
akan dipertahankan di antara pemuatan ulang halaman. Anda dapat mencabutnya melalui
sheet informasi situs.
Masukan
Tim Chrome ingin mengetahui pengalaman Anda saat menggunakan Local Font Access API.
Beri tahu kami tentang desain API
Apakah ada sesuatu pada API yang tidak berfungsi seperti yang Anda harapkan? Atau apakah ada metode atau properti yang hilang yang Anda butuhkan untuk menerapkan ide Anda? Punya pertanyaan atau komentar tentang model keamanan? Laporkan masalah spesifikasi di repo GitHub yang sesuai, atau tambahkan pendapat Anda ke masalah yang sudah ada.
Melaporkan masalah terkait penerapan
Apakah Anda menemukan bug pada implementasi Chrome? Atau apakah implementasinya berbeda dari spesifikasi?
Laporkan bug di new.crbug.com. Pastikan untuk menyertakan detail sebanyak mungkin,
petunjuk sederhana untuk mereproduksi, dan masukkan Blink>Storage>FontAccess
di kotak Components.
Glitch berfungsi dengan baik untuk berbagi repro yang cepat dan mudah.
Menunjukkan dukungan untuk API
Apakah Anda berencana menggunakan Local Font Access API? Dukungan publik Anda membantu tim Chrome memprioritaskan fitur dan menunjukkan kepada vendor browser lain betapa pentingnya mendukung fitur tersebut.
Kirim tweet ke @ChromiumDev menggunakan hashtag
#LocalFontAccess
dan beri tahu
kami 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 ditinjau oleh Joe Medley, Dominik Röttsches, dan Olivier Yiptong. Banner besar oleh Brett Jordan di Unsplash.