зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1036394 - Use CRC32 to query hidden fonts, r=jfkthame
This commit is contained in:
Родитель
a7fb246d17
Коммит
0861dbb935
|
@ -1406,7 +1406,7 @@ PreloadAsUserFontFaces(nsStringHashKey::KeyType aKey,
|
|||
|
||||
// XXX Should we move the i/o here off the main thread?
|
||||
|
||||
// Map the font data in fe->mFilename, so we can generate a data: URI.
|
||||
// Map the font data in fe->mFilename, so we can calculate its CRC32.
|
||||
int fd = open(fe->mFilename.get(), O_RDONLY);
|
||||
if (fd < 0) {
|
||||
continue;
|
||||
|
@ -1423,36 +1423,22 @@ PreloadAsUserFontFaces(nsStringHashKey::KeyType aKey,
|
|||
continue;
|
||||
}
|
||||
|
||||
// First byte is sufficient to distinguish WOFF from uncompressed
|
||||
// OpenType (either TrueType or CFF).
|
||||
bool isWoff = (data[0] == 'w');
|
||||
|
||||
// Generate a corresponding data: URI that apps could use.
|
||||
nsCString encodedData;
|
||||
nsresult rv = Base64Encode(Substring(data, buf.st_size), encodedData);
|
||||
// Calculate CRC32
|
||||
uint32_t crc = crc32(0, nullptr, 0);
|
||||
crc = crc32(crc, (Bytef*)data, buf.st_size);
|
||||
munmap(data, buf.st_size);
|
||||
if (NS_FAILED(rv)) {
|
||||
continue;
|
||||
}
|
||||
nsCString spec("data:font/");
|
||||
spec.Append(isWoff ? "woff" : "opentype");
|
||||
spec.Append(";base64,");
|
||||
spec.Append(encodedData);
|
||||
|
||||
#if 0
|
||||
ALOG("\n**** Preloading family [%s] face [%s]:\n%s\n\n",
|
||||
ALOG("\n**** Preloading family [%s] face [%s] CRC32 [0x%08x]",
|
||||
NS_ConvertUTF16toUTF8(family->Name()).get(),
|
||||
fe->mFilename.get(),
|
||||
spec.get());
|
||||
crc);
|
||||
#endif
|
||||
|
||||
// Record the URI in gfxUserFontData on the entry.
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
if (NS_FAILED(NS_NewURI(getter_AddRefs(uri), spec))) {
|
||||
continue;
|
||||
}
|
||||
fe->mUserFontData = new gfxUserFontData;
|
||||
fe->mUserFontData->mURI = uri;
|
||||
fe->mUserFontData->mRealName = fe->Name();
|
||||
fe->mUserFontData->mCRC32 = crc;
|
||||
fe->mUserFontData->mLength = buf.st_size;
|
||||
|
||||
// Stash it persistently in the user-font cache.
|
||||
gfxUserFontSet::UserFontCache::CacheFont(
|
||||
|
|
|
@ -12,8 +12,10 @@
|
|||
#include "gfxPlatform.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIJARChannel.h"
|
||||
#include "nsIProtocolHandler.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIZipReader.h"
|
||||
#include "gfxFontConstants.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
|
@ -945,25 +947,34 @@ IgnorePrincipal(nsIURI *aURI)
|
|||
bool
|
||||
gfxUserFontSet::UserFontCache::Entry::KeyEquals(const KeyTypePointer aKey) const
|
||||
{
|
||||
bool result;
|
||||
if (NS_FAILED(mURI->Equals(aKey->mURI, &result)) || !result) {
|
||||
return false;
|
||||
}
|
||||
const gfxFontEntry *fe = aKey->mFontEntry;
|
||||
// CRC32 checking mode
|
||||
if (mLength || aKey->mLength) {
|
||||
if (aKey->mLength != mLength ||
|
||||
aKey->mCRC32 != mCRC32) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
bool result;
|
||||
if (NS_FAILED(mURI->Equals(aKey->mURI, &result)) || !result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// For data: URIs, we don't care about the principal; otherwise, check it.
|
||||
if (!IgnorePrincipal(mURI)) {
|
||||
NS_ASSERTION(mPrincipal && aKey->mPrincipal,
|
||||
"only data: URIs are allowed to omit the principal");
|
||||
if (NS_FAILED(mPrincipal->Equals(aKey->mPrincipal, &result)) || !result) {
|
||||
// For data: URIs, we don't care about the principal; otherwise, check it.
|
||||
if (!IgnorePrincipal(mURI)) {
|
||||
NS_ASSERTION(mPrincipal && aKey->mPrincipal,
|
||||
"only data: URIs are allowed to omit the principal");
|
||||
if (NS_FAILED(mPrincipal->Equals(aKey->mPrincipal, &result)) ||
|
||||
!result) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (mPrivate != aKey->mPrivate) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (mPrivate != aKey->mPrivate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const gfxFontEntry *fe = aKey->mFontEntry;
|
||||
if (mFontEntry->mItalic != fe->mItalic ||
|
||||
mFontEntry->mWeight != fe->mWeight ||
|
||||
mFontEntry->mStretch != fe->mStretch ||
|
||||
|
@ -997,17 +1008,25 @@ gfxUserFontSet::UserFontCache::CacheFont(gfxFontEntry *aFontEntry,
|
|||
}
|
||||
|
||||
gfxUserFontData *data = aFontEntry->mUserFontData;
|
||||
// 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;
|
||||
if (IgnorePrincipal(data->mURI)) {
|
||||
principal = nullptr;
|
||||
if (data->mLength) {
|
||||
MOZ_ASSERT(aPersistence == kPersistent);
|
||||
MOZ_ASSERT(!data->mPrivate);
|
||||
sUserFonts->PutEntry(Key(data->mCRC32, data->mLength, aFontEntry,
|
||||
data->mPrivate, aPersistence));
|
||||
} else {
|
||||
principal = data->mPrincipal;
|
||||
MOZ_ASSERT(aPersistence == kDiscardable);
|
||||
// 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;
|
||||
if (IgnorePrincipal(data->mURI)) {
|
||||
principal = nullptr;
|
||||
} else {
|
||||
principal = data->mPrincipal;
|
||||
}
|
||||
sUserFonts->PutEntry(Key(data->mURI, principal, aFontEntry,
|
||||
data->mPrivate, aPersistence));
|
||||
}
|
||||
sUserFonts->PutEntry(Key(data->mURI, principal, aFontEntry,
|
||||
data->mPrivate, aPersistence));
|
||||
|
||||
#ifdef DEBUG_USERFONT_CACHE
|
||||
printf("userfontcache added fontentry: %p\n", aFontEntry);
|
||||
|
@ -1060,6 +1079,30 @@ gfxUserFontSet::UserFontCache::GetFont(nsIURI *aSrcURI,
|
|||
return entry->GetFontEntry();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIChannel> chan;
|
||||
if (NS_FAILED(NS_NewChannel(getter_AddRefs(chan), aSrcURI))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIJARChannel> jarchan = do_QueryInterface(chan);
|
||||
if (!jarchan) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIZipEntry> zipentry;
|
||||
if (NS_FAILED(jarchan->GetZipEntry(getter_AddRefs(zipentry)))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t crc32, length;
|
||||
zipentry->GetCRC32(&crc32);
|
||||
zipentry->GetRealSize(&length);
|
||||
|
||||
entry = sUserFonts->GetEntry(Key(crc32, length, aProxy, aPrivate));
|
||||
if (entry) {
|
||||
return entry->GetFontEntry();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,8 @@ operator==(const gfxFontFaceSrc& a, const gfxFontFaceSrc& b)
|
|||
class gfxUserFontData {
|
||||
public:
|
||||
gfxUserFontData()
|
||||
: mSrcIndex(0), mFormat(0), mMetaOrigLen(0), mPrivate(false)
|
||||
: mSrcIndex(0), mFormat(0), mMetaOrigLen(0),
|
||||
mCRC32(0), mLength(0), mPrivate(false)
|
||||
{ }
|
||||
virtual ~gfxUserFontData() { }
|
||||
|
||||
|
@ -73,6 +74,8 @@ public:
|
|||
uint32_t mSrcIndex; // index in the rule's source list
|
||||
uint32_t mFormat; // format hint for the source used, if any
|
||||
uint32_t mMetaOrigLen; // length needed to decompress metadata
|
||||
uint32_t mCRC32; // Checksum
|
||||
uint32_t mLength; // Font length
|
||||
bool mPrivate; // whether font belongs to a private window
|
||||
};
|
||||
|
||||
|
@ -335,6 +338,8 @@ public:
|
|||
nsCOMPtr<nsIURI> mURI;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal; // use nullptr with data: URLs
|
||||
gfxFontEntry *mFontEntry;
|
||||
uint32_t mCRC32;
|
||||
uint32_t mLength;
|
||||
bool mPrivate;
|
||||
EntryPersistence mPersistence;
|
||||
|
||||
|
@ -344,6 +349,20 @@ public:
|
|||
: mURI(aURI),
|
||||
mPrincipal(aPrincipal),
|
||||
mFontEntry(aFontEntry),
|
||||
mCRC32(0),
|
||||
mLength(0),
|
||||
mPrivate(aPrivate),
|
||||
mPersistence(aPersistence)
|
||||
{ }
|
||||
|
||||
Key(uint32_t aCRC32, uint32_t aLength,
|
||||
gfxFontEntry* aFontEntry, bool aPrivate,
|
||||
EntryPersistence aPersistence = kDiscardable)
|
||||
: mURI(nullptr),
|
||||
mPrincipal(nullptr),
|
||||
mFontEntry(aFontEntry),
|
||||
mCRC32(aCRC32),
|
||||
mLength(aLength),
|
||||
mPrivate(aPrivate),
|
||||
mPersistence(aPersistence)
|
||||
{ }
|
||||
|
@ -358,6 +377,8 @@ public:
|
|||
: mURI(aKey->mURI),
|
||||
mPrincipal(aKey->mPrincipal),
|
||||
mFontEntry(aKey->mFontEntry),
|
||||
mCRC32(aKey->mCRC32),
|
||||
mLength(aKey->mLength),
|
||||
mPrivate(aKey->mPrivate),
|
||||
mPersistence(aKey->mPersistence)
|
||||
{ }
|
||||
|
@ -366,6 +387,8 @@ public:
|
|||
: mURI(aOther.mURI),
|
||||
mPrincipal(aOther.mPrincipal),
|
||||
mFontEntry(aOther.mFontEntry),
|
||||
mCRC32(aOther.mCRC32),
|
||||
mLength(aOther.mLength),
|
||||
mPrivate(aOther.mPrivate),
|
||||
mPersistence(aOther.mPersistence)
|
||||
{ }
|
||||
|
@ -377,6 +400,9 @@ public:
|
|||
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
|
||||
|
||||
static PLDHashNumber HashKey(const KeyTypePointer aKey) {
|
||||
if (aKey->mLength) {
|
||||
return aKey->mCRC32;
|
||||
}
|
||||
uint32_t principalHash = 0;
|
||||
if (aKey->mPrincipal) {
|
||||
aKey->mPrincipal->GetHashValue(&principalHash);
|
||||
|
@ -418,6 +444,9 @@ public:
|
|||
nsCOMPtr<nsIURI> mURI;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal; // or nullptr for data: URLs
|
||||
|
||||
uint32_t mCRC32;
|
||||
uint32_t mLength;
|
||||
|
||||
// The "real" font entry corresponding to this downloaded font.
|
||||
// The font entry MUST notify the cache when it is destroyed
|
||||
// (by calling Forget()).
|
||||
|
|
Загрузка…
Ссылка в новой задаче