Commit fffc6331 authored by Alex Turner's avatar Alex Turner Committed by Commit Bot

Instrument PostScript name to typeface mapping for identifiability study

Currently, local font lookups are instrumented with a digest of the
lookup value and a digest of the resulting typeface being recorded. We
expand this recording for successful local font lookups: we now also
record a digest of the resulting typeface's PostScript name with the
typeface digest. This will allow the identifiability study to measure
the diversity of installed typeface files with the same PostScript name
(for example, differing versions of the same typeface) and thus
evaluate the privacy impact of that variation.

Bug: 1136210
Change-Id: Id7ac6229db287af776474f43abd200c51319992e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2453439Reviewed-by: default avatarDominik Röttsches <drott@chromium.org>
Reviewed-by: default avatarAsanka Herath <asanka@chromium.org>
Commit-Queue: Alex Turner <alexmt@chromium.org>
Cr-Commit-Position: refs/heads/master@{#815773}
parent 53e08203
......@@ -171,7 +171,7 @@ class IdentifiableSurface {
// FontSelectionRequest (i.e. weight, width and slope).
kLocalFontLookupByFallbackCharacter = 13,
// Represents loading a font locally as a last resort. Input is the
// Represents looking up a font locally as a last resort. Input is the
// FontSelectionRequest (i.e. weight, width and slope).
kLocalFontLookupAsLastResort = 14,
......@@ -201,6 +201,9 @@ class IdentifiableSurface {
// the hint parameter.
kNavigatorUAData_GetHighEntropyValues = 24,
// Represents loading a font locally. Input is the PostScript name.
kLocalFontLoadPostScriptName = 29,
// We can use values up to and including |kMax|.
kMax = (1 << kTypeBits) - 1
};
......
......@@ -7,12 +7,13 @@
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
#include "third_party/blink/renderer/platform/fonts/font_unique_name_lookup.h"
#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_cache.h"
#include "third_party/blink/renderer/platform/privacy_budget/identifiability_digest_helpers.h"
#include "third_party/blink/renderer/platform/wtf/thread_specific.h"
// While the size of this cache should usually be small (up to tens), we protect
// against the possibility of it growing quickly to thousands when animating
// variable font parameters.
static constexpr size_t kTypefaceDigestCacheMaxSize = 250;
// While the size of these caches should usually be small (up to tens), we
// protect against the possibility of it growing quickly to thousands when
// animating variable font parameters.
static constexpr size_t kCachesMaxSize = 250;
namespace blink {
......@@ -28,7 +29,8 @@ FontGlobalContext* FontGlobalContext::Get(CreateIfNeeded create_if_needed) {
FontGlobalContext::FontGlobalContext()
: harfbuzz_font_funcs_skia_advances_(nullptr),
harfbuzz_font_funcs_harfbuzz_advances_(nullptr),
typeface_digest_cache_(kTypefaceDigestCacheMaxSize) {}
typeface_digest_cache_(kCachesMaxSize),
postscript_name_digest_cache_(kCachesMaxSize) {}
FontGlobalContext::~FontGlobalContext() = default;
......@@ -67,12 +69,33 @@ IdentifiableToken FontGlobalContext::GetOrComputeTypefaceDigest(
return *cached_value;
}
IdentifiableToken FontGlobalContext::GetOrComputePostScriptNameDigest(
const FontPlatformData& source) {
SkTypeface* typeface = source.Typeface();
if (!typeface)
return IdentifiableToken();
SkFontID font_id = typeface->uniqueID();
IdentifiableToken* cached_value = postscript_name_digest_cache_.Get(font_id);
if (!cached_value) {
postscript_name_digest_cache_.Put(
font_id, IdentifiabilityBenignStringToken(source.GetPostScriptName()));
cached_value = postscript_name_digest_cache_.Get(font_id);
} else {
DCHECK(*cached_value ==
IdentifiabilityBenignStringToken(source.GetPostScriptName()));
}
return *cached_value;
}
void FontGlobalContext::ClearMemory() {
if (!Get(kDoNotCreate))
return;
GetFontCache().Invalidate();
Get()->typeface_digest_cache_.Clear();
Get()->postscript_name_digest_cache_.Clear();
}
} // namespace blink
......@@ -59,6 +59,8 @@ class PLATFORM_EXPORT FontGlobalContext {
static FontUniqueNameLookup* GetFontUniqueNameLookup();
IdentifiableToken GetOrComputeTypefaceDigest(const FontPlatformData& source);
IdentifiableToken GetOrComputePostScriptNameDigest(
const FontPlatformData& source);
// Called by MemoryPressureListenerRegistry to clear memory.
static void ClearMemory();
......@@ -75,6 +77,7 @@ class PLATFORM_EXPORT FontGlobalContext {
hb_font_funcs_t* harfbuzz_font_funcs_harfbuzz_advances_;
std::unique_ptr<FontUniqueNameLookup> font_unique_name_lookup_;
WTF::LruCache<SkFontID, IdentifiableToken> typeface_digest_cache_;
WTF::LruCache<SkFontID, IdentifiableToken> postscript_name_digest_cache_;
DISALLOW_COPY_AND_ASSIGN(FontGlobalContext);
};
......
......@@ -109,6 +109,12 @@ void FontMatchingMetrics::InsertFontHashIntoMap(IdentifiableTokenKey input_key,
return;
IdentifiableToken output_token(GetHashForFontData(font_data));
hash_map.insert(input_key, output_token);
if (!font_data)
return;
IdentifiableTokenKey postscript_name_key(
GetPostScriptNameTokenForFontData(font_data));
font_load_postscript_name_.insert(postscript_name_key, output_token);
}
IdentifiableTokenBuilder
......@@ -245,6 +251,8 @@ void FontMatchingMetrics::PublishIdentifiabilityMetrics() {
IdentifiableSurface::Type::kLocalFontLookupAsLastResort},
{&generic_font_lookups_,
IdentifiableSurface::Type::kGenericFontLookup},
{&font_load_postscript_name_,
IdentifiableSurface::Type::kLocalFontLoadPostScriptName},
};
for (const auto& surface_entry : hash_maps_with_corresponding_surface_types) {
......@@ -310,4 +318,11 @@ int64_t FontMatchingMetrics::GetHashForFontData(SimpleFontData* font_data) {
: 0;
}
IdentifiableToken FontMatchingMetrics::GetPostScriptNameTokenForFontData(
SimpleFontData* font_data) {
DCHECK(font_data);
return FontGlobalContext::Get()->GetOrComputePostScriptNameDigest(
font_data->PlatformData());
}
} // namespace blink
......@@ -193,7 +193,9 @@ class PLATFORM_EXPORT FontMatchingMetrics {
IdentifiableTokenKeyHashTraits>;
// Adds a digest of the |font_data|'s typeface to |hash_map| using the key
// |input_key|, unless that key is already present.
// |input_key|, unless that key is already present. If |font_data| is not
// nullptr, then the typeface digest will also be saved with its PostScript
// name in |font_load_postscript_name_|.
void InsertFontHashIntoMap(IdentifiableTokenKey input_key,
SimpleFontData* font_data,
TokenToTokenHashMap hash_map);
......@@ -208,6 +210,11 @@ class PLATFORM_EXPORT FontMatchingMetrics {
void Initialize();
// Get a token that uniquely represents the typeface's PostScript name. May
// represent the empty string if no PostScript name was found.
IdentifiableToken GetPostScriptNameTokenForFontData(
SimpleFontData* font_data);
// Font family names successfully matched.
HashSet<AtomicString> successful_font_families_;
......@@ -235,6 +242,7 @@ class PLATFORM_EXPORT FontMatchingMetrics {
TokenToTokenHashMap font_lookups_by_fallback_character_;
TokenToTokenHashMap font_lookups_as_last_resort_;
TokenToTokenHashMap generic_font_lookups_;
TokenToTokenHashMap font_load_postscript_name_;
ukm::UkmRecorder* const ukm_recorder_;
const ukm::SourceId source_id_;
......
......@@ -338,4 +338,13 @@ IdentifiableToken FontPlatformData::ComputeTypefaceDigest() const {
return builder.GetToken(); // hasher.GetHash();
}
String FontPlatformData::GetPostScriptName() const {
if (!typeface_)
return String();
SkString postscript_name;
bool success = typeface_->getPostScriptName(&postscript_name);
return success ? postscript_name.c_str() : String();
}
} // namespace blink
......@@ -145,6 +145,9 @@ class PLATFORM_EXPORT FontPlatformData {
// the fingerprinting algorithm.
IdentifiableToken ComputeTypefaceDigest() const;
// Gets the postscript name from the typeface.
String GetPostScriptName() const;
private:
#if !defined(OS_WIN) && !defined(OS_MAC)
WebFontRenderStyle QuerySystemRenderStyle(const std::string& family,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment