diff --git a/gfx/tests/mochitest/mochitest.ini b/gfx/tests/mochitest/mochitest.ini index d7c583d41f9d..adcac24ea284 100644 --- a/gfx/tests/mochitest/mochitest.ini +++ b/gfx/tests/mochitest/mochitest.ini @@ -6,6 +6,7 @@ subsuite = gpu fail-if = (os == "win" && os_version == "5.1" && e10s) # Bug 1253862 [test_bug509244.html] [test_bug513439.html] +[test_font_whitelist.html] [test_overdraw.html] # Disable test until bug 1064136 is fixed skip-if = true diff --git a/gfx/tests/mochitest/test_font_whitelist.html b/gfx/tests/mochitest/test_font_whitelist.html new file mode 100644 index 000000000000..52c88662c2bc --- /dev/null +++ b/gfx/tests/mochitest/test_font_whitelist.html @@ -0,0 +1,85 @@ + + + + + Test for Bug 1121643 + + + + + +Mozilla Bug 1121643 +M +M +M + + + + diff --git a/gfx/thebes/gfxDWriteFontList.cpp b/gfx/thebes/gfxDWriteFontList.cpp index 56092abecee1..26f550cacca3 100644 --- a/gfx/thebes/gfxDWriteFontList.cpp +++ b/gfx/thebes/gfxDWriteFontList.cpp @@ -739,7 +739,7 @@ gfxDWriteFontList::gfxDWriteFontList() // Arial to avoid this. gfxFontFamily * -gfxDWriteFontList::GetDefaultFont(const gfxFontStyle *aStyle) +gfxDWriteFontList::GetDefaultFontForPlatform(const gfxFontStyle *aStyle) { nsAutoString resolvedName; @@ -855,7 +855,7 @@ enum DWriteInitError { }; nsresult -gfxDWriteFontList::InitFontList() +gfxDWriteFontList::InitFontListForPlatform() { LARGE_INTEGER frequency; // ticks per second LARGE_INTEGER t1, t2, t3, t4, t5; // ticks @@ -876,8 +876,6 @@ gfxDWriteFontList::InitFontList() Preferences::GetBool("gfx.font_rendering.directwrite.use_gdi_table_loading", false); - gfxPlatformFontList::InitFontList(); - mFontSubstitutes.Clear(); mNonExistingFonts.Clear(); @@ -1409,7 +1407,8 @@ gfxDWriteFontList::GlobalFontFallback(const uint32_t aCh, uint32_t& aCmapCount, gfxFontFamily** aMatchedFamily) { - bool useCmaps = gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback(); + bool useCmaps = IsFontFamilyWhitelistActive() || + gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback(); if (useCmaps) { return gfxPlatformFontList::GlobalFontFallback(aCh, diff --git a/gfx/thebes/gfxDWriteFontList.h b/gfx/thebes/gfxDWriteFontList.h index a53d6fc56405..868e09dbd9e5 100644 --- a/gfx/thebes/gfxDWriteFontList.h +++ b/gfx/thebes/gfxDWriteFontList.h @@ -357,9 +357,7 @@ public: } // initialize font lists - virtual nsresult InitFontList(); - - virtual gfxFontFamily* GetDefaultFont(const gfxFontStyle* aStyle); + virtual nsresult InitFontListForPlatform() override; virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName, uint16_t aWeight, @@ -391,6 +389,10 @@ public: virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, FontListSizes* aSizes) const; +protected: + virtual gfxFontFamily* + GetDefaultFontForPlatform(const gfxFontStyle* aStyle) override; + private: friend class gfxDWriteFontFamily; diff --git a/gfx/thebes/gfxFT2FontList.cpp b/gfx/thebes/gfxFT2FontList.cpp index f49e6ae5f917..e0c3096ded03 100644 --- a/gfx/thebes/gfxFT2FontList.cpp +++ b/gfx/thebes/gfxFT2FontList.cpp @@ -1053,7 +1053,7 @@ gfxFT2FontList::AddFaceToList(const nsCString& aEntryName, uint32_t aIndex, // build the font entry name and create an FT2FontEntry, // but do -not- keep a reference to the FT_Face - FT2FontEntry* fe = + RefPtr fe = CreateNamedFontEntry(aFace, aEntryName.get(), aIndex); auto& fontFamilies = @@ -1063,7 +1063,7 @@ gfxFT2FontList::AddFaceToList(const nsCString& aEntryName, uint32_t aIndex, if (fe) { NS_ConvertUTF8toUTF16 name(aFace->family_name); BuildKeyNameFromFontName(name); - gfxFontFamily *family = fontFamilies.GetWeak(name); + RefPtr family = fontFamilies.GetWeak(name); if (!family) { family = new FT2FontFamily(name); fontFamilies.Put(name, family); @@ -1368,7 +1368,7 @@ gfxFT2FontList::AppendFaceFromFontListEntry(const FontListEntry& aFLE, aFLE.isHidden() ? mHiddenFontFamilies : mFontFamilies; fe->mStandardFace = (aStdFile == kStandard); nsAutoString name(aFLE.familyName()); - gfxFontFamily *family = fontFamilies.GetWeak(name); + RefPtr family = fontFamilies.GetWeak(name); if (!family) { family = new FT2FontFamily(name); fontFamilies.Put(name, family); @@ -1470,10 +1470,9 @@ PreloadAsUserFontFaces(nsStringHashKey::KeyType aKey, } nsresult -gfxFT2FontList::InitFontList() +gfxFT2FontList::InitFontListForPlatform() { - // reset font lists - gfxPlatformFontList::InitFontList(); + // reset hidden font list mHiddenFontFamilies.Clear(); LoadSkipSpaceLookupCheck(mSkipSpaceLookupCheckFamilies); @@ -1562,7 +1561,7 @@ searchDone: } gfxFontFamily* -gfxFT2FontList::GetDefaultFont(const gfxFontStyle* aStyle) +gfxFT2FontList::GetDefaultFontForPlatform(const gfxFontStyle* aStyle) { gfxFontFamily *ff = nullptr; #ifdef MOZ_WIDGET_GONK diff --git a/gfx/thebes/gfxFT2FontList.h b/gfx/thebes/gfxFT2FontList.h index d3311fef7aef..63187ba26597 100644 --- a/gfx/thebes/gfxFT2FontList.h +++ b/gfx/thebes/gfxFT2FontList.h @@ -121,8 +121,6 @@ public: gfxFT2FontList(); virtual ~gfxFT2FontList(); - virtual gfxFontFamily* GetDefaultFont(const gfxFontStyle* aStyle); - virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName, uint16_t aWeight, int16_t aStretch, @@ -151,7 +149,8 @@ protected: kStandard } StandardFile; - virtual nsresult InitFontList(); + // initialize font lists + virtual nsresult InitFontListForPlatform() override; void AppendFaceFromFontListEntry(const FontListEntry& aFLE, StandardFile aStdFile); @@ -185,6 +184,9 @@ protected: void FindFontsInDir(const nsCString& aDir, FontNameCache* aFNC, FT2FontFamily::Visibility aVisibility); + virtual gfxFontFamily* + GetDefaultFontForPlatform(const gfxFontStyle* aStyle) override; + nsTHashtable mSkipSpaceLookupCheckFamilies; private: diff --git a/gfx/thebes/gfxFcPlatformFontList.cpp b/gfx/thebes/gfxFcPlatformFontList.cpp index c4e6b01f0322..6dbd8fac28b3 100644 --- a/gfx/thebes/gfxFcPlatformFontList.cpp +++ b/gfx/thebes/gfxFcPlatformFontList.cpp @@ -985,7 +985,7 @@ gfxFcPlatformFontList::AddFontSetFamilies(FcFontSet* aFontSet, bool aAppFonts) } FcChar8* lastFamilyName = (FcChar8*)""; - gfxFontconfigFontFamily* fontFamily = nullptr; + RefPtr fontFamily; nsAutoString familyName; for (int f = 0; f < aFontSet->nfont; f++) { FcPattern* font = aFontSet->fonts[f]; @@ -1061,13 +1061,10 @@ gfxFcPlatformFontList::AddFontSetFamilies(FcFontSet* aFontSet, bool aAppFonts) } nsresult -gfxFcPlatformFontList::InitFontList() +gfxFcPlatformFontList::InitFontListForPlatform() { mLastConfig = FcConfigGetCurrent(); - // reset font lists - gfxPlatformFontList::InitFontList(); - mLocalNames.Clear(); mFcSubstituteCache.Clear(); @@ -1182,7 +1179,7 @@ gfxFcPlatformFontList::GetFontList(nsIAtom *aLangGroup, } gfxFontFamily* -gfxFcPlatformFontList::GetDefaultFont(const gfxFontStyle* aStyle) +gfxFcPlatformFontList::GetDefaultFontForPlatform(const gfxFontStyle* aStyle) { // Get the default font by using a fake name to retrieve the first // scalable font that fontconfig suggests for the given language. diff --git a/gfx/thebes/gfxFcPlatformFontList.h b/gfx/thebes/gfxFcPlatformFontList.h index e87f758f5e1e..26e05809c8cb 100644 --- a/gfx/thebes/gfxFcPlatformFontList.h +++ b/gfx/thebes/gfxFcPlatformFontList.h @@ -218,16 +218,13 @@ public: } // initialize font lists - nsresult InitFontList() override; + virtual nsresult InitFontListForPlatform() override; void GetFontList(nsIAtom *aLangGroup, const nsACString& aGenericFamily, nsTArray& aListOfFonts) override; - gfxFontFamily* - GetDefaultFont(const gfxFontStyle* aStyle) override; - gfxFontEntry* LookupLocalFont(const nsAString& aFontName, uint16_t aWeight, int16_t aStretch, uint8_t aStyle) override; @@ -280,6 +277,9 @@ protected: static void CheckFontUpdates(nsITimer *aTimer, void *aThis); + virtual gfxFontFamily* + GetDefaultFontForPlatform(const gfxFontStyle* aStyle) override; + #ifdef MOZ_BUNDLED_FONTS void ActivateBundledFonts(); nsCString mBundledFontsPath; diff --git a/gfx/thebes/gfxGDIFontList.cpp b/gfx/thebes/gfxGDIFontList.cpp index 2ed3511c129e..d80c49356bbe 100644 --- a/gfx/thebes/gfxGDIFontList.cpp +++ b/gfx/thebes/gfxGDIFontList.cpp @@ -652,13 +652,10 @@ gfxGDIFontList::GetFontSubstitutes() } nsresult -gfxGDIFontList::InitFontList() +gfxGDIFontList::InitFontListForPlatform() { Telemetry::AutoTimer timer; - // reset font lists - gfxPlatformFontList::InitFontList(); - mFontSubstitutes.Clear(); mNonExistingFonts.Clear(); @@ -920,7 +917,7 @@ gfxGDIFontList::FindAndAddFamilies(const nsAString& aFamily, } gfxFontFamily* -gfxGDIFontList::GetDefaultFont(const gfxFontStyle* aStyle) +gfxGDIFontList::GetDefaultFontForPlatform(const gfxFontStyle* aStyle) { gfxFontFamily *ff = nullptr; diff --git a/gfx/thebes/gfxGDIFontList.h b/gfx/thebes/gfxGDIFontList.h index ba2511d0de04..ffb513d649c7 100644 --- a/gfx/thebes/gfxGDIFontList.h +++ b/gfx/thebes/gfxGDIFontList.h @@ -301,9 +301,7 @@ public: } // initialize font lists - virtual nsresult InitFontList(); - - virtual gfxFontFamily* GetDefaultFont(const gfxFontStyle* aStyle); + virtual nsresult InitFontListForPlatform() override; bool FindAndAddFamilies(const nsAString& aFamily, nsTArray* aOutput, @@ -327,6 +325,10 @@ public: virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, FontListSizes* aSizes) const; +protected: + virtual gfxFontFamily* + GetDefaultFontForPlatform(const gfxFontStyle* aStyle) override; + private: friend class gfxWindowsPlatform; diff --git a/gfx/thebes/gfxMacPlatformFontList.h b/gfx/thebes/gfxMacPlatformFontList.h index f517c5a2ddaf..72a237f0cbac 100644 --- a/gfx/thebes/gfxMacPlatformFontList.h +++ b/gfx/thebes/gfxMacPlatformFontList.h @@ -82,8 +82,6 @@ public: static int32_t AppleWeightToCSSWeight(int32_t aAppleWeight); - gfxFontFamily* GetDefaultFont(const gfxFontStyle* aStyle) override; - bool GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName) override; gfxFontEntry* LookupLocalFont(const nsAString& aFontName, @@ -110,6 +108,10 @@ public: gfxFontStyle &aFontStyle, float aDevPixPerCSSPixel); +protected: + virtual gfxFontFamily* + GetDefaultFontForPlatform(const gfxFontStyle* aStyle) override; + private: friend class gfxPlatformMac; @@ -117,7 +119,7 @@ private: virtual ~gfxMacPlatformFontList(); // initialize font lists - nsresult InitFontList() override; + virtual nsresult InitFontListForPlatform() override; // special case font faces treated as font families (set via prefs) void InitSingleFaceList(); diff --git a/gfx/thebes/gfxMacPlatformFontList.mm b/gfx/thebes/gfxMacPlatformFontList.mm index 540034dbcaa3..eda91c71ad61 100644 --- a/gfx/thebes/gfxMacPlatformFontList.mm +++ b/gfx/thebes/gfxMacPlatformFontList.mm @@ -703,7 +703,7 @@ gfxMacPlatformFontList::AddFamily(CFStringRef aFamily) nsAutoString key; ToLowerCase(familyName, key); - gfxFontFamily* familyEntry = new gfxMacFontFamily(familyName, sizeHint); + RefPtr familyEntry = new gfxMacFontFamily(familyName, sizeHint); table.Put(key, familyEntry); // check the bad underline blacklist @@ -713,14 +713,13 @@ gfxMacPlatformFontList::AddFamily(CFStringRef aFamily) } nsresult -gfxMacPlatformFontList::InitFontList() +gfxMacPlatformFontList::InitFontListForPlatform() { nsAutoreleasePool localPool; Telemetry::AutoTimer timer; - // reset font lists - gfxPlatformFontList::InitFontList(); + // reset system font list mSystemFontFamilies.Clear(); // iterate over available families @@ -780,7 +779,7 @@ gfxMacPlatformFontList::InitSingleFaceList() // add only if doesn't exist already if (!mFontFamilies.GetWeak(key)) { - gfxFontFamily *familyEntry = + RefPtr familyEntry = new gfxSingleFaceMacFontFamily(familyName); // LookupLocalFont sets this, need to clear fontEntry->mIsLocalUserFont = false; @@ -927,7 +926,8 @@ gfxMacPlatformFontList::GlobalFontFallback(const uint32_t aCh, uint32_t& aCmapCount, gfxFontFamily** aMatchedFamily) { - bool useCmaps = gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback(); + bool useCmaps = IsFontFamilyWhitelistActive() || + gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback(); if (useCmaps) { return gfxPlatformFontList::GlobalFontFallback(aCh, @@ -1017,7 +1017,7 @@ gfxMacPlatformFontList::GlobalFontFallback(const uint32_t aCh, } gfxFontFamily* -gfxMacPlatformFontList::GetDefaultFont(const gfxFontStyle* aStyle) +gfxMacPlatformFontList::GetDefaultFontForPlatform(const gfxFontStyle* aStyle) { nsAutoreleasePool localPool; diff --git a/gfx/thebes/gfxPlatformFontList.cpp b/gfx/thebes/gfxPlatformFontList.cpp index 4eff107925f6..3fad73253971 100644 --- a/gfx/thebes/gfxPlatformFontList.cpp +++ b/gfx/thebes/gfxPlatformFontList.cpp @@ -100,6 +100,8 @@ static const char* kObservedPrefs[] = { nullptr }; +static const char kFontSystemWhitelistPref[] = "font.system.whitelist"; + // xxx - this can probably be eliminated by reworking pref font handling code static const char *gPrefLangNames[] = { #define FONT_PREF_LANG(enum_id_, str_, atom_id_) str_ @@ -173,7 +175,8 @@ gfxPlatformFontList::MemoryReporter::CollectReports( gfxPlatformFontList::gfxPlatformFontList(bool aNeedFullnamePostscriptNames) : mFontFamilies(64), mOtherFamilyNames(16), mBadUnderlineFamilyNames(8), mSharedCmaps(8), - mStartIndex(0), mIncrement(1), mNumFamilies(0), mFontlistInitCount(0) + mStartIndex(0), mIncrement(1), mNumFamilies(0), mFontlistInitCount(0), + mFontFamilyWhitelistActive(false) { mOtherFamilyNamesInitialized = false; @@ -191,6 +194,9 @@ gfxPlatformFontList::gfxPlatformFontList(bool aNeedFullnamePostscriptNames) NS_ADDREF(gFontListPrefObserver); Preferences::AddStrongObservers(gFontListPrefObserver, kObservedPrefs); + Preferences::RegisterCallback(FontWhitelistPrefChanged, + kFontSystemWhitelistPref); + RegisterStrongMemoryReporter(new MemoryReporter()); } @@ -200,12 +206,43 @@ gfxPlatformFontList::~gfxPlatformFontList() ClearLangGroupPrefFonts(); NS_ASSERTION(gFontListPrefObserver, "There is no font list pref observer"); Preferences::RemoveObservers(gFontListPrefObserver, kObservedPrefs); + Preferences::UnregisterCallback(FontWhitelistPrefChanged, + kFontSystemWhitelistPref); NS_RELEASE(gFontListPrefObserver); } // number of CSS generic font families const uint32_t kNumGenerics = 5; +void +gfxPlatformFontList::ApplyWhitelist() +{ + nsTArray list; + gfxFontUtils::GetPrefsFontList(kFontSystemWhitelistPref, list); + uint32_t numFonts = list.Length(); + mFontFamilyWhitelistActive = (numFonts > 0); + if (!mFontFamilyWhitelistActive) { + return; + } + nsTHashtable familyNamesWhitelist; + for (uint32_t i = 0; i < numFonts; i++) { + nsString key; + ToLowerCase(list[i], key); + familyNamesWhitelist.PutEntry(key); + } + for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) { + // Don't continue if we only have one font left. + if (mFontFamilies.Count() == 1) { + break; + } + nsString fontFamilyName(iter.Key()); + ToLowerCase(fontFamilyName); + if (!familyNamesWhitelist.Contains(fontFamilyName)) { + iter.Remove(); + } + } +} + nsresult gfxPlatformFontList::InitFontList() { @@ -243,6 +280,12 @@ gfxPlatformFontList::InitFontList() sPlatformFontList = this; + nsresult rv = InitFontListForPlatform(); + if (NS_FAILED(rv)) { + return rv; + } + + ApplyWhitelist(); return NS_OK; } @@ -1147,6 +1190,21 @@ gfxPlatformFontList::GetDefaultGeneric(eFontPrefLang aLang) return eFamily_serif; } + +gfxFontFamily* +gfxPlatformFontList::GetDefaultFont(const gfxFontStyle* aStyle) +{ + gfxFontFamily* family = GetDefaultFontForPlatform(aStyle); + if (family) { + return family; + } + // Something has gone wrong and we were unable to retrieve a default font + // from the platform. (Likely the whitelist has blocked all potential + // default fonts.) As a last resort, we return the first font listed in + // mFontFamilies. + return mFontFamilies.Iter().Data(); +} + void gfxPlatformFontList::GetFontFamilyNames(nsTArray& aFontFamilyNames) { @@ -1598,5 +1656,11 @@ gfxPlatformFontList::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf, AddSizeOfExcludingThis(aMallocSizeOf, aSizes); } +bool +gfxPlatformFontList::IsFontFamilyWhitelistActive() +{ + return mFontFamilyWhitelistActive; +} + #undef LOG #undef LOG_ENABLED diff --git a/gfx/thebes/gfxPlatformFontList.h b/gfx/thebes/gfxPlatformFontList.h index e6452d7320fb..c23d97df5be1 100644 --- a/gfx/thebes/gfxPlatformFontList.h +++ b/gfx/thebes/gfxPlatformFontList.h @@ -114,7 +114,7 @@ public: virtual ~gfxPlatformFontList(); // initialize font lists - virtual nsresult InitFontList(); + nsresult InitFontList(); virtual void GetFontList(nsIAtom *aLangGroup, const nsACString& aGenericFamily, @@ -155,7 +155,7 @@ public: // pure virtual functions, to be provided by concrete subclasses // get the system default font family - virtual gfxFontFamily* GetDefaultFont(const gfxFontStyle* aStyle) = 0; + gfxFontFamily* GetDefaultFont(const gfxFontStyle* aStyle); // look up a font by name on the host platform virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName, @@ -248,6 +248,13 @@ public: void GetSampleLangForGroup(nsIAtom* aLanguage, nsACString& aLangStr, bool aCheckEnvironment = true); + // Returns true if the font family whitelist is not empty. + bool IsFontFamilyWhitelistActive(); + + static void FontWhitelistPrefChanged(const char *aPref, void *aClosure) { + gfxPlatformFontList::PlatformFontList()->UpdateFontList(); + } + protected: class MemoryReporter final : public nsIMemoryReporter { @@ -361,6 +368,10 @@ protected: eFontPrefLang aPrefLang, nsTArray>* aGenericFamilies); + virtual nsresult InitFontListForPlatform() = 0; + + void ApplyWhitelist(); + typedef nsRefPtrHashtable FontFamilyTable; typedef nsRefPtrHashtable FontEntryTable; @@ -372,6 +383,10 @@ protected: SizeOfFontEntryTableExcludingThis(const FontEntryTable& aTable, mozilla::MallocSizeOf aMallocSizeOf); + // Platform-specific helper for GetDefaultFont(...). + virtual gfxFontFamily* + GetDefaultFontForPlatform(const gfxFontStyle* aStyle) = 0; + // canonical family name ==> family entry (unique, one name per family entry) FontFamilyTable mFontFamilies; @@ -437,6 +452,8 @@ protected: nsCOMPtr mLangService; nsTArray mCJKPrefLangs; nsTArray mDefaultGenericsLangGroup; + + bool mFontFamilyWhitelistActive; }; #endif /* GFXPLATFORMFONTLIST_H_ */ diff --git a/gfx/thebes/gfxUserFontSet.cpp b/gfx/thebes/gfxUserFontSet.cpp index c91b2b508fa2..2ba95fa7b51d 100644 --- a/gfx/thebes/gfxUserFontSet.cpp +++ b/gfx/thebes/gfxUserFontSet.cpp @@ -422,7 +422,10 @@ gfxUserFontEntry::LoadNextSrc() // src local ==> lookup and load immediately if (currSrc.mSourceType == gfxFontFaceSrc::eSourceType_Local) { - gfxFontEntry* fe = + // Don't look up local fonts if the font whitelist is being used. + gfxFontEntry* fe = gfxPlatformFontList::PlatformFontList()-> + IsFontFamilyWhitelistActive() ? + nullptr : gfxPlatform::GetPlatform()->LookupLocalFont(currSrc.mLocalName, mWeight, mStretch,