Bug 1782710 - Avoid accessing network service or principals on worker threads with font pathways. r=jfkthame

We do some initialization of gfxFontSrcURI and gfxFontFaceSrc that is
main thread only on the DOM worker threads. These portions of the
initialization can easily be deferred to on demand access since they are
only ever used on the main thread itself.

Differential Revision: https://phabricator.services.mozilla.com/D153461
This commit is contained in:
Andrew Osmond 2022-08-03 11:39:34 +00:00
parent 1c23a90c8e
commit 128c09ccdd
6 changed files with 57 additions and 31 deletions

View File

@ -5,6 +5,7 @@
#include "gfxFontSrcURI.h"
#include "mozilla/ServoStyleSet.h"
#include "nsIProtocolHandler.h"
#include "nsProxyRelease.h"
#include "nsNetUtil.h"
@ -18,12 +19,9 @@ static bool HasFlag(nsIURI* aURI, uint32_t aFlag) {
return NS_SUCCEEDED(rv) && value;
}
gfxFontSrcURI::gfxFontSrcURI(nsIURI* aURI) {
MOZ_ASSERT(NS_IsMainThread());
gfxFontSrcURI::gfxFontSrcURI(nsIURI* aURI) : mURI(aURI) {
MOZ_ASSERT(aURI);
mURI = aURI;
// If we have a data: URI, we know that it is backed by an nsSimpleURI,
// and that we don't need to serialize it ahead of time.
nsCString scheme;
@ -49,14 +47,21 @@ gfxFontSrcURI::gfxFontSrcURI(nsIURI* aURI) {
}
mHash = nsURIHashKey::HashKey(mURI);
mInheritsSecurityContext =
HasFlag(aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT);
mSyncLoadIsOK = HasFlag(aURI, nsIProtocolHandler::URI_SYNC_LOAD_IS_OK);
}
gfxFontSrcURI::~gfxFontSrcURI() {
NS_ReleaseOnMainThread("gfxFontSrcURI::mURI", mURI.forget());
gfxFontSrcURI::~gfxFontSrcURI() = default;
void gfxFontSrcURI::EnsureInitialized() {
MOZ_ASSERT(NS_IsMainThread() || mozilla::ServoStyleSet::IsInServoTraversal());
if (mInitialized) {
return;
}
mInheritsSecurityContext =
HasFlag(mURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT);
mSyncLoadIsOK = HasFlag(mURI, nsIProtocolHandler::URI_SYNC_LOAD_IS_OK);
mInitialized = true;
}
bool gfxFontSrcURI::Equals(gfxFontSrcURI* aOther) {

View File

@ -22,7 +22,7 @@ class nsSimpleURI;
* A wrapper for an nsIURI that can be used OMT, which has cached information
* useful for the gfxUserFontSet.
*/
class gfxFontSrcURI {
class gfxFontSrcURI final {
public:
explicit gfxFontSrcURI(nsIURI* aURI);
@ -35,12 +35,22 @@ class gfxFontSrcURI {
nsCString GetSpecOrDefault();
PLDHashNumber Hash() const { return mHash; }
bool InheritsSecurityContext() const { return mInheritsSecurityContext; }
bool SyncLoadIsOK() const { return mSyncLoadIsOK; }
bool InheritsSecurityContext() {
EnsureInitialized();
return mInheritsSecurityContext;
}
bool SyncLoadIsOK() {
EnsureInitialized();
return mSyncLoadIsOK;
}
private:
~gfxFontSrcURI();
void EnsureInitialized();
// The URI.
nsCOMPtr<nsIURI> mURI;
@ -57,12 +67,15 @@ class gfxFontSrcURI {
// Precomputed hash for mURI.
PLDHashNumber mHash;
// Whether the font has been initialized on the main thread.
bool mInitialized = false;
// Whether the nsIURI's protocol handler has the URI_INHERITS_SECURITY_CONTEXT
// flag.
bool mInheritsSecurityContext;
bool mInheritsSecurityContext = false;
// Whether the nsIURI's protocol handler has teh URI_SYNC_LOAD_IS_OK flag.
bool mSyncLoadIsOK;
bool mSyncLoadIsOK = false;
};
#endif // MOZILLA_GFX_FONTSRCURI_H

View File

@ -2012,11 +2012,9 @@ void gfxFontGroup::AddFamilyToFontList(fontlist::Family* aFamily,
StyleGenericFontFamily aGeneric) {
gfxPlatformFontList* pfl = gfxPlatformFontList::PlatformFontList();
if (!aFamily->IsInitialized()) {
if (!NS_IsMainThread() && ServoStyleSet::Current()) {
if (ServoStyleSet* set = gfxFontUtils::CurrentServoStyleSet()) {
// If we need to initialize a Family record, but we're on a style
// worker thread, we have to defer it.
ServoStyleSet* set = ServoStyleSet::Current();
MOZ_ASSERT(set);
set->AppendTask(PostTraversalTask::InitializeFamily(aFamily));
set->AppendTask(PostTraversalTask::FontInfoUpdate(set));
return;

View File

@ -257,7 +257,8 @@ gfxUserFontFamily::~gfxUserFontFamily() {
already_AddRefed<gfxFontSrcPrincipal> gfxFontFaceSrc::LoadPrincipal(
const gfxUserFontSet& aFontSet) const {
MOZ_ASSERT(mSourceType == eSourceType_URL);
if (mUseOriginPrincipal && mOriginPrincipal) {
if (mUseOriginPrincipal) {
MOZ_ASSERT(mOriginPrincipal);
return RefPtr{mOriginPrincipal}.forget();
}
return aFontSet.GetStandardFontLoadPrincipal();

View File

@ -75,17 +75,18 @@ struct gfxFontFaceSrc {
SourceType mSourceType;
// if url, whether to use the origin principal or not
bool mUseOriginPrincipal;
bool mUseOriginPrincipal = false;
// format hint flags, union of all possible formats
// (e.g. TrueType, EOT, SVG, etc.)
// see FLAG_FORMAT_* enum values below
uint32_t mFormatFlags;
nsCString mLocalName; // full font name if local
RefPtr<gfxFontSrcURI> mURI; // uri if url
nsCOMPtr<nsIReferrerInfo> mReferrerInfo; // referrer info if url
RefPtr<gfxFontSrcPrincipal> mOriginPrincipal; // principal if url
nsCString mLocalName; // full font name if local
RefPtr<gfxFontSrcURI> mURI; // uri if url
nsCOMPtr<nsIReferrerInfo> mReferrerInfo; // referrer info if url
RefPtr<gfxFontSrcPrincipal>
mOriginPrincipal; // principal if url and mUseOriginPrincipal
RefPtr<gfxFontFaceBufferSource> mBuffer;
@ -106,12 +107,18 @@ inline bool operator==(const gfxFontFaceSrc& a, const gfxFontFaceSrc& b) {
case gfxFontFaceSrc::eSourceType_Local:
return a.mLocalName == b.mLocalName;
case gfxFontFaceSrc::eSourceType_URL: {
if (a.mUseOriginPrincipal != b.mUseOriginPrincipal) {
return false;
}
if (a.mUseOriginPrincipal &&
!a.mOriginPrincipal->Equals(b.mOriginPrincipal)) {
return false;
}
bool equals;
return a.mUseOriginPrincipal == b.mUseOriginPrincipal &&
a.mFormatFlags == b.mFormatFlags &&
return a.mFormatFlags == b.mFormatFlags &&
(a.mURI == b.mURI || a.mURI->Equals(b.mURI)) &&
NS_SUCCEEDED(a.mReferrerInfo->Equals(b.mReferrerInfo, &equals)) &&
equals && a.mOriginPrincipal->Equals(b.mOriginPrincipal);
equals;
}
case gfxFontFaceSrc::eSourceType_Buffer:
return a.mBuffer == b.mBuffer;

View File

@ -513,15 +513,17 @@ FontFaceSetImpl::FindOrCreateUserFontEntryFromFontFace(
face->mURI = uri ? new gfxFontSrcURI(uri) : nullptr;
const URLExtraData& extraData = url->ExtraData();
face->mReferrerInfo = extraData.ReferrerInfo();
face->mOriginPrincipal = new gfxFontSrcPrincipal(
extraData.Principal(), extraData.Principal());
// agent and user stylesheets are treated slightly differently,
// the same-site origin check and access control headers are
// enforced against the sheet principal rather than the document
// principal to allow user stylesheets to include @font-face rules
face->mUseOriginPrincipal =
aOrigin == StyleOrigin::User || aOrigin == StyleOrigin::UserAgent;
if (aOrigin == StyleOrigin::User ||
aOrigin == StyleOrigin::UserAgent) {
face->mUseOriginPrincipal = true;
face->mOriginPrincipal = new gfxFontSrcPrincipal(
extraData.Principal(), extraData.Principal());
}
face->mLocalName.Truncate();
face->mFormatFlags = 0;