<rdar://problem/9835028> Font loading during layout can cause layout code to be re...
authormitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 25 Jul 2011 20:00:49 +0000 (20:00 +0000)
committermitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 25 Jul 2011 20:00:49 +0000 (20:00 +0000)
https://bugs.webkit.org/show_bug.cgi?id=65123

Reviewed by Anders Carlsson.

Since CSSFontFaceSource::getFontData() can get called during layout, avoid calling out to loader
code from under it, and instead defer that work using a zero-delay timer.

* css/CSSFontFaceSource.cpp:
(WebCore::CSSFontFaceSource::CSSFontFaceSource):
(WebCore::CSSFontFaceSource::~CSSFontFaceSource):
(WebCore::CSSFontFaceSource::getFontData): Rather than starting the font load here, schedule
a zero-delay timer to do it.
(WebCore::CSSFontFaceSource::startLoadingTimerFired): Added. Starts loading the font if needed.
* css/CSSFontFaceSource.h:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@91699 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/css/CSSFontFaceSource.cpp
Source/WebCore/css/CSSFontFaceSource.h

index 80b7fad..fbf2929 100644 (file)
@@ -1,3 +1,21 @@
+2011-07-25  Dan Bernstein  <mitz@apple.com>
+
+        <rdar://problem/9835028> Font loading during layout can cause layout code to be re-entered via resource load delegate
+        https://bugs.webkit.org/show_bug.cgi?id=65123
+
+        Reviewed by Anders Carlsson.
+
+        Since CSSFontFaceSource::getFontData() can get called during layout, avoid calling out to loader
+        code from under it, and instead defer that work using a zero-delay timer.
+
+        * css/CSSFontFaceSource.cpp:
+        (WebCore::CSSFontFaceSource::CSSFontFaceSource):
+        (WebCore::CSSFontFaceSource::~CSSFontFaceSource):
+        (WebCore::CSSFontFaceSource::getFontData): Rather than starting the font load here, schedule
+        a zero-delay timer to do it.
+        (WebCore::CSSFontFaceSource::startLoadingTimerFired): Added. Starts loading the font if needed.
+        * css/CSSFontFaceSource.h:
+
 2011-07-25  Andrew Wason  <rectalogic@rectalogic.com>
 
         [Qt] Adopt GraphicsContext3DOpenGL.cpp and ANGLE (part 2)
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
 {
index e87fbfc..9831bcd 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "CachedResourceClient.h"
 #include "CachedResourceHandle.h"
+#include "Timer.h"
 #include <wtf/HashMap.h>
 #include <wtf/text/AtomicString.h>
 
@@ -70,11 +71,16 @@ public:
 #endif
 
 private:
+    void startLoadingTimerFired(Timer<CSSFontFaceSource>*);
+
     AtomicString m_string; // URI for remote, built-in font name for local.
     CachedResourceHandle<CachedFont> m_font; // For remote fonts, a pointer to our cached resource.
     CSSFontFace* m_face; // Our owning font face.
     HashMap<unsigned, SimpleFontData*> m_fontDataTable; // The hash key is composed of size synthetic styles.
 
+    Timer<CSSFontFaceSource> m_startLoadingTimer;
+    RefPtr<CSSFontSelector> m_fontSelector;
+
 #if ENABLE(SVG_FONTS)
     RefPtr<SVGFontFaceElement> m_svgFontFaceElement;
     RefPtr<SVGFontElement> m_externalSVGFontElement;