summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/font-access
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /testing/web-platform/tests/font-access
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/font-access')
-rw-r--r--testing/web-platform/tests/font-access/README.md2
-rw-r--r--testing/web-platform/tests/font-access/font_access_basic.tentative.https.window.js39
-rw-r--r--testing/web-platform/tests/font-access/font_access_blob.tentative.https.window.js33
-rw-r--r--testing/web-platform/tests/font-access/font_access_detached_iframe.tentative.https.window.js44
-rw-r--r--testing/web-platform/tests/font-access/font_access_permission.tentative.https.window.js25
-rw-r--r--testing/web-platform/tests/font-access/font_access_query_select.tentative.https.window.js94
-rw-r--r--testing/web-platform/tests/font-access/font_access_sorted.tentative.https.window.js19
-rw-r--r--testing/web-platform/tests/font-access/permissions-policy/local-fonts-allowed-by-permissions-policy-attribute-redirect-on-load.https.sub.html28
-rw-r--r--testing/web-platform/tests/font-access/permissions-policy/local-fonts-allowed-by-permissions-policy-attribute.https.sub.html27
-rw-r--r--testing/web-platform/tests/font-access/permissions-policy/local-fonts-allowed-by-permissions-policy.https.sub.html35
-rw-r--r--testing/web-platform/tests/font-access/permissions-policy/local-fonts-allowed-by-permissions-policy.https.sub.html.headers1
-rw-r--r--testing/web-platform/tests/font-access/permissions-policy/local-fonts-default-permissions-policy.https.sub.html35
-rw-r--r--testing/web-platform/tests/font-access/permissions-policy/local-fonts-disabled-by-permissions-policy.https.sub.html33
-rw-r--r--testing/web-platform/tests/font-access/permissions-policy/local-fonts-disabled-by-permissions-policy.https.sub.html.headers1
-rw-r--r--testing/web-platform/tests/font-access/permissions-policy/local-fonts-supported-by-permissions-policy.html11
-rw-r--r--testing/web-platform/tests/font-access/resources/font-asserts.js38
-rw-r--r--testing/web-platform/tests/font-access/resources/font-data.js66
-rw-r--r--testing/web-platform/tests/font-access/resources/font-test-utils.js100
18 files changed, 631 insertions, 0 deletions
diff --git a/testing/web-platform/tests/font-access/README.md b/testing/web-platform/tests/font-access/README.md
new file mode 100644
index 0000000000..f0d654ed39
--- /dev/null
+++ b/testing/web-platform/tests/font-access/README.md
@@ -0,0 +1,2 @@
+This directory contains (tentative) tests for the
+[Font Access](https://wicg.github.io/local-font-access/) specification.
diff --git a/testing/web-platform/tests/font-access/font_access_basic.tentative.https.window.js b/testing/web-platform/tests/font-access/font_access_basic.tentative.https.window.js
new file mode 100644
index 0000000000..4e714dcf5c
--- /dev/null
+++ b/testing/web-platform/tests/font-access/font_access_basic.tentative.https.window.js
@@ -0,0 +1,39 @@
+// META: script=/resources/testdriver.js
+// META: script=/resources/testdriver-vendor.js
+// META: script=resources/font-asserts.js
+// META: script=resources/font-data.js
+// META: script=resources/font-test-utils.js
+// META: timeout=long
+
+'use strict';
+
+font_access_test(async t => {
+ // Fonts we know about. Not all expected fonts are included.
+ const testData = getTestData();
+
+ // Get the system fonts.
+ const fonts = await self.queryLocalFonts();
+ assert_true(Array.isArray(fonts), 'Result of query() should be an Array');
+ assert_greater_than_equal(fonts.length, 1, 'Need a least one font');
+
+ fonts.forEach(font => {
+ assert_true(
+ font instanceof FontData, 'Results should be FontData instances');
+
+ // Verify properties and types.
+ assert_equals(typeof font.postscriptName, 'string');
+ assert_true(
+ font.postscriptName.split('').every(c => (' ' <= c && c < '\x7f')),
+ `postscriptName should be printable ASCII: "${font.postscriptName}"`);
+ assert_equals(typeof font.fullName, 'string', 'fullName attribute type');
+ assert_equals(typeof font.family, 'string', 'family attribute type');
+ assert_equals(typeof font.style, 'string', 'style attribute type');
+
+ // If the sample test data contains the returned system font,
+ // then verify the values of FontData.
+ const expectedFont = testData.get(font.postscriptName);
+ if (expectedFont) {
+ assert_font_equals(font, expectedFont);
+ }
+ });
+}, 'queryLocalFonts(): FontData property types and values');
diff --git a/testing/web-platform/tests/font-access/font_access_blob.tentative.https.window.js b/testing/web-platform/tests/font-access/font_access_blob.tentative.https.window.js
new file mode 100644
index 0000000000..16691d0ab5
--- /dev/null
+++ b/testing/web-platform/tests/font-access/font_access_blob.tentative.https.window.js
@@ -0,0 +1,33 @@
+// META: script=/resources/testdriver.js
+// META: script=/resources/testdriver-vendor.js
+// META: script=resources/font-asserts.js
+// META: script=resources/font-data.js
+// META: script=resources/font-test-utils.js
+// META: timeout=long
+
+'use strict';
+
+font_access_test(async t => {
+ const fonts = await self.queryLocalFonts();
+
+ // Fonts we know about. Not all expected fonts are included.
+ const testData = getTestData();
+ // Reduce down the size of results for testing purposes.
+ const filteredFonts = filterFonts(fonts, [...testData.keys()]);
+
+ for (const font of filteredFonts) {
+ const data = await font.blob();
+ assert_not_equals(data.size, 0, 'Blob has a positive size.');
+ assert_equals(
+ data.type, 'application/octet-stream',
+ 'Returned Blob is of type octet-stream.');
+ const buffer = await data.arrayBuffer();
+ assert_not_equals(buffer.length, 0, 'Returned ArrayBuffer is not empty.');
+
+ const parsedData = await parseFontData(data);
+ assert_version_info(parsedData.versionTag);
+ assert_not_equals(
+ parsedData.tables.size, 0, 'Should not have tables of size zero.');
+ assert_font_has_tables(font.postscriptName, parsedData.tables, BASE_TABLES);
+ }
+}, 'FontData.blob(): blob has expected format and parsable table data.');
diff --git a/testing/web-platform/tests/font-access/font_access_detached_iframe.tentative.https.window.js b/testing/web-platform/tests/font-access/font_access_detached_iframe.tentative.https.window.js
new file mode 100644
index 0000000000..ca8171aec0
--- /dev/null
+++ b/testing/web-platform/tests/font-access/font_access_detached_iframe.tentative.https.window.js
@@ -0,0 +1,44 @@
+// META: script=/resources/testdriver.js
+// META: script=/resources/testdriver-vendor.js
+// META: script=resources/font-test-utils.js
+// META: timeout=long
+
+'use strict';
+
+font_access_test(async t => {
+ const iframe = document.createElement('iframe');
+ document.body.appendChild(iframe);
+
+ const frameWindow = iframe.contentWindow;
+ const frameDOMException = iframe.contentWindow.DOMException;
+ iframe.remove();
+
+ await promise_rejects_dom(
+ t, 'InvalidStateError', frameDOMException, frameWindow.queryLocalFonts());
+}, 'queryLocalFonts() must return an error when called from a detached frame.');
+
+font_access_test(async t => {
+ const iframe = document.createElement('iframe');
+ document.body.appendChild(iframe);
+
+ iframe.contentWindow.queryLocalFonts;
+ iframe.remove();
+
+ // Call queryLocalFonts() in the main frame. This should keep the test running
+ // long enough to catch any crash from the queryLocalFonts() call in the
+ // removed iframe.
+ await self.queryLocalFonts();
+}, 'Detaching iframe while queryLocalFonts() settles.');
+
+font_access_test(async t => {
+ const iframe = document.createElement('iframe');
+ document.body.appendChild(iframe);
+
+ const iframeFonts = await iframe.contentWindow.queryLocalFonts();
+ assert_greater_than_equal(iframeFonts.length, 1, 'Need a least one font');
+ const iframeFontData = iframeFonts[0];
+ const frameDOMException = iframe.contentWindow.DOMException;
+ iframe.remove();
+
+ iframeFontData.blob();
+}, 'FontData.blob() should not crash when called from a detached iframe.');
diff --git a/testing/web-platform/tests/font-access/font_access_permission.tentative.https.window.js b/testing/web-platform/tests/font-access/font_access_permission.tentative.https.window.js
new file mode 100644
index 0000000000..fbd0d1d885
--- /dev/null
+++ b/testing/web-platform/tests/font-access/font_access_permission.tentative.https.window.js
@@ -0,0 +1,25 @@
+// META: script=/resources/testdriver.js
+// META: script=/resources/testdriver-vendor.js
+// META: timeout=long
+
+'use strict';
+
+promise_test(async t => {
+ const fonts = await self.queryLocalFonts();
+ assert_equals(
+ fonts.length, 0, 'Fonts are not returned with permission not given.');
+}, 'queryLocalFonts(): permission not given');
+
+promise_test(async t => {
+ await test_driver.set_permission({name: 'local-fonts'}, 'denied');
+ const fonts = await self.queryLocalFonts();
+ assert_equals(
+ fonts.length, 0, 'Fonts are not returned with permission denied.');
+}, 'queryLocalFonts(): permission denied');
+
+promise_test(async t => {
+ await test_driver.set_permission({name: 'local-fonts'}, 'granted');
+ const fonts = await self.queryLocalFonts();
+ assert_greater_than_equal(
+ fonts.length, 1, 'Fonts are returned with permission granted.');
+}, 'queryLocalFonts(): permission granted');
diff --git a/testing/web-platform/tests/font-access/font_access_query_select.tentative.https.window.js b/testing/web-platform/tests/font-access/font_access_query_select.tentative.https.window.js
new file mode 100644
index 0000000000..df89ea7938
--- /dev/null
+++ b/testing/web-platform/tests/font-access/font_access_query_select.tentative.https.window.js
@@ -0,0 +1,94 @@
+// META: script=/resources/testdriver.js
+// META: script=/resources/testdriver-vendor.js
+// META: script=resources/font-asserts.js
+// META: script=resources/font-data.js
+// META: script=resources/font-test-utils.js
+// META: timeout=long
+
+font_access_test(async t => {
+ const testData = getTestData();
+ assert_greater_than_equal(
+ testData.size, 1, 'Need a least one test font data.');
+ const testFont = testData.values().next().value;
+
+ const queryInput = {postscriptNames: [testFont.postscriptName]};
+ const fonts = await self.queryLocalFonts(queryInput);
+
+ assert_equals(
+ fonts.length, 1, 'The result length should match the test length.');
+ assert_font_equals(fonts[0], testFont);
+}, 'queryLocalFonts(): valid postscript name in QueryOptions');
+
+font_access_test(async t => {
+ const queryInput = {postscriptNames: ['invalid_postscript_name']};
+ const fonts = await self.queryLocalFonts(queryInput);
+
+ assert_equals(
+ fonts.length, 0,
+ 'Fonts should not be selected for an invalid postscript name.');
+}, 'queryLocalFonts(): invalid postscript name in QueryOptions');
+
+font_access_test(async t => {
+ const fonts = await self.queryLocalFonts({});
+
+ assert_greater_than_equal(
+ fonts.length, 1,
+ 'All available fonts should be returned when an empty object is passed.');
+}, 'queryLocalFonts(): empty object for QueryOptions.postscriptNames');
+
+font_access_test(async t => {
+ const queryInput = {invalidFieldName: []};
+ const fonts = await self.queryLocalFonts(queryInput);
+
+ assert_greater_than_equal(
+ fonts.length, 1,
+ 'All available fonts should be returned when an invalid field name for ' +
+ 'QueryOptions is passed.');
+}, 'queryLocalFonts(): invalid QueryOptions field');
+
+font_access_test(async t => {
+ const queryInput = {postscriptNames: []};
+ const fonts = await self.queryLocalFonts(queryInput);
+
+ assert_equals(
+ fonts.length, 0,
+ 'Fonts should not be selected when an empty list for ' +
+ 'QueryOptions.postscriptNames is passed.');
+}, 'queryLocalFonts(): empty QueryOptions.postscriptNames list');
+
+font_access_test(async t => {
+ const fonts = await self.queryLocalFonts(undefined);
+
+ assert_greater_than_equal(
+ fonts.length, 1,
+ 'All available fonts should be returned when undefined is passed for ' +
+ 'input.');
+}, 'queryLocalFonts(): undefined QueryOptions');
+
+const non_ascii_input = [
+ {postscriptNames: ['¥']},
+ {postscriptNames: ['ß']},
+ {postscriptNames: ['🎵']},
+ // UTF-16LE, encodes to the same first four bytes as "Ahem" in ASCII.
+ {postscriptNames: ['\u6841\u6d65']},
+ // U+6C34 CJK UNIFIED IDEOGRAPH (water)
+ {postscriptNames: ['\u6C34']},
+ // U+1D11E MUSICAL SYMBOL G-CLEF (UTF-16 surrogate pair)
+ {postscriptNames: ['\uD834\uDD1E']},
+ // U+FFFD REPLACEMENT CHARACTER
+ {postscriptNames: ['\uFFFD']},
+ // UTF-16 surrogate lead
+ {postscriptNames: ['\uD800']},
+ // UTF-16 surrogate trail
+ {postscriptNames: ['\uDC00']},
+];
+
+for (const test of non_ascii_input) {
+ font_access_test(async t => {
+ const fonts = await self.queryLocalFonts(test);
+ assert_equals(
+ fonts.length, 0,
+ 'Fonts should not be selected for non-ASCII character input: ' +
+ JSON.stringify(fonts));
+ }, `queryLocalFonts(): non-ASCII character input: ${JSON.stringify(test)}`);
+} \ No newline at end of file
diff --git a/testing/web-platform/tests/font-access/font_access_sorted.tentative.https.window.js b/testing/web-platform/tests/font-access/font_access_sorted.tentative.https.window.js
new file mode 100644
index 0000000000..4391c9270c
--- /dev/null
+++ b/testing/web-platform/tests/font-access/font_access_sorted.tentative.https.window.js
@@ -0,0 +1,19 @@
+// META: script=/resources/testdriver.js
+// META: script=/resources/testdriver-vendor.js
+// META: script=resources/font-asserts.js
+// META: script=resources/font-test-utils.js
+// META: timeout=long
+
+'use strict';
+
+font_access_test(async t => {
+ // The following tests that fonts are sorted. Postscript names are expected to
+ // be encoded in a subset of the ASCII character set.
+ // See: https://docs.microsoft.com/en-us/typography/opentype/spec/name
+ // Should the Postscript name contain characters that are multi-byte, this
+ // test may erroneously fail.
+ const fonts = await self.queryLocalFonts();
+ const fontNames = fonts.map(fontData => fontData.postscriptName);
+ const expectedFontNames = [...fontNames].sort();
+ assert_array_equals(fontNames, expectedFontNames);
+}, 'queryLocalFonts(): fonts are sorted');
diff --git a/testing/web-platform/tests/font-access/permissions-policy/local-fonts-allowed-by-permissions-policy-attribute-redirect-on-load.https.sub.html b/testing/web-platform/tests/font-access/permissions-policy/local-fonts-allowed-by-permissions-policy-attribute-redirect-on-load.https.sub.html
new file mode 100644
index 0000000000..d829cc4a3b
--- /dev/null
+++ b/testing/web-platform/tests/font-access/permissions-policy/local-fonts-allowed-by-permissions-policy-attribute-redirect-on-load.https.sub.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<body>
+ <script src=/font-access/resources/font-test-utils.js></script>
+ <script src=/resources/testdriver.js></script>
+ <script src=/resources/testdriver-vendor.js></script>
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src=/permissions-policy/resources/permissions-policy.js></script>
+ <script>
+ 'use strict';
+ const relative_path = '/permissions-policy/resources/permissions-policy-local-fonts.html';
+ const base_src = '/permissions-policy/resources/redirect-on-load.html#';
+ const same_origin_src = base_src + relative_path;
+ const cross_origin_src =
+ base_src + 'https://{{domains[www]}}:{{ports[https][0]}}' + relative_path;
+ const header = 'permissions policy allow="local-fonts"';
+
+ async_test(t => {
+ test_feature_availability('local-fonts', t, same_origin_src,
+ expect_feature_available_default, 'local-fonts');
+ }, header + ' allows same-origin navigation in an iframe.');
+
+ async_test(t => {
+ test_feature_availability('local-fonts', t, cross_origin_src,
+ expect_feature_unavailable_default, 'local-fonts');
+ }, header + ' disallows cross-origin navigation in an iframe.');
+ </script>
+</body> \ No newline at end of file
diff --git a/testing/web-platform/tests/font-access/permissions-policy/local-fonts-allowed-by-permissions-policy-attribute.https.sub.html b/testing/web-platform/tests/font-access/permissions-policy/local-fonts-allowed-by-permissions-policy-attribute.https.sub.html
new file mode 100644
index 0000000000..ba802606a1
--- /dev/null
+++ b/testing/web-platform/tests/font-access/permissions-policy/local-fonts-allowed-by-permissions-policy-attribute.https.sub.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<body>
+ <script src=/font-access/resources/font-test-utils.js></script>
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src=/resources/testdriver.js></script>
+ <script src=/resources/testdriver-vendor.js></script>
+ <script src=/permissions-policy/resources/permissions-policy.js></script>
+ <script>
+ 'use strict';
+ const same_origin_src = '/permissions-policy/resources/permissions-policy-local-fonts.html';
+ const cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+ same_origin_src;
+ const feature_name = 'permissions policy "local-fonts"';
+ const header = 'allow="local-fonts" attribute';
+
+ async_test(t => {
+ test_feature_availability('local-fonts', t, same_origin_src,
+ expect_feature_available_default, 'local-fonts');
+ }, feature_name + ' can be enabled in same-origin iframe using ' + header);
+
+ async_test(t => {
+ test_feature_availability('local-fonts', t, cross_origin_src,
+ expect_feature_available_default, 'local-fonts');
+ }, feature_name + ' can be enabled in cross-origin iframe using ' + header);
+ </script>
+</body> \ No newline at end of file
diff --git a/testing/web-platform/tests/font-access/permissions-policy/local-fonts-allowed-by-permissions-policy.https.sub.html b/testing/web-platform/tests/font-access/permissions-policy/local-fonts-allowed-by-permissions-policy.https.sub.html
new file mode 100644
index 0000000000..4f63b6e013
--- /dev/null
+++ b/testing/web-platform/tests/font-access/permissions-policy/local-fonts-allowed-by-permissions-policy.https.sub.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta name="timeout" content="long"> <!-- this is a long-running test at least on some platforms ! -->
+<body>
+ <script src=/font-access/resources/font-test-utils.js></script>
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src=/resources/testdriver.js></script>
+ <script src=/resources/testdriver-vendor.js></script>
+ <script src=/permissions-policy/resources/permissions-policy.js></script>
+ <script>
+ 'use strict';
+ const same_origin_src = '/permissions-policy/resources/permissions-policy-local-fonts.html';
+ const cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+ same_origin_src;
+ const header = 'permissions policy header: local-fonts *';
+
+ font_access_test(async t => {
+ try {
+ await self.queryLocalFonts();
+ } catch (error) {
+ assert_unreached(error);
+ }
+ }, header + ' allows the top-level document.');
+
+ async_test(t => {
+ test_feature_availability('local-fonts', t, same_origin_src,
+ expect_feature_available_default);
+ }, header + ' allows same-origin iframes.');
+
+ async_test(t => {
+ test_feature_availability('local-fonts', t, cross_origin_src,
+ expect_feature_unavailable_default);
+ }, header + ' disallows cross-origin iframes.');
+ </script>
+</body> \ No newline at end of file
diff --git a/testing/web-platform/tests/font-access/permissions-policy/local-fonts-allowed-by-permissions-policy.https.sub.html.headers b/testing/web-platform/tests/font-access/permissions-policy/local-fonts-allowed-by-permissions-policy.https.sub.html.headers
new file mode 100644
index 0000000000..d88db128d9
--- /dev/null
+++ b/testing/web-platform/tests/font-access/permissions-policy/local-fonts-allowed-by-permissions-policy.https.sub.html.headers
@@ -0,0 +1 @@
+Permissions-Policy: local-fonts=* \ No newline at end of file
diff --git a/testing/web-platform/tests/font-access/permissions-policy/local-fonts-default-permissions-policy.https.sub.html b/testing/web-platform/tests/font-access/permissions-policy/local-fonts-default-permissions-policy.https.sub.html
new file mode 100644
index 0000000000..c0cfdc070d
--- /dev/null
+++ b/testing/web-platform/tests/font-access/permissions-policy/local-fonts-default-permissions-policy.https.sub.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta name="timeout" content="long"> <!-- this is a long-running test at least on some platforms ! -->
+<body>
+ <script src=/font-access/resources/font-test-utils.js></script>
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src=/resources/testdriver.js></script>
+ <script src=/resources/testdriver-vendor.js></script>
+ <script src=/permissions-policy/resources/permissions-policy.js></script>
+ <script>
+ 'use strict';
+ const same_origin_src = '/permissions-policy/resources/permissions-policy-local-fonts.html';
+ const cross_origin_src =
+ 'https://{{domains[www]}}:{{ports[https][0]}}' + same_origin_src;
+ const header = 'Default "local-fonts" permissions policy ["self"]';
+
+ font_access_test(async t => {
+ try {
+ await self.queryLocalFonts();
+ } catch (error) {
+ assert_unreached(error);
+ }
+ }, header + ' allows the top-level document.');
+
+ async_test(t => {
+ test_feature_availability('local-fonts', t, same_origin_src,
+ expect_feature_available_default);
+ }, header + ' allows same-origin iframes.');
+
+ async_test(t => {
+ test_feature_availability('local-fonts', t, cross_origin_src,
+ expect_feature_unavailable_default);
+ }, header + ' disallows cross-origin iframes.');
+ </script>
+</body> \ No newline at end of file
diff --git a/testing/web-platform/tests/font-access/permissions-policy/local-fonts-disabled-by-permissions-policy.https.sub.html b/testing/web-platform/tests/font-access/permissions-policy/local-fonts-disabled-by-permissions-policy.https.sub.html
new file mode 100644
index 0000000000..c9912c6dc3
--- /dev/null
+++ b/testing/web-platform/tests/font-access/permissions-policy/local-fonts-disabled-by-permissions-policy.https.sub.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<meta name="timeout" content="long"> <!-- this is a long-running test at least on some platforms ! -->
+<body>
+ <script src=/font-access/resources/font-test-utils.js></script>
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src=/resources/testdriver.js></script>
+ <script src=/resources/testdriver-vendor.js></script>
+ <script src=/permissions-policy/resources/permissions-policy.js></script>
+ <script>
+ 'use strict';
+ const same_origin_src = '/permissions-policy/resources/permissions-policy-local-fonts.html';
+ const cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+ same_origin_src;
+ const header = 'permissions policy header: "local-fonts=()"';
+
+ font_access_test(async t => {
+ await promise_rejects_dom(t, 'SecurityError', self.queryLocalFonts(),
+ 'queryLocalFonts() throws security error when disallowed by ' +
+ 'permission policy');
+ }, header + ' disallows the top-level document.');
+
+ async_test(t => {
+ test_feature_availability('local-fonts', t, same_origin_src,
+ expect_feature_unavailable_default);
+ }, header + ' disallows same-origin iframes.');
+
+ async_test(t => {
+ test_feature_availability('local-fonts', t, cross_origin_src,
+ expect_feature_unavailable_default);
+ }, header + ' disallows cross-origin iframes.');
+ </script>
+</body> \ No newline at end of file
diff --git a/testing/web-platform/tests/font-access/permissions-policy/local-fonts-disabled-by-permissions-policy.https.sub.html.headers b/testing/web-platform/tests/font-access/permissions-policy/local-fonts-disabled-by-permissions-policy.https.sub.html.headers
new file mode 100644
index 0000000000..f52d4e0d72
--- /dev/null
+++ b/testing/web-platform/tests/font-access/permissions-policy/local-fonts-disabled-by-permissions-policy.https.sub.html.headers
@@ -0,0 +1 @@
+Permissions-Policy: local-fonts=() \ No newline at end of file
diff --git a/testing/web-platform/tests/font-access/permissions-policy/local-fonts-supported-by-permissions-policy.html b/testing/web-platform/tests/font-access/permissions-policy/local-fonts-supported-by-permissions-policy.html
new file mode 100644
index 0000000000..671c0fa539
--- /dev/null
+++ b/testing/web-platform/tests/font-access/permissions-policy/local-fonts-supported-by-permissions-policy.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<title>Test that local fonts is advertised in the feature list</title>
+<link rel="help" href="https://w3c.github.io/webappsec-permissions-policy/#dom-permissions-policy-features">
+<link rel="help" href="https://wicg.github.io/local-fonts/#permissions-policy">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+ test(() => {
+ assert_in_array('local-fonts', document.featurePolicy.features());
+ }, 'document.featurePolicy.features should advertise local-fonts.');
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/font-access/resources/font-asserts.js b/testing/web-platform/tests/font-access/resources/font-asserts.js
new file mode 100644
index 0000000000..7094d8f0bf
--- /dev/null
+++ b/testing/web-platform/tests/font-access/resources/font-asserts.js
@@ -0,0 +1,38 @@
+'use strict';
+
+function assert_font_equals(actualFont, expectedFont) {
+ assert_equals(
+ actualFont.postscriptName, expectedFont.postscriptName,
+ `${actualFont.postscriptName}: postscriptName should match`);
+ assert_equals(
+ actualFont.fullName, expectedFont.fullName,
+ `${actualFont.postscriptName}: fullName should match`);
+ assert_equals(
+ actualFont.family, expectedFont.family,
+ `${actualFont.postscriptName}: family should match`);
+ assert_equals(
+ actualFont.style, expectedFont.style,
+ `${actualFont.postscriptName}: style should match`);
+}
+
+function assert_font_has_tables(fontName, actualTables, expectedTables) {
+ for (const expectedTable of expectedTables) {
+ assert_equals(
+ expectedTable.length, 4, 'Table names are always 4 characters long.');
+ assert_true(
+ actualTables.has(expectedTable),
+ `Font ${fontName} did not have required table ${expectedTable}.`);
+ assert_greater_than(
+ actualTables.get(expectedTable).size, 0,
+ `Font ${fontName} has table ${expectedTable} of size 0.`);
+ }
+}
+
+function assert_version_info(versionTag) {
+ // Spec: https://docs.microsoft.com/en-us/typography/opentype/spec/otff#organization-of-an-opentype-font
+ assert_true(versionTag === '\x00\x01\x00\x00' ||
+ versionTag === 'true' ||
+ versionTag === 'typ1' ||
+ versionTag === 'OTTO',
+ `Invalid sfnt version tag: ${versionTag}`);
+} \ No newline at end of file
diff --git a/testing/web-platform/tests/font-access/resources/font-data.js b/testing/web-platform/tests/font-access/resources/font-data.js
new file mode 100644
index 0000000000..f8e7023e67
--- /dev/null
+++ b/testing/web-platform/tests/font-access/resources/font-data.js
@@ -0,0 +1,66 @@
+'use strict';
+
+// The OpenType spec mentions that the follow tables are required for a font to
+// function correctly. We'll have all the tables listed except for OS/2, which
+// is not present in all fonts on Mac OS.
+// https://docs.microsoft.com/en-us/typography/opentype/spec/otff#font-tables
+const BASE_TABLES = [
+ 'cmap',
+ 'head',
+ 'hhea',
+ 'hmtx',
+ 'maxp',
+ 'name',
+ 'post',
+];
+
+const MAC_FONTS = new Map([
+ ['Monaco', {
+ postscriptName: 'Monaco',
+ fullName: 'Monaco',
+ family: 'Monaco',
+ style: 'Regular',
+ }],
+ ['Menlo-Regular', {
+ postscriptName: 'Menlo-Regular',
+ fullName: 'Menlo Regular',
+ family: 'Menlo',
+ style: 'Regular',
+ }],
+]);
+
+const WIN_FONTS = new Map([
+ ['Verdana', {
+ postscriptName: 'Verdana',
+ fullName: 'Verdana',
+ family: 'Verdana',
+ style: 'Regular',
+ }],
+]);
+
+const LINUX_FONTS = new Map([
+ ['Ahem', {
+ postscriptName: 'Ahem',
+ fullName: 'Ahem',
+ family: 'Ahem',
+ style: 'Regular',
+ }],
+]);
+
+// Returns a map of known system fonts, mapping a font's postscript name to
+// FontData.
+function getTestData() {
+ let output = undefined;
+ if (navigator.platform.indexOf("Win") !== -1) {
+ output = WIN_FONTS;
+ } else if (navigator.platform.indexOf("Mac") !== -1) {
+ output = MAC_FONTS;
+ } else if (navigator.platform.indexOf("Linux") !== -1) {
+ output = LINUX_FONTS;
+ }
+
+ assert_not_equals(
+ output, undefined, 'Cannot get test set due to unsupported platform.');
+
+ return output;
+} \ No newline at end of file
diff --git a/testing/web-platform/tests/font-access/resources/font-test-utils.js b/testing/web-platform/tests/font-access/resources/font-test-utils.js
new file mode 100644
index 0000000000..9d2d915e2d
--- /dev/null
+++ b/testing/web-platform/tests/font-access/resources/font-test-utils.js
@@ -0,0 +1,100 @@
+'use strict';
+
+// Filters an array of FontData by font names. Used to reduce down
+// the size of test data.
+function filterFonts(fonts, filter) {
+ const filteredFont = [];
+ for (const font of fonts) {
+ if (filter.includes(font.postscriptName)) {
+ filteredFont.push(font);
+ }
+ }
+ return filteredFont;
+}
+
+async function parseFontData(fontBlob) {
+ // Parsed result to be returned.
+ const fontInfo = {};
+
+ try {
+ // Parse the version info.
+ fontInfo.versionTag = await getTag(fontBlob, 0);
+ // Parse the table data.
+ const numTables = await getUint16(fontBlob, 4);
+ [fontInfo.tables, fontInfo.tableMeta] =
+ await getTableData(fontBlob, numTables);
+ } catch (error) {
+ throw `Error parsing font table: ${error.message}`;
+ }
+
+ return fontInfo;
+}
+
+async function getTableData(fontBlob, numTables) {
+ const dataMap = new Map();
+ const metaMap = new Map();
+ let blobOffset = 12;
+
+ for (let i = 0; i < numTables; i++) {
+ const tag = await getTag(fontBlob, blobOffset);
+ const checksum = await getUint32(fontBlob, blobOffset + 4);
+ const offset = await getUint32(fontBlob, blobOffset + 8);
+ const size = await getUint32(fontBlob, blobOffset + 12);
+ const tableBlob = fontBlob.slice(offset, offset + size);
+ dataMap.set(tag, tableBlob);
+ metaMap.set(tag, {checksum, offset, size});
+ blobOffset += 16;
+ }
+
+ return [dataMap, metaMap];
+}
+
+async function getTag(blob, offset) {
+ return (new TextDecoder)
+ .decode(await blob.slice(offset, offset + 4).arrayBuffer());
+}
+
+async function getUint16(blob, offset) {
+ const slice = blob.slice(offset, offset + 2);
+ const buf = await slice.arrayBuffer();
+ const dataView = new DataView(buf);
+ return dataView.getUint16(0);
+}
+
+async function getUint32(blob, offset) {
+ const slice = blob.slice(offset, offset + 4);
+ const buf = await slice.arrayBuffer();
+ const dataView = new DataView(buf);
+ return dataView.getUint32(0);
+}
+
+function promiseDocumentReady() {
+ return new Promise(resolve => {
+ if (document.readyState === 'complete') {
+ resolve();
+ }
+ window.addEventListener('load', () => {
+ resolve();
+ }, {once: true});
+ });
+}
+
+function isPlatformSupported() {
+ if (navigator.platform.indexOf('Mac') !== -1 ||
+ navigator.platform.indexOf('Win') !== -1 ||
+ navigator.platform.indexOf('Linux') !== -1) {
+ return true;
+ }
+ return false;
+}
+
+function font_access_test(test_function, name, properties) {
+ return promise_test(async (t) => {
+ if (!isPlatformSupported()) {
+ await promise_rejects_dom(t, 'NotSupportedError', self.queryLocalFonts());
+ return;
+ }
+ await test_driver.set_permission({name: 'local-fonts'}, 'granted');
+ await test_function(t, name, properties);
+ });
+}