Verified Commit c5250895 authored by Pier Angelo Vendrame's avatar Pier Angelo Vendrame 🎃 Committed by ma1
Browse files

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.
parent 6891a997
Loading
Loading
Loading
Loading
+65 −0
Original line number Diff line number Diff line
@@ -199,3 +199,68 @@ static const char* kLangPackFonts[] = {
//  "Rockwell Nova",  // Pan-European Supplemental Fonts - EXCLUDED
//  "Verdana Pro",  // Pan-European Supplemental Fonts - EXCLUDED
};

struct FontSubstitute {
  const char *substituteName;
  const char *actualFontName;
};

static const FontSubstitute kFontSubstitutes[] = {
  // Common substitutions
  {"Arabic Transparent", "Arial"},
  {"Arabic Transparent Bold", "Arial Bold"},
  {"Arial Baltic", "Arial"},
  {"Arial CE", "Arial"},
  {"Arial CYR", "Arial"},
  {"Arial Greek", "Arial"},
  {"Arial TUR", "Arial"},
  {"Courier New Baltic", "Courier New"},
  {"Courier New CE", "Courier New"},
  {"Courier New CYR", "Courier New"},
  {"Courier New Greek", "Courier New"},
  {"Courier New TUR", "Courier New"},
  {"Helv", "MS Sans Serif"},
  {"Helvetica", "Arial"},
  {"MS Shell Dlg 2", "Tahoma"},
  {"Tahoma Armenian", "Tahoma"},
  {"Times", "Times New Roman"},
  {"Times New Roman Baltic", "Times New Roman"},
  {"Times New Roman CE", "Times New Roman"},
  {"Times New Roman CYR", "Times New Roman"},
  {"Times New Roman Greek", "Times New Roman"},
  {"Times New Roman TUR", "Times New Roman"},
  {"Tms Rmn", "MS Serif"},
  // Common, except Japanese (which uses MS UI Gothic, instead)
  {"MS Shell Dlg", "Microsoft Sans Serif"},
  // Arabic
  {"Arial (Arabic)", "Arial"},
  {"Courier New (Arabic)", "Courier New"},
  {"Times New Roman (Arabic)", "Times New Roman"},
  // Cyrillic + Greek
  {"Courier", "Courier New"},
  // Greek
  {"Fixedsys Greek", "Fixedsys"},
  {"MS Serif Greek", "MS Serif"},
  {"MS Sans Serif Greek", "MS Sans Serif"},
  {"Small Fonts Greek", "Small Fonts"},
  {"System Greek", "System"},
  // Hebrew
  {"Arial (Hebrew)", "Arial"},
  {"Courier New (Hebrew)", "Courier New"},
  {"David Transparent", "David"},
  {"Fixed Miriam Transparent", "Miriam Fixed"},
  {"Miriam Transparent", "Miriam"},
  {"Rod Transparent", "Rod"},
  {"Times New Roman (Hebrew)", "Times New Roman"},
  // Japanese
  {"標準明朝", "MS 明朝"},
  {"標準ゴシック", "MS ゴシック"},
  {"ゴシック", "MS ゴシック"},
  {"ゴシック", "MS ゴシック"},
  {"クーリエ", "Courier"},
  {"タイムズロマン", "Times New Roman"},
  {"ヘルベチカ", "Arial"},
  // Simplified Chinese
  {"FangSong_GB2312", "FangSong"},
  {"KaiTi_GB2312", "KaiTi"},
};
+49 −28
Original line number Diff line number Diff line
@@ -1923,6 +1923,20 @@ static void RemoveCharsetFromFontSubstitute(nsACString& aName) {
#define MAX_VALUE_DATA 512

nsresult gfxDWriteFontList::GetFontSubstitutes() {
  if (nsContentUtils::ShouldResistFingerprinting(
          "Ignore any fingerprintable user font customization and normalize "
          "font substitutes across different Windows SKUs.",
          RFPTarget::Unknown)) {
    for (const FontSubstitute& fs : kFontSubstitutes) {
      nsAutoCString substituteName(fs.substituteName);
      nsAutoCString actualFontName(fs.actualFontName);
      BuildKeyNameFromFontName(substituteName);
      BuildKeyNameFromFontName(actualFontName);
      AddSubstitute(substituteName, actualFontName);
    }
    return NS_OK;
  }

  HKEY hKey;
  DWORD i, rv, lenAlias, lenActual, valueType;
  WCHAR aliasName[MAX_VALUE_NAME];
@@ -1957,15 +1971,24 @@ nsresult gfxDWriteFontList::GetFontSubstitutes() {
    BuildKeyNameFromFontName(substituteName);
    RemoveCharsetFromFontSubstitute(actualFontName);
    BuildKeyNameFromFontName(actualFontName);
    AddSubstitute(substituteName, actualFontName);
  }

  return NS_OK;
}

void gfxDWriteFontList::AddSubstitute(const nsCString& substituteName,
                                      const nsCString& actualFontName) {
  if (SharedFontList()) {
      // Skip substitution if the original font is available, unless the option
      // to apply substitutions unconditionally is enabled.
    // Skip substitution if the original font is available, unless the
    // option to apply substitutions unconditionally is enabled.
    if (!StaticPrefs::gfx_windows_font_substitutes_always_AtStartup()) {
        // Font substitutions are recorded for the canonical family names; we
        // don't need FindFamily to consider localized aliases when searching.
      // Font substitutions are recorded for the canonical family names;
      // we don't need FindFamily to consider localized aliases when
      // searching.
      if (SharedFontList()->FindFamily(substituteName,
                                       /*aPrimaryNameOnly*/ true)) {
          continue;
        return;
      }
    }
    if (SharedFontList()->FindFamily(actualFontName,
@@ -1989,8 +2012,6 @@ nsresult gfxDWriteFontList::GetFontSubstitutes() {
    }
  }
}
  return NS_OK;
}

struct FontSubstitution {
  const char* aliasName;
+3 −0
Original line number Diff line number Diff line
@@ -466,6 +466,9 @@ class gfxDWriteFontList final : public gfxPlatformFontList {
      const nsTArray<nsCString>* aForceClassicFams = nullptr)
      MOZ_REQUIRES(mLock);

  void AddSubstitute(const nsCString& substituteName,
                     const nsCString& actualFontName);

#ifdef MOZ_BUNDLED_FONTS
  already_AddRefed<IDWriteFontCollection> CreateBundledFontsCollection(
      IDWriteFactory* aFactory);
+28 −0
Original line number Diff line number Diff line
@@ -31,6 +31,10 @@
#include "mozilla/StaticPrefs_gfx.h"
#include "mozilla/Telemetry.h"

#include "nsContentUtils.h"

#include "StandardFonts-win10.inc"

#include <usp10.h>

using namespace mozilla;
@@ -50,6 +54,10 @@ static __inline void BuildKeyNameFromFontName(nsAString& aName) {
  if (aName.Length() >= LF_FACESIZE) aName.Truncate(LF_FACESIZE - 1);
  ToLowerCase(aName);
}
static __inline void BuildKeyNameFromFontName(nsACString& aName) {
  if (aName.Length() >= LF_FACESIZE) aName.Truncate(LF_FACESIZE - 1);
  ToLowerCase(aName);
}

// Implementation of gfxPlatformFontList for Win32 GDI,
// using GDI font enumeration APIs to get the list of fonts
@@ -529,6 +537,26 @@ static void RemoveCharsetFromFontSubstitute(nsAString& aName) {
#define MAX_VALUE_DATA 512

nsresult gfxGDIFontList::GetFontSubstitutes() {
  if (nsContentUtils::ShouldResistFingerprinting(
          "Ignore any fingerprintable user font customization and normalize "
          "font substitutes across different Windows SKUs.",
          RFPTarget::Unknown)) {
    for (const FontSubstitute& fs : kFontSubstitutes) {
      nsAutoCString substituteName(fs.substituteName);
      nsAutoCString actualFontName(fs.actualFontName);
      BuildKeyNameFromFontName(substituteName);
      BuildKeyNameFromFontName(actualFontName);
      gfxFontFamily* ff;
      if (!actualFontName.IsEmpty() &&
          (ff = mFontFamilies.GetWeak(actualFontName))) {
        mFontSubstitutes.InsertOrUpdate(substituteName, RefPtr{ff});
      } else {
        mNonExistingFonts.AppendElement(substituteName);
      }
    }
    return NS_OK;
  }

  HKEY hKey;
  DWORD i, rv, lenAlias, lenActual, valueType;
  WCHAR aliasName[MAX_VALUE_NAME];