Commits:
-
2d505062
by Pier Angelo Vendrame at 2024-04-08T20:10:54+00:00
Bug 41901: Hardcode normalized FontSubstitutes.
Windows has a system to set font aliases through the registry.
This allows some customization that could be used as a fingerprinting
vector.
Moreover, this mechanism is used by Windows itself, and different SKUs
might have different default FontSubstitutes.
4 changed files:
Changes:
gfx/thebes/StandardFonts-win10.inc
... |
... |
@@ -199,3 +199,68 @@ static const char* kLangPackFonts[] = { |
199
|
199
|
// "Rockwell Nova", // Pan-European Supplemental Fonts - EXCLUDED
|
200
|
200
|
// "Verdana Pro", // Pan-European Supplemental Fonts - EXCLUDED
|
201
|
201
|
};
|
|
202
|
+
|
|
203
|
+struct FontSubstitute {
|
|
204
|
+ const char *substituteName;
|
|
205
|
+ const char *actualFontName;
|
|
206
|
+};
|
|
207
|
+
|
|
208
|
+static const FontSubstitute kFontSubstitutes[] = {
|
|
209
|
+ // Common substitutions
|
|
210
|
+ {"Arabic Transparent", "Arial"},
|
|
211
|
+ {"Arabic Transparent Bold", "Arial Bold"},
|
|
212
|
+ {"Arial Baltic", "Arial"},
|
|
213
|
+ {"Arial CE", "Arial"},
|
|
214
|
+ {"Arial CYR", "Arial"},
|
|
215
|
+ {"Arial Greek", "Arial"},
|
|
216
|
+ {"Arial TUR", "Arial"},
|
|
217
|
+ {"Courier New Baltic", "Courier New"},
|
|
218
|
+ {"Courier New CE", "Courier New"},
|
|
219
|
+ {"Courier New CYR", "Courier New"},
|
|
220
|
+ {"Courier New Greek", "Courier New"},
|
|
221
|
+ {"Courier New TUR", "Courier New"},
|
|
222
|
+ {"Helv", "MS Sans Serif"},
|
|
223
|
+ {"Helvetica", "Arial"},
|
|
224
|
+ {"MS Shell Dlg 2", "Tahoma"},
|
|
225
|
+ {"Tahoma Armenian", "Tahoma"},
|
|
226
|
+ {"Times", "Times New Roman"},
|
|
227
|
+ {"Times New Roman Baltic", "Times New Roman"},
|
|
228
|
+ {"Times New Roman CE", "Times New Roman"},
|
|
229
|
+ {"Times New Roman CYR", "Times New Roman"},
|
|
230
|
+ {"Times New Roman Greek", "Times New Roman"},
|
|
231
|
+ {"Times New Roman TUR", "Times New Roman"},
|
|
232
|
+ {"Tms Rmn", "MS Serif"},
|
|
233
|
+ // Common, except Japanese (which uses MS UI Gothic, instead)
|
|
234
|
+ {"MS Shell Dlg", "Microsoft Sans Serif"},
|
|
235
|
+ // Arabic
|
|
236
|
+ {"Arial (Arabic)", "Arial"},
|
|
237
|
+ {"Courier New (Arabic)", "Courier New"},
|
|
238
|
+ {"Times New Roman (Arabic)", "Times New Roman"},
|
|
239
|
+ // Cyrillic + Greek
|
|
240
|
+ {"Courier", "Courier New"},
|
|
241
|
+ // Greek
|
|
242
|
+ {"Fixedsys Greek", "Fixedsys"},
|
|
243
|
+ {"MS Serif Greek", "MS Serif"},
|
|
244
|
+ {"MS Sans Serif Greek", "MS Sans Serif"},
|
|
245
|
+ {"Small Fonts Greek", "Small Fonts"},
|
|
246
|
+ {"System Greek", "System"},
|
|
247
|
+ // Hebrew
|
|
248
|
+ {"Arial (Hebrew)", "Arial"},
|
|
249
|
+ {"Courier New (Hebrew)", "Courier New"},
|
|
250
|
+ {"David Transparent", "David"},
|
|
251
|
+ {"Fixed Miriam Transparent", "Miriam Fixed"},
|
|
252
|
+ {"Miriam Transparent", "Miriam"},
|
|
253
|
+ {"Rod Transparent", "Rod"},
|
|
254
|
+ {"Times New Roman (Hebrew)", "Times New Roman"},
|
|
255
|
+ // Japanese
|
|
256
|
+ {"標準明朝", "MS 明朝"},
|
|
257
|
+ {"標準ゴシック", "MS ゴシック"},
|
|
258
|
+ {"ゴシック", "MS ゴシック"},
|
|
259
|
+ {"ゴシック", "MS ゴシック"},
|
|
260
|
+ {"クーリエ", "Courier"},
|
|
261
|
+ {"タイムズロマン", "Times New Roman"},
|
|
262
|
+ {"ヘルベチカ", "Arial"},
|
|
263
|
+ // Simplified Chinese
|
|
264
|
+ {"FangSong_GB2312", "FangSong"},
|
|
265
|
+ {"KaiTi_GB2312", "KaiTi"},
|
|
266
|
+}; |
gfx/thebes/gfxDWriteFontList.cpp
... |
... |
@@ -1923,6 +1923,20 @@ static void RemoveCharsetFromFontSubstitute(nsACString& aName) { |
1923
|
1923
|
#define MAX_VALUE_DATA 512
|
1924
|
1924
|
|
1925
|
1925
|
nsresult gfxDWriteFontList::GetFontSubstitutes() {
|
|
1926
|
+ if (nsContentUtils::ShouldResistFingerprinting(
|
|
1927
|
+ "Ignore any fingerprintable user font customization and normalize "
|
|
1928
|
+ "font substitutes across different Windows SKUs.",
|
|
1929
|
+ RFPTarget::Unknown)) {
|
|
1930
|
+ for (const FontSubstitute& fs : kFontSubstitutes) {
|
|
1931
|
+ nsAutoCString substituteName(fs.substituteName);
|
|
1932
|
+ nsAutoCString actualFontName(fs.actualFontName);
|
|
1933
|
+ BuildKeyNameFromFontName(substituteName);
|
|
1934
|
+ BuildKeyNameFromFontName(actualFontName);
|
|
1935
|
+ AddSubstitute(substituteName, actualFontName);
|
|
1936
|
+ }
|
|
1937
|
+ return NS_OK;
|
|
1938
|
+ }
|
|
1939
|
+
|
1926
|
1940
|
HKEY hKey;
|
1927
|
1941
|
DWORD i, rv, lenAlias, lenActual, valueType;
|
1928
|
1942
|
WCHAR aliasName[MAX_VALUE_NAME];
|
... |
... |
@@ -1957,39 +1971,46 @@ nsresult gfxDWriteFontList::GetFontSubstitutes() { |
1957
|
1971
|
BuildKeyNameFromFontName(substituteName);
|
1958
|
1972
|
RemoveCharsetFromFontSubstitute(actualFontName);
|
1959
|
1973
|
BuildKeyNameFromFontName(actualFontName);
|
1960
|
|
- if (SharedFontList()) {
|
1961
|
|
- // Skip substitution if the original font is available, unless the option
|
1962
|
|
- // to apply substitutions unconditionally is enabled.
|
1963
|
|
- if (!StaticPrefs::gfx_windows_font_substitutes_always_AtStartup()) {
|
1964
|
|
- // Font substitutions are recorded for the canonical family names; we
|
1965
|
|
- // don't need FindFamily to consider localized aliases when searching.
|
1966
|
|
- if (SharedFontList()->FindFamily(substituteName,
|
1967
|
|
- /*aPrimaryNameOnly*/ true)) {
|
1968
|
|
- continue;
|
1969
|
|
- }
|
1970
|
|
- }
|
1971
|
|
- if (SharedFontList()->FindFamily(actualFontName,
|
|
1974
|
+ AddSubstitute(substituteName, actualFontName);
|
|
1975
|
+ }
|
|
1976
|
+
|
|
1977
|
+ return NS_OK;
|
|
1978
|
+}
|
|
1979
|
+
|
|
1980
|
+void gfxDWriteFontList::AddSubstitute(const nsCString& substituteName,
|
|
1981
|
+ const nsCString& actualFontName) {
|
|
1982
|
+ if (SharedFontList()) {
|
|
1983
|
+ // Skip substitution if the original font is available, unless the
|
|
1984
|
+ // option to apply substitutions unconditionally is enabled.
|
|
1985
|
+ if (!StaticPrefs::gfx_windows_font_substitutes_always_AtStartup()) {
|
|
1986
|
+ // Font substitutions are recorded for the canonical family names;
|
|
1987
|
+ // we don't need FindFamily to consider localized aliases when
|
|
1988
|
+ // searching.
|
|
1989
|
+ if (SharedFontList()->FindFamily(substituteName,
|
1972
|
1990
|
/*aPrimaryNameOnly*/ true)) {
|
1973
|
|
- mSubstitutions.InsertOrUpdate(substituteName,
|
1974
|
|
- MakeUnique<nsCString>(actualFontName));
|
1975
|
|
- } else if (mSubstitutions.Get(actualFontName)) {
|
1976
|
|
- mSubstitutions.InsertOrUpdate(
|
1977
|
|
- substituteName,
|
1978
|
|
- MakeUnique<nsCString>(*mSubstitutions.Get(actualFontName)));
|
1979
|
|
- } else {
|
1980
|
|
- mNonExistingFonts.AppendElement(substituteName);
|
|
1991
|
+ return;
|
1981
|
1992
|
}
|
|
1993
|
+ }
|
|
1994
|
+ if (SharedFontList()->FindFamily(actualFontName,
|
|
1995
|
+ /*aPrimaryNameOnly*/ true)) {
|
|
1996
|
+ mSubstitutions.InsertOrUpdate(substituteName,
|
|
1997
|
+ MakeUnique<nsCString>(actualFontName));
|
|
1998
|
+ } else if (mSubstitutions.Get(actualFontName)) {
|
|
1999
|
+ mSubstitutions.InsertOrUpdate(
|
|
2000
|
+ substituteName,
|
|
2001
|
+ MakeUnique<nsCString>(*mSubstitutions.Get(actualFontName)));
|
1982
|
2002
|
} else {
|
1983
|
|
- gfxFontFamily* ff;
|
1984
|
|
- if (!actualFontName.IsEmpty() &&
|
1985
|
|
- (ff = mFontFamilies.GetWeak(actualFontName))) {
|
1986
|
|
- mFontSubstitutes.InsertOrUpdate(substituteName, RefPtr{ff});
|
1987
|
|
- } else {
|
1988
|
|
- mNonExistingFonts.AppendElement(substituteName);
|
1989
|
|
- }
|
|
2003
|
+ mNonExistingFonts.AppendElement(substituteName);
|
|
2004
|
+ }
|
|
2005
|
+ } else {
|
|
2006
|
+ gfxFontFamily* ff;
|
|
2007
|
+ if (!actualFontName.IsEmpty() &&
|
|
2008
|
+ (ff = mFontFamilies.GetWeak(actualFontName))) {
|
|
2009
|
+ mFontSubstitutes.InsertOrUpdate(substituteName, RefPtr{ff});
|
|
2010
|
+ } else {
|
|
2011
|
+ mNonExistingFonts.AppendElement(substituteName);
|
1990
|
2012
|
}
|
1991
|
2013
|
}
|
1992
|
|
- return NS_OK;
|
1993
|
2014
|
}
|
1994
|
2015
|
|
1995
|
2016
|
struct FontSubstitution {
|
gfx/thebes/gfxDWriteFontList.h
... |
... |
@@ -466,6 +466,9 @@ class gfxDWriteFontList final : public gfxPlatformFontList { |
466
|
466
|
const nsTArray<nsCString>* aForceClassicFams = nullptr)
|
467
|
467
|
MOZ_REQUIRES(mLock);
|
468
|
468
|
|
|
469
|
+ void AddSubstitute(const nsCString& substituteName,
|
|
470
|
+ const nsCString& actualFontName);
|
|
471
|
+
|
469
|
472
|
#ifdef MOZ_BUNDLED_FONTS
|
470
|
473
|
already_AddRefed<IDWriteFontCollection> CreateBundledFontsCollection(
|
471
|
474
|
IDWriteFactory* aFactory);
|
gfx/thebes/gfxGDIFontList.cpp
... |
... |
@@ -31,6 +31,10 @@ |
31
|
31
|
#include "mozilla/StaticPrefs_gfx.h"
|
32
|
32
|
#include "mozilla/Telemetry.h"
|
33
|
33
|
|
|
34
|
+#include "nsContentUtils.h"
|
|
35
|
+
|
|
36
|
+#include "StandardFonts-win10.inc"
|
|
37
|
+
|
34
|
38
|
#include <usp10.h>
|
35
|
39
|
|
36
|
40
|
using namespace mozilla;
|
... |
... |
@@ -50,6 +54,10 @@ static __inline void BuildKeyNameFromFontName(nsAString& aName) { |
50
|
54
|
if (aName.Length() >= LF_FACESIZE) aName.Truncate(LF_FACESIZE - 1);
|
51
|
55
|
ToLowerCase(aName);
|
52
|
56
|
}
|
|
57
|
+static __inline void BuildKeyNameFromFontName(nsACString& aName) {
|
|
58
|
+ if (aName.Length() >= LF_FACESIZE) aName.Truncate(LF_FACESIZE - 1);
|
|
59
|
+ ToLowerCase(aName);
|
|
60
|
+}
|
53
|
61
|
|
54
|
62
|
// Implementation of gfxPlatformFontList for Win32 GDI,
|
55
|
63
|
// using GDI font enumeration APIs to get the list of fonts
|
... |
... |
@@ -529,6 +537,26 @@ static void RemoveCharsetFromFontSubstitute(nsAString& aName) { |
529
|
537
|
#define MAX_VALUE_DATA 512
|
530
|
538
|
|
531
|
539
|
nsresult gfxGDIFontList::GetFontSubstitutes() {
|
|
540
|
+ if (nsContentUtils::ShouldResistFingerprinting(
|
|
541
|
+ "Ignore any fingerprintable user font customization and normalize "
|
|
542
|
+ "font substitutes across different Windows SKUs.",
|
|
543
|
+ RFPTarget::Unknown)) {
|
|
544
|
+ for (const FontSubstitute& fs : kFontSubstitutes) {
|
|
545
|
+ nsAutoCString substituteName(fs.substituteName);
|
|
546
|
+ nsAutoCString actualFontName(fs.actualFontName);
|
|
547
|
+ BuildKeyNameFromFontName(substituteName);
|
|
548
|
+ BuildKeyNameFromFontName(actualFontName);
|
|
549
|
+ gfxFontFamily* ff;
|
|
550
|
+ if (!actualFontName.IsEmpty() &&
|
|
551
|
+ (ff = mFontFamilies.GetWeak(actualFontName))) {
|
|
552
|
+ mFontSubstitutes.InsertOrUpdate(substituteName, RefPtr{ff});
|
|
553
|
+ } else {
|
|
554
|
+ mNonExistingFonts.AppendElement(substituteName);
|
|
555
|
+ }
|
|
556
|
+ }
|
|
557
|
+ return NS_OK;
|
|
558
|
+ }
|
|
559
|
+
|
532
|
560
|
HKEY hKey;
|
533
|
561
|
DWORD i, rv, lenAlias, lenActual, valueType;
|
534
|
562
|
WCHAR aliasName[MAX_VALUE_NAME];
|
|