Bug 1694123 - Pass userfont source index to font loader and decoder tasks, to avoid potential race with the field in the gfxUserFontEntry being reset on the main thread. r=layout-reviewers,emilio

This is a preliminary step that is needed in order for the following patch to be safe. (It's
mostly just plumbing, although the patch looks big because we need to pass the index through
so many functions.)

The issue is that loading a font resource involves a couple of tasks that happen asynchronously -
fetching the data from the network, and decoding/sanitizing the font data. We have an implicit
assumption that once a font load has been initiated, the state of the associated gfxUserFontEntry
will not change; in particular, we depend on mSrcIndex remaining constant, because we may use it
to index into the mSrcList array and access the gfxFontFaceSrc record again in the various
completion tasks that are executed after the async steps finish.

But the following patch breaks this assumption, because it may reset mSrcIndex at arbitrary times
when we discover that we need to re-resolve the @font-face to potentially recognize a src:local()
resource that was earlier in the list, but was previously unavailable. If this happens while
a font-load is doing its off-main-thread work, then when it completes, it will end up accessing
the wrong gfxFontFaceSrc record, which would result at least in incorrect behavior, but can also
result in a crash (e.g. if the record is of the wrong type altogether, such as trying to use the
principal or URI fields from a record of type src:local).

To avoid this problem, we should pass the source index at the time the font load is initiated
through to the OMT tasks and back to their main-thread completion routines, so that we do not
depend on the field in the gfxUserFontEntry remaining frozen. This makes the loading process
safe even if the source index in the entry gets reset while loading tasks are in progress.

Differential Revision: https://phabricator.services.mozilla.com/D110911
This commit is contained in:
Jonathan Kew 2021-04-06 16:23:17 +00:00
parent 3cf3cf1042
commit 87da9bf675
8 changed files with 155 additions and 127 deletions

View File

@ -796,7 +796,7 @@ gfxFont::gfxFont(const RefPtr<UnscaledFont>& aUnscaledFont,
: mFontEntry(aFontEntry),
mUnscaledFont(aUnscaledFont),
mStyle(*aFontStyle),
mAdjustedSize(-1.0), // negative to indicate "not yet initialized"
mAdjustedSize(-1.0), // negative to indicate "not yet initialized"
mFUnitsConvFactor(-1.0f), // negative to indicate "not yet initialized"
mAntialiasOption(anAAOption),
mIsValid(true),

View File

@ -1492,7 +1492,9 @@ class gfxFont {
// but it may be overridden by a value computed in metrics initialization
// from font-size-adjust.
if (mAdjustedSize < 0.0) {
mAdjustedSize = mStyle.sizeAdjust == 0.0 ? 0.0 : mStyle.size * mFontEntry->mSizeAdjust;
mAdjustedSize = mStyle.sizeAdjust == 0.0
? 0.0
: mStyle.size * mFontEntry->mSizeAdjust;
}
return mAdjustedSize;
}

View File

@ -55,7 +55,7 @@ gfxUserFontEntry::gfxUserFontEntry(
mFontSet(aFontSet) {
mIsUserFontContainer = true;
mSrcList = aFontFaceSrcList.Clone();
mSrcIndex = 0;
mCurrentSrcIndex = 0;
mWeightRange = aWeight;
mStretchRange = aStretch;
mStyleRange = aStyle;
@ -120,8 +120,7 @@ bool gfxUserFontEntry::Matches(
mSrcList == aFontFaceSrcList && mFontDisplay == aFontDisplay &&
mRangeFlags == aRangeFlags && mAscentOverride == aAscentOverride &&
mDescentOverride == aDescentOverride &&
mLineGapOverride == aLineGapOverride &&
mSizeAdjust == aSizeAdjust &&
mLineGapOverride == aLineGapOverride && mSizeAdjust == aSizeAdjust &&
((!aUnicodeRanges && !mCharacterMap) ||
(aUnicodeRanges && mCharacterMap &&
mCharacterMap->Equals(aUnicodeRanges)));
@ -207,7 +206,7 @@ const uint8_t* gfxUserFontEntry::SanitizeOpenTypeData(
}
void gfxUserFontEntry::StoreUserFontData(gfxFontEntry* aFontEntry,
bool aPrivate,
uint32_t aSrcIndex, bool aPrivate,
const nsACString& aOriginalName,
FallibleTArray<uint8_t>* aMetadata,
uint32_t aMetaOrigLen,
@ -216,8 +215,8 @@ void gfxUserFontEntry::StoreUserFontData(gfxFontEntry* aFontEntry,
aFontEntry->mUserFontData = MakeUnique<gfxUserFontData>();
}
gfxUserFontData* userFontData = aFontEntry->mUserFontData.get();
userFontData->mSrcIndex = mSrcIndex;
const gfxFontFaceSrc& src = mSrcList[mSrcIndex];
userFontData->mSrcIndex = aSrcIndex;
const gfxFontFaceSrc& src = mSrcList[aSrcIndex];
switch (src.mSourceType) {
case gfxFontFaceSrc::eSourceType_Local:
userFontData->mLocalName = src.mLocalName;
@ -263,16 +262,17 @@ gfxFontSrcPrincipal* gfxFontFaceSrc::LoadPrincipal(
return aFontSet.GetStandardFontLoadPrincipal();
}
void gfxUserFontEntry::GetFamilyNameAndURIForLogging(nsACString& aFamilyName,
void gfxUserFontEntry::GetFamilyNameAndURIForLogging(uint32_t aSrcIndex,
nsACString& aFamilyName,
nsACString& aURI) {
aFamilyName = mFamilyName;
aURI.Truncate();
if (mSrcIndex == mSrcList.Length()) {
if (aSrcIndex == mSrcList.Length()) {
aURI.AppendLiteral("(end of source list)");
} else {
if (mSrcList[mSrcIndex].mURI) {
mSrcList[mSrcIndex].mURI->GetSpec(aURI);
if (mSrcList[aSrcIndex].mURI) {
mSrcList[aSrcIndex].mURI->GetSpec(aURI);
// If the source URI was very long, elide the middle of it.
// In principle, the byte-oriented chopping here could leave us
// with partial UTF-8 characters at the point where we cut it,
@ -355,7 +355,7 @@ void CopyWOFFMetadata(const uint8_t* aFontData, uint32_t aLength,
}
void gfxUserFontEntry::LoadNextSrc() {
NS_ASSERTION(mSrcIndex < mSrcList.Length(),
NS_ASSERTION(mCurrentSrcIndex < mSrcList.Length(),
"already at the end of the src list for user font");
NS_ASSERTION((mUserFontLoadState == STATUS_NOT_LOADED ||
mUserFontLoadState == STATUS_LOAD_PENDING ||
@ -371,7 +371,7 @@ void gfxUserFontEntry::LoadNextSrc() {
// we were already loading; move to the next source,
// but don't reset state - if we've already timed out,
// that counts against the new download
mSrcIndex++;
mCurrentSrcIndex++;
}
DoLoadNextSrc(false);
@ -379,7 +379,7 @@ void gfxUserFontEntry::LoadNextSrc() {
void gfxUserFontEntry::ContinueLoad() {
MOZ_ASSERT(mUserFontLoadState == STATUS_LOAD_PENDING);
MOZ_ASSERT(mSrcList[mSrcIndex].mSourceType ==
MOZ_ASSERT(mSrcList[mCurrentSrcIndex].mSourceType ==
gfxFontFaceSrc::eSourceType_URL);
SetLoadState(STATUS_LOADING);
@ -411,8 +411,8 @@ void gfxUserFontEntry::DoLoadNextSrc(bool aForceAsync) {
// load each src entry in turn, until a local face is found
// or a download begins successfully
while (mSrcIndex < numSrc) {
gfxFontFaceSrc& currSrc = mSrcList[mSrcIndex];
while (mCurrentSrcIndex < numSrc) {
gfxFontFaceSrc& currSrc = mSrcList[mCurrentSrcIndex];
// src local ==> lookup and load immediately
@ -433,8 +433,8 @@ void gfxUserFontEntry::DoLoadNextSrc(bool aForceAsync) {
}
if (fe) {
LOG(("userfonts (%p) [src %d] loaded local: (%s) for (%s) gen: %8.8x\n",
mFontSet, mSrcIndex, currSrc.mLocalName.get(), mFamilyName.get(),
uint32_t(mFontSet->mGeneration)));
mFontSet, mCurrentSrcIndex, currSrc.mLocalName.get(),
mFamilyName.get(), uint32_t(mFontSet->mGeneration)));
fe->mFeatureSettings.AppendElements(mFeatureSettings);
fe->mVariationSettings.AppendElements(mVariationSettings);
fe->mLanguageOverride = mLanguageOverride;
@ -447,7 +447,7 @@ void gfxUserFontEntry::DoLoadNextSrc(bool aForceAsync) {
// For src:local(), we don't care whether the request is from
// a private window as there's no issue of caching resources;
// local fonts are just available all the time.
StoreUserFontData(fe, false, nsCString(), nullptr, 0,
StoreUserFontData(fe, mCurrentSrcIndex, false, nsCString(), nullptr, 0,
gfxUserFontData::kUnknownCompression);
mPlatformFontEntry = fe;
SetLoadState(STATUS_LOADED);
@ -456,7 +456,7 @@ void gfxUserFontEntry::DoLoadNextSrc(bool aForceAsync) {
return;
} else {
LOG(("userfonts (%p) [src %d] failed local: (%s) for (%s)\n", mFontSet,
mSrcIndex, currSrc.mLocalName.get(), mFamilyName.get()));
mCurrentSrcIndex, currSrc.mLocalName.get(), mFamilyName.get()));
}
}
@ -487,8 +487,8 @@ void gfxUserFontEntry::DoLoadNextSrc(bool aForceAsync) {
LOG(
("userfonts (%p) [src %d] "
"loaded uri from cache: (%s) for (%s)\n",
mFontSet, mSrcIndex, currSrc.mURI->GetSpecOrDefault().get(),
mFamilyName.get()));
mFontSet, mCurrentSrcIndex,
currSrc.mURI->GetSpecOrDefault().get(), mFamilyName.get()));
}
return;
}
@ -515,30 +515,32 @@ void gfxUserFontEntry::DoLoadNextSrc(bool aForceAsync) {
nsresult rv =
mFontSet->SyncLoadFontData(this, &currSrc, buffer, bufferLength);
if (NS_SUCCEEDED(rv) && LoadPlatformFontSync(buffer, bufferLength)) {
if (NS_SUCCEEDED(rv) &&
LoadPlatformFontSync(mCurrentSrcIndex, buffer, bufferLength)) {
SetLoadState(STATUS_LOADED);
Telemetry::Accumulate(Telemetry::WEBFONT_SRCTYPE,
currSrc.mSourceType + 1);
return;
} else {
mFontSet->LogMessage(this, "font load failed",
mFontSet->LogMessage(this, mCurrentSrcIndex, "font load failed",
nsIScriptError::errorFlag, rv);
}
} else {
// otherwise load font async
nsresult rv = mFontSet->StartLoad(this, &currSrc);
nsresult rv = mFontSet->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, mSrcIndex, currSrc.mURI->GetSpecOrDefault().get(),
mFamilyName.get()));
mFontSet, mCurrentSrcIndex,
currSrc.mURI->GetSpecOrDefault().get(), mFamilyName.get()));
}
return;
} else {
mFontSet->LogMessage(this, "failed to start download",
mFontSet->LogMessage(this, mCurrentSrcIndex,
"failed to start download",
nsIScriptError::errorFlag, rv);
}
}
@ -559,7 +561,8 @@ void gfxUserFontEntry::DoLoadNextSrc(bool aForceAsync) {
// sync load font immediately
currSrc.mBuffer->TakeBuffer(buffer, bufferLength);
if (buffer && LoadPlatformFontSync(buffer, bufferLength)) {
if (buffer &&
LoadPlatformFontSync(mCurrentSrcIndex, buffer, bufferLength)) {
// LoadPlatformFontSync takes ownership of the buffer, so no need
// to free it here.
SetLoadState(STATUS_LOADED);
@ -567,16 +570,16 @@ void gfxUserFontEntry::DoLoadNextSrc(bool aForceAsync) {
currSrc.mSourceType + 1);
return;
} else {
mFontSet->LogMessage(this, "font load failed",
mFontSet->LogMessage(this, mCurrentSrcIndex, "font load failed",
nsIScriptError::errorFlag);
}
}
mSrcIndex++;
mCurrentSrcIndex++;
}
if (mUnsupportedFormat) {
mFontSet->LogMessage(this, "no supported format found",
mFontSet->LogMessage(this, mCurrentSrcIndex, "no supported format found",
nsIScriptError::warningFlag);
}
@ -593,7 +596,8 @@ void gfxUserFontEntry::SetLoadState(UserFontLoadState aLoadState) {
MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC(UserFontMallocSizeOfOnAlloc)
bool gfxUserFontEntry::LoadPlatformFontSync(const uint8_t* aFontData,
bool gfxUserFontEntry::LoadPlatformFontSync(uint32_t aSrcIndex,
const uint8_t* aFontData,
uint32_t aLength) {
AUTO_PROFILER_LABEL("gfxUserFontEntry::LoadPlatformFontSync", OTHER);
NS_ASSERTION((mUserFontLoadState == STATUS_NOT_LOADED ||
@ -613,12 +617,12 @@ bool gfxUserFontEntry::LoadPlatformFontSync(const uint8_t* aFontData,
const uint8_t* saneData =
SanitizeOpenTypeData(aFontData, aLength, saneLen, fontType, messages);
return LoadPlatformFont(aFontData, aLength, fontType, saneData, saneLen,
std::move(messages));
return LoadPlatformFont(aSrcIndex, aFontData, aLength, fontType, saneData,
saneLen, std::move(messages));
}
void gfxUserFontEntry::StartPlatformFontLoadOnBackgroundThread(
const uint8_t* aFontData, uint32_t aLength,
uint32_t aSrcIndex, const uint8_t* aFontData, uint32_t aLength,
nsMainThreadPtrHandle<nsIFontLoadCompleteCallback> aCallback) {
MOZ_ASSERT(!NS_IsMainThread());
@ -629,16 +633,18 @@ void gfxUserFontEntry::StartPlatformFontLoadOnBackgroundThread(
SanitizeOpenTypeData(aFontData, aLength, saneLen, fontType, messages);
nsCOMPtr<nsIRunnable> event =
NewRunnableMethod<const uint8_t*, uint32_t, gfxUserFontType,
NewRunnableMethod<uint32_t, const uint8_t*, uint32_t, gfxUserFontType,
const uint8_t*, uint32_t, nsTArray<OTSMessage>&&,
nsMainThreadPtrHandle<nsIFontLoadCompleteCallback>>(
"gfxUserFontEntry::ContinuePlatformFontLoadOnMainThread", this,
&gfxUserFontEntry::ContinuePlatformFontLoadOnMainThread, aFontData,
aLength, fontType, saneData, saneLen, std::move(messages), aCallback);
&gfxUserFontEntry::ContinuePlatformFontLoadOnMainThread, aSrcIndex,
aFontData, aLength, fontType, saneData, saneLen, std::move(messages),
aCallback);
NS_DispatchToMainThread(event.forget());
}
bool gfxUserFontEntry::LoadPlatformFont(const uint8_t* aOriginalFontData,
bool gfxUserFontEntry::LoadPlatformFont(uint32_t aSrcIndex,
const uint8_t* aOriginalFontData,
uint32_t aOriginalLength,
gfxUserFontType aFontType,
const uint8_t* aSanitizedFontData,
@ -647,20 +653,20 @@ bool gfxUserFontEntry::LoadPlatformFont(const uint8_t* aOriginalFontData,
MOZ_ASSERT(NS_IsMainThread());
for (const auto& msg : aMessages) {
mFontSet->LogMessage(this, msg.mMessage.get(),
mFontSet->LogMessage(this, aSrcIndex, msg.mMessage.get(),
msg.mLevel > 0 ? nsIScriptError::warningFlag
: nsIScriptError::errorFlag);
}
if (!aSanitizedFontData) {
mFontSet->LogMessage(this, "rejected by sanitizer");
mFontSet->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, "not a supported OpenType format");
mFontSet->LogMessage(this, aSrcIndex, "not a supported OpenType format");
free((void*)aSanitizedFontData);
aSanitizedFontData = nullptr;
}
@ -708,7 +714,7 @@ bool gfxUserFontEntry::LoadPlatformFont(const uint8_t* aOriginalFontData,
mName, Weight(), Stretch(), SlantStyle(), aSanitizedFontData,
aSanitizedLength);
if (!fe) {
mFontSet->LogMessage(this, "not usable by platform");
mFontSet->LogMessage(this, aSrcIndex, "not usable by platform");
}
}
@ -742,14 +748,14 @@ bool gfxUserFontEntry::LoadPlatformFont(const uint8_t* aOriginalFontData,
fe->mDescentOverride = mDescentOverride;
fe->mLineGapOverride = mLineGapOverride;
fe->mSizeAdjust = mSizeAdjust;
StoreUserFontData(fe, mFontSet->GetPrivateBrowsing(), originalFullName,
&metadata, metaOrigLen, compression);
StoreUserFontData(fe, aSrcIndex, mFontSet->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, mSrcIndex,
mSrcList[mSrcIndex].mURI->GetSpecOrDefault().get(), mFamilyName.get(),
mFontSet, aSrcIndex,
mSrcList[aSrcIndex].mURI->GetSpecOrDefault().get(), mFamilyName.get(),
this, uint32_t(mFontSet->mGeneration), fontCompressionRatio));
}
mPlatformFontEntry = fe;
@ -760,8 +766,8 @@ bool gfxUserFontEntry::LoadPlatformFont(const uint8_t* aOriginalFontData,
LOG(
("userfonts (%p) [src %d] failed uri: (%s) for (%s)"
" error making platform font\n",
mFontSet, mSrcIndex,
mSrcList[mSrcIndex].mURI->GetSpecOrDefault().get(),
mFontSet, aSrcIndex,
mSrcList[aSrcIndex].mURI->GetSpecOrDefault().get(),
mFamilyName.get()));
}
}
@ -791,8 +797,8 @@ void gfxUserFontEntry::IncrementGeneration() {
// Ownership of aFontData passes in here, and the font set must
// ensure that it is eventually deleted via free().
void gfxUserFontEntry::FontDataDownloadComplete(
const uint8_t* aFontData, uint32_t aLength, nsresult aDownloadStatus,
nsIFontLoadCompleteCallback* aCallback) {
uint32_t aSrcIndex, const uint8_t* aFontData, uint32_t aLength,
nsresult aDownloadStatus, nsIFontLoadCompleteCallback* aCallback) {
MOZ_ASSERT(NS_IsMainThread());
// forget about the loader, as we no longer potentially need to cancel it
@ -803,9 +809,9 @@ void gfxUserFontEntry::FontDataDownloadComplete(
if (NS_SUCCEEDED(aDownloadStatus) &&
mFontDataLoadingState != LOADING_TIMED_OUT) {
if (StaticPrefs::gfx_downloadable_fonts_sanitize_omt()) {
LoadPlatformFontAsync(aFontData, aLength, aCallback);
LoadPlatformFontAsync(aSrcIndex, aFontData, aLength, aCallback);
} else {
bool loaded = LoadPlatformFontSync(aFontData, aLength);
bool loaded = LoadPlatformFontSync(aSrcIndex, aFontData, aLength);
aFontData = nullptr;
if (loaded) {
IncrementGeneration();
@ -819,11 +825,12 @@ void gfxUserFontEntry::FontDataDownloadComplete(
// download failed or font-display timeout passed
if (mFontDataLoadingState == LOADING_TIMED_OUT) {
mFontSet->LogMessage(this, "font-display timeout, webfont not used",
mFontSet->LogMessage(this, aSrcIndex,
"font-display timeout, webfont not used",
nsIScriptError::infoFlag, aDownloadStatus);
} else {
mFontSet->LogMessage(this, "download failed", nsIScriptError::errorFlag,
aDownloadStatus);
mFontSet->LogMessage(this, aSrcIndex, "download failed",
nsIScriptError::errorFlag, aDownloadStatus);
}
if (aFontData) {
@ -834,7 +841,7 @@ void gfxUserFontEntry::FontDataDownloadComplete(
}
void gfxUserFontEntry::LoadPlatformFontAsync(
const uint8_t* aFontData, uint32_t aLength,
uint32_t aSrcIndex, const uint8_t* aFontData, uint32_t aLength,
nsIFontLoadCompleteCallback* aCallback) {
nsMainThreadPtrHandle<nsIFontLoadCompleteCallback> cb(
new nsMainThreadPtrHolder<nsIFontLoadCompleteCallback>("FontLoader",
@ -850,24 +857,25 @@ void gfxUserFontEntry::LoadPlatformFontAsync(
mFontSet->AddRef();
nsCOMPtr<nsIRunnable> event =
NewRunnableMethod<const uint8_t*, uint32_t,
NewRunnableMethod<uint32_t, const uint8_t*, uint32_t,
nsMainThreadPtrHandle<nsIFontLoadCompleteCallback>>(
"gfxUserFontEntry::StartPlatformFontLoadOnBackgroundThread", this,
&gfxUserFontEntry::StartPlatformFontLoadOnBackgroundThread, aFontData,
aLength, cb);
&gfxUserFontEntry::StartPlatformFontLoadOnBackgroundThread, aSrcIndex,
aFontData, aLength, cb);
MOZ_ALWAYS_SUCCEEDS(NS_DispatchBackgroundTask(event.forget()));
}
void gfxUserFontEntry::ContinuePlatformFontLoadOnMainThread(
const uint8_t* aOriginalFontData, uint32_t aOriginalLength,
gfxUserFontType aFontType, const uint8_t* aSanitizedFontData,
uint32_t aSanitizedLength, nsTArray<OTSMessage>&& aMessages,
uint32_t aSrcIndex, const uint8_t* aOriginalFontData,
uint32_t aOriginalLength, gfxUserFontType aFontType,
const uint8_t* aSanitizedFontData, uint32_t aSanitizedLength,
nsTArray<OTSMessage>&& aMessages,
nsMainThreadPtrHandle<nsIFontLoadCompleteCallback> aCallback) {
MOZ_ASSERT(NS_IsMainThread());
bool loaded = LoadPlatformFont(aOriginalFontData, aOriginalLength, aFontType,
aSanitizedFontData, aSanitizedLength,
std::move(aMessages));
bool loaded = LoadPlatformFont(aSrcIndex, aOriginalFontData, aOriginalLength,
aFontType, aSanitizedFontData,
aSanitizedLength, std::move(aMessages));
aOriginalFontData = nullptr;
aSanitizedFontData = nullptr;
@ -955,11 +963,11 @@ already_AddRefed<gfxUserFontEntry> gfxUserFontSet::FindOrCreateUserFontEntry(
}
if (!entry) {
entry = CreateUserFontEntry(
aFontFaceSrcList, aWeight, aStretch, aStyle, aFeatureSettings,
aVariationSettings, aLanguageOverride, aUnicodeRanges, aFontDisplay,
aRangeFlags, aAscentOverride, aDescentOverride, aLineGapOverride,
aSizeAdjust);
entry = CreateUserFontEntry(aFontFaceSrcList, aWeight, aStretch, aStyle,
aFeatureSettings, aVariationSettings,
aLanguageOverride, aUnicodeRanges, aFontDisplay,
aRangeFlags, aAscentOverride, aDescentOverride,
aLineGapOverride, aSizeAdjust);
entry->mFamilyName = aFamilyName;
}

View File

@ -266,8 +266,8 @@ class gfxUserFontSet {
const nsTArray<mozilla::gfx::FontVariation>& aVariationSettings,
uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges,
mozilla::StyleFontDisplay aFontDisplay, RangeFlags aRangeFlags,
float aAscentOverride, float aDescentOverride,
float aLineGapOverride, float aSizeAdjust) = 0;
float aAscentOverride, float aDescentOverride, float aLineGapOverride,
float aSizeAdjust) = 0;
// creates a font face for the specified family, or returns an existing
// matching entry on the family if there is one
@ -308,7 +308,7 @@ class gfxUserFontSet {
// initialize the process that loads external font data, which upon
// completion will call FontDataDownloadComplete method
virtual nsresult StartLoad(gfxUserFontEntry* aUserFontEntry,
const gfxFontFaceSrc* aFontFaceSrc) = 0;
uint32_t aSrcIndex) = 0;
// generation - each time a face is loaded, generation is
// incremented so that the change can be recognized
@ -514,7 +514,7 @@ class gfxUserFontSet {
// report a problem of some kind (implemented in nsUserFontSet)
virtual nsresult LogMessage(gfxUserFontEntry* aUserFontEntry,
const char* aMessage,
uint32_t aSrcIndex, const char* aMessage,
uint32_t aFlags = nsIScriptError::errorFlag,
nsresult aStatus = NS_OK) = 0;
@ -649,8 +649,8 @@ class gfxUserFontEntry : public gfxFontEntry {
void SetLoader(nsFontFaceLoader* aLoader) { mLoader = aLoader; }
nsFontFaceLoader* GetLoader() const { return mLoader; }
gfxFontSrcPrincipal* GetPrincipal() const { return mPrincipal; }
uint32_t GetSrcIndex() const { return mSrcIndex; }
void GetFamilyNameAndURIForLogging(nsACString& aFamilyName, nsACString& aURI);
void GetFamilyNameAndURIForLogging(uint32_t aSrcIndex,
nsACString& aFamilyName, nsACString& aURI);
gfxFontEntry* Clone() const override {
MOZ_ASSERT_UNREACHABLE("cannot Clone user fonts");
@ -663,6 +663,12 @@ class gfxUserFontEntry : public gfxFontEntry {
const nsTArray<gfxFontFaceSrc>& SourceList() const { return mSrcList; }
// Returns a weak reference to the requested source record, which is owned
// by the gfxUserFontEntry.
const gfxFontFaceSrc& SourceAt(uint32_t aSrcIndex) const {
return mSrcList[aSrcIndex];
}
// The variation-query APIs should not be called on placeholders.
bool HasVariations() override {
MOZ_ASSERT_UNREACHABLE("not meaningful for a userfont placeholder");
@ -698,34 +704,37 @@ class gfxUserFontEntry : public gfxFontEntry {
// aDownloadStatus == NS_OK ==> download succeeded, error otherwise
// Ownership of aFontData is passed in here; the font set must
// ensure that it is eventually deleted with free().
void FontDataDownloadComplete(const uint8_t* aFontData, uint32_t aLength,
nsresult aDownloadStatus,
void FontDataDownloadComplete(uint32_t aSrcIndex, const uint8_t* aFontData,
uint32_t aLength, nsresult aDownloadStatus,
nsIFontLoadCompleteCallback* aCallback);
// helper method for creating a platform font
// returns true if platform font creation successful
// Ownership of aFontData is passed in here; the font must
// ensure that it is eventually deleted with free().
bool LoadPlatformFontSync(const uint8_t* aFontData, uint32_t aLength);
bool LoadPlatformFontSync(uint32_t aSrcIndex, const uint8_t* aFontData,
uint32_t aLength);
void LoadPlatformFontAsync(const uint8_t* aFontData, uint32_t aLength,
void LoadPlatformFontAsync(uint32_t aSrcIndex, const uint8_t* aFontData,
uint32_t aLength,
nsIFontLoadCompleteCallback* aCallback);
// helper method for LoadPlatformFontAsync; runs on a background thread
void StartPlatformFontLoadOnBackgroundThread(
const uint8_t* aFontData, uint32_t aLength,
uint32_t aSrcIndex, const uint8_t* aFontData, uint32_t aLength,
nsMainThreadPtrHandle<nsIFontLoadCompleteCallback> aCallback);
// helper method for LoadPlatformFontAsync; runs on the main thread
void ContinuePlatformFontLoadOnMainThread(
const uint8_t* aOriginalFontData, uint32_t aOriginalLength,
gfxUserFontType aFontType, const uint8_t* aSanitizedFontData,
uint32_t aSanitizedLength, nsTArray<OTSMessage>&& aMessages,
uint32_t aSrcIndex, const uint8_t* aOriginalFontData,
uint32_t aOriginalLength, gfxUserFontType aFontType,
const uint8_t* aSanitizedFontData, uint32_t aSanitizedLength,
nsTArray<OTSMessage>&& aMessages,
nsMainThreadPtrHandle<nsIFontLoadCompleteCallback> aCallback);
// helper method for LoadPlatformFontSync and
// ContinuePlatformFontLoadOnMainThread; runs on the main thread
bool LoadPlatformFont(const uint8_t* aOriginalFontData,
bool LoadPlatformFont(uint32_t aSrcIndex, const uint8_t* aOriginalFontData,
uint32_t aOriginalLength, gfxUserFontType aFontType,
const uint8_t* aSanitizedFontData,
uint32_t aSanitizedLength,
@ -736,8 +745,8 @@ class gfxUserFontEntry : public gfxFontEntry {
void FontLoadFailed(nsIFontLoadCompleteCallback* aCallback);
// store metadata and src details for current src into aFontEntry
void StoreUserFontData(gfxFontEntry* aFontEntry, bool aPrivate,
const nsACString& aOriginalName,
void StoreUserFontData(gfxFontEntry* aFontEntry, uint32_t aSrcIndex,
bool aPrivate, const nsACString& aOriginalName,
FallibleTArray<uint8_t>* aMetadata,
uint32_t aMetaOrigLen, uint8_t aCompression);
@ -773,7 +782,7 @@ class gfxUserFontEntry : public gfxFontEntry {
RefPtr<gfxFontEntry> mPlatformFontEntry;
nsTArray<gfxFontFaceSrc> mSrcList;
uint32_t mSrcIndex; // index of loading src item
uint32_t mCurrentSrcIndex; // index of src item to be loaded next
// This field is managed by the nsFontFaceLoader. In the destructor and
// Cancel() methods of nsFontFaceLoader this reference is nulled out.
nsFontFaceLoader* MOZ_NON_OWNING_REF

View File

@ -565,20 +565,22 @@ void FontFaceSet::RemoveLoader(nsFontFaceLoader* aLoader) {
}
nsresult FontFaceSet::StartLoad(gfxUserFontEntry* aUserFontEntry,
const gfxFontFaceSrc* aFontFaceSrc) {
uint32_t aSrcIndex) {
nsresult rv;
nsCOMPtr<nsIStreamLoader> streamLoader;
RefPtr<nsFontFaceLoader> fontLoader;
const gfxFontFaceSrc& src = aUserFontEntry->SourceAt(aSrcIndex);
auto preloadKey =
PreloadHashKey::CreateAsFont(aFontFaceSrc->mURI->get(), CORS_ANONYMOUS);
PreloadHashKey::CreateAsFont(src.mURI->get(), CORS_ANONYMOUS);
RefPtr<PreloaderBase> preload =
mDocument->Preloads().LookupPreload(preloadKey);
if (preload) {
fontLoader = new nsFontFaceLoader(aUserFontEntry, aFontFaceSrc->mURI->get(),
this, preload->Channel());
fontLoader = new nsFontFaceLoader(aUserFontEntry, aSrcIndex, this,
preload->Channel());
rv = NS_NewStreamLoader(getter_AddRefs(streamLoader), fontLoader,
fontLoader);
@ -598,22 +600,20 @@ nsresult FontFaceSet::StartLoad(gfxUserFontEntry* aUserFontEntry,
if (NS_FAILED(rv)) {
nsCOMPtr<nsIChannel> channel;
rv = FontPreloader::BuildChannel(
getter_AddRefs(channel), aFontFaceSrc->mURI->get(), CORS_ANONYMOUS,
dom::ReferrerPolicy::_empty /* not used */, aUserFontEntry,
aFontFaceSrc, mDocument, loadGroup, nullptr, false);
getter_AddRefs(channel), src.mURI->get(), CORS_ANONYMOUS,
dom::ReferrerPolicy::_empty /* not used */, aUserFontEntry, &src,
mDocument, loadGroup, nullptr, false);
NS_ENSURE_SUCCESS(rv, rv);
fontLoader = new nsFontFaceLoader(aUserFontEntry, aFontFaceSrc->mURI->get(),
this, channel);
fontLoader = new nsFontFaceLoader(aUserFontEntry, aSrcIndex, this, channel);
if (LOG_ENABLED()) {
nsCOMPtr<nsIURI> referrer =
aFontFaceSrc->mReferrerInfo
? aFontFaceSrc->mReferrerInfo->GetOriginalReferrer()
: nullptr;
nsCOMPtr<nsIURI> referrer = src.mReferrerInfo
? src.mReferrerInfo->GetOriginalReferrer()
: nullptr;
LOG((
"userfonts (%p) download start - font uri: (%s) referrer uri: (%s)\n",
fontLoader.get(), aFontFaceSrc->mURI->GetSpecOrDefault().get(),
fontLoader.get(), src.mURI->GetSpecOrDefault().get(),
referrer ? referrer->GetSpecOrDefault().get() : ""));
}
@ -629,7 +629,7 @@ nsresult FontFaceSet::StartLoad(gfxUserFontEntry* aUserFontEntry,
mLoaders.PutEntry(fontLoader);
net::PredictorLearn(aFontFaceSrc->mURI->get(), mDocument->GetDocumentURI(),
net::PredictorLearn(src.mURI->get(), mDocument->GetDocumentURI(),
nsINetworkPredictor::LEARN_LOAD_SUBRESOURCE, loadGroup);
if (NS_SUCCEEDED(rv)) {
@ -1190,8 +1190,8 @@ RawServoFontFaceRule* FontFaceSet::FindRuleForUserFontEntry(
}
nsresult FontFaceSet::LogMessage(gfxUserFontEntry* aUserFontEntry,
const char* aMessage, uint32_t aFlags,
nsresult aStatus) {
uint32_t aSrcIndex, const char* aMessage,
uint32_t aFlags, nsresult aStatus) {
MOZ_ASSERT(NS_IsMainThread() ||
ServoStyleSet::IsCurrentThreadInServoTraversal());
@ -1203,7 +1203,7 @@ nsresult FontFaceSet::LogMessage(gfxUserFontEntry* aUserFontEntry,
nsAutoCString familyName;
nsAutoCString fontURI;
aUserFontEntry->GetFamilyNameAndURIForLogging(familyName, fontURI);
aUserFontEntry->GetFamilyNameAndURIForLogging(aSrcIndex, familyName, fontURI);
nsAutoCString weightString;
aUserFontEntry->Weight().ToString(weightString);
@ -1214,7 +1214,7 @@ nsresult FontFaceSet::LogMessage(gfxUserFontEntry* aUserFontEntry,
"(font-family: \"%s\" style:%s weight:%s stretch:%s src index:%d)",
aMessage, familyName.get(),
aUserFontEntry->IsItalic() ? "italic" : "normal", // XXX todo: oblique?
weightString.get(), stretchString.get(), aUserFontEntry->GetSrcIndex());
weightString.get(), stretchString.get(), aSrcIndex);
if (NS_FAILED(aStatus)) {
message.AppendLiteral(": ");
@ -1763,12 +1763,12 @@ void FontFaceSet::UserFontSet::DispatchFontLoadViolations(
}
/* virtual */
nsresult FontFaceSet::UserFontSet::StartLoad(
gfxUserFontEntry* aUserFontEntry, const gfxFontFaceSrc* aFontFaceSrc) {
nsresult FontFaceSet::UserFontSet::StartLoad(gfxUserFontEntry* aUserFontEntry,
uint32_t aSrcIndex) {
if (!mFontFaceSet) {
return NS_ERROR_FAILURE;
}
return mFontFaceSet->StartLoad(aUserFontEntry, aFontFaceSrc);
return mFontFaceSet->StartLoad(aUserFontEntry, aSrcIndex);
}
void FontFaceSet::UserFontSet::RecordFontLoadDone(uint32_t aFontSize,
@ -1791,13 +1791,15 @@ void FontFaceSet::UserFontSet::RecordFontLoadDone(uint32_t aFontSize,
/* virtual */
nsresult FontFaceSet::UserFontSet::LogMessage(gfxUserFontEntry* aUserFontEntry,
uint32_t aSrcIndex,
const char* aMessage,
uint32_t aFlags,
nsresult aStatus) {
if (!mFontFaceSet) {
return NS_ERROR_FAILURE;
}
return mFontFaceSet->LogMessage(aUserFontEntry, aMessage, aFlags, aStatus);
return mFontFaceSet->LogMessage(aUserFontEntry, aSrcIndex, aMessage, aFlags,
aStatus);
}
/* virtual */

View File

@ -72,7 +72,7 @@ class FontFaceSet final : public DOMEventTargetHelper,
nsTArray<nsCOMPtr<nsIRunnable>>& aViolations) override;
virtual nsresult StartLoad(gfxUserFontEntry* aUserFontEntry,
const gfxFontFaceSrc* aFontFaceSrc) override;
uint32_t aSrcIndex) override;
void RecordFontLoadDone(uint32_t aFontSize, TimeStamp aDoneTime) override;
@ -87,7 +87,7 @@ class FontFaceSet final : public DOMEventTargetHelper,
uint8_t*& aBuffer,
uint32_t& aBufferLength) override;
virtual nsresult LogMessage(gfxUserFontEntry* aUserFontEntry,
const char* aMessage,
uint32_t aSrcIndex, const char* aMessage,
uint32_t aFlags = nsIScriptError::errorFlag,
nsresult aStatus = NS_OK) override;
virtual void DoRebuildUserFontSet() override;
@ -98,8 +98,8 @@ class FontFaceSet final : public DOMEventTargetHelper,
const nsTArray<gfxFontVariation>& aVariationSettings,
uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges,
StyleFontDisplay aFontDisplay, RangeFlags aRangeFlags,
float aAscentOverride, float aDescentOverride,
float aLineGapOverride, float aSizeAdjust) override;
float aAscentOverride, float aDescentOverride, float aLineGapOverride,
float aSizeAdjust) override;
private:
RefPtr<FontFaceSet> mFontFaceSet;
@ -266,8 +266,7 @@ class FontFaceSet final : public DOMEventTargetHelper,
RawServoFontFaceRule* FindRuleForUserFontEntry(
gfxUserFontEntry* aUserFontEntry);
nsresult StartLoad(gfxUserFontEntry* aUserFontEntry,
const gfxFontFaceSrc* aFontFaceSrc);
nsresult StartLoad(gfxUserFontEntry* aUserFontEntry, uint32_t aSrcIndex);
gfxFontSrcPrincipal* GetStandardFontLoadPrincipal();
nsresult CheckFontLoad(const gfxFontFaceSrc* aFontFaceSrc,
gfxFontSrcPrincipal** aPrincipal, bool* aBypassCache);
@ -277,8 +276,8 @@ class FontFaceSet final : public DOMEventTargetHelper,
nsresult SyncLoadFontData(gfxUserFontEntry* aFontToLoad,
const gfxFontFaceSrc* aFontFaceSrc,
uint8_t*& aBuffer, uint32_t& aBufferLength);
nsresult LogMessage(gfxUserFontEntry* aUserFontEntry, const char* aMessage,
uint32_t aFlags, nsresult aStatus);
nsresult LogMessage(gfxUserFontEntry* aUserFontEntry, uint32_t aSrcIndex,
const char* aMessage, uint32_t aFlags, nsresult aStatus);
void InsertRuleFontFace(FontFace* aFontFace, StyleOrigin aOrigin,
nsTArray<FontFaceRecord>& aOldRecords,

View File

@ -44,15 +44,21 @@ static uint32_t GetShortFallbackDelay() {
}
nsFontFaceLoader::nsFontFaceLoader(gfxUserFontEntry* aUserFontEntry,
nsIURI* aFontURI, FontFaceSet* aFontFaceSet,
uint32_t aSrcIndex,
FontFaceSet* aFontFaceSet,
nsIChannel* aChannel)
: mUserFontEntry(aUserFontEntry),
mFontURI(aFontURI),
mFontFaceSet(aFontFaceSet),
mChannel(aChannel),
mStreamLoader(nullptr) {
mStreamLoader(nullptr),
mSrcIndex(aSrcIndex) {
MOZ_ASSERT(mFontFaceSet,
"We should get a valid FontFaceSet from the caller!");
const gfxFontFaceSrc& src = aUserFontEntry->SourceAt(mSrcIndex);
MOZ_ASSERT(src.mSourceType == gfxFontFaceSrc::eSourceType_URL);
mFontURI = src.mURI->get();
mStartTime = TimeStamp::Now();
// We add an explicit load block rather than just rely on the network
@ -276,7 +282,8 @@ nsFontFaceLoader::OnStreamComplete(nsIStreamLoader* aLoader,
// FontDataDownloadComplete will load the platform font on a worker thread,
// and will call FontLoadComplete when it has finished its work.
mUserFontEntry->FontDataDownloadComplete(aString, aStringLen, aStatus, this);
mUserFontEntry->FontDataDownloadComplete(mSrcIndex, aString, aStringLen,
aStatus, this);
return NS_SUCCESS_ADOPTED_DATA;
}

View File

@ -27,7 +27,7 @@ class nsFontFaceLoader final : public nsIStreamLoaderObserver,
public nsIRequestObserver,
public nsIFontLoadCompleteCallback {
public:
nsFontFaceLoader(gfxUserFontEntry* aFontToLoad, nsIURI* aFontURI,
nsFontFaceLoader(gfxUserFontEntry* aUserFontEntry, uint32_t aSrcIndex,
mozilla::dom::FontFaceSet* aFontFaceSet,
nsIChannel* aChannel);
@ -65,6 +65,7 @@ class nsFontFaceLoader final : public nsIStreamLoaderObserver,
nsCOMPtr<nsITimer> mLoadTimer;
mozilla::TimeStamp mStartTime;
nsIStreamLoader* mStreamLoader;
uint32_t mSrcIndex;
bool mInStreamComplete = false;
bool mInLoadTimerCallback = false;
};