Bug 1376964 - Part 9: Use gfxFontSrcPrincipal in the user font set and cache. r=jfkthame

MozReview-Commit-ID: LRRFbkhbgts

--HG--
extra : rebase_source : 1dac8a8e9a817edb086bb75f9f842c1d4df37a1a
This commit is contained in:
Cameron McCormack 2017-07-12 16:36:42 +08:00
parent 8f58fdb304
commit 82079904e6
5 changed files with 103 additions and 41 deletions

View File

@ -540,7 +540,7 @@ gfxUserFontEntry::DoLoadNextSrc(bool aForceAsync)
return;
}
nsIPrincipal* principal = nullptr;
gfxFontSrcPrincipal* principal = nullptr;
bool bypassCache;
nsresult rv = mFontSet->CheckFontLoad(&currSrc, &principal,
&bypassCache);
@ -1155,9 +1155,7 @@ gfxUserFontSet::UserFontCache::Entry::KeyEquals(const KeyTypePointer aKey) const
if (!IgnorePrincipal(mURI)) {
NS_ASSERTION(mPrincipal && aKey->mPrincipal,
"only data: URIs are allowed to omit the principal");
bool result;
if (NS_FAILED(mPrincipal->Equals(aKey->mPrincipal, &result)) ||
!result) {
if (!mPrincipal->Equals(aKey->mPrincipal)) {
return false;
}
}
@ -1222,7 +1220,7 @@ gfxUserFontSet::UserFontCache::CacheFont(gfxFontEntry* aFontEntry)
// For data: URIs, the principal is ignored; anyone who has the same
// data: URI is able to load it and get an equivalent font.
// Otherwise, the principal is used as part of the cache key.
nsIPrincipal* principal;
gfxFontSrcPrincipal* principal;
if (IgnorePrincipal(data->mURI)) {
principal = nullptr;
} else {
@ -1265,7 +1263,7 @@ gfxUserFontSet::UserFontCache::ForgetFont(gfxFontEntry* aFontEntry)
gfxFontEntry*
gfxUserFontSet::UserFontCache::GetFont(gfxFontSrcURI* aSrcURI,
nsIPrincipal* aPrincipal,
gfxFontSrcPrincipal* aPrincipal,
gfxUserFontEntry* aUserFontEntry,
bool aPrivate)
{
@ -1275,7 +1273,7 @@ gfxUserFontSet::UserFontCache::GetFont(gfxFontSrcURI* aSrcURI,
}
// Ignore principal when looking up a data: URI.
nsIPrincipal* principal;
gfxFontSrcPrincipal* principal;
if (IgnorePrincipal(aSrcURI)) {
principal = nullptr;
} else {
@ -1298,8 +1296,9 @@ gfxUserFontSet::UserFontCache::GetFont(gfxFontSrcURI* aSrcURI,
} else {
// Call IsFontLoadAllowed directly, since we are on the main thread.
MOZ_ASSERT(NS_IsMainThread());
nsIPrincipal* principal = aPrincipal ? aPrincipal->get() : nullptr;
allowed = aUserFontEntry->mFontSet->IsFontLoadAllowed(aSrcURI->get(),
aPrincipal);
principal);
MOZ_ASSERT(!entry->IsFontSetAllowedKnown(aUserFontEntry->mFontSet) ||
entry->IsFontSetAllowed(aUserFontEntry->mFontSet) == allowed,
"why does IsFontLoadAllowed return a different value from "
@ -1326,7 +1325,7 @@ gfxUserFontSet::UserFontCache::UpdateAllowedFontSets(
for (auto iter = sUserFonts->Iter(); !iter.Done(); iter.Next()) {
Entry* entry = iter.Get();
if (!entry->IsFontSetAllowedKnown(aUserFontSet)) {
nsIPrincipal* principal = entry->GetPrincipal();
gfxFontSrcPrincipal* principal = entry->GetPrincipal();
if (!principal) {
// This is a data: URI. Just get the standard principal the
// font set uses. (For cases when mUseOriginPrincipal is true,
@ -1336,7 +1335,7 @@ gfxUserFontSet::UserFontCache::UpdateAllowedFontSets(
}
bool allowed =
aUserFontSet->IsFontLoadAllowed(entry->GetURI()->get(),
principal);
principal->get());
entry->SetIsFontSetAllowed(aUserFontSet, allowed);
}
}
@ -1430,7 +1429,7 @@ gfxUserFontSet::UserFontCache::Entry::ReportMemory(
}
if (mPrincipal) {
nsCOMPtr<nsIURI> uri;
mPrincipal->GetURI(getter_AddRefs(uri));
mPrincipal->get()->GetURI(getter_AddRefs(uri));
if (uri) {
nsCString spec = uri->GetSpecOrDefault();
if (!spec.IsEmpty()) {
@ -1490,13 +1489,13 @@ gfxUserFontSet::UserFontCache::Entry::Dump()
if (mPrincipal) {
nsCOMPtr<nsIURI> principalURI;
rv = mPrincipal->GetURI(getter_AddRefs(principalURI));
rv = mPrincipal->get()->GetURI(getter_AddRefs(principalURI));
if (NS_SUCCEEDED(rv)) {
principalURI->GetSpec(principalURISpec);
}
nsCOMPtr<nsIURI> domainURI;
mPrincipal->GetDomain(getter_AddRefs(domainURI));
mPrincipal->get()->GetDomain(getter_AddRefs(domainURI));
if (domainURI) {
setDomain = true;
}

View File

@ -8,6 +8,7 @@
#include "gfxFont.h"
#include "gfxFontFamilyList.h"
#include "gfxFontSrcPrincipal.h"
#include "gfxFontSrcURI.h"
#include "nsRefPtrHashtable.h"
#include "nsCOMPtr.h"
@ -59,7 +60,7 @@ struct gfxFontFaceSrc {
RefPtr<gfxFontSrcURI> mURI; // uri if url
nsCOMPtr<nsIURI> mReferrer; // referrer url if url
mozilla::net::ReferrerPolicy mReferrerPolicy;
nsCOMPtr<nsIPrincipal> mOriginPrincipal; // principal if url
RefPtr<gfxFontSrcPrincipal> mOriginPrincipal; // principal if url
RefPtr<gfxFontFaceBufferSource> mBuffer;
};
@ -112,7 +113,7 @@ public:
nsTArray<uint8_t> mMetadata; // woff metadata block (compressed), if any
RefPtr<gfxFontSrcURI> mURI; // URI of the source, if it was url()
nsCOMPtr<nsIPrincipal> mPrincipal; // principal for the download, if url()
RefPtr<gfxFontSrcPrincipal> mPrincipal; // principal for the download, if url()
nsString mLocalName; // font name used for the source, if local()
nsString mRealName; // original fullname from the font resource
uint32_t mSrcIndex; // index in the rule's source list
@ -257,10 +258,10 @@ public:
// returns the Principal (for use in the key when caching the loaded font),
// and whether the load should bypass the cache (force-reload).
virtual nsresult CheckFontLoad(const gfxFontFaceSrc* aFontFaceSrc,
nsIPrincipal** aPrincipal,
gfxFontSrcPrincipal** aPrincipal,
bool* aBypassCache) = 0;
virtual nsIPrincipal* GetStandardFontLoadPrincipal() = 0;
virtual gfxFontSrcPrincipal* GetStandardFontLoadPrincipal() = 0;
// check whether content policies allow the given URI to load.
virtual bool IsFontLoadAllowed(nsIURI* aFontLocation,
@ -303,7 +304,7 @@ public:
// so we can avoid leaking fonts cached in private windows mode out to
// normal windows.
static gfxFontEntry* GetFont(gfxFontSrcURI* aSrcURI,
nsIPrincipal* aPrincipal,
gfxFontSrcPrincipal* aPrincipal,
gfxUserFontEntry* aUserFontEntry,
bool aPrivate);
@ -369,13 +370,13 @@ public:
// entry and the corresponding "real" font entry.
struct Key {
RefPtr<gfxFontSrcURI> mURI;
nsCOMPtr<nsIPrincipal> mPrincipal; // use nullptr with data: URLs
RefPtr<gfxFontSrcPrincipal> mPrincipal; // use nullptr with data: URLs
// The font entry MUST notify the cache when it is destroyed
// (by calling ForgetFont()).
gfxFontEntry* MOZ_NON_OWNING_REF mFontEntry;
bool mPrivate;
Key(gfxFontSrcURI* aURI, nsIPrincipal* aPrincipal,
Key(gfxFontSrcURI* aURI, gfxFontSrcPrincipal* aPrincipal,
gfxFontEntry* aFontEntry, bool aPrivate)
: mURI(aURI),
mPrincipal(aPrincipal),
@ -410,10 +411,8 @@ public:
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
static PLDHashNumber HashKey(const KeyTypePointer aKey) {
uint32_t principalHash = 0;
if (aKey->mPrincipal) {
aKey->mPrincipal->GetHashValue(&principalHash);
}
PLDHashNumber principalHash =
aKey->mPrincipal ? aKey->mPrincipal->Hash() : 0;
return mozilla::HashGeneric(principalHash + int(aKey->mPrivate),
aKey->mURI->Hash(),
HashFeatures(aKey->mFontEntry->mFeatureSettings),
@ -427,7 +426,7 @@ public:
enum { ALLOW_MEMMOVE = false };
gfxFontSrcURI* GetURI() const { return mURI; }
nsIPrincipal* GetPrincipal() const { return mPrincipal; }
gfxFontSrcPrincipal* GetPrincipal() const { return mPrincipal; }
gfxFontEntry* GetFontEntry() const { return mFontEntry; }
bool IsPrivate() const { return mPrivate; }
@ -465,7 +464,7 @@ public:
nsDataHashtable<nsPtrHashKey<gfxUserFontSet>, bool> mAllowedFontSets;
RefPtr<gfxFontSrcURI> mURI;
nsCOMPtr<nsIPrincipal> mPrincipal; // or nullptr for data: URLs
RefPtr<gfxFontSrcPrincipal> mPrincipal; // or nullptr for data: URLs
// The "real" font entry corresponding to this downloaded font.
// The font entry MUST notify the cache when it is destroyed
@ -629,7 +628,7 @@ public:
// since we can't make that class a friend
void SetLoader(nsFontFaceLoader* aLoader) { mLoader = aLoader; }
nsFontFaceLoader* GetLoader() { return mLoader; }
nsIPrincipal* GetPrincipal() { return mPrincipal; }
gfxFontSrcPrincipal* GetPrincipal() { return mPrincipal; }
uint32_t GetSrcIndex() { return mSrcIndex; }
void GetFamilyNameAndURIForLogging(nsACString& aFamilyName,
nsACString& aURI);
@ -708,7 +707,7 @@ protected:
// methods of nsFontFaceLoader this reference is nulled out.
nsFontFaceLoader* MOZ_NON_OWNING_REF mLoader; // current loader for this entry, if any
gfxUserFontSet* mFontSet; // font-set which owns this userfont entry
nsCOMPtr<nsIPrincipal> mPrincipal;
RefPtr<gfxFontSrcPrincipal> mPrincipal;
};

View File

@ -7,6 +7,7 @@
#include "FontFaceSet.h"
#include "gfxFontConstants.h"
#include "gfxFontSrcPrincipal.h"
#include "gfxFontSrcURI.h"
#include "mozilla/css/Declaration.h"
#include "mozilla/css/Loader.h"
@ -109,6 +110,7 @@ FontFaceSet::FontFaceSet(nsPIDOMWindowInner* aWindow, nsIDocument* aDocument)
, mDelayedLoadCheck(false)
, mBypassCache(false)
, mPrivateBrowsing(false)
, mHasStandardFontLoadPrincipalChanged(false)
{
MOZ_ASSERT(mDocument, "We should get a valid document from the caller!");
@ -625,6 +627,7 @@ FontFaceSet::StartLoad(gfxUserFontEntry* aUserFontEntry,
nsCOMPtr<nsIStreamLoader> streamLoader;
nsCOMPtr<nsILoadGroup> loadGroup(mDocument->GetDocumentLoadGroup());
gfxFontSrcPrincipal* principal = aUserFontEntry->GetPrincipal();
nsCOMPtr<nsIChannel> channel;
// Note we are calling NS_NewChannelWithTriggeringPrincipal() with both a
@ -634,7 +637,7 @@ FontFaceSet::StartLoad(gfxUserFontEntry* aUserFontEntry,
rv = NS_NewChannelWithTriggeringPrincipal(getter_AddRefs(channel),
aFontFaceSrc->mURI->get(),
mDocument,
aUserFontEntry->GetPrincipal(),
principal ? principal->get() : nullptr,
nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS,
nsIContentPolicy::TYPE_FONT,
loadGroup);
@ -1127,7 +1130,8 @@ FontFaceSet::FindOrCreateUserFontEntryFromFontFace(const nsAString& aFamilyName,
URLValue* url = val.GetURLStructValue();
face->mReferrer = url->mExtraData->GetReferrer();
face->mReferrerPolicy = mDocument->GetReferrerPolicy();
face->mOriginPrincipal = url->mExtraData->GetPrincipal();
face->mOriginPrincipal =
new gfxFontSrcPrincipal(url->mExtraData->GetPrincipal());
NS_ASSERTION(face->mOriginPrincipal, "null origin principal in @font-face rule");
// agent and user stylesheets are treated slightly differently,
@ -1330,15 +1334,19 @@ FontFaceSet::LogMessage(gfxUserFontEntry* aUserFontEntry,
return NS_OK;
}
nsIPrincipal*
gfxFontSrcPrincipal*
FontFaceSet::GetStandardFontLoadPrincipal()
{
return mDocument->NodePrincipal();
if (!ServoStyleSet::IsInServoTraversal()) {
UpdateStandardFontLoadPrincipal();
}
return mStandardFontLoadPrincipal;
}
nsresult
FontFaceSet::CheckFontLoad(const gfxFontFaceSrc* aFontFaceSrc,
nsIPrincipal** aPrincipal,
gfxFontSrcPrincipal** aPrincipal,
bool* aBypassCache)
{
NS_ASSERTION(aFontFaceSrc &&
@ -1395,6 +1403,8 @@ FontFaceSet::SyncLoadFontData(gfxUserFontEntry* aFontToLoad,
{
nsresult rv;
gfxFontSrcPrincipal* principal = aFontToLoad->GetPrincipal();
nsCOMPtr<nsIChannel> channel;
// Note we are calling NS_NewChannelWithTriggeringPrincipal() with both a
// node and a principal. This is because the document where the font is
@ -1406,7 +1416,7 @@ FontFaceSet::SyncLoadFontData(gfxUserFontEntry* aFontToLoad,
rv = NS_NewChannelWithTriggeringPrincipal(getter_AddRefs(channel),
aFontFaceSrc->mURI->get(),
mDocument,
aFontToLoad->GetPrincipal(),
principal ? principal->get() : nullptr,
nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS,
nsIContentPolicy::TYPE_FONT);
@ -1794,11 +1804,27 @@ FontFaceSet::GetPresContext()
return shell ? shell->GetPresContext() : nullptr;
}
void
FontFaceSet::UpdateStandardFontLoadPrincipal()
{
MOZ_ASSERT(NS_IsMainThread());
nsIPrincipal* documentPrincipal = mDocument->NodePrincipal();
if (!mStandardFontLoadPrincipal ||
mStandardFontLoadPrincipal->get() != documentPrincipal) {
if (mStandardFontLoadPrincipal) {
mHasStandardFontLoadPrincipalChanged = true;
}
mStandardFontLoadPrincipal = new gfxFontSrcPrincipal(documentPrincipal);
}
}
// -- FontFaceSet::UserFontSet ------------------------------------------------
/* virtual */ nsresult
FontFaceSet::UserFontSet::CheckFontLoad(const gfxFontFaceSrc* aFontFaceSrc,
nsIPrincipal** aPrincipal,
gfxFontSrcPrincipal** aPrincipal,
bool* aBypassCache)
{
if (!mFontFaceSet) {
@ -1807,7 +1833,7 @@ FontFaceSet::UserFontSet::CheckFontLoad(const gfxFontFaceSrc* aFontFaceSrc,
return mFontFaceSet->CheckFontLoad(aFontFaceSrc, aPrincipal, aBypassCache);
}
/* virtual */ nsIPrincipal*
/* virtual */ gfxFontSrcPrincipal*
FontFaceSet::UserFontSet::GetStandardFontLoadPrincipal()
{
if (!mFontFaceSet) {

View File

@ -14,6 +14,7 @@
#include "nsICSSLoaderObserver.h"
struct gfxFontFaceSrc;
class gfxFontSrcPrincipal;
class gfxUserFontEntry;
class nsFontFaceLoader;
class nsIPrincipal;
@ -63,10 +64,10 @@ public:
FontFaceSet* GetFontFaceSet() { return mFontFaceSet; }
nsIPrincipal* GetStandardFontLoadPrincipal() override;
gfxFontSrcPrincipal* GetStandardFontLoadPrincipal() override;
virtual nsresult CheckFontLoad(const gfxFontFaceSrc* aFontFaceSrc,
nsIPrincipal** aPrincipal,
gfxFontSrcPrincipal** aPrincipal,
bool* aBypassCache) override;
virtual bool IsFontLoadAllowed(nsIURI* aFontLocation,
@ -166,6 +167,15 @@ public:
return set ? set->GetPresContext() : nullptr;
}
void UpdateStandardFontLoadPrincipal();
bool HasStandardFontLoadPrincipalChanged()
{
bool changed = mHasStandardFontLoadPrincipalChanged;
mHasStandardFontLoadPrincipalChanged = false;
return changed;
}
nsIDocument* Document() const { return mDocument; }
// -- Web IDL --------------------------------------------------------------
@ -263,9 +273,9 @@ private:
nsresult StartLoad(gfxUserFontEntry* aUserFontEntry,
const gfxFontFaceSrc* aFontFaceSrc);
nsIPrincipal* GetStandardFontLoadPrincipal();
gfxFontSrcPrincipal* GetStandardFontLoadPrincipal();
nsresult CheckFontLoad(const gfxFontFaceSrc* aFontFaceSrc,
nsIPrincipal** aPrincipal,
gfxFontSrcPrincipal** aPrincipal,
bool* aBypassCache);
bool IsFontLoadAllowed(nsIURI* aFontLocation, nsIPrincipal* aPrincipal);
nsresult SyncLoadFontData(gfxUserFontEntry* aFontToLoad,
@ -317,6 +327,20 @@ private:
// The document this is a FontFaceSet for.
nsCOMPtr<nsIDocument> mDocument;
// The document's node principal, which is the principal font loads for
// this FontFaceSet will generally use. (This principal is not used for
// @font-face rules in UA and user sheets, where the principal of the
// sheet is used instead.)
//
// This field is used from GetStandardFontLoadPrincipal. When on a
// style worker thread, we use mStandardFontLoadPrincipal assuming
// it is up to date. Because mDocument's principal can change over time,
// its value must be updated by a call to UpdateStandardFontLoadPrincipal
// before a restyle. (When called while on the main thread,
// GetStandardFontLoadPrincipal will call UpdateStandardFontLoadPrincipal
// to ensure its value is up to date.)
RefPtr<gfxFontSrcPrincipal> mStandardFontLoadPrincipal;
// A Promise that is fulfilled once all of the FontFace objects
// in mRuleFaces and mNonRuleFaces that started or were loading at the
// time the Promise was created have finished loading. It is rejected if
@ -365,6 +389,10 @@ private:
// Whether the docshell for our document indicates that we are in private
// browsing mode.
bool mPrivateBrowsing;
// Whether mStandardFontLoadPrincipal has changed since the last call to
// HasStandardFontLoadPrincipalChanged.
bool mHasStandardFontLoadPrincipalChanged;
};
} // namespace dom

View File

@ -15,6 +15,7 @@
#include "mozilla/css/Loader.h"
#include "mozilla/dom/AnonymousContent.h"
#include "mozilla/dom/ChildIterator.h"
#include "mozilla/dom/FontFaceSet.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/ElementInlines.h"
#include "mozilla/RestyleManagerInlines.h"
@ -307,10 +308,19 @@ ServoStyleSet::PreTraverseSync()
mUserFontSetUpdateGeneration = generation;
}
// Ensure that the FontFaceSet's cached document principal is up to date.
FontFaceSet* fontFaceSet =
static_cast<FontFaceSet::UserFontSet*>(userFontSet)->GetFontFaceSet();
fontFaceSet->UpdateStandardFontLoadPrincipal();
bool principalChanged = fontFaceSet->HasStandardFontLoadPrincipalChanged();
// Ensure that the user font cache holds up-to-date data on whether
// our font set is allowed to re-use fonts from the cache.
uint32_t cacheGeneration = gfxUserFontSet::UserFontCache::Generation();
if (cacheGeneration != mUserFontCacheUpdateGeneration) {
if (principalChanged) {
gfxUserFontSet::UserFontCache::ClearAllowedFontSets(userFontSet);
}
if (cacheGeneration != mUserFontCacheUpdateGeneration || principalChanged) {
gfxUserFontSet::UserFontCache::UpdateAllowedFontSets(userFontSet);
mUserFontCacheUpdateGeneration = cacheGeneration;
}