Bug 1036394 - Use CRC32 to query hidden fonts, r=jfkthame

This commit is contained in:
Michael Wu 2014-08-04 12:26:55 -04:00
Родитель a7fb246d17
Коммит 0861dbb935
3 изменённых файлов: 105 добавлений и 47 удалений

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

@ -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()).