Differential Revision: https://phabricator.services.mozilla.com/D162616
This commit is contained in:
Andrew Osmond 2022-11-24 18:20:20 +00:00
Родитель ed5352a0d8
Коммит 161a4eb3e8
4 изменённых файлов: 183 добавлений и 70 удалений

Просмотреть файл

@ -38,8 +38,8 @@ mozilla::LogModule* gfxUserFontSet::GetUserFontsLog() {
static Atomic<uint64_t> sFontSetGeneration(0);
gfxUserFontEntry::gfxUserFontEntry(
gfxUserFontSet* aFontSet, const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
WeightRange aWeight, StretchRange aStretch, SlantStyleRange aStyle,
const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList, WeightRange aWeight,
StretchRange aStretch, SlantStyleRange aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
const nsTArray<gfxFontVariation>& aVariationSettings,
uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges,
@ -52,8 +52,7 @@ gfxUserFontEntry::gfxUserFontEntry(
mSeenLocalSource(false),
mUnsupportedFormat(false),
mFontDisplay(aFontDisplay),
mLoader(nullptr),
mFontSet(aFontSet) {
mLoader(nullptr) {
mIsUserFontContainer = true;
mSrcList = aFontFaceSrcList.Clone();
mCurrentSrcIndex = 0;
@ -410,6 +409,15 @@ static bool IgnorePrincipal(gfxFontSrcURI* aURI) {
}
void gfxUserFontEntry::DoLoadNextSrc(bool aForceAsync) {
RefPtr<gfxUserFontSet> fontSet = GetUserFontSet();
if (NS_WARN_IF(!fontSet)) {
LOG(("userfonts (%p) failed expired font set for (%s)\n", fontSet.get(),
mFamilyName.get()));
mFontDataLoadingState = LOADING_FAILED;
SetLoadState(STATUS_FAILED);
return;
}
uint32_t numSrc = mSrcList.Length();
// load each src entry in turn, until a local face is found
@ -425,7 +433,7 @@ void gfxUserFontEntry::DoLoadNextSrc(bool aForceAsync) {
gfxFontEntry* fe = nullptr;
if (!pfl->IsFontFamilyWhitelistActive()) {
fe = gfxPlatform::GetPlatform()->LookupLocalFont(
mFontSet->GetPresContext(), currSrc.mLocalName, Weight(), Stretch(),
fontSet->GetPresContext(), currSrc.mLocalName, Weight(), Stretch(),
SlantStyle());
// Note that we've attempted a local lookup, even if it failed,
// as this means we are dependent on any updates to the font list.
@ -440,8 +448,8 @@ void gfxUserFontEntry::DoLoadNextSrc(bool aForceAsync) {
}
if (fe) {
LOG(("userfonts (%p) [src %d] loaded local: (%s) for (%s) gen: %8.8x\n",
mFontSet, mCurrentSrcIndex, currSrc.mLocalName.get(),
mFamilyName.get(), uint32_t(mFontSet->mGeneration)));
fontSet.get(), mCurrentSrcIndex, currSrc.mLocalName.get(),
mFamilyName.get(), uint32_t(fontSet->mGeneration)));
fe->mFeatureSettings.AppendElements(mFeatureSettings);
fe->mVariationSettings.AppendElements(mVariationSettings);
fe->mLanguageOverride = mLanguageOverride;
@ -462,8 +470,9 @@ void gfxUserFontEntry::DoLoadNextSrc(bool aForceAsync) {
currSrc.mSourceType + 1);
return;
} else {
LOG(("userfonts (%p) [src %d] failed local: (%s) for (%s)\n", mFontSet,
mCurrentSrcIndex, currSrc.mLocalName.get(), mFamilyName.get()));
LOG(("userfonts (%p) [src %d] failed local: (%s) for (%s)\n",
fontSet.get(), mCurrentSrcIndex, currSrc.mLocalName.get(),
mFamilyName.get()));
}
}
@ -494,7 +503,7 @@ void gfxUserFontEntry::DoLoadNextSrc(bool aForceAsync) {
LOG(
("userfonts (%p) [src %d] "
"loaded uri from cache: (%s) for (%s)\n",
mFontSet, mCurrentSrcIndex,
fontSet.get(), mCurrentSrcIndex,
currSrc.mURI->GetSpecOrDefault().get(), mFamilyName.get()));
}
return;
@ -510,7 +519,7 @@ void gfxUserFontEntry::DoLoadNextSrc(bool aForceAsync) {
// record the principal we should use for the load for use when
// creating a channel and when caching the loaded entry.
mPrincipal = currSrc.LoadPrincipal(*mFontSet);
mPrincipal = currSrc.LoadPrincipal(*fontSet);
bool loadDoesntSpin = !aForceAsync && currSrc.mURI->SyncLoadIsOK();
@ -520,7 +529,7 @@ void gfxUserFontEntry::DoLoadNextSrc(bool aForceAsync) {
// sync load font immediately
nsresult rv =
mFontSet->SyncLoadFontData(this, &currSrc, buffer, bufferLength);
fontSet->SyncLoadFontData(this, &currSrc, buffer, bufferLength);
if (NS_SUCCEEDED(rv) &&
LoadPlatformFontSync(mCurrentSrcIndex, buffer, bufferLength)) {
@ -529,26 +538,26 @@ void gfxUserFontEntry::DoLoadNextSrc(bool aForceAsync) {
currSrc.mSourceType + 1);
return;
} else {
mFontSet->LogMessage(this, mCurrentSrcIndex, "font load failed",
nsIScriptError::errorFlag, rv);
fontSet->LogMessage(this, mCurrentSrcIndex, "font load failed",
nsIScriptError::errorFlag, rv);
}
} else {
// otherwise load font async
nsresult rv = mFontSet->StartLoad(this, mCurrentSrcIndex);
nsresult rv = fontSet->StartLoad(this, mCurrentSrcIndex);
bool loadOK = NS_SUCCEEDED(rv);
if (loadOK) {
if (LOG_ENABLED()) {
LOG(("userfonts (%p) [src %d] loading uri: (%s) for (%s)\n",
mFontSet, mCurrentSrcIndex,
fontSet.get(), mCurrentSrcIndex,
currSrc.mURI->GetSpecOrDefault().get(), mFamilyName.get()));
}
return;
} else {
mFontSet->LogMessage(this, mCurrentSrcIndex,
"failed to start download",
nsIScriptError::errorFlag, rv);
fontSet->LogMessage(this, mCurrentSrcIndex,
"failed to start download",
nsIScriptError::errorFlag, rv);
}
}
} else {
@ -577,8 +586,8 @@ void gfxUserFontEntry::DoLoadNextSrc(bool aForceAsync) {
currSrc.mSourceType + 1);
return;
} else {
mFontSet->LogMessage(this, mCurrentSrcIndex, "font load failed",
nsIScriptError::errorFlag);
fontSet->LogMessage(this, mCurrentSrcIndex, "font load failed",
nsIScriptError::errorFlag);
}
}
@ -586,12 +595,12 @@ void gfxUserFontEntry::DoLoadNextSrc(bool aForceAsync) {
}
if (mUnsupportedFormat) {
mFontSet->LogMessage(this, mCurrentSrcIndex, "no supported format found",
nsIScriptError::warningFlag);
fontSet->LogMessage(this, mCurrentSrcIndex, "no supported format found",
nsIScriptError::warningFlag);
}
// all src's failed; mark this entry as unusable (so fallback will occur)
LOG(("userfonts (%p) failed all src for (%s)\n", mFontSet,
LOG(("userfonts (%p) failed all src for (%s)\n", fontSet.get(),
mFamilyName.get()));
mFontDataLoadingState = LOADING_FAILED;
SetLoadState(STATUS_FAILED);
@ -658,22 +667,27 @@ bool gfxUserFontEntry::LoadPlatformFont(uint32_t aSrcIndex,
uint32_t aSanitizedLength,
nsTArray<OTSMessage>&& aMessages) {
MOZ_ASSERT(NS_IsMainThread());
RefPtr<gfxUserFontSet> fontSet = GetUserFontSet();
if (NS_WARN_IF(!fontSet)) {
free((void*)aOriginalFontData);
return false;
}
for (const auto& msg : aMessages) {
mFontSet->LogMessage(this, aSrcIndex, msg.mMessage.get(),
msg.mLevel > 0 ? nsIScriptError::warningFlag
: nsIScriptError::errorFlag);
fontSet->LogMessage(this, aSrcIndex, msg.mMessage.get(),
msg.mLevel > 0 ? nsIScriptError::warningFlag
: nsIScriptError::errorFlag);
}
if (!aSanitizedFontData) {
mFontSet->LogMessage(this, aSrcIndex, "rejected by sanitizer");
fontSet->LogMessage(this, aSrcIndex, "rejected by sanitizer");
} else {
// Check whether aSanitizedFontData is a known OpenType format; it might be
// a TrueType Collection, which OTS would accept but we don't yet
// know how to handle. If so, discard.
if (gfxFontUtils::DetermineFontDataType(
aSanitizedFontData, aSanitizedLength) != GFX_USERFONT_OPENTYPE) {
mFontSet->LogMessage(this, aSrcIndex, "not a supported OpenType format");
fontSet->LogMessage(this, aSrcIndex, "not a supported OpenType format");
free((void*)aSanitizedFontData);
aSanitizedFontData = nullptr;
}
@ -721,7 +735,7 @@ bool gfxUserFontEntry::LoadPlatformFont(uint32_t aSrcIndex,
mName, Weight(), Stretch(), SlantStyle(), aSanitizedFontData,
aSanitizedLength);
if (!fe) {
mFontSet->LogMessage(this, aSrcIndex, "not usable by platform");
fontSet->LogMessage(this, aSrcIndex, "not usable by platform");
}
}
@ -755,15 +769,15 @@ bool gfxUserFontEntry::LoadPlatformFont(uint32_t aSrcIndex,
fe->mDescentOverride = mDescentOverride;
fe->mLineGapOverride = mLineGapOverride;
fe->mSizeAdjust = mSizeAdjust;
StoreUserFontData(fe, aSrcIndex, mFontSet->GetPrivateBrowsing(),
StoreUserFontData(fe, aSrcIndex, fontSet->GetPrivateBrowsing(),
originalFullName, &metadata, metaOrigLen, compression);
if (LOG_ENABLED()) {
LOG((
"userfonts (%p) [src %d] loaded uri: (%s) for (%s) "
"(%p) gen: %8.8x compress: %d%%\n",
mFontSet, aSrcIndex,
fontSet.get(), aSrcIndex,
mSrcList[aSrcIndex].mURI->GetSpecOrDefault().get(), mFamilyName.get(),
this, uint32_t(mFontSet->mGeneration), fontCompressionRatio));
this, uint32_t(fontSet->mGeneration), fontCompressionRatio));
}
mPlatformFontEntry = fe;
SetLoadState(STATUS_LOADED);
@ -773,7 +787,7 @@ bool gfxUserFontEntry::LoadPlatformFont(uint32_t aSrcIndex,
LOG(
("userfonts (%p) [src %d] failed uri: (%s) for (%s)"
" error making platform font\n",
mFontSet, aSrcIndex,
fontSet.get(), aSrcIndex,
mSrcList[aSrcIndex].mURI->GetSpecOrDefault().get(),
mFamilyName.get()));
}
@ -830,14 +844,17 @@ void gfxUserFontEntry::FontDataDownloadComplete(
return;
}
// download failed or font-display timeout passed
if (mFontDataLoadingState == LOADING_TIMED_OUT) {
mFontSet->LogMessage(this, aSrcIndex,
"font-display timeout, webfont not used",
nsIScriptError::infoFlag, aDownloadStatus);
} else {
mFontSet->LogMessage(this, aSrcIndex, "download failed",
nsIScriptError::errorFlag, aDownloadStatus);
RefPtr<gfxUserFontSet> fontSet = GetUserFontSet();
if (fontSet) {
// download failed or font-display timeout passed
if (mFontDataLoadingState == LOADING_TIMED_OUT) {
fontSet->LogMessage(this, aSrcIndex,
"font-display timeout, webfont not used",
nsIScriptError::infoFlag, aDownloadStatus);
} else {
fontSet->LogMessage(this, aSrcIndex, "download failed",
nsIScriptError::errorFlag, aDownloadStatus);
}
}
if (aFontData) {
@ -860,8 +877,12 @@ void gfxUserFontEntry::LoadPlatformFontAsync(
// We hold a strong reference to the gfxUserFontSet during this work, since
// the document might be closed while we are OMT, and release it at the end
// of ContinuePlatformFontLoadOnMainThread.
//
// If the set has already been freed, then the loading will fail when we
// resume on the main thread.
mFontSet->AddRef();
MOZ_ASSERT(!mLoadingFontSet);
mLoadingFontSet = GetUserFontSet();
nsCOMPtr<nsIRunnable> event =
NewRunnableMethod<uint32_t, const uint8_t*, uint32_t,
@ -893,7 +914,10 @@ void gfxUserFontEntry::ContinuePlatformFontLoadOnMainThread(
FontLoadFailed(aCallback);
}
mFontSet->Release(); // for the AddRef in LoadPlatformFontAsync
// Set in LoadPlatformFontAsync. If it is null, then the font set should have
// already been freed and we would not succeed in loading the font.
MOZ_ASSERT_IF(loaded, mLoadingFontSet);
mLoadingFontSet = nullptr;
}
void gfxUserFontEntry::FontLoadFailed(nsIFontLoadCompleteCallback* aCallback) {
@ -919,7 +943,10 @@ void gfxUserFontEntry::FontLoadFailed(nsIFontLoadCompleteCallback* aCallback) {
void gfxUserFontEntry::GetUserFontSets(
nsTArray<RefPtr<gfxUserFontSet>>& aResult) {
aResult.Clear();
aResult.AppendElement(mFontSet);
RefPtr<gfxUserFontSet> fontSet = GetUserFontSet();
if (fontSet) {
aResult.AppendElement(std::move(fontSet));
}
}
gfxUserFontSet::gfxUserFontSet()
@ -1260,19 +1287,23 @@ void gfxUserFontSet::UserFontCache::ForgetFont(gfxFontEntry* aFontEntry) {
gfxFontEntry* gfxUserFontSet::UserFontCache::GetFont(
const gfxFontFaceSrc& aSrc, const gfxUserFontEntry& aUserFontEntry) {
if (!sUserFonts || aUserFontEntry.mFontSet->BypassCache() ||
if (!sUserFonts ||
Preferences::GetBool("gfx.downloadable_fonts.disable_cache")) {
return nullptr;
}
RefPtr<gfxUserFontSet> srcFontSet = aUserFontEntry.GetUserFontSet();
if (NS_WARN_IF(!srcFontSet) || srcFontSet->BypassCache()) {
return nullptr;
}
// Ignore principal when looking up a data: URI.
RefPtr<gfxFontSrcPrincipal> principal =
IgnorePrincipal(aSrc.mURI) ? nullptr
: aSrc.LoadPrincipal(*aUserFontEntry.mFontSet);
IgnorePrincipal(aSrc.mURI) ? nullptr : aSrc.LoadPrincipal(*srcFontSet);
Entry* entry = sUserFonts->GetEntry(
Key(aSrc.mURI, principal, const_cast<gfxUserFontEntry*>(&aUserFontEntry),
aUserFontEntry.mFontSet->GetPrivateBrowsing()));
srcFontSet->GetPrivateBrowsing()));
if (!entry) {
return nullptr;
}
@ -1280,7 +1311,7 @@ gfxFontEntry* gfxUserFontSet::UserFontCache::GetFont(
// We have to perform another content policy check here to prevent
// cache poisoning. E.g. a.com loads a font into the cache but
// b.com has a CSP not allowing any fonts to be loaded.
if (!aUserFontEntry.mFontSet->IsFontLoadAllowed(aSrc)) {
if (!srcFontSet->IsFontLoadAllowed(aSrc)) {
return nullptr;
}

Просмотреть файл

@ -56,7 +56,7 @@ enum class StyleFontDisplay : uint8_t;
} // namespace mozilla
class nsFontFaceLoader;
//#define DEBUG_USERFONT_CACHE
// #define DEBUG_USERFONT_CACHE
class gfxFontFaceBufferSource {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxFontFaceBufferSource)
@ -561,7 +561,6 @@ class gfxUserFontEntry : public gfxFontEntry {
};
gfxUserFontEntry(
gfxUserFontSet* aFontSet,
const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList, WeightRange aWeight,
StretchRange aStretch, SlantStyleRange aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
@ -603,6 +602,8 @@ class gfxUserFontEntry : public gfxFontEntry {
UserFontLoadState LoadState() const { return mUserFontLoadState; }
void LoadCanceled() {
MOZ_ASSERT(NS_IsMainThread());
mUserFontLoadState = STATUS_NOT_LOADED;
mFontDataLoadingState = NOT_LOADING;
mLoader = nullptr;
@ -647,8 +648,16 @@ class gfxUserFontEntry : public gfxFontEntry {
// methods to expose some information to FontFaceSet::UserFontSet
// since we can't make that class a friend
void SetLoader(nsFontFaceLoader* aLoader) { mLoader = aLoader; }
nsFontFaceLoader* GetLoader() const { return mLoader; }
void SetLoader(nsFontFaceLoader* aLoader) {
MOZ_ASSERT(NS_IsMainThread());
mLoader = aLoader;
}
nsFontFaceLoader* GetLoader() const {
MOZ_ASSERT(NS_IsMainThread());
return mLoader;
}
gfxFontSrcPrincipal* GetPrincipal() const { return mPrincipal; }
void GetFamilyNameAndURIForLogging(uint32_t aSrcIndex,
nsACString& aFamilyName, nsACString& aURI);
@ -658,9 +667,7 @@ class gfxUserFontEntry : public gfxFontEntry {
return nullptr;
}
#ifdef DEBUG
gfxUserFontSet* GetUserFontSet() const { return mFontSet; }
#endif
virtual already_AddRefed<gfxUserFontSet> GetUserFontSet() const = 0;
const nsTArray<gfxFontFaceSrc>& SourceList() const { return mSrcList; }
@ -752,8 +759,8 @@ class gfxUserFontEntry : public gfxFontEntry {
uint32_t aMetaOrigLen, uint8_t aCompression);
// Clears and then adds to aResult all of the user font sets that this user
// font entry has been added to. This will at least include mFontSet, the
// owner of this user font entry.
// font entry has been added to. This will at least include the owner of this
// user font entry.
virtual void GetUserFontSets(nsTArray<RefPtr<gfxUserFontSet>>& aResult);
// Calls IncrementGeneration() on all user font sets that contain this
@ -789,8 +796,7 @@ class gfxUserFontEntry : public gfxFontEntry {
// Cancel() methods of nsFontFaceLoader this reference is nulled out.
nsFontFaceLoader* MOZ_NON_OWNING_REF
mLoader; // current loader for this entry, if any
gfxUserFontSet* MOZ_NON_OWNING_REF
mFontSet; // font-set which owns this userfont entry
RefPtr<gfxUserFontSet> mLoadingFontSet;
RefPtr<gfxFontSrcPrincipal> mPrincipal;
};

Просмотреть файл

@ -519,14 +519,12 @@ void FontFaceImpl::SetUserFontEntry(gfxUserFontEntry* aEntry) {
}
if (mUserFontEntry) {
MutexAutoLock lock(mUserFontEntry->mMutex);
mUserFontEntry->mFontFaces.RemoveElement(this);
mUserFontEntry->RemoveFontFace(this);
}
auto* entry = static_cast<Entry*>(aEntry);
if (entry) {
MutexAutoLock lock(entry->mMutex);
entry->mFontFaces.AppendElement(this);
entry->AddFontFace(this);
}
mUserFontEntry = entry;
@ -535,7 +533,7 @@ void FontFaceImpl::SetUserFontEntry(gfxUserFontEntry* aEntry) {
return;
}
MOZ_ASSERT(mUserFontEntry->GetUserFontSet() == mFontFaceSet,
MOZ_ASSERT(mUserFontEntry->HasUserFontSet(mFontFaceSet),
"user font entry must be associated with the same user font set "
"as the FontFace");
@ -700,6 +698,11 @@ void FontFaceImpl::RemoveFontFaceSet(FontFaceSetImpl* aFontFaceSet) {
} else {
mOtherFontFaceSets.RemoveElement(aFontFaceSet);
}
// The caller should be holding a strong reference to the FontFaceSetImpl.
if (mUserFontEntry) {
mUserFontEntry->CheckUserFontSet();
}
}
gfxCharacterMap* FontFaceImpl::GetUnicodeRangeAsCharacterMap() {
@ -766,6 +769,11 @@ void FontFaceImpl::Entry::GetUserFontSets(
MutexAutoLock lock(mMutex);
aResult.Clear();
if (mFontSet) {
aResult.AppendElement(mFontSet);
}
for (FontFaceImpl* f : mFontFaces) {
if (f->mInFontFaceSet) {
aResult.AppendElement(f->mFontFaceSet);
@ -781,6 +789,40 @@ void FontFaceImpl::Entry::GetUserFontSets(
aResult.TruncateLength(it - aResult.begin());
}
/* virtual */ already_AddRefed<gfxUserFontSet>
FontFaceImpl::Entry::GetUserFontSet() const {
MutexAutoLock lock(mMutex);
if (mFontSet) {
return do_AddRef(mFontSet);
}
if (NS_IsMainThread() && mLoadingFontSet) {
return do_AddRef(mLoadingFontSet);
}
return nullptr;
}
void FontFaceImpl::Entry::CheckUserFontSetLocked() {
// If this is the last font containing a strong reference to the set, we need
// to clear the reference as there is no longer anything guaranteeing the set
// will be kept alive.
if (mFontSet) {
auto* set = static_cast<FontFaceSetImpl*>(mFontSet);
for (FontFaceImpl* f : mFontFaces) {
if (f->mFontFaceSet == set || f->mOtherFontFaceSets.Contains(set)) {
return;
}
}
}
// If possible, promote the most recently added FontFace and its owning
// FontFaceSetImpl as the primary set.
if (!mFontFaces.IsEmpty()) {
mFontSet = mFontFaces.LastElement()->mFontFaceSet;
} else {
mFontSet = nullptr;
}
}
void FontFaceImpl::Entry::FindFontFaceOwners(nsTHashSet<FontFace*>& aOwners) {
MutexAutoLock lock(mMutex);
for (FontFaceImpl* f : mFontFaces) {
@ -790,5 +832,17 @@ void FontFaceImpl::Entry::FindFontFaceOwners(nsTHashSet<FontFace*>& aOwners) {
}
}
void FontFaceImpl::Entry::AddFontFace(FontFaceImpl* aFontFace) {
MutexAutoLock lock(mMutex);
mFontFaces.AppendElement(aFontFace);
CheckUserFontSetLocked();
}
void FontFaceImpl::Entry::RemoveFontFace(FontFaceImpl* aFontFace) {
MutexAutoLock lock(mMutex);
mFontFaces.RemoveElement(aFontFace);
CheckUserFontSetLocked();
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -56,19 +56,41 @@ class FontFaceImpl final {
StyleFontDisplay aFontDisplay, RangeFlags aRangeFlags,
float aAscentOverride, float aDescentOverride, float aLineGapOverride,
float aSizeAdjust)
: gfxUserFontEntry(aFontSet, aFontFaceSrcList, aWeight, aStretch,
aStyle, aFeatureSettings, aVariationSettings,
: gfxUserFontEntry(aFontFaceSrcList, aWeight, aStretch, aStyle,
aFeatureSettings, aVariationSettings,
aLanguageOverride, aUnicodeRanges, aFontDisplay,
aRangeFlags, aAscentOverride, aDescentOverride,
aLineGapOverride, aSizeAdjust),
mMutex("FontFaceImpl::Entry::mMutex") {}
mMutex("FontFaceImpl::Entry::mMutex"),
mFontSet(aFontSet) {}
void SetLoadState(UserFontLoadState aLoadState) override;
void GetUserFontSets(nsTArray<RefPtr<gfxUserFontSet>>& aResult) override;
already_AddRefed<gfxUserFontSet> GetUserFontSet() const override;
void CheckUserFontSet() {
MutexAutoLock lock(mMutex);
CheckUserFontSetLocked();
}
#ifdef DEBUG
bool HasUserFontSet(gfxUserFontSet* aFontSet) const {
MutexAutoLock lock(mMutex);
return mFontSet == aFontSet;
}
#endif
void AddFontFace(FontFaceImpl* aOwner);
void RemoveFontFace(FontFaceImpl* aOwner);
void FindFontFaceOwners(nsTHashSet<FontFace*>& aOwners);
protected:
Mutex mMutex;
void CheckUserFontSetLocked() MOZ_REQUIRES(mMutex);
mutable Mutex mMutex;
// Font set which owns this entry;
gfxUserFontSet* MOZ_NON_OWNING_REF mFontSet;
// The FontFace objects that use this user font entry. We need to store
// an array of these, not just a single pointer, since the user font