Skip to content

[css-font-loading] FontFaceSet.check() method: reality vs spec vs privacy #5744

@jfkthame

Description

@jfkthame

The description in the spec of the FontFaceSet.check() method does not match reality as implemented in any of the major browsers I've tried; moreover, the behavior called for by the spec is bad for privacy as it trivially exposes the set of installed fonts.

Consider the behavior of document.fonts.check("12px foobar"), assuming no font family named "foobar" is present.

According to step 3 of the algorithm in the spec,

If found faces is false, throw an XXX error and abort this algorithm.

this should throw an (unspecified?) error.

No browser I have tested does this. It seems that:

  • Gecko (Firefox) returns true, which makes sense in terms of the general description of what check() does:

If the given text/font combo will render without attempting to use any unloaded or currently-loading fonts, this method will return true

but does not take account of step 3 in the algorithm, which is explicitly called out as the second "special case" in the note.

  • Webkit (Safari) also returns true.

  • Blink (Chrome, Brave) returns false, which I believe must be considered a bug: the given font/text will not "use any unloaded or currently-loading fonts", so this is both misleading to the author (it implies the given font is known but currently unloaded or loading) and non-spec-compliant.

The fact that browsers are supposed (per spec) to throw if check() is called with a non-existent font name was noted 5 years ago in bug reports against both (Gecko)[https://bugzilla.mozilla.org/show_bug.cgi?id=1252821#c7] and (Blink)[https://bugs.chromium.org/p/chromium/issues/detail?id=591602#c7], but the situation remains unchanged: no browser does so.

Given that:

  • Nobody has apparently implemented step 3 of the specified algorithm (so the web cannot be depending on it); and

  • If implemented, it would offer authors a trivial way to probe the set of installed system fonts, which represents an attractive fingerprinting vector;

I propose we should simply remove this step (and the corresponding note about the special-case behavior) from the spec.

(I am aware that font fingerprinting can also be achieved through @font-face, as mentioned in the spec, but FontFaceSet.check() with the throw-on-unknown-font behavior would make it particularly easy and efficient for authors.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions