bug 739858 - cancel any in-progress loaders for @font-face rules that have been discarded when the font set is updated. r=jdaggett
authorJonathan Kew <jkew@mozilla.com>
Thu, 26 Apr 2012 18:50:41 +0100
changeset 92554 8388eea0115168cbaf9df935a6cf090d184fae99
parent 92553 82c388f7e770e75ad2318aa72ab2ebd6753fc25d
child 92555 0bf543de76dbc8ead9595dc35d2b57ecca0a09e3
push id22544
push useremorley@mozilla.com
push dateFri, 27 Apr 2012 11:53:27 +0000
treeherdermozilla-central@d871849ac3a3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdaggett
bugs739858
milestone15.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 739858 - cancel any in-progress loaders for @font-face rules that have been discarded when the font set is updated. r=jdaggett
gfx/thebes/gfxUserFontSet.cpp
gfx/thebes/gfxUserFontSet.h
layout/style/nsFontFaceLoader.cpp
--- a/gfx/thebes/gfxUserFontSet.cpp
+++ b/gfx/thebes/gfxUserFontSet.cpp
@@ -72,17 +72,18 @@ gfxProxyFontEntry::gfxProxyFontEntry(con
              PRUint32 aWeight,
              PRUint32 aStretch,
              PRUint32 aItalicStyle,
              const nsTArray<gfxFontFeature>& aFeatureSettings,
              PRUint32 aLanguageOverride,
              gfxSparseBitSet *aUnicodeRanges)
     : gfxFontEntry(NS_LITERAL_STRING("Proxy"), aFamily),
       mLoadingState(NOT_LOADING),
-      mUnsupportedFormat(false)
+      mUnsupportedFormat(false),
+      mLoader(nsnull)
 {
     mIsProxy = true;
     mSrcList = aFontFaceSrcList;
     mSrcIndex = 0;
     mWeight = aWeight;
     mStretch = aStretch;
     mItalic = (aItalicStyle & (NS_FONT_STYLE_ITALIC | NS_FONT_STYLE_OBLIQUE)) != 0;
     mFeatureSettings.AppendElements(aFeatureSettings);
@@ -451,16 +452,20 @@ gfxUserFontSet::CopyWOFFMetadata(const P
 // This is called when a font download finishes.
 // Ownership of aFontData passes in here, and the font set must
 // ensure that it is eventually deleted via NS_Free().
 bool
 gfxUserFontSet::OnLoadComplete(gfxProxyFontEntry *aProxy,
                                const PRUint8 *aFontData, PRUint32 aLength,
                                nsresult aDownloadStatus)
 {
+    // forget about the loader, as we no longer potentially need to cancel it
+    // if the entry is obsoleted
+    aProxy->mLoader = nsnull;
+
     // download successful, make platform font using font data
     if (NS_SUCCEEDED(aDownloadStatus)) {
         gfxFontEntry *fe = LoadFont(aProxy, aFontData, aLength);
         aFontData = nsnull;
 
         if (fe) {
             IncrementGeneration();
             return true;
@@ -621,17 +626,17 @@ gfxUserFontSet::IncrementGeneration()
 gfxFontEntry*
 gfxUserFontSet::LoadFont(gfxProxyFontEntry *aProxy,
                          const PRUint8 *aFontData, PRUint32 &aLength)
 {
     // if the proxy doesn't belong to a family, we just bail as it won't be
     // accessible/usable anyhow (maybe the font set got modified right as
     // the load was completing?)
     if (!aProxy->Family()) {
-        NS_Free(aFontData);
+        NS_Free(const_cast<PRUint8*>(aFontData));
         return nsnull;
     }
 
     gfxFontEntry *fe = nsnull;
 
     gfxUserFontType fontType =
         gfxFontUtils::DetermineFontDataType(aFontData, aLength);
 
--- a/gfx/thebes/gfxUserFontSet.h
+++ b/gfx/thebes/gfxUserFontSet.h
@@ -46,16 +46,17 @@
 #include "nsCOMPtr.h"
 #include "nsIURI.h"
 #include "nsIFile.h"
 #include "nsISupportsImpl.h"
 #include "nsIScriptError.h"
 
 class nsIURI;
 class gfxMixedFontFamily;
+class nsFontFaceLoader;
 
 // parsed CSS @font-face rule information
 // lifetime: from when @font-face rule processed until font is loaded
 struct gfxFontFaceSrc {
     bool                   mIsLocal;       // url or local
 
     // if url, whether to use the origin principal or not
     bool                   mUseOriginPrincipal;
@@ -335,12 +336,13 @@ public:
                              // so use the fallback font
         LOADING_FAILED       // failed to load any source: use fallback
     };
     LoadingState             mLoadingState;
     bool                     mUnsupportedFormat;
 
     nsTArray<gfxFontFaceSrc> mSrcList;
     PRUint32                 mSrcIndex; // index of loading src item
+    nsFontFaceLoader        *mLoader; // current loader for this entry, if any
 };
 
 
 #endif /* GFX_USER_FONT_SET_H */
--- a/layout/style/nsFontFaceLoader.cpp
+++ b/layout/style/nsFontFaceLoader.cpp
@@ -93,16 +93,19 @@ nsFontFaceLoader::nsFontFaceLoader(gfxPr
   : mFontEntry(aProxy), mFontURI(aFontURI), mFontSet(aFontSet),
     mChannel(aChannel)
 {
   mFontFamily = aProxy->Family();
 }
 
 nsFontFaceLoader::~nsFontFaceLoader()
 {
+  if (mFontEntry) {
+    mFontEntry->mLoader = nsnull;
+  }
   if (mLoadTimer) {
     mLoadTimer->Cancel();
     mLoadTimer = nsnull;
   }
   if (mFontSet) {
     mFontSet->RemoveLoader(this);
   }
 }
@@ -254,16 +257,17 @@ nsFontFaceLoader::OnStreamComplete(nsISt
 
   return NS_SUCCESS_ADOPTED_DATA;
 }
 
 void
 nsFontFaceLoader::Cancel()
 {
   mFontEntry->mLoadingState = gfxProxyFontEntry::NOT_LOADING;
+  mFontEntry->mLoader = nsnull;
   mFontSet = nsnull;
   if (mLoadTimer) {
     mLoadTimer->Cancel();
     mLoadTimer = nsnull;
   }
   mChannel->Cancel(NS_BINDING_ABORTED);
 }
 
@@ -416,16 +420,18 @@ nsUserFontSet::StartLoad(gfxProxyFontEnt
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = channel->AsyncOpen(listener, nsnull);
   }
 
   if (NS_SUCCEEDED(rv)) {
     mLoaders.PutEntry(fontLoader);
     fontLoader->StartedLoading(streamLoader);
+    aProxy->mLoader = fontLoader; // let the font entry remember the loader,
+                                  // in case we need to cancel it
   }
 
   return rv;
 }
 
 static PLDHashOperator DetachFontEntries(const nsAString& aKey,
                                          nsRefPtr<gfxMixedFontFamily>& aFamily,
                                          void* aUserArg)
@@ -461,16 +467,29 @@ nsUserFontSet::UpdateRules(const nsTArra
     // rather than creating new ones; set  modified  to true if we detect
     // that rule ordering has changed, or if a new entry is created
     InsertRule(aRules[i].mRule, aRules[i].mSheetType, oldRules, modified);
   }
 
   // if any rules are left in the old list, note that the set has changed
   if (oldRules.Length() > 0) {
     modified = true;
+    // any in-progress loaders for obsolete rules should be cancelled
+    size_t count = oldRules.Length();
+    for (size_t i = 0; i < count; ++i) {
+      gfxFontEntry *fe = oldRules[i].mFontEntry;
+      if (!fe->mIsProxy) {
+        continue;
+      }
+      gfxProxyFontEntry *proxy = static_cast<gfxProxyFontEntry*>(fe);
+      if (proxy->mLoader != nsnull) {
+        proxy->mLoader->Cancel();
+        RemoveLoader(proxy->mLoader);
+      }
+    }
   }
 
   if (modified) {
     IncrementGeneration();
   }
 
   return modified;
 }