Bug 1062058 part 3 - make userfont entry a container of the platform font entry. r=heycam
authorJohn Daggett <jdaggett@mozilla.com>
Mon, 08 Sep 2014 16:23:20 +0900
changeset 227249 c47072d34566299a981b09a1c588f6e2a3014d06
parent 227248 41f6469b5218a0b1f8b9e289bfe99aee3d8751de
child 227250 dd3961697eb5dadc1ed28f6b198abfe91e976ab5
child 227354 71f28ed35eaab37c79bd82958fda9fd190cafbd6
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1062058
milestone35.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 1062058 part 3 - make userfont entry a container of the platform font entry. r=heycam
gfx/thebes/gfxFont.cpp
gfx/thebes/gfxFont.h
gfx/thebes/gfxPangoFonts.cpp
gfx/thebes/gfxUserFontSet.cpp
gfx/thebes/gfxUserFontSet.h
layout/style/nsFontFaceLoader.cpp
layout/style/nsFontFaceLoader.h
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -1328,16 +1328,37 @@ gfxFontFamily::CheckForSimpleFamily()
         if (mAvailableFonts[i].get() != faces[i]) {
             mAvailableFonts[i].swap(faces[i]);
         }
     }
 
     mIsSimpleFamily = true;
 }
 
+#ifdef DEBUG
+bool
+gfxFontFamily::ContainsFace(gfxFontEntry* aFontEntry) {
+    uint32_t i, numFonts = mAvailableFonts.Length();
+    for (i = 0; i < numFonts; i++) {
+        if (mAvailableFonts[i] == aFontEntry) {
+            return true;
+        }
+        // userfonts contain the actual real font entry
+        if (mAvailableFonts[i]->mIsUserFontContainer) {
+            gfxUserFontEntry* ufe =
+                static_cast<gfxUserFontEntry*>(mAvailableFonts[i].get());
+            if (ufe->GetPlatformFontEntry() == aFontEntry) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+#endif
+
 static inline uint32_t
 StyleDistance(gfxFontEntry *aFontEntry,
               bool anItalic, int16_t aStretch)
 {
     // Compute a measure of the "distance" between the requested style
     // and the given fontEntry,
     // considering italicness and font-stretch but not weight.
 
@@ -5036,28 +5057,33 @@ gfxFontGroup::FindPlatformFont(const nsA
         // here; we'll fall back to the next name in the CSS font-family list.
         if (mUserFontSet) {
             // If the fontSet matches the family, but the font has not yet finished
             // loading (nor has its load timeout fired), the fontGroup should wait
             // for the download, and not actually draw its text yet.
             family = mUserFontSet->LookupFamily(aName);
             if (family) {
                 bool waitForUserFont = false;
-                fe = mUserFontSet->FindFontEntry(family, mStyle,
-                                                 needsBold, waitForUserFont);
+                gfxUserFontEntry* userFontEntry = nullptr;
+                userFontEntry = mUserFontSet->FindUserFontEntry(family, mStyle,
+                                                                needsBold,
+                                                                waitForUserFont);
+                if (userFontEntry) {
+                    fe = userFontEntry->GetPlatformFontEntry();
+                }
                 if (!fe && waitForUserFont) {
                     mSkipDrawing = true;
                 }
             }
         }
     }
 
     // Not known in the user font set ==> check system fonts
     if (!family) {
-        gfxPlatformFontList *fontList = gfxPlatformFontList::PlatformFontList();
+        gfxPlatformFontList* fontList = gfxPlatformFontList::PlatformFontList();
         family = fontList->FindFamily(aName, mStyle.systemFont);
         if (family) {
             fe = family->FindFontForStyle(mStyle, needsBold);
         }
     }
 
     // add to the font group, unless it's already there
     if (fe && !HasFont(fe)) {
--- a/gfx/thebes/gfxFont.h
+++ b/gfx/thebes/gfxFont.h
@@ -552,19 +552,19 @@ public:
 
     nsString         mName;
     nsString         mFamilyName;
 
     bool             mItalic      : 1;
     bool             mFixedPitch  : 1;
     bool             mIsValid     : 1;
     bool             mIsBadUnderlineFont : 1;
-    bool             mIsUserFontContainer : 1;
-    bool             mIsDataUserFont : 1;
-    bool             mIsLocalUserFont : 1;
+    bool             mIsUserFontContainer : 1; // userfont entry
+    bool             mIsDataUserFont : 1;      // platform font entry (data)
+    bool             mIsLocalUserFont : 1;     // platform font entry (local)
     bool             mStandardFace : 1;
     bool             mSymbolFont  : 1;
     bool             mIgnoreGDEF  : 1;
     bool             mIgnoreGSUB  : 1;
     bool             mSVGInitialized : 1;
     bool             mMathInitialized : 1;
     bool             mHasSpaceFeaturesInitialized : 1;
     bool             mHasSpaceFeatures : 1;
@@ -927,26 +927,20 @@ public:
     void CheckForSimpleFamily();
 
     // For memory reporter
     virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
                                         FontListSizes* aSizes) const;
     virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
                                         FontListSizes* aSizes) const;
 
+#ifdef DEBUG
     // Only used for debugging checks - does a linear search
-    bool ContainsFace(gfxFontEntry* aFontEntry) {
-        uint32_t i, numFonts = mAvailableFonts.Length();
-        for (i = 0; i < numFonts; i++) {
-            if (mAvailableFonts[i] == aFontEntry) {
-                return true;
-            }
-        }
-        return false;
-    }
+    bool ContainsFace(gfxFontEntry* aFontEntry);
+#endif
 
     void SetSkipSpaceFeatureCheck(bool aSkipCheck) {
         mSkipDefaultFeatureSpaceCheck = aSkipCheck;
     }
 
 protected:
     // Protected destructor, to discourage deletion outside of Release():
     virtual ~gfxFontFamily()
--- a/gfx/thebes/gfxPangoFonts.cpp
+++ b/gfx/thebes/gfxPangoFonts.cpp
@@ -807,26 +807,37 @@ FindFontPatterns(gfxUserFontSet *mUserFo
     gfxFontStyle style;
     style.style = aStyle;
     style.weight = aWeight;
     style.stretch = aStretch;
 
     gfxUserFcFontEntry *fontEntry = nullptr;
     gfxFontFamily *family = mUserFontSet->LookupFamily(utf16Family);
     if (family) {
-        fontEntry = static_cast<gfxUserFcFontEntry*>
-            (mUserFontSet->FindFontEntry(family, style, needsBold,
-                                         aWaitForUserFont));
+        gfxUserFontEntry* userFontEntry =
+            mUserFontSet->FindUserFontEntry(family, style, needsBold,
+                                            aWaitForUserFont);
+        if (userFontEntry) {
+            fontEntry = static_cast<gfxUserFcFontEntry*>
+                (userFontEntry->GetPlatformFontEntry());
+        }
 
         // Accept synthetic oblique for italic and oblique.
+        // xxx - this isn't really ideal behavior, for docs that only use a
+        //       single italic face it will also pull down the normal face
+        //       and probably never use it
         if (!fontEntry && aStyle != NS_FONT_STYLE_NORMAL) {
             style.style = NS_FONT_STYLE_NORMAL;
-            fontEntry = static_cast<gfxUserFcFontEntry*>
-                (mUserFontSet->FindFontEntry(family, style, needsBold,
-                                             aWaitForUserFont));
+            userFontEntry = mUserFontSet->FindUserFontEntry(family, style,
+                                                            needsBold,
+                                                            aWaitForUserFont);
+            if (userFontEntry) {
+                fontEntry = static_cast<gfxUserFcFontEntry*>
+                    (userFontEntry->GetPlatformFontEntry());
+            }
         }
     }
 
     if (!fontEntry) {
         return nullptr;
     }
 
     return &fontEntry->GetPatterns();
@@ -1004,17 +1015,17 @@ gfxFcFontSet::SortPreferredFonts(bool &a
             // CSS family names
             if (isUserFont) {
                 font = FcPatternDuplicate(font);
                 FcPatternDel(font, FC_FAMILY);
                 FcPatternAddString(font, FC_FAMILY, family);
             }
 
             // User fonts are already filtered by slant (but not size) in
-            // mUserFontSet->FindFontEntry().
+            // mUserFontSet->FindUserFontEntry().
             if (requestedSize != -1.0 && !SizeIsAcceptable(font, requestedSize))
                 continue;
 
             for (uint32_t r = 0; r < requiredLangs.Length(); ++r) {
                 const LangSupportEntry& entry = requiredLangs[r];
                 FcLangResult support =
                     gfxFontconfigUtils::GetLangSupport(font, entry.mLang);
                 if (support <= entry.mBestSupport) { // lower is better
--- a/gfx/thebes/gfxUserFontSet.cpp
+++ b/gfx/thebes/gfxUserFontSet.cpp
@@ -22,20 +22,20 @@
 #include "gfxPlatformFontList.h"
 
 #include "opentype-sanitiser.h"
 #include "ots-memory-stream.h"
 
 using namespace mozilla;
 
 #ifdef PR_LOGGING
-PRLogModuleInfo *
+PRLogModuleInfo*
 gfxUserFontSet::GetUserFontsLog()
 {
-    static PRLogModuleInfo *sLog;
+    static PRLogModuleInfo* sLog;
     if (!sLog)
         sLog = PR_NewLogModule("userfonts");
     return sLog;
 }
 #endif /* PR_LOGGING */
 
 #define LOG(args) PR_LOG(gfxUserFontSet::GetUserFontsLog(), PR_LOG_DEBUG, args)
 #define LOG_ENABLED() PR_LOG_TEST(gfxUserFontSet::GetUserFontsLog(), PR_LOG_DEBUG)
@@ -60,17 +60,17 @@ public:
     // so the caller becomes responsible to call NS_Free
     // when finished with it
     void* forget() {
         void* p = mPtr;
         mPtr = nullptr;
         return p;
     }
 
-    bool WriteRaw(const void *data, size_t length) {
+    bool WriteRaw(const void* data, size_t length) {
         if ((mOff + length > mLength) ||
             (mLength > std::numeric_limits<size_t>::max() - mOff)) {
             if (mLength == mLimit) {
                 return false;
             }
             size_t newLength = (mLength + 1) * 2;
             if (newLength < mLength) {
                 return false;
@@ -106,24 +106,24 @@ private:
     void*        mPtr;
     size_t       mLength;
     const size_t mLimit;
     off_t        mOff;
 };
 
 // TODO: support for unicode ranges not yet implemented
 
-gfxUserFontEntry::gfxUserFontEntry(gfxUserFontSet *aFontSet,
+gfxUserFontEntry::gfxUserFontEntry(gfxUserFontSet* aFontSet,
              const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
              uint32_t aWeight,
              int32_t aStretch,
              uint32_t aItalicStyle,
              const nsTArray<gfxFontFeature>& aFeatureSettings,
              uint32_t aLanguageOverride,
-             gfxSparseBitSet *aUnicodeRanges)
+             gfxSparseBitSet* aUnicodeRanges)
     : gfxFontEntry(NS_LITERAL_STRING("userfont")),
       mLoadingState(NOT_LOADING),
       mUnsupportedFormat(false),
       mLoader(nullptr),
       mFontSet(aFontSet)
 {
     mIsUserFontContainer = true;
     mSrcList = aFontFaceSrcList;
@@ -143,92 +143,93 @@ gfxUserFontEntry::~gfxUserFontEntry()
 
 bool
 gfxUserFontEntry::Matches(const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
                           uint32_t aWeight,
                           int32_t aStretch,
                           uint32_t aItalicStyle,
                           const nsTArray<gfxFontFeature>& aFeatureSettings,
                           uint32_t aLanguageOverride,
-                          gfxSparseBitSet *aUnicodeRanges)
+                          gfxSparseBitSet* aUnicodeRanges)
 {
     // XXX font entries don't distinguish italic from oblique (bug 543715)
     bool isItalic =
         (aItalicStyle & (NS_FONT_STYLE_ITALIC | NS_FONT_STYLE_OBLIQUE)) != 0;
 
     return mWeight == aWeight &&
            mStretch == aStretch &&
            mItalic == isItalic &&
            mFeatureSettings == aFeatureSettings &&
            mLanguageOverride == aLanguageOverride &&
            mSrcList == aFontFaceSrcList;
            // XXX once we support unicode-range (bug 475891),
            // we'll need to compare that here as well
 }
 
 gfxFont*
-gfxUserFontEntry::CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold)
+gfxUserFontEntry::CreateFontInstance(const gfxFontStyle* aFontStyle, bool aNeedsBold)
 {
+    NS_NOTREACHED("should only be creating a gfxFont"
+                  " with an actual platform font entry");
+
     // userfont entry is a container, can't create font from the container
     return nullptr;
 }
 
 class gfxOTSContext : public ots::OTSContext {
 public:
-    gfxOTSContext(gfxUserFontFamily *aFamily, gfxUserFontEntry *aUserFontEntry)
-        : mFamily(aFamily), mUserFontEntry(aUserFontEntry) {}
+    gfxOTSContext(gfxUserFontEntry* aUserFontEntry)
+        : mUserFontEntry(aUserFontEntry) {}
 
     virtual ots::TableAction GetTableAction(uint32_t aTag) MOZ_OVERRIDE {
         // preserve Graphite, color glyph and SVG tables
         if (aTag == TRUETYPE_TAG('S', 'i', 'l', 'f') ||
             aTag == TRUETYPE_TAG('S', 'i', 'l', 'l') ||
             aTag == TRUETYPE_TAG('G', 'l', 'o', 'c') ||
             aTag == TRUETYPE_TAG('G', 'l', 'a', 't') ||
             aTag == TRUETYPE_TAG('F', 'e', 'a', 't') ||
             aTag == TRUETYPE_TAG('S', 'V', 'G', ' ') ||
             aTag == TRUETYPE_TAG('C', 'O', 'L', 'R') ||
             aTag == TRUETYPE_TAG('C', 'P', 'A', 'L')) {
             return ots::TABLE_ACTION_PASSTHRU;
         }
         return ots::TABLE_ACTION_DEFAULT;
     }
 
-    virtual void Message(const char *format, ...) MSGFUNC_FMT_ATTR MOZ_OVERRIDE {
+    virtual void Message(const char* format, ...) MSGFUNC_FMT_ATTR MOZ_OVERRIDE {
         va_list va;
         va_start(va, format);
 
         // buf should be more than adequate for any message OTS generates,
         // so we don't worry about checking the result of vsnprintf()
         char buf[512];
         (void)vsnprintf(buf, sizeof(buf), format, va);
 
         va_end(va);
 
-        mUserFontEntry->mFontSet->LogMessage(mFamily, mUserFontEntry, buf);
+        mUserFontEntry->mFontSet->LogMessage(mUserFontEntry, buf);
     }
 
 private:
-    gfxUserFontFamily *mFamily;
-    gfxUserFontEntry  *mUserFontEntry;
+    gfxUserFontEntry* mUserFontEntry;
 };
 
 // Call the OTS library to sanitize an sfnt before attempting to use it.
 // Returns a newly-allocated block, or nullptr in case of fatal errors.
 const uint8_t*
-gfxUserFontEntry::SanitizeOpenTypeData(gfxUserFontFamily *aFamily,
-                                       const uint8_t* aData,
+gfxUserFontEntry::SanitizeOpenTypeData(const uint8_t* aData,
                                        uint32_t       aLength,
                                        uint32_t&      aSaneLength,
                                        bool           aIsCompressed)
 {
     // limit output/expansion to 256MB
     ExpandingMemoryStream output(aIsCompressed ? aLength * 2 : aLength,
                                  1024 * 1024 * 256);
 
-    gfxOTSContext otsContext(aFamily, this);
+    gfxOTSContext otsContext(this);
 
     if (otsContext.Process(&output, aData, aLength)) {
         aSaneLength = output.Tell();
         return static_cast<uint8_t*>(output.forget());
     } else {
         aSaneLength = 0;
         return nullptr;
     }
@@ -305,18 +306,17 @@ CopyWOFFMetadata(const uint8_t* aFontDat
     if (!aMetadata->SetLength(woff->metaCompLen)) {
         return;
     }
     memcpy(aMetadata->Elements(), aFontData + metaOffset, metaCompLen);
     *aMetaOrigLen = woff->metaOrigLen;
 }
 
 gfxUserFontEntry::LoadStatus
-gfxUserFontEntry::LoadNext(gfxUserFontFamily *aFamily,
-                           bool& aLocalRulesUsed)
+gfxUserFontEntry::LoadNext()
 {
     uint32_t numSrc = mSrcList.Length();
 
     NS_ASSERTION(mSrcIndex < numSrc,
                  "already at the end of the src list for user font");
 
     if (mLoadingState == NOT_LOADING) {
         mLoadingState = LOADING_STARTED;
@@ -331,172 +331,171 @@ gfxUserFontEntry::LoadNext(gfxUserFontFa
     // load each src entry in turn, until a local face is found
     // or a download begins successfully
     while (mSrcIndex < numSrc) {
         const gfxFontFaceSrc& currSrc = mSrcList[mSrcIndex];
 
         // src local ==> lookup and load immediately
 
         if (currSrc.mIsLocal) {
-            gfxFontEntry *fe =
+            gfxFontEntry* fe =
                 gfxPlatform::GetPlatform()->LookupLocalFont(currSrc.mLocalName,
                                                             mWeight,
                                                             mStretch,
                                                             mItalic);
-            aLocalRulesUsed = true;
+            mFontSet->SetLocalRulesUsed();
             if (fe) {
                 LOG(("fontset (%p) [src %d] loaded local: (%s) for (%s) gen: %8.8x\n",
                      mFontSet, mSrcIndex,
                      NS_ConvertUTF16toUTF8(currSrc.mLocalName).get(),
                      NS_ConvertUTF16toUTF8(mFamilyName).get(),
                      uint32_t(mFontSet->mGeneration)));
                 fe->mFeatureSettings.AppendElements(mFeatureSettings);
                 fe->mLanguageOverride = mLanguageOverride;
                 fe->mFamilyName = mFamilyName;
                 // For src:local(), we don't care whether the request is from
                 // a private window as there's no issue of caching resources;
                 // local fonts are just available all the time.
                 StoreUserFontData(fe, false, nsString(), nullptr, 0);
-                mFontSet->ReplaceFontEntry(aFamily, this, fe);
+                mPlatformFontEntry = fe;
                 return STATUS_LOADED;
             } else {
                 LOG(("fontset (%p) [src %d] failed local: (%s) for (%s)\n",
                      mFontSet, mSrcIndex,
                      NS_ConvertUTF16toUTF8(currSrc.mLocalName).get(),
                      NS_ConvertUTF16toUTF8(mFamilyName).get()));
             }
         }
 
         // src url ==> start the load process
         else {
             if (gfxPlatform::GetPlatform()->IsFontFormatSupported(currSrc.mURI,
                     currSrc.mFormatFlags)) {
 
-                nsIPrincipal *principal = nullptr;
+                nsIPrincipal* principal = nullptr;
                 bool bypassCache;
                 nsresult rv = mFontSet->CheckFontLoad(&currSrc, &principal,
                                                       &bypassCache);
 
                 if (NS_SUCCEEDED(rv) && principal != nullptr) {
                     if (!bypassCache) {
                         // see if we have an existing entry for this source
-                        gfxFontEntry *fe = gfxUserFontSet::
+                        gfxFontEntry* fe = gfxUserFontSet::
                             UserFontCache::GetFont(currSrc.mURI,
                                                    principal,
                                                    this,
                                                    mFontSet->GetPrivateBrowsing());
                         if (fe) {
-                            mFontSet->ReplaceFontEntry(aFamily, this, fe);
+                            mPlatformFontEntry = fe;
                             return STATUS_LOADED;
                         }
                     }
 
                     // record the principal returned by CheckFontLoad,
                     // for use when creating a channel
                     // and when caching the loaded entry
                     mPrincipal = principal;
 
                     bool loadDoesntSpin = false;
                     rv = NS_URIChainHasFlags(currSrc.mURI,
                            nsIProtocolHandler::URI_SYNC_LOAD_IS_OK,
                            &loadDoesntSpin);
 
                     if (NS_SUCCEEDED(rv) && loadDoesntSpin) {
-                        uint8_t *buffer = nullptr;
+                        uint8_t* buffer = nullptr;
                         uint32_t bufferLength = 0;
 
                         // sync load font immediately
                         rv = mFontSet->SyncLoadFontData(this, &currSrc, buffer,
                                                         bufferLength);
 
                         if (NS_SUCCEEDED(rv) &&
-                            LoadFont(aFamily, buffer, bufferLength)) {
+                            LoadFont(buffer, bufferLength)) {
                             return STATUS_LOADED;
                         } else {
-                            mFontSet->LogMessage(aFamily, this,
+                            mFontSet->LogMessage(this,
                                                  "font load failed",
                                                  nsIScriptError::errorFlag,
                                                  rv);
                         }
 
                     } else {
                         // otherwise load font async
-                        rv = mFontSet->StartLoad(aFamily, this, &currSrc);
+                        rv = mFontSet->StartLoad(this, &currSrc);
                         bool loadOK = NS_SUCCEEDED(rv);
 
                         if (loadOK) {
 #ifdef PR_LOGGING
                             if (LOG_ENABLED()) {
                                 nsAutoCString fontURI;
                                 currSrc.mURI->GetSpec(fontURI);
                                 LOG(("userfonts (%p) [src %d] loading uri: (%s) for (%s)\n",
                                      mFontSet, mSrcIndex, fontURI.get(),
                                      NS_ConvertUTF16toUTF8(mFamilyName).get()));
                             }
 #endif
                             return STATUS_LOADING;
                         } else {
-                            mFontSet->LogMessage(aFamily, this,
+                            mFontSet->LogMessage(this,
                                                  "download failed",
                                                  nsIScriptError::errorFlag,
                                                  rv);
                         }
                     }
                 } else {
-                    mFontSet->LogMessage(aFamily, this, "download not allowed",
+                    mFontSet->LogMessage(this, "download not allowed",
                                          nsIScriptError::errorFlag, rv);
                 }
             } else {
                 // We don't log a warning to the web console yet,
                 // as another source may load successfully
                 mUnsupportedFormat = true;
             }
         }
 
         mSrcIndex++;
     }
 
     if (mUnsupportedFormat) {
-        mFontSet->LogMessage(aFamily, this, "no supported format found",
+        mFontSet->LogMessage(this, "no supported format found",
                              nsIScriptError::warningFlag);
     }
 
     // all src's failed; mark this entry as unusable (so fallback will occur)
     LOG(("userfonts (%p) failed all src for (%s)\n",
         mFontSet, NS_ConvertUTF16toUTF8(mFamilyName).get()));
     mLoadingState = LOADING_FAILED;
 
     return STATUS_END_OF_LIST;
 }
 
-gfxFontEntry*
-gfxUserFontEntry::LoadFont(gfxUserFontFamily *aFamily,
-                           const uint8_t* aFontData, uint32_t &aLength)
+bool
+gfxUserFontEntry::LoadFont(const uint8_t* aFontData, uint32_t &aLength)
 {
-    gfxFontEntry *fe = nullptr;
+    gfxFontEntry* fe = nullptr;
 
     gfxUserFontType fontType =
         gfxFontUtils::DetermineFontDataType(aFontData, aLength);
 
     // Unwrap/decompress/sanitize or otherwise munge the downloaded data
     // to make a usable sfnt structure.
 
     // Because platform font activation code may replace the name table
     // in the font with a synthetic one, we save the original name so that
     // it can be reported via the nsIDOMFontFace API.
     nsAutoString originalFullName;
 
     // Call the OTS sanitizer; this will also decode WOFF to sfnt
     // if necessary. The original data in aFontData is left unchanged.
     uint32_t saneLen;
     const uint8_t* saneData =
-        SanitizeOpenTypeData(aFamily, aFontData, aLength, saneLen,
+        SanitizeOpenTypeData(aFontData, aLength, saneLen,
                              fontType == GFX_USERFONT_WOFF);
     if (!saneData) {
-        mFontSet->LogMessage(aFamily, this, "rejected by sanitizer");
+        mFontSet->LogMessage(this, "rejected by sanitizer");
     }
     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
         // memory, and GetFullNameFromSFNT is not directly exposed to
         // arbitrary/malicious data from the web.
         gfxFontUtils::GetFullNameFromSFNT(saneData, saneLen,
                                           originalFullName);
@@ -505,17 +504,17 @@ gfxUserFontEntry::LoadFont(gfxUserFontFa
 
         fe = gfxPlatform::GetPlatform()->MakePlatformFont(mName,
                                                           mWeight,
                                                           mStretch,
                                                           mItalic,
                                                           saneData,
                                                           saneLen);
         if (!fe) {
-            mFontSet->LogMessage(aFamily, this, "not usable by platform");
+            mFontSet->LogMessage(this, "not usable by platform");
         }
     }
 
     if (fe) {
         // Save a copy of the metadata block (if present) for nsIDOMFontFace
         // to use if required. Ownership of the metadata block will be passed
         // to the gfxUserFontData record below.
         FallibleTArray<uint8_t> metadata;
@@ -536,17 +535,17 @@ gfxUserFontEntry::LoadFont(gfxUserFontFa
             nsAutoCString fontURI;
             mSrcList[mSrcIndex].mURI->GetSpec(fontURI);
             LOG(("userfonts (%p) [src %d] loaded uri: (%s) for (%s) gen: %8.8x\n",
                  this, mSrcIndex, fontURI.get(),
                  NS_ConvertUTF16toUTF8(mFamilyName).get(),
                  uint32_t(mFontSet->mGeneration)));
         }
 #endif
-        mFontSet->ReplaceFontEntry(aFamily, this, fe);
+        mPlatformFontEntry = fe;
         gfxUserFontSet::UserFontCache::CacheFont(fe);
     } else {
 #ifdef PR_LOGGING
         if (LOG_ENABLED()) {
             nsAutoCString fontURI;
             mSrcList[mSrcIndex].mURI->GetSpec(fontURI);
             LOG(("userfonts (%p) [src %d] failed uri: (%s) for (%s)"
                  " error making platform font\n",
@@ -555,32 +554,75 @@ gfxUserFontEntry::LoadFont(gfxUserFontFa
         }
 #endif
     }
 
     // The downloaded data can now be discarded; the font entry is using the
     // sanitized copy
     NS_Free((void*)aFontData);
 
-    return fe;
+    return fe != nullptr;
+}
+
+// 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
+gfxUserFontEntry::OnLoadComplete(const uint8_t* aFontData, uint32_t aLength,
+                                 nsresult aDownloadStatus)
+{
+    // forget about the loader, as we no longer potentially need to cancel it
+    // if the entry is obsoleted
+    mLoader = nullptr;
+
+    // download successful, make platform font using font data
+    if (NS_SUCCEEDED(aDownloadStatus)) {
+        bool loaded = LoadFont(aFontData, aLength);
+        aFontData = nullptr;
+
+        if (loaded) {
+            mFontSet->IncrementGeneration();
+            return true;
+        }
+
+    } else {
+        // download failed
+        mFontSet->LogMessage(this,
+                             "download failed", nsIScriptError::errorFlag,
+                             aDownloadStatus);
+    }
+
+    if (aFontData) {
+        moz_free((void*)aFontData);
+    }
+
+    // error occurred, load next src
+    LoadNext();
+
+    // We ignore the status returned by LoadNext();
+    // even if loading failed, we need to bump the font-set generation
+    // and return true in order to trigger reflow, so that fallback
+    // will be used where the text was "masked" by the pending download
+    mFontSet->IncrementGeneration();
+    return true;
 }
 
 gfxUserFontSet::gfxUserFontSet()
     : mFontFamilies(4), mLocalRulesUsed(false)
 {
     IncrementGeneration();
-    gfxPlatformFontList *fp = gfxPlatformFontList::PlatformFontList();
+    gfxPlatformFontList* fp = gfxPlatformFontList::PlatformFontList();
     if (fp) {
         fp->AddUserFontSet(this);
     }
 }
 
 gfxUserFontSet::~gfxUserFontSet()
 {
-    gfxPlatformFontList *fp = gfxPlatformFontList::PlatformFontList();
+    gfxPlatformFontList* fp = gfxPlatformFontList::PlatformFontList();
     if (fp) {
         fp->RemoveUserFontSet(this);
     }
 }
 
 already_AddRefed<gfxUserFontEntry>
 gfxUserFontSet::FindOrCreateFontFace(
                                const nsAString& aFamilyName,
@@ -681,121 +723,82 @@ gfxUserFontSet::FindExistingUserFontEntr
         return existingUserFontEntry;
     }
 
     return nullptr;
 }
 
 void
 gfxUserFontSet::AddFontFace(const nsAString& aFamilyName,
-                            gfxFontEntry     *aFontEntry)
+                            gfxUserFontEntry* aUserFontEntry)
 {
     gfxUserFontFamily* family = GetFamily(aFamilyName);
-    family->AddFontEntry(aFontEntry);
+    family->AddFontEntry(aUserFontEntry);
 
 #ifdef PR_LOGGING
     if (LOG_ENABLED()) {
         LOG(("userfonts (%p) added \"%s\" (%p)",
-             this, NS_ConvertUTF16toUTF8(aFamilyName).get(), aFontEntry));
+             this, NS_ConvertUTF16toUTF8(aFamilyName).get(), aUserFontEntry));
     }
 #endif
 }
 
-gfxFontEntry*
-gfxUserFontSet::FindFontEntry(gfxFontFamily *aFamily,
-                              const gfxFontStyle& aFontStyle,
-                              bool& aNeedsBold,
-                              bool& aWaitForUserFont)
+gfxUserFontEntry*
+gfxUserFontSet::FindUserFontEntry(gfxFontFamily* aFamily,
+                                  const gfxFontStyle& aFontStyle,
+                                  bool& aNeedsBold,
+                                  bool& aWaitForUserFont)
 {
     aWaitForUserFont = false;
-    gfxUserFontFamily *family = static_cast<gfxUserFontFamily*>(aFamily);
+    gfxUserFontFamily* family = static_cast<gfxUserFontFamily*>(aFamily);
 
     gfxFontEntry* fe = family->FindFontForStyle(aFontStyle, aNeedsBold);
 
+    NS_ASSERTION(!fe || fe->mIsUserFontContainer,
+                 "should only have userfont entries in userfont families");
+
     // if not a userfont entry, font has already been loaded
-    if (!fe->mIsUserFontContainer) {
-        return fe;
+    if (!fe || !fe->mIsUserFontContainer) {
+        return nullptr;
     }
 
-    gfxUserFontEntry *userFontEntry = static_cast<gfxUserFontEntry*> (fe);
+    gfxUserFontEntry* userFontEntry = static_cast<gfxUserFontEntry*> (fe);
+
+    if (userFontEntry->GetPlatformFontEntry()) {
+        return userFontEntry;
+    }
 
     // if currently loading, return null for now
     if (userFontEntry->mLoadingState > gfxUserFontEntry::NOT_LOADING) {
         aWaitForUserFont =
             (userFontEntry->mLoadingState < gfxUserFontEntry::LOADING_SLOWLY);
         return nullptr;
     }
 
     // hasn't been loaded yet, start the load process
     gfxUserFontEntry::LoadStatus status;
 
     // NOTE that if all sources in the entry fail, this will delete userFontEntry,
     // so we cannot use it again if status==STATUS_END_OF_LIST
-    status = userFontEntry->LoadNext(family, mLocalRulesUsed);
+    status = userFontEntry->LoadNext();
 
-    // if the load succeeded immediately, the font entry was replaced so
-    // search again
+    // if the load succeeded immediately, return
     if (status == gfxUserFontEntry::STATUS_LOADED) {
-        return family->FindFontForStyle(aFontStyle, aNeedsBold);
+        return userFontEntry;
     }
 
     // check whether we should wait for load to complete before painting
     // a fallback font -- but not if all sources failed (bug 633500)
     aWaitForUserFont = (status != gfxUserFontEntry::STATUS_END_OF_LIST) &&
         (userFontEntry->mLoadingState < gfxUserFontEntry::LOADING_SLOWLY);
 
     // if either loading or an error occurred, return null
     return nullptr;
 }
 
-// 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(gfxUserFontFamily *aFamily,
-                               gfxUserFontEntry *aUserFontEntry,
-                               const uint8_t* aFontData, uint32_t aLength,
-                               nsresult aDownloadStatus)
-{
-    // forget about the loader, as we no longer potentially need to cancel it
-    // if the entry is obsoleted
-    aUserFontEntry->mLoader = nullptr;
-
-    // download successful, make platform font using font data
-    if (NS_SUCCEEDED(aDownloadStatus)) {
-        gfxFontEntry *fe = aUserFontEntry->LoadFont(aFamily, aFontData, aLength);
-        aFontData = nullptr;
-
-        if (fe) {
-            IncrementGeneration();
-            return true;
-        }
-
-    } else {
-        // download failed
-        LogMessage(aFamily, aUserFontEntry,
-                   "download failed", nsIScriptError::errorFlag,
-                   aDownloadStatus);
-    }
-
-    if (aFontData) {
-        moz_free((void*)aFontData);
-    }
-
-    // error occurred, load next src
-    (void)aUserFontEntry->LoadNext(aFamily, mLocalRulesUsed);
-
-    // We ignore the status returned by LoadNext();
-    // even if loading failed, we need to bump the font-set generation
-    // and return true in order to trigger reflow, so that fallback
-    // will be used where the text was "masked" by the pending download
-    IncrementGeneration();
-    return true;
-}
-
 void
 gfxUserFontSet::IncrementGeneration()
 {
     // add one, increment again if zero
     ++sFontSetGeneration;
     if (sFontSetGeneration == 0)
        ++sFontSetGeneration;
     mGeneration = sFontSetGeneration;
@@ -827,43 +830,16 @@ gfxUserFontSet::GetFamily(const nsAStrin
     gfxUserFontFamily* family = mFontFamilies.GetWeak(key);
     if (!family) {
         family = new gfxUserFontFamily(aFamilyName);
         mFontFamilies.Put(key, family);
     }
     return family;
 }
 
-struct FindFamilyCallbackData {
-    gfxFontEntry  *mFontEntry;
-    gfxFontFamily *mFamily;
-};
-
-static PLDHashOperator
-FindFamilyCallback(const nsAString& aName,
-                   gfxUserFontFamily* aFamily,
-                   void* aUserArg)
-{
-    FindFamilyCallbackData *d = static_cast<FindFamilyCallbackData*>(aUserArg);
-    if (aFamily->ContainsFace(d->mFontEntry)) {
-        d->mFamily = aFamily;
-        return PL_DHASH_STOP;
-    }
-
-    return PL_DHASH_NEXT;
-}
-
-gfxFontFamily*
-gfxUserFontSet::FindFamilyFor(gfxFontEntry* aFontEntry) const
-{
-    FindFamilyCallbackData d = { aFontEntry, nullptr };
-    mFontFamilies.EnumerateRead(FindFamilyCallback, &d);
-    return d.mFamily;
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 // gfxUserFontSet::UserFontCache - re-use platform font entries for user fonts
 // across pages/fontsets rather than instantiating new platform fonts.
 //
 // Entries are added to this cache when a platform font is instantiated from
 // downloaded data, and removed when the platform font entry is destroyed.
 // We don't need to use a timed expiration scheme here because the gfxFontEntry
 // for a downloaded font will be kept alive by its corresponding gfxFont
@@ -927,30 +903,30 @@ gfxUserFontSet::UserFontCache::Flusher::
     } else {
         NS_NOTREACHED("unexpected topic");
     }
 
     return NS_OK;
 }
 
 static bool
-IgnorePrincipal(nsIURI *aURI)
+IgnorePrincipal(nsIURI* aURI)
 {
     nsresult rv;
     bool inherits = false;
     rv = NS_URIChainHasFlags(aURI,
                              nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
                              &inherits);
     return NS_SUCCEEDED(rv) && inherits;
 }
 
 bool
 gfxUserFontSet::UserFontCache::Entry::KeyEquals(const KeyTypePointer aKey) const
 {
-    const gfxFontEntry *fe = aKey->mFontEntry;
+    const gfxFontEntry* fe = aKey->mFontEntry;
     // CRC32 checking mode
     if (mLength || aKey->mLength) {
         if (aKey->mLength != mLength ||
             aKey->mCRC32 != mCRC32) {
             return false;
         }
     } else {
         bool result;
@@ -981,64 +957,64 @@ gfxUserFontSet::UserFontCache::Entry::Ke
         mFontEntry->mFamilyName       != fe->mFamilyName) {
         return false;
     }
 
     return true;
 }
 
 void
-gfxUserFontSet::UserFontCache::CacheFont(gfxFontEntry *aFontEntry,
+gfxUserFontSet::UserFontCache::CacheFont(gfxFontEntry* aFontEntry,
                                          EntryPersistence aPersistence)
 {
     NS_ASSERTION(aFontEntry->mFamilyName.Length() != 0,
                  "caching a font associated with no family yet");
     if (!sUserFonts) {
         sUserFonts = new nsTHashtable<Entry>;
 
         nsCOMPtr<nsIObserverService> obs =
             mozilla::services::GetObserverService();
         if (obs) {
-            Flusher *flusher = new Flusher;
+            Flusher* flusher = new Flusher;
             obs->AddObserver(flusher, "cacheservice:empty-cache",
                              false);
             obs->AddObserver(flusher, "last-pb-context-exited", false);
             obs->AddObserver(flusher, "xpcom-shutdown", false);
         }
     }
 
-    gfxUserFontData *data = aFontEntry->mUserFontData;
+    gfxUserFontData* data = aFontEntry->mUserFontData;
     if (data->mLength) {
         MOZ_ASSERT(aPersistence == kPersistent);
         MOZ_ASSERT(!data->mPrivate);
         sUserFonts->PutEntry(Key(data->mCRC32, data->mLength, aFontEntry,
                                  data->mPrivate, aPersistence));
     } else {
         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;
+        nsIPrincipal* principal;
         if (IgnorePrincipal(data->mURI)) {
             principal = nullptr;
         } else {
             principal = data->mPrincipal;
         }
         sUserFonts->PutEntry(Key(data->mURI, principal, aFontEntry,
                                  data->mPrivate, aPersistence));
     }
 
 #ifdef DEBUG_USERFONT_CACHE
     printf("userfontcache added fontentry: %p\n", aFontEntry);
     Dump();
 #endif
 }
 
 void
-gfxUserFontSet::UserFontCache::ForgetFont(gfxFontEntry *aFontEntry)
+gfxUserFontSet::UserFontCache::ForgetFont(gfxFontEntry* aFontEntry)
 {
     if (!sUserFonts) {
         // if we've already deleted the cache (i.e. during shutdown),
         // just ignore this
         return;
     }
 
     // We can't simply use RemoveEntry here because it's possible the principal
@@ -1049,27 +1025,27 @@ gfxUserFontSet::UserFontCache::ForgetFon
 
 #ifdef DEBUG_USERFONT_CACHE
     printf("userfontcache removed fontentry: %p\n", aFontEntry);
     Dump();
 #endif
 }
 
 gfxFontEntry*
-gfxUserFontSet::UserFontCache::GetFont(nsIURI            *aSrcURI,
-                                       nsIPrincipal      *aPrincipal,
-                                       gfxUserFontEntry  *aUserFontEntry,
-                                       bool               aPrivate)
+gfxUserFontSet::UserFontCache::GetFont(nsIURI* aSrcURI,
+                                       nsIPrincipal* aPrincipal,
+                                       gfxUserFontEntry* aUserFontEntry,
+                                       bool aPrivate)
 {
     if (!sUserFonts) {
         return nullptr;
     }
 
     // Ignore principal when looking up a data: URI.
-    nsIPrincipal *principal;
+    nsIPrincipal* principal;
     if (IgnorePrincipal(aSrcURI)) {
         principal = nullptr;
     } else {
         principal = aPrincipal;
     }
 
     Entry* entry = sUserFonts->GetEntry(Key(aSrcURI, principal, aUserFontEntry,
                                             aPrivate));
--- a/gfx/thebes/gfxUserFontSet.h
+++ b/gfx/thebes/gfxUserFontSet.h
@@ -86,74 +86,38 @@ class gfxUserFontFamily : public gfxFont
 public:
     friend class gfxUserFontSet;
 
     explicit gfxUserFontFamily(const nsAString& aName)
         : gfxFontFamily(aName) { }
 
     virtual ~gfxUserFontFamily() { }
 
-    // Add the given font entry to the end of the family's list.
-    // Any earlier occurrence is removed, so this has the effect of "advancing"
-    // the entry to the end of the list.
-    void AddFontEntry(gfxFontEntry *aFontEntry) {
-        // We append to mAvailableFonts -before- searching for and removing
-        // any existing reference to avoid the risk that we'll remove the last
-        // reference to the font entry, and thus delete it.
+    // add the given font entry to the end of the family's list
+    void AddFontEntry(gfxFontEntry* aFontEntry) {
+        // keep ref while removing existing entry
+        nsRefPtr<gfxFontEntry> fe = aFontEntry;
+        // remove existing entry, if already present
+        mAvailableFonts.RemoveElement(aFontEntry);
         mAvailableFonts.AppendElement(aFontEntry);
-        uint32_t i = mAvailableFonts.Length() - 1;
-        while (i > 0) {
-            if (mAvailableFonts[--i] == aFontEntry) {
-                mAvailableFonts.RemoveElementAt(i);
-                break;
-            }
-        }
+
         if (aFontEntry->mFamilyName.IsEmpty()) {
             aFontEntry->mFamilyName = Name();
         } else {
 #ifdef DEBUG
             nsString thisName = Name();
             nsString entryName = aFontEntry->mFamilyName;
             ToLowerCase(thisName);
             ToLowerCase(entryName);
             MOZ_ASSERT(thisName.Equals(entryName));
 #endif
         }
         ResetCharacterMap();
     }
 
-    // Replace userfont entry in the family's list with aRealFontEntry.
-    void ReplaceFontEntry(gfxFontEntry *aUserFontEntry,
-                          gfxFontEntry *aRealFontEntry) {
-        uint32_t numFonts = mAvailableFonts.Length();
-        uint32_t i;
-        for (i = 0; i < numFonts; i++) {
-            gfxFontEntry *fe = mAvailableFonts[i];
-            if (fe == aUserFontEntry) {
-                // Note that this may delete aUserFontEntry, if there's no
-                // other reference to it except from its family.
-                mAvailableFonts[i] = aRealFontEntry;
-                if (aRealFontEntry->mFamilyName.IsEmpty()) {
-                    aRealFontEntry->mFamilyName = Name();
-                } else {
-#ifdef DEBUG
-                  nsString thisName = Name();
-                  nsString entryName = aRealFontEntry->mFamilyName;
-                  ToLowerCase(thisName);
-                  ToLowerCase(entryName);
-                  MOZ_ASSERT(thisName.Equals(entryName));
-#endif
-                }
-                break;
-            }
-        }
-        NS_ASSERTION(i < numFonts, "font entry not found in family!");
-        ResetCharacterMap();
-    }
-
     // Remove all font entries from the family
     void DetachFontEntries() {
         mAvailableFonts.Clear();
     }
 };
 
 class gfxUserFontEntry;
 class gfxOTSContext;
@@ -206,72 +170,48 @@ public:
                                const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
                                uint32_t aWeight,
                                int32_t aStretch,
                                uint32_t aItalicStyle,
                                const nsTArray<gfxFontFeature>& aFeatureSettings,
                                uint32_t aLanguageOverride,
                                gfxSparseBitSet* aUnicodeRanges);
 
-    // add in a font face for which we have the gfxFontEntry already
-    void AddFontFace(const nsAString& aFamilyName, gfxFontEntry* aFontEntry);
+    // add in a font face for which we have the gfxUserFontEntry already
+    void AddFontFace(const nsAString& aFamilyName,
+                     gfxUserFontEntry* aUserFontEntry);
 
     // Whether there is a face with this family name
     bool HasFamily(const nsAString& aFamilyName) const
     {
         return LookupFamily(aFamilyName) != nullptr;
     }
 
     // Look up and return the gfxUserFontFamily in mFontFamilies with
     // the given name
     gfxUserFontFamily* LookupFamily(const nsAString& aName) const;
 
     // Lookup a font entry for a given style, returns null if not loaded.
     // aFamily must be a family returned by our LookupFamily method.
-    gfxFontEntry *FindFontEntry(gfxFontFamily *aFamily,
-                                const gfxFontStyle& aFontStyle,
-                                bool& aNeedsBold,
-                                bool& aWaitForUserFont);
-
-    // Find a family (possibly one of several!) that owns the given entry.
-    // This may be somewhat expensive, as it enumerates all the fonts in
-    // the set. Currently used only by the Linux (gfxPangoFontGroup) backend,
-    // which does not directly track families in the font group's list.
-    gfxFontFamily *FindFamilyFor(gfxFontEntry *aFontEntry) const;
+    gfxUserFontEntry* FindUserFontEntry(gfxFontFamily* aFamily,
+                                        const gfxFontStyle& aFontStyle,
+                                        bool& aNeedsBold,
+                                        bool& aWaitForUserFont);
 
     // check whether the given source is allowed to be loaded;
     // 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,
-                                   bool *aBypassCache) = 0;
+    virtual nsresult CheckFontLoad(const gfxFontFaceSrc* aFontFaceSrc,
+                                   nsIPrincipal** aPrincipal,
+                                   bool* aBypassCache) = 0;
 
     // initialize the process that loads external font data, which upon 
     // completion will call OnLoadComplete method
-    virtual nsresult StartLoad(gfxUserFontFamily *aFamily,
-                               gfxUserFontEntry *aUserFontEntry,
-                               const gfxFontFaceSrc *aFontFaceSrc) = 0;
-
-    // when download has been completed, pass back data here
-    // aDownloadStatus == NS_OK ==> download succeeded, error otherwise
-    // returns true if platform font creation sucessful (or local()
-    // reference was next in line)
-    // Ownership of aFontData is passed in here; the font set must
-    // ensure that it is eventually deleted with NS_Free().
-    bool OnLoadComplete(gfxUserFontFamily *aFamily,
-                        gfxUserFontEntry *aUserFontEntry,
-                        const uint8_t* aFontData, uint32_t aLength,
-                        nsresult aDownloadStatus);
-
-    // Replace a userfont entry with a real fontEntry; this is implemented in
-    // nsUserFontSet in order to keep track of the entry corresponding
-    // to each @font-face rule.
-    virtual void ReplaceFontEntry(gfxUserFontFamily *aFamily,
-                                  gfxUserFontEntry *aUserFontEntry,
-                                  gfxFontEntry *aFontEntry) = 0;
+    virtual nsresult StartLoad(gfxUserFontEntry* aUserFontEntry,
+                               const gfxFontFaceSrc* aFontFaceSrc) = 0;
 
     // generation - each time a face is loaded, generation is
     // incremented so that the change can be recognized 
     uint64_t GetGeneration() { return mGeneration; }
 
     // increment the generation on font load
     void IncrementGeneration();
 
@@ -288,31 +228,31 @@ public:
         } EntryPersistence;
 
         // Record a loaded user-font in the cache. This requires that the
         // font-entry's userFontData has been set up already, as it relies
         // on the URI and Principal recorded there.
         // If aPersistence is Persistent, the entry will remain in the cache
         // across cacheservice:empty-cache notifications. This is used for
         // "preloaded hidden fonts" on FxOS.
-        static void CacheFont(gfxFontEntry *aFontEntry,
+        static void CacheFont(gfxFontEntry* aFontEntry,
                               EntryPersistence aPersistence = kDiscardable);
 
         // The given gfxFontEntry is being destroyed, so remove any record that
         // refers to it.
-        static void ForgetFont(gfxFontEntry *aFontEntry);
+        static void ForgetFont(gfxFontEntry* aFontEntry);
 
         // Return the gfxFontEntry corresponding to a given URI and principal,
         // and the features of the given userfont entry, or nullptr if none is available.
         // The aPrivate flag is set for requests coming from private windows,
         // so we can avoid leaking fonts cached in private windows mode out to
         // normal windows.
-        static gfxFontEntry* GetFont(nsIURI           *aSrcURI,
-                                     nsIPrincipal     *aPrincipal,
-                                     gfxUserFontEntry *aUserFontEntry,
+        static gfxFontEntry* GetFont(nsIURI* aSrcURI,
+                                     nsIPrincipal* aPrincipal,
+                                     gfxUserFontEntry* aUserFontEntry,
                                      bool              aPrivate);
 
         // Clear everything so that we don't leak URIs and Principals.
         static void Shutdown();
 
 #ifdef DEBUG_USERFONT_CACHE
         // dump contents
         static void Dump();
@@ -334,17 +274,17 @@ public:
         // Note that key comparison does *not* use the mFontEntry field
         // as a whole; it only compares specific fields within the entry
         // (weight/width/style/features) that could affect font selection
         // or rendering, and that must match between a font-set's userfont
         // entry and the corresponding "real" font entry.
         struct Key {
             nsCOMPtr<nsIURI>        mURI;
             nsCOMPtr<nsIPrincipal>  mPrincipal; // use nullptr with data: URLs
-            gfxFontEntry           *mFontEntry;
+            gfxFontEntry*           mFontEntry;
             uint32_t                mCRC32;
             uint32_t                mLength;
             bool                    mPrivate;
             EntryPersistence        mPersistence;
 
             Key(nsIURI* aURI, nsIPrincipal* aPrincipal,
                 gfxFontEntry* aFontEntry, bool aPrivate,
                 EntryPersistence aPersistence = kDiscardable)
@@ -447,45 +387,48 @@ public:
             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()).
-            gfxFontEntry          *mFontEntry;
+            gfxFontEntry*          mFontEntry;
 
             // Whether this font was loaded from a private window.
             bool                   mPrivate;
 
             // Whether this entry should survive cache-flushing.
             EntryPersistence       mPersistence;
         };
 
-        static nsTHashtable<Entry> *sUserFonts;
+        static nsTHashtable<Entry>* sUserFonts;
     };
 
+    void SetLocalRulesUsed() {
+        mLocalRulesUsed = true;
+    }
+
 protected:
     // Protected destructor, to discourage deletion outside of Release():
     virtual ~gfxUserFontSet();
 
     // Return whether the font set is associated with a private-browsing tab.
     virtual bool GetPrivateBrowsing() = 0;
 
     // parse data for a data URL
-    virtual nsresult SyncLoadFontData(gfxUserFontEntry *aFontToLoad,
-                                      const gfxFontFaceSrc *aFontFaceSrc,
+    virtual nsresult SyncLoadFontData(gfxUserFontEntry* aFontToLoad,
+                                      const gfxFontFaceSrc* aFontFaceSrc,
                                       uint8_t* &aBuffer,
                                       uint32_t &aBufferLength) = 0;
 
     // report a problem of some kind (implemented in nsUserFontSet)
-    virtual nsresult LogMessage(gfxUserFontFamily *aFamily,
-                                gfxUserFontEntry *aUserFontEntry,
-                                const char *aMessage,
+    virtual nsresult LogMessage(gfxUserFontEntry* aUserFontEntry,
+                                const char* aMessage,
                                 uint32_t aFlags = nsIScriptError::errorFlag,
                                 nsresult aStatus = NS_OK) = 0;
 
     // helper method for performing the actual userfont set rebuild
     virtual void DoRebuildUserFontSet() = 0;
 
     // helper method for FindOrCreateFontFace
     gfxUserFontEntry* FindExistingUserFontEntry(
@@ -525,57 +468,63 @@ public:
     enum LoadStatus {
         STATUS_LOADING = 0,
         STATUS_LOADED,
         STATUS_FORMAT_NOT_SUPPORTED,
         STATUS_ERROR,
         STATUS_END_OF_LIST
     };
 
-    gfxUserFontEntry(gfxUserFontSet *aFontSet,
+    gfxUserFontEntry(gfxUserFontSet* aFontSet,
                      const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
                      uint32_t aWeight,
                      int32_t aStretch,
                      uint32_t aItalicStyle,
                      const nsTArray<gfxFontFeature>& aFeatureSettings,
                      uint32_t aLanguageOverride,
-                     gfxSparseBitSet *aUnicodeRanges);
+                     gfxSparseBitSet* aUnicodeRanges);
 
     virtual ~gfxUserFontEntry();
 
     // Return whether the entry matches the given list of attributes
     bool Matches(const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
                  uint32_t aWeight,
                  int32_t aStretch,
                  uint32_t aItalicStyle,
                  const nsTArray<gfxFontFeature>& aFeatureSettings,
                  uint32_t aLanguageOverride,
-                 gfxSparseBitSet *aUnicodeRanges);
+                 gfxSparseBitSet* aUnicodeRanges);
+
+    virtual gfxFont* CreateFontInstance(const gfxFontStyle* aFontStyle, bool aNeedsBold);
+
+    gfxFontEntry* GetPlatformFontEntry() { return mPlatformFontEntry; }
 
-    virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold);
+    // when download has been completed, pass back data here
+    // aDownloadStatus == NS_OK ==> download succeeded, error otherwise
+    // returns true if platform font creation sucessful (or local()
+    // reference was next in line)
+    // Ownership of aFontData is passed in here; the font set must
+    // ensure that it is eventually deleted with NS_Free().
+    bool OnLoadComplete(const uint8_t* aFontData, uint32_t aLength,
+                        nsresult aDownloadStatus);
 
 protected:
-    const uint8_t* SanitizeOpenTypeData(gfxUserFontFamily *aFamily,
-                                        const uint8_t* aData,
+    const uint8_t* SanitizeOpenTypeData(const uint8_t* aData,
                                         uint32_t aLength,
                                         uint32_t& aSaneLength,
                                         bool aIsCompressed);
 
     // Attempt to load the next resource in the src list.
-    // aLocalRules is set to true if an attempt was made to load a
-    // local() font was loaded, and left as it is otherwise.
-    LoadStatus LoadNext(gfxUserFontFamily *aFamily,
-                        bool& aLocalRulesUsed);
+    LoadStatus LoadNext();
 
     // helper method for creating a platform font
-    // returns font entry if platform font creation successful
+    // returns true if platform font creation successful
     // Ownership of aFontData is passed in here; the font must
     // ensure that it is eventually deleted with NS_Free().
-    gfxFontEntry* LoadFont(gfxUserFontFamily *aFamily,
-                           const uint8_t* aFontData, uint32_t &aLength);
+    bool LoadFont(const uint8_t* aFontData, uint32_t &aLength);
 
     // store metadata and src details for current src into aFontEntry
     void StoreUserFontData(gfxFontEntry*      aFontEntry,
                            bool               aPrivate,
                            const nsAString&   aOriginalName,
                            FallibleTArray<uint8_t>* aMetadata,
                            uint32_t           aMetaOrigLen);
 
@@ -587,17 +536,18 @@ protected:
                              // so keep hiding fallback font
         LOADING_SLOWLY,      // timeout happened and we're not nearly done,
                              // so use the fallback font
         LOADING_FAILED       // failed to load any source: use fallback
     };
     LoadingState             mLoadingState;
     bool                     mUnsupportedFormat;
 
+    nsRefPtr<gfxFontEntry>   mPlatformFontEntry;
     nsTArray<gfxFontFaceSrc> mSrcList;
     uint32_t                 mSrcIndex; // index of loading src item
-    nsFontFaceLoader        *mLoader; // current loader for this entry, if any
-    gfxUserFontSet          *mFontSet; // font-set to which the userfont entry belongs
+    nsFontFaceLoader*        mLoader; // current loader for this entry, if any
+    gfxUserFontSet*          mFontSet; // font-set to which the userfont entry belongs
     nsCOMPtr<nsIPrincipal>   mPrincipal;
 };
 
 
 #endif /* GFX_USER_FONT_SET_H */
--- a/layout/style/nsFontFaceLoader.cpp
+++ b/layout/style/nsFontFaceLoader.cpp
@@ -50,33 +50,31 @@ GetFontDownloaderLog()
   return sLog;
 }
 #endif /* PR_LOGGING */
 
 #define LOG(args) PR_LOG(GetFontDownloaderLog(), PR_LOG_DEBUG, args)
 #define LOG_ENABLED() PR_LOG_TEST(GetFontDownloaderLog(), PR_LOG_DEBUG)
 
 
-nsFontFaceLoader::nsFontFaceLoader(gfxUserFontFamily* aFontFamily,
-                                   gfxUserFontEntry* aUserFontEntry,
+nsFontFaceLoader::nsFontFaceLoader(gfxUserFontEntry* aUserFontEntry,
                                    nsIURI* aFontURI,
                                    nsUserFontSet* aFontSet,
                                    nsIChannel* aChannel)
-  : mFontFamily(aFontFamily),
-    mFontEntry(aUserFontEntry),
+  : mUserFontEntry(aUserFontEntry),
     mFontURI(aFontURI),
     mFontSet(aFontSet),
     mChannel(aChannel)
 {
 }
 
 nsFontFaceLoader::~nsFontFaceLoader()
 {
-  if (mFontEntry) {
-    mFontEntry->mLoader = nullptr;
+  if (mUserFontEntry) {
+    mUserFontEntry->mLoader = nullptr;
   }
   if (mLoadTimer) {
     mLoadTimer->Cancel();
     mLoadTimer = nullptr;
   }
   if (mFontSet) {
     mFontSet->RemoveLoader(this);
   }
@@ -91,32 +89,32 @@ nsFontFaceLoader::StartedLoading(nsIStre
     mLoadTimer = do_CreateInstance("@mozilla.org/timer;1");
     if (mLoadTimer) {
       mLoadTimer->InitWithFuncCallback(LoadTimerCallback,
                                        static_cast<void*>(this),
                                        loadTimeout,
                                        nsITimer::TYPE_ONE_SHOT);
     }
   } else {
-    mFontEntry->mLoadingState = gfxUserFontEntry::LOADING_SLOWLY;
+    mUserFontEntry->mLoadingState = gfxUserFontEntry::LOADING_SLOWLY;
   }
   mStreamLoader = aStreamLoader;
 }
 
 void
 nsFontFaceLoader::LoadTimerCallback(nsITimer* aTimer, void* aClosure)
 {
   nsFontFaceLoader* loader = static_cast<nsFontFaceLoader*>(aClosure);
 
   if (!loader->mFontSet) {
     // We've been canceled
     return;
   }
 
-  gfxUserFontEntry* ufe = loader->mFontEntry.get();
+  gfxUserFontEntry* ufe = loader->mUserFontEntry.get();
   bool updateUserFontSet = true;
 
   // If the entry is loading, check whether it's >75% done; if so,
   // we allow another timeout period before showing a fallback font.
   if (ufe->mLoadingState == gfxUserFontEntry::LOADING_STARTED) {
     int64_t contentLength;
     uint32_t numBytesRead;
     if (NS_SUCCEEDED(loader->mChannel->GetContentLength(&contentLength)) &&
@@ -204,24 +202,24 @@ nsFontFaceLoader::OnStreamComplete(nsISt
       bool succeeded;
       nsresult rv = httpChannel->GetRequestSucceeded(&succeeded);
       if (NS_SUCCEEDED(rv) && !succeeded) {
         aStatus = NS_ERROR_NOT_AVAILABLE;
       }
     }
   }
 
-  // The userFontSet is responsible for freeing the downloaded data
+  // The userFontEntry is responsible for freeing the downloaded data
   // (aString) when finished with it; the pointer is no longer valid
   // after OnLoadComplete returns.
   // This is called even in the case of a failed download (HTTP 404, etc),
   // as there may still be data to be freed (e.g. an error page),
   // and we need the fontSet to initiate loading the next source.
-  bool fontUpdate = mFontSet->OnLoadComplete(mFontFamily, mFontEntry, aString,
-                                             aStringLen, aStatus);
+  bool fontUpdate = mUserFontEntry->OnLoadComplete(aString,
+                                                   aStringLen, aStatus);
 
   // when new font loaded, need to reflow
   if (fontUpdate) {
     // Update layout for the presence of the new font.  Since this is
     // asynchronous, reflows will coalesce.
     ctx->UserFontSetUpdated();
     LOG(("fontdownloader (%p) reflow\n", this));
   }
@@ -234,18 +232,18 @@ nsFontFaceLoader::OnStreamComplete(nsISt
   }
 
   return NS_SUCCESS_ADOPTED_DATA;
 }
 
 void
 nsFontFaceLoader::Cancel()
 {
-  mFontEntry->mLoadingState = gfxUserFontEntry::NOT_LOADING;
-  mFontEntry->mLoader = nullptr;
+  mUserFontEntry->mLoadingState = gfxUserFontEntry::NOT_LOADING;
+  mUserFontEntry->mLoader = nullptr;
   mFontSet = nullptr;
   if (mLoadTimer) {
     mLoadTimer->Cancel();
     mLoadTimer = nullptr;
   }
   mChannel->Cancel(NS_BINDING_ABORTED);
 }
 
@@ -314,18 +312,17 @@ nsUserFontSet::Destroy()
 
 void
 nsUserFontSet::RemoveLoader(nsFontFaceLoader* aLoader)
 {
   mLoaders.RemoveEntry(aLoader);
 }
 
 nsresult
-nsUserFontSet::StartLoad(gfxUserFontFamily* aFamily,
-                         gfxUserFontEntry* aUserFontEntry,
+nsUserFontSet::StartLoad(gfxUserFontEntry* aUserFontEntry,
                          const gfxFontFaceSrc* aFontFaceSrc)
 {
   nsresult rv;
 
   nsIPresShell* ps = mPresContext->PresShell();
   if (!ps)
     return NS_ERROR_FAILURE;
 
@@ -349,17 +346,17 @@ nsUserFontSet::StartLoad(gfxUserFontFami
                      loadGroup,
                      nullptr,
                      nsIRequest::LOAD_NORMAL,
                      channelPolicy);
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsRefPtr<nsFontFaceLoader> fontLoader =
-    new nsFontFaceLoader(aFamily, aUserFontEntry, aFontFaceSrc->mURI, this, channel);
+    new nsFontFaceLoader(aUserFontEntry, aFontFaceSrc->mURI, this, channel);
 
   if (!fontLoader)
     return NS_ERROR_OUT_OF_MEMORY;
 
 #ifdef PR_LOGGING
   if (LOG_ENABLED()) {
     nsAutoCString fontURI, referrerURI;
     aFontFaceSrc->mURI->GetSpec(fontURI);
@@ -469,21 +466,17 @@ nsUserFontSet::UpdateRules(const nsTArra
     modified = true;
     // Any in-progress loaders for obsolete rules should be cancelled,
     // as the resource being downloaded will no longer be required.
     // We need to explicitly remove any loaders here, otherwise the loaders
     // will keep their "orphaned" font entries alive until they complete,
     // even after the oldRules array is deleted.
     size_t count = oldRules.Length();
     for (size_t i = 0; i < count; ++i) {
-      gfxFontEntry* fe = oldRules[i].mFontEntry;
-      if (!fe->mIsUserFontContainer) {
-        continue;
-      }
-      gfxUserFontEntry* userFontEntry = static_cast<gfxUserFontEntry*>(fe);
+      gfxUserFontEntry* userFontEntry = oldRules[i].mUserFontEntry;
       nsFontFaceLoader* loader = userFontEntry->mLoader;
       if (loader) {
         loader->Cancel();
         RemoveLoader(loader);
       }
     }
   }
 
@@ -549,53 +542,53 @@ nsUserFontSet::InsertRule(nsCSSFontFaceR
       if (mLocalRulesUsed) {
         aRule->GetDesc(eCSSFontDesc_Src, val);
         unit = val.GetUnit();
         if (unit == eCSSUnit_Array && HasLocalSrc(val.GetArrayValue())) {
           break;
         }
       }
 
-      AddFontFace(fontfamily, ruleRec.mFontEntry);
+      AddFontFace(fontfamily, ruleRec.mUserFontEntry);
       mRules.AppendElement(ruleRec);
       aOldRules.RemoveElementAt(i);
       // note the set has been modified if an old rule was skipped to find
       // this one - something has been dropped, or ordering changed
       if (i > 0) {
         aFontSetModified = true;
       }
       return;
     }
   }
 
   // this is a new rule:
   FontFaceRuleRecord ruleRec;
-  ruleRec.mFontEntry =
+  ruleRec.mUserFontEntry =
     FindOrCreateFontFaceFromRule(fontfamily, aRule, aSheetType);
 
-  if (!ruleRec.mFontEntry) {
+  if (!ruleRec.mUserFontEntry) {
     return;
   }
 
   ruleRec.mContainer.mRule = aRule;
   ruleRec.mContainer.mSheetType = aSheetType;
 
   // Add the entry to the end of the list.  If an existing userfont entry was
   // returned by FindOrCreateFontFaceFromRule that was already stored on the
   // family, gfxUserFontFamily::AddFontEntry(), which AddFontFace calls,
   // will automatically remove the earlier occurrence of the same userfont entry.
-  AddFontFace(fontfamily, ruleRec.mFontEntry);
+  AddFontFace(fontfamily, ruleRec.mUserFontEntry);
 
   mRules.AppendElement(ruleRec);
 
   // this was a new rule and font entry, so note that the set was modified
   aFontSetModified = true;
 }
 
-already_AddRefed<gfxFontEntry>
+already_AddRefed<gfxUserFontEntry>
 nsUserFontSet::FindOrCreateFontFaceFromRule(const nsAString& aFamilyName,
                                             nsCSSFontFaceRule* aRule,
                                             uint8_t aSheetType)
 {
   nsCSSValue val;
   uint32_t unit;
 
   uint32_t weight = NS_STYLE_FONT_WEIGHT_NORMAL;
@@ -754,50 +747,44 @@ nsUserFontSet::FindOrCreateFontFaceFromR
 
   nsRefPtr<gfxUserFontEntry> entry =
     FindOrCreateFontFace(aFamilyName, srcArray, weight, stretch, italicStyle,
                          featureSettings, languageOverride,
                          nullptr /* aUnicodeRanges */);
   return entry.forget();
 }
 
-void
-nsUserFontSet::ReplaceFontEntry(gfxUserFontFamily* aFamily,
-                                gfxUserFontEntry* aUserFontEntry,
-                                gfxFontEntry* aFontEntry)
+nsCSSFontFaceRule*
+nsUserFontSet::FindRuleForEntry(gfxFontEntry* aFontEntry)
 {
-  // aUserFontEntry is being supplanted by the "real" font aFontEntry, so we need to
-  // update any rules that refer to it. Note that there may be multiple rules
-  // that refer to the same userfont entry - e.g. if a stylesheet was loaded multiple
-  // times, so that several identical @font-face rules are present.
+  NS_ASSERTION(!aFontEntry->mIsUserFontContainer, "only platform font entries");
   for (uint32_t i = 0; i < mRules.Length(); ++i) {
-    if (mRules[i].mFontEntry == aUserFontEntry) {
-      mRules[i].mFontEntry = aFontEntry;
+    if (mRules[i].mUserFontEntry->GetPlatformFontEntry() == aFontEntry) {
+      return mRules[i].mContainer.mRule;
     }
   }
-  aFamily->ReplaceFontEntry(aUserFontEntry, aFontEntry);
+  return nullptr;
 }
 
 nsCSSFontFaceRule*
-nsUserFontSet::FindRuleForEntry(gfxFontEntry* aFontEntry)
+nsUserFontSet::FindRuleForUserFontEntry(gfxUserFontEntry* aUserFontEntry)
 {
   for (uint32_t i = 0; i < mRules.Length(); ++i) {
-    if (mRules[i].mFontEntry == aFontEntry) {
+    if (mRules[i].mUserFontEntry == aUserFontEntry) {
       return mRules[i].mContainer.mRule;
     }
   }
   return nullptr;
 }
 
 nsresult
-nsUserFontSet::LogMessage(gfxUserFontFamily* aFamily,
-                          gfxUserFontEntry* aUserFontEntry,
-                          const char*        aMessage,
-                          uint32_t          aFlags,
-                          nsresult          aStatus)
+nsUserFontSet::LogMessage(gfxUserFontEntry* aUserFontEntry,
+                          const char* aMessage,
+                          uint32_t aFlags,
+                          nsresult aStatus)
 {
   nsCOMPtr<nsIConsoleService>
     console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
   if (!console) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   NS_ConvertUTF16toUTF8 familyName(aUserFontEntry->mFamilyName);
@@ -856,17 +843,17 @@ nsUserFontSet::LogMessage(gfxUserFontFam
 #ifdef PR_LOGGING
   if (PR_LOG_TEST(GetUserFontsLog(), PR_LOG_DEBUG)) {
     PR_LOG(GetUserFontsLog(), PR_LOG_DEBUG,
            ("userfonts (%p) %s", this, message.get()));
   }
 #endif
 
   // try to give the user an indication of where the rule came from
-  nsCSSFontFaceRule* rule = FindRuleForEntry(aUserFontEntry);
+  nsCSSFontFaceRule* rule = FindRuleForUserFontEntry(aUserFontEntry);
   nsString href;
   nsString text;
   nsresult rv;
   if (rule) {
     rv = rule->GetCssText(text);
     NS_ENSURE_SUCCESS(rv, rv);
     nsCOMPtr<nsIDOMCSSStyleSheet> sheet;
     rv = rule->GetParentStyleSheet(getter_AddRefs(sheet));
--- a/layout/style/nsFontFaceLoader.h
+++ b/layout/style/nsFontFaceLoader.h
@@ -29,59 +29,54 @@ class nsUserFontSet : public gfxUserFont
 public:
   explicit nsUserFontSet(nsPresContext* aContext);
 
   // Called when this font set is no longer associated with a presentation.
   void Destroy();
 
   // starts loading process, creating and initializing a nsFontFaceLoader obj
   // returns whether load process successfully started or not
-  nsresult StartLoad(gfxUserFontFamily* aFamily,
-                     gfxUserFontEntry* aFontToLoad,
+  nsresult StartLoad(gfxUserFontEntry* aFontToLoad,
                      const gfxFontFaceSrc* aFontFaceSrc) MOZ_OVERRIDE;
 
   // Called by nsFontFaceLoader when the loader has completed normally.
   // It's removed from the mLoaders set.
   void RemoveLoader(nsFontFaceLoader* aLoader);
 
   bool UpdateRules(const nsTArray<nsFontFaceRuleContainer>& aRules);
 
   nsPresContext* GetPresContext() { return mPresContext; }
 
-  virtual void ReplaceFontEntry(gfxUserFontFamily* aFamily,
-                                gfxUserFontEntry* aUserFontEntry,
-                                gfxFontEntry* aFontEntry) MOZ_OVERRIDE;
-
+  // search for @font-face rule that matches a platform font entry
   nsCSSFontFaceRule* FindRuleForEntry(gfxFontEntry* aFontEntry);
 
 protected:
   // Protected destructor, to discourage deletion outside of Release()
   // (since we inherit from refcounted class gfxUserFontSet):
   ~nsUserFontSet();
 
   // The font-set keeps track of the collection of rules, and their
   // corresponding font entries (whether proxies or real entries),
   // so that we can update the set without having to throw away
   // all the existing fonts.
   struct FontFaceRuleRecord {
-    nsRefPtr<gfxFontEntry>       mFontEntry;
+    nsRefPtr<gfxUserFontEntry>   mUserFontEntry;
     nsFontFaceRuleContainer      mContainer;
   };
 
   void InsertRule(nsCSSFontFaceRule* aRule, uint8_t aSheetType,
                   nsTArray<FontFaceRuleRecord>& oldRules,
                   bool& aFontSetModified);
 
-  already_AddRefed<gfxFontEntry> FindOrCreateFontFaceFromRule(
+  already_AddRefed<gfxUserFontEntry> FindOrCreateFontFaceFromRule(
                                                    const nsAString& aFamilyName,
                                                    nsCSSFontFaceRule* aRule,
                                                    uint8_t aSheetType);
 
-  virtual nsresult LogMessage(gfxUserFontFamily* aFamily,
-                              gfxUserFontEntry* aUserFontEntry,
+  virtual nsresult LogMessage(gfxUserFontEntry* aUserFontEntry,
                               const char* aMessage,
                               uint32_t aFlags = nsIScriptError::errorFlag,
                               nsresult aStatus = NS_OK) MOZ_OVERRIDE;
 
   virtual nsresult CheckFontLoad(const gfxFontFaceSrc* aFontFaceSrc,
                                  nsIPrincipal** aPrincipal,
                                  bool* aBypassCache) MOZ_OVERRIDE;
 
@@ -89,31 +84,33 @@ protected:
                                     const gfxFontFaceSrc* aFontFaceSrc,
                                     uint8_t*& aBuffer,
                                     uint32_t& aBufferLength) MOZ_OVERRIDE;
 
   virtual bool GetPrivateBrowsing() MOZ_OVERRIDE;
 
   virtual void DoRebuildUserFontSet() MOZ_OVERRIDE;
 
+  // search for @font-face rule that matches a userfont font entry
+  nsCSSFontFaceRule* FindRuleForUserFontEntry(gfxUserFontEntry* aUserFontEntry);
+
   nsPresContext* mPresContext;  // weak reference
 
   // Set of all loaders pointing to us. These are not strong pointers,
   // but that's OK because nsFontFaceLoader always calls RemoveLoader on
   // us before it dies (unless we die first).
   nsTHashtable< nsPtrHashKey<nsFontFaceLoader> > mLoaders;
 
   nsTArray<FontFaceRuleRecord>   mRules;
 };
 
 class nsFontFaceLoader : public nsIStreamLoaderObserver
 {
 public:
-  nsFontFaceLoader(gfxUserFontFamily* aFontFamily,
-                   gfxUserFontEntry* aFontToLoad, nsIURI* aFontURI,
+  nsFontFaceLoader(gfxUserFontEntry* aFontToLoad, nsIURI* aFontURI,
                    nsUserFontSet* aFontSet, nsIChannel* aChannel);
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSISTREAMLOADEROBSERVER 
 
   // initiate the load
   nsresult Init();
   // cancel the load and remove its reference to mFontSet
@@ -128,18 +125,17 @@ public:
   static nsresult CheckLoadAllowed(nsIPrincipal* aSourcePrincipal,
                                    nsIURI* aTargetURI,
                                    nsISupports* aContext);
 
 protected:
   virtual ~nsFontFaceLoader();
 
 private:
-  nsRefPtr<gfxUserFontFamily> mFontFamily;
-  nsRefPtr<gfxUserFontEntry>  mFontEntry;
+  nsRefPtr<gfxUserFontEntry>  mUserFontEntry;
   nsCOMPtr<nsIURI>        mFontURI;
   nsRefPtr<nsUserFontSet> mFontSet;
   nsCOMPtr<nsIChannel>    mChannel;
   nsCOMPtr<nsITimer>      mLoadTimer;
 
   nsIStreamLoader*        mStreamLoader;
 };