diff --git a/gfx/thebes/gfxUserFontSet.cpp b/gfx/thebes/gfxUserFontSet.cpp index 1b469dc3e834..68b8360c63d9 100644 --- a/gfx/thebes/gfxUserFontSet.cpp +++ b/gfx/thebes/gfxUserFontSet.cpp @@ -55,11 +55,11 @@ using namespace mozilla; #ifdef PR_LOGGING -static PRLogModuleInfo *gUserFontsLog = PR_NewLogModule("userfonts"); +PRLogModuleInfo *gfxUserFontSet::sUserFontsLog = PR_NewLogModule("userfonts"); #endif /* PR_LOGGING */ -#define LOG(args) PR_LOG(gUserFontsLog, PR_LOG_DEBUG, args) -#define LOG_ENABLED() PR_LOG_TEST(gUserFontsLog, PR_LOG_DEBUG) +#define LOG(args) PR_LOG(sUserFontsLog, PR_LOG_DEBUG, args) +#define LOG_ENABLED() PR_LOG_TEST(sUserFontsLog, PR_LOG_DEBUG) static PRUint64 sFontSetGeneration = LL_INIT(0, 0); @@ -445,7 +445,7 @@ CopyWOFFMetadata(const PRUint8* aFontData, PRUint32 aLength, // ensure that it is eventually deleted via NS_Free(). PRBool gfxUserFontSet::OnLoadComplete(gfxProxyFontEntry *aProxy, - const PRUint8 *aFontData, PRUint32 aLength, + const PRUint8 *aFontData, PRUint32 aLength, nsresult aDownloadStatus) { // download successful, make platform font using font data @@ -482,14 +482,9 @@ gfxUserFontSet::OnLoadComplete(gfxProxyFontEntry *aProxy, const PRUint8* saneData = SanitizeOpenTypeData(aFontData, aLength, saneLen, fontType == GFX_USERFONT_WOFF); -#ifdef DEBUG if (!saneData) { - char buf[1000]; - sprintf(buf, "downloaded font rejected for \"%s\"", - NS_ConvertUTF16toUTF8(aProxy->FamilyName()).get()); - NS_WARNING(buf); + LogMessage(aProxy, "rejected by sanitizer"); } -#endif if (saneData) { // The sanitizer ensures that we have a valid sfnt and a usable // name table, so this should never fail unless we're out of @@ -503,7 +498,7 @@ gfxUserFontSet::OnLoadComplete(gfxProxyFontEntry *aProxy, saneData, saneLen); if (!fe) { - NS_WARNING("failed to make platform font from download"); + LogMessage(aProxy, "not usable by platform"); } } } else { @@ -523,11 +518,14 @@ gfxUserFontSet::OnLoadComplete(gfxProxyFontEntry *aProxy, fe = gfxPlatform::GetPlatform()->MakePlatformFont(aProxy, aFontData, aLength); + if (!fe) { + LogMessage(aProxy, "not usable by platform"); + } aFontData = nsnull; // we must NOT free this below! } else { // the data was unusable, so just discard it // (error will be reported below, if logging is enabled) - NS_WARNING("failed to make platform font from download"); + LogMessage(aProxy, "SFNT header or tables invalid"); } } } @@ -572,16 +570,8 @@ gfxUserFontSet::OnLoadComplete(gfxProxyFontEntry *aProxy, } } else { // download failed -#ifdef PR_LOGGING - if (LOG_ENABLED()) { - nsCAutoString fontURI; - aProxy->mSrcList[aProxy->mSrcIndex].mURI->GetSpec(fontURI); - LOG(("userfonts (%p) [src %d] failed uri: (%s) for (%s) error %8.8x downloading font data\n", - this, aProxy->mSrcIndex, fontURI.get(), - NS_ConvertUTF16toUTF8(aProxy->mFamily->Name()).get(), - aDownloadStatus)); - } -#endif + LogMessage(aProxy, "download failed", nsIScriptError::errorFlag, + aDownloadStatus); } if (aFontData) { @@ -606,7 +596,8 @@ gfxUserFontSet::LoadNext(gfxProxyFontEntry *aProxyEntry) { PRUint32 numSrc = aProxyEntry->mSrcList.Length(); - NS_ASSERTION(aProxyEntry->mSrcIndex < numSrc, "already at the end of the src list for user font"); + NS_ASSERTION(aProxyEntry->mSrcIndex < numSrc, + "already at the end of the src list for user font"); if (aProxyEntry->mLoadingState == gfxProxyFontEntry::NOT_LOADING) { aProxyEntry->mLoadingState = gfxProxyFontEntry::LOADING_STARTED; @@ -617,21 +608,22 @@ gfxUserFontSet::LoadNext(gfxProxyFontEntry *aProxyEntry) aProxyEntry->mSrcIndex++; } - // load each src entry in turn, until a local face is found or a download begins successfully + // load each src entry in turn, until a local face is found + // or a download begins successfully while (aProxyEntry->mSrcIndex < numSrc) { const gfxFontFaceSrc& currSrc = aProxyEntry->mSrcList[aProxyEntry->mSrcIndex]; - // src local ==> lookup and load + // src local ==> lookup and load if (currSrc.mIsLocal) { gfxFontEntry *fe = gfxPlatform::GetPlatform()->LookupLocalFont(aProxyEntry, currSrc.mLocalName); if (fe) { - LOG(("userfonts (%p) [src %d] loaded local: (%s) for (%s) gen: %8.8x\n", - this, aProxyEntry->mSrcIndex, - NS_ConvertUTF16toUTF8(currSrc.mLocalName).get(), - NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get(), + LOG(("userfonts (%p) [src %d] loaded local: (%s) for (%s) gen: %8.8x\n", + this, aProxyEntry->mSrcIndex, + NS_ConvertUTF16toUTF8(currSrc.mLocalName).get(), + NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get(), PRUint32(mGeneration))); fe->mFeatureSettings.AppendElements(aProxyEntry->mFeatureSettings); fe->mLanguageOverride = aProxyEntry->mLanguageOverride; @@ -639,52 +631,37 @@ gfxUserFontSet::LoadNext(gfxProxyFontEntry *aProxyEntry) ReplaceFontEntry(aProxyEntry, fe); return STATUS_LOADED; } else { - LOG(("userfonts (%p) [src %d] failed local: (%s) for (%s)\n", - this, aProxyEntry->mSrcIndex, - NS_ConvertUTF16toUTF8(currSrc.mLocalName).get(), - NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get())); + LOG(("userfonts (%p) [src %d] failed local: (%s) for (%s)\n", + this, aProxyEntry->mSrcIndex, + NS_ConvertUTF16toUTF8(currSrc.mLocalName).get(), + NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get())); } - } + } // src url ==> start the load process else { - if (gfxPlatform::GetPlatform()->IsFontFormatSupported(currSrc.mURI, + if (gfxPlatform::GetPlatform()->IsFontFormatSupported(currSrc.mURI, currSrc.mFormatFlags)) { nsresult rv = StartLoad(aProxyEntry, &currSrc); PRBool loadOK = NS_SUCCEEDED(rv); - if (loadOK) { #ifdef PR_LOGGING if (LOG_ENABLED()) { nsCAutoString fontURI; currSrc.mURI->GetSpec(fontURI); - LOG(("userfonts (%p) [src %d] loading uri: (%s) for (%s)\n", - this, aProxyEntry->mSrcIndex, fontURI.get(), + LOG(("userfonts (%p) [src %d] loading uri: (%s) for (%s)\n", + this, aProxyEntry->mSrcIndex, fontURI.get(), NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get())); } #endif - return STATUS_LOADING; + return STATUS_LOADING; } else { -#ifdef PR_LOGGING - if (LOG_ENABLED()) { - nsCAutoString fontURI; - currSrc.mURI->GetSpec(fontURI); - LOG(("userfonts (%p) [src %d] failed uri: (%s) for (%s) download failed\n", - this, aProxyEntry->mSrcIndex, fontURI.get(), - NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get())); - } -#endif + LogMessage(aProxyEntry, "download failed", + nsIScriptError::errorFlag, rv); } } else { -#ifdef PR_LOGGING - if (LOG_ENABLED()) { - nsCAutoString fontURI; - currSrc.mURI->GetSpec(fontURI); - LOG(("userfonts (%p) [src %d] failed uri: (%s) for (%s) format not supported\n", - this, aProxyEntry->mSrcIndex, fontURI.get(), - NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get())); - } -#endif + LogMessage(aProxyEntry, "format not supported", + nsIScriptError::warningFlag); } } @@ -692,8 +669,8 @@ gfxUserFontSet::LoadNext(gfxProxyFontEntry *aProxyEntry) } // all src's failed; mark this entry as unusable (so fallback will occur) - LOG(("userfonts (%p) failed all src for (%s)\n", - this, NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get())); + LOG(("userfonts (%p) failed all src for (%s)\n", + this, NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get())); aProxyEntry->mLoadingState = gfxProxyFontEntry::LOADING_FAILED; return STATUS_END_OF_LIST; diff --git a/gfx/thebes/gfxUserFontSet.h b/gfx/thebes/gfxUserFontSet.h index 3274e8a0864d..4455263e4781 100644 --- a/gfx/thebes/gfxUserFontSet.h +++ b/gfx/thebes/gfxUserFontSet.h @@ -47,6 +47,7 @@ #include "nsIURI.h" #include "nsIFile.h" #include "nsISupportsImpl.h" +#include "nsIScriptError.h" class nsIURI; class gfxMixedFontFamily; @@ -252,10 +253,18 @@ protected: gfxMixedFontFamily *GetFamily(const nsAString& aName) const; + // report a problem of some kind (implemented in nsUserFontSet) + virtual nsresult LogMessage(gfxProxyFontEntry *aProxy, + const char *aMessage, + PRUint32 aFlags = nsIScriptError::errorFlag, + nsresult aStatus = 0) = 0; + // font families defined by @font-face rules nsRefPtrHashtable mFontFamilies; PRUint64 mGeneration; + + static PRLogModuleInfo *sUserFontsLog; }; // acts a placeholder until the real font is downloaded diff --git a/layout/style/nsFontFaceLoader.cpp b/layout/style/nsFontFaceLoader.cpp index 32ad9b4ce34d..8bc03b061dab 100644 --- a/layout/style/nsFontFaceLoader.cpp +++ b/layout/style/nsFontFaceLoader.cpp @@ -73,6 +73,8 @@ #include "nsIChannelPolicy.h" #include "nsChannelPolicy.h" +#include "nsIConsoleService.h" + #include "nsStyleSet.h" using namespace mozilla; @@ -342,17 +344,7 @@ nsUserFontSet::StartLoad(gfxProxyFontEntry *aProxy, rv = nsFontFaceLoader::CheckLoadAllowed(principal, aFontFaceSrc->mURI, ps->GetDocument()); if (NS_FAILED(rv)) { -#ifdef PR_LOGGING - if (LOG_ENABLED()) { - nsCAutoString fontURI, referrerURI; - aFontFaceSrc->mURI->GetSpec(fontURI); - if (aFontFaceSrc->mReferrer) - aFontFaceSrc->mReferrer->GetSpec(referrerURI); - LOG(("fontdownloader download blocked - font uri: (%s) " - "referrer uri: (%s) err: %8.8x\n", - fontURI.get(), referrerURI.get(), rv)); - } -#endif + LogMessage(aProxy, "download not allowed", nsIScriptError::errorFlag, rv); return rv; } @@ -697,3 +689,105 @@ nsUserFontSet::FindRuleForEntry(gfxFontEntry *aFontEntry) } return nsnull; } + +nsresult +nsUserFontSet::LogMessage(gfxProxyFontEntry *aProxy, + const char *aMessage, + PRUint32 aFlags, + nsresult aStatus) +{ + nsCOMPtr + console(do_GetService(NS_CONSOLESERVICE_CONTRACTID)); + if (!console) { + return NS_ERROR_NOT_AVAILABLE; + } + + NS_ConvertUTF16toUTF8 familyName(aProxy->FamilyName()); + nsCAutoString fontURI; + aProxy->mSrcList[aProxy->mSrcIndex].mURI->GetSpec(fontURI); + + char weightKeywordBuf[8]; // plenty to sprintf() a PRUint16 + const char *weightKeyword; + const nsAFlatCString& weightKeywordString = + nsCSSProps::ValueToKeyword(aProxy->Weight(), + nsCSSProps::kFontWeightKTable); + if (weightKeywordString.Length() > 0) { + weightKeyword = weightKeywordString.get(); + } else { + sprintf(weightKeywordBuf, "%u", aProxy->Weight()); + weightKeyword = weightKeywordBuf; + } + + nsPrintfCString + msg(1024, + "downloadable font: %s " + "(font-family: \"%s\" style:%s weight:%s stretch:%s src index:%d)", + aMessage, + familyName.get(), + aProxy->IsItalic() ? "italic" : "normal", + weightKeyword, + nsCSSProps::ValueToKeyword(aProxy->Stretch(), + nsCSSProps::kFontStretchKTable).get(), + aProxy->mSrcIndex); + + if (aStatus != 0) { + msg.Append(": "); + switch (aStatus) { + case NS_ERROR_DOM_BAD_URI: + msg.Append("bad URI or cross-site access not allowed"); + break; + case NS_ERROR_CONTENT_BLOCKED: + msg.Append("content blocked"); + break; + default: + msg.Append("status="); + msg.AppendInt(aStatus); + break; + } + } + msg.Append("\nsource: "); + msg.Append(fontURI); + +#ifdef PR_LOGGING + if (PR_LOG_TEST(sUserFontsLog, PR_LOG_DEBUG)) { + PR_LOG(sUserFontsLog, PR_LOG_DEBUG, + ("userfonts (%p) %s", this, msg.get())); + } +#endif + + // try to give the user an indication of where the rule came from + nsCSSFontFaceRule* rule = FindRuleForEntry(aProxy); + nsString href; + nsString text; + nsresult rv; + if (rule) { + rv = rule->GetCssText(text); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr sheet; + rv = rule->GetParentStyleSheet(getter_AddRefs(sheet)); + NS_ENSURE_SUCCESS(rv, rv); + rv = sheet->GetHref(href); + NS_ENSURE_SUCCESS(rv, rv); + } + + nsCOMPtr scriptError = + do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + PRUint64 windowID = GetPresContext()->Document()->OuterWindowID(); + rv = scriptError->InitWithWindowID(NS_ConvertUTF8toUTF16(msg).get(), + href.get(), // file + text.get(), // src line + 0, 0, // line & column number + aFlags, // flags + "CSS Loader", // category (make separate?) + windowID); + if (NS_SUCCEEDED(rv)){ + nsCOMPtr logError = do_QueryInterface(scriptError); + if (logError) { + console->LogMessage(logError); + } + } + + return NS_OK; +} diff --git a/layout/style/nsFontFaceLoader.h b/layout/style/nsFontFaceLoader.h index 1b55ef264276..69070cb005fd 100644 --- a/layout/style/nsFontFaceLoader.h +++ b/layout/style/nsFontFaceLoader.h @@ -102,6 +102,11 @@ protected: nsTArray& oldRules, PRBool& aFontSetModified); + virtual nsresult LogMessage(gfxProxyFontEntry *aProxy, + const char *aMessage, + PRUint32 aFlags = nsIScriptError::errorFlag, + nsresult aStatus = 0); + nsPresContext *mPresContext; // weak reference // Set of all loaders pointing to us. These are not strong pointers,