Title: [92840] branches/chromium/835/Source
Revision
92840
Author
[email protected]
Date
2011-08-11 05:44:15 -0700 (Thu, 11 Aug 2011)

Log Message

Merge 92269 - [Chromium] Fix OOP font loading to work on 10.6.6 and above.
https://bugs.webkit.org/show_bug.cgi?id=65543

In 10.6.6 the function used to get the unique ID for an NSFont in the
renderer was changed so it fails in the sandbox (it now tries to access
the on-disk font file). In order to work around this, we get the font
ID from the browser process.

To speed things up, we introduce 2 levels of caching in WebKit. A font
name cache where we can perform a quick lookup without the need for the
font id and a font id cache which we can only lookup in after getting
the unique ID from the browser process.

Reviewed by Kenneth Russell.

No new tests since this is not readily testable.

Source/WebCore:

* platform/chromium/PlatformBridge.h:
* platform/graphics/chromium/CrossProcessFontLoading.h:
* platform/graphics/chromium/CrossProcessFontLoading.mm:
(WebCore::MemoryActivatedFont::create):
(WebCore::MemoryActivatedFont::MemoryActivatedFont):
(WebCore::MemoryActivatedFont::~MemoryActivatedFont):

Source/WebKit/chromium:

* public/mac/WebSandboxSupport.h: Plumb font ID parameter through.
* src/PlatformBridge.cpp:
(WebCore::PlatformBridge::loadFont): ditto.


[email protected]
Review URL: http://codereview.chromium.org/7618010

Modified Paths

Diff

Modified: branches/chromium/835/Source/WebCore/platform/chromium/PlatformBridge.h (92839 => 92840)


--- branches/chromium/835/Source/WebCore/platform/chromium/PlatformBridge.h	2011-08-11 12:40:57 UTC (rev 92839)
+++ branches/chromium/835/Source/WebCore/platform/chromium/PlatformBridge.h	2011-08-11 12:44:15 UTC (rev 92840)
@@ -151,7 +151,7 @@
     static bool ensureFontLoaded(HFONT);
 #endif
 #if OS(DARWIN)
-    static bool loadFont(NSFont* srcFont, ATSFontContainerRef* out);
+    static bool loadFont(NSFont* srcFont, ATSFontContainerRef*, uint32_t* fontID);
 #elif OS(UNIX)
     static void getRenderStyleForStrike(const char* family, int sizeAndStyle, FontRenderStyle* result);
     static String getFontFamilyForCharacters(const UChar*, size_t numCharacters, const char* preferredLocale);

Modified: branches/chromium/835/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.h (92839 => 92840)


--- branches/chromium/835/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.h	2011-08-11 12:40:57 UTC (rev 92839)
+++ branches/chromium/835/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.h	2011-08-11 12:44:15 UTC (rev 92840)
@@ -33,6 +33,7 @@
 
 #import <wtf/RefCounted.h>
 #import <wtf/RetainPtr.h>
+#import <wtf/text/WTFString.h>
 
 typedef struct CGFont* CGFontRef;
 typedef UInt32 ATSFontContainerRef;
@@ -73,7 +74,7 @@
 class MemoryActivatedFont : public RefCounted<MemoryActivatedFont> {
 public:
     // Use to create a new object, see docs on constructor below.
-    static PassRefPtr<MemoryActivatedFont> create(ATSFontContainerRef srcFontContainerRef, ATSFontContainerRef container);
+    static PassRefPtr<MemoryActivatedFont> create(uint32_t fontID, NSFont*, ATSFontContainerRef);
     ~MemoryActivatedFont();
     
     // Get cached CGFontRef corresponding to the in-memory font.
@@ -87,12 +88,13 @@
     // load in-process.
     // container - a font container corresponding to an identical font that
     // we loaded cross-process.
-    MemoryActivatedFont(ATSFontContainerRef srcFontContainerRef, ATSFontContainerRef container);
+    MemoryActivatedFont(uint32_t fontID, NSFont*, ATSFontContainerRef);
 
     ATSFontContainerRef m_fontContainer;
     WTF::RetainPtr<CGFontRef> m_cgFont;
     ATSFontRef m_atsFontRef;
-    ATSFontContainerRef m_srcFontContainerRef;
+    uint32_t m_fontID;
+    WTF::String m_inSandboxHashKey;
 };
 
 } // namespace WebCore

Modified: branches/chromium/835/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm (92839 => 92840)


--- branches/chromium/835/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm	2011-08-11 12:40:57 UTC (rev 92839)
+++ branches/chromium/835/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm	2011-08-11 12:44:15 UTC (rev 92840)
@@ -38,7 +38,8 @@
 
 namespace {
 
-typedef HashMap<ATSFontContainerRef, MemoryActivatedFont*> FontContainerRefMemoryFontHash;
+typedef HashMap<uint32, MemoryActivatedFont*> FontContainerRefMemoryFontHash;
+typedef HashMap<WTF::String, MemoryActivatedFont*> FontNameMemoryFontHash;
 
 // On 10.5, font loading is not blocked by the sandbox and thus there is no
 // need for the cross-process font loading mechanim.
@@ -54,12 +55,52 @@
     return systemVersion >= 0x1060;
 }
 
-FontContainerRefMemoryFontHash& fontCacheBySrcFontContainerRef()
+// Caching:
+//
+// Requesting a font from the browser process is expensive and so is
+// "activating" said font.  Caching of loaded fonts is complicated by the fact
+// that it's impossible to get a unique identifier for the on-disk font file
+// from inside the sandboxed renderer process.
+// This means that when loading a font we need to round-trip through the browser
+// process in order to get the unique font file identifer which we might already
+// have activated and cached.
+//
+// In order to save as much work as we can, we maintain 2 levels of caching
+// for the font data:
+// 1. A dumb cache keyed by the font name/style (information we can determine
+// from inside the sandbox).
+// 2. A smarter cache keyed by the real "unique font id".
+//
+// In order to perform a lookup in #2 we need to consult with the browser to get
+// us the lookup key.  While this doesn't save us the font load, it does save
+// us font activation.
+//
+// It's important to remember that existing FontPlatformData objects are already
+// cached, so a cache miss in the code in this file isn't necessarily so bad.
+
+FontContainerRefMemoryFontHash& fontCacheByFontID()
 {
-    DEFINE_STATIC_LOCAL(FontContainerRefMemoryFontHash, srcFontRefCache, ());
-    return srcFontRefCache;
+    DEFINE_STATIC_LOCAL(FontContainerRefMemoryFontHash, srcFontIDCache, ());
+    return srcFontIDCache;
 }
 
+
+FontNameMemoryFontHash& fontCacheByFontName()
+{
+    DEFINE_STATIC_LOCAL(FontNameMemoryFontHash, srcFontNameCache, ());
+    return srcFontNameCache;
+}
+
+// Given a font specified by |srcFont|, use the information we can query in
+// the sandbox to construct a key which we hope will be as unique as possible
+// to the containing font file.
+WTF::String hashKeyFromNSFont(NSFont* srcFont)
+{
+    NSFontDescriptor* desc = [srcFont fontDescriptor];
+    NSFontSymbolicTraits traits = [desc symbolicTraits];
+    return WTF::String::format("%s %x", [[srcFont fontName] UTF8String], traits);
+}
+
 ATSFontContainerRef fontContainerRefFromNSFont(NSFont* srcFont)
 {
     ATSFontRef fontRef = CTFontGetPlatformFont(toCTFontRef(srcFont), 0);
@@ -85,29 +126,39 @@
 // On failure this function returns a PassRefPtr pointing to 0.
 PassRefPtr<MemoryActivatedFont> loadFontFromBrowserProcess(NSFont* nsFont)
 {
+    // First try to lookup in our cache with the limited information we have.
+    WTF::String hashKey = hashKeyFromNSFont(nsFont);
+    RefPtr<MemoryActivatedFont> font(fontCacheByFontName().get(hashKey));
+    if (font)
+        return font;
+
     ATSFontContainerRef container;
+    uint32_t fontID;
     // Send cross-process request to load font.
-    if (!PlatformBridge::loadFont(nsFont, &container))
+    if (!PlatformBridge::loadFont(nsFont, &container, &fontID))
         return 0;
-    
-    ATSFontContainerRef srcFontContainerRef = fontContainerRefFromNSFont(nsFont);
-    if (!srcFontContainerRef) {
+
+    // Now that we have the fontID from the browser process, we can consult
+    // the ID cache.
+    font = fontCacheByFontID().get(fontID);
+    if (font) {
+        // We can safely discard the new container since we already have the
+        // font in our cache.
+        // FIXME: PlatformBridge::loadFont() should consult the id cache
+        // before activating the font.  Then we can save this activate/deactive
+        // dance altogether.
         ATSFontDeactivate(container, 0, kATSOptionFlagsDefault);
-        return 0;
+        return font;
     }
-    
-    PassRefPtr<MemoryActivatedFont> font = adoptRef(fontCacheBySrcFontContainerRef().get(srcFontContainerRef));
-    if (font.get())
-        return font;
 
-    return MemoryActivatedFont::create(srcFontContainerRef, container);
+    return MemoryActivatedFont::create(fontID, nsFont, container);
 }
 
 } // namespace
 
-PassRefPtr<MemoryActivatedFont> MemoryActivatedFont::create(ATSFontContainerRef srcFontContainerRef, ATSFontContainerRef container)
+PassRefPtr<MemoryActivatedFont> MemoryActivatedFont::create(uint32_t fontID, NSFont* nsFont, ATSFontContainerRef container)
 {
-  MemoryActivatedFont* font = new MemoryActivatedFont(srcFontContainerRef, container);
+  MemoryActivatedFont* font = new MemoryActivatedFont(fontID, nsFont, container);
   if (!font->cgFont())  // Object construction failed.
   {
       delete font;
@@ -116,10 +167,11 @@
   return adoptRef(font);
 }
 
-MemoryActivatedFont::MemoryActivatedFont(ATSFontContainerRef srcFontContainerRef, ATSFontContainerRef container)
+MemoryActivatedFont::MemoryActivatedFont(uint32_t fontID, NSFont* nsFont, ATSFontContainerRef container)
     : m_fontContainer(container)
     , m_atsFontRef(kATSFontRefUnspecified)
-    , m_srcFontContainerRef(srcFontContainerRef)
+    , m_fontID(fontID)
+    , m_inSandboxHashKey(hashKeyFromNSFont(nsFont))
 {
     if (!container)
         return;
@@ -139,22 +191,25 @@
     // Cache CGFont representation of the font.
     m_cgFont.adoptCF(CGFontCreateWithPlatformFont(&m_atsFontRef));
     
-    if (!m_cgFont.get())
+    if (!m_cgFont)
         return;
     
-    // Add ourselves to cache.
-    fontCacheBySrcFontContainerRef().add(m_srcFontContainerRef, this);
+    // Add ourselves to caches.
+    fontCacheByFontID().add(fontID, this);
+    fontCacheByFontName().add(m_inSandboxHashKey, this);
 }
 
 // Destructor - Unload font container from memory and remove ourselves
 // from cache.
 MemoryActivatedFont::~MemoryActivatedFont()
 {
-    if (m_cgFont.get()) {
+    if (m_cgFont) {
         // First remove ourselves from the caches.
-        ASSERT(fontCacheBySrcFontContainerRef().contains(m_srcFontContainerRef));
+        ASSERT(fontCacheByFontID().contains(m_fontID));
+        ASSERT(fontCacheByFontName().contains(m_inSandboxHashKey));
         
-        fontCacheBySrcFontContainerRef().remove(m_srcFontContainerRef);
+        fontCacheByFontID().remove(m_fontID);
+        fontCacheByFontName().remove(m_inSandboxHashKey);
         
         // Make sure the CGFont is destroyed before its font container.
         m_cgFont.releaseRef();
@@ -192,7 +247,7 @@
         
         // Font loading was blocked by the Sandbox.
         m_inMemoryFont = loadFontFromBrowserProcess(outNSFont);
-        if (m_inMemoryFont.get()) {
+        if (m_inMemoryFont) {
             cgFont = m_inMemoryFont->cgFont();
             
             // Need to add an extra retain so output semantics of this function

Modified: branches/chromium/835/Source/WebKit/chromium/public/mac/WebSandboxSupport.h (92839 => 92840)


--- branches/chromium/835/Source/WebKit/chromium/public/mac/WebSandboxSupport.h	2011-08-11 12:40:57 UTC (rev 92839)
+++ branches/chromium/835/Source/WebKit/chromium/public/mac/WebSandboxSupport.h	2011-08-11 12:44:15 UTC (rev 92840)
@@ -46,7 +46,8 @@
 public:
     // Given an input font - |srcFont| [which can't be loaded due to sandbox
     // restrictions].  Return a font container belonging to an equivalent
-    // font file that can be used to access the font.
+    // font file that can be used to access the font and a unique identifier
+    // corresponding to the on-disk font file.
     //
     // Note that a font container may contain multiple fonts, the caller is
     // responsible for retreiving the appropriate font from the container.
@@ -55,7 +56,7 @@
     // parameter and must call ATSFontDeactivate() to unload it when done.
     //
     // Returns: true on success, false on error.
-    virtual bool loadFont(NSFont* srcFont, ATSFontContainerRef* out) = 0;
+    virtual bool loadFont(NSFont* srcFont, ATSFontContainerRef*, uint32_t* fontID) = 0;
 };
 
 } // namespace WebKit

Modified: branches/chromium/835/Source/WebKit/chromium/src/PlatformBridge.cpp (92839 => 92840)


--- branches/chromium/835/Source/WebKit/chromium/src/PlatformBridge.cpp	2011-08-11 12:40:57 UTC (rev 92839)
+++ branches/chromium/835/Source/WebKit/chromium/src/PlatformBridge.cpp	2011-08-11 12:44:15 UTC (rev 92840)
@@ -444,17 +444,18 @@
 #endif
 
 #if OS(DARWIN)
-bool PlatformBridge::loadFont(NSFont* srcFont, ATSFontContainerRef* out)
+bool PlatformBridge::loadFont(NSFont* srcFont, ATSFontContainerRef* container, uint32_t* fontID)
 {
     WebSandboxSupport* ss = webKitClient()->sandboxSupport();
     if (ss)
-        return ss->loadFont(srcFont, out);
+        return ss->loadFont(srcFont, container, fontID);
 
     // This function should only be called in response to an error loading a
     // font due to being blocked by the sandbox.
     // This by definition shouldn't happen if there is no sandbox support.
     ASSERT_NOT_REACHED();
-    *out = 0;
+    *container = 0;
+    *fontID = 0;
     return false;
 }
 #elif OS(UNIX)
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to