<rdar://problem/9835028> Font loading during layout can cause layout code to be re...
[WebKit.git] / Source / WebCore / css / CSSFontFaceSource.cpp
index 4a851ac..3a6e85e 100644 (file)
@@ -50,6 +50,7 @@ CSSFontFaceSource::CSSFontFaceSource(const String& str, CachedFont* font)
     : m_string(str)
     , m_font(font)
     , m_face(0)
+    , m_startLoadingTimer(this, &CSSFontFaceSource::startLoadingTimerFired)
 #if ENABLE(SVG_FONTS)
     , m_hasExternalSVGFont(false)
 #endif
@@ -60,6 +61,7 @@ CSSFontFaceSource::CSSFontFaceSource(const String& str, CachedFont* font)
 
 CSSFontFaceSource::~CSSFontFaceSource()
 {
+    m_startLoadingTimer.stop();
     if (m_font)
         m_font->removeClient(this);
     pruneTable();
@@ -172,9 +174,12 @@ SimpleFontData* CSSFontFaceSource::getFontData(const FontDescription& fontDescri
 #endif
         }
     } else {
-        // Kick off the load now.
-        if (CachedResourceLoader* cachedResourceLoader = fontSelector->cachedResourceLoader())
-            m_font->beginLoadIfNeeded(cachedResourceLoader);
+        // Kick off the load now. Do it on a zero-delay timer rather than synchronously, because we may be in
+        // the middle of layout, and the loader may invoke aribtrary delegate or event handler code.
+        m_fontSelector = fontSelector;
+        if (!m_startLoadingTimer.isActive())
+            m_startLoadingTimer.startOneShot(0);
+
         // FIXME: m_string is a URL so it makes no sense to pass it as a family name.
         SimpleFontData* tempData = fontCache()->getCachedFontData(fontDescription, m_string);
         if (!tempData)
@@ -189,6 +194,17 @@ SimpleFontData* CSSFontFaceSource::getFontData(const FontDescription& fontDescri
     return fontDataRawPtr;
 }
 
+void CSSFontFaceSource::startLoadingTimerFired(Timer<WebCore::CSSFontFaceSource>*)
+{
+    ASSERT(m_font);
+    ASSERT(m_fontSelector);
+
+    if (CachedResourceLoader* cachedResourceLoader = m_fontSelector->cachedResourceLoader())
+        m_font->beginLoadIfNeeded(cachedResourceLoader);
+
+    m_fontSelector = nullptr;
+}
+
 #if ENABLE(SVG_FONTS)
 SVGFontFaceElement* CSSFontFaceSource::svgFontFaceElement() const
 {