Changeset 92269 in webkit


Ignore:
Timestamp:
Aug 3, 2011 3:48:22 AM (13 years ago)
Author:
jeremy@chromium.org
Message:

[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.

Location:
trunk/Source
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r92266 r92269  
     12011-08-03  Jeremy Moskovich  <jeremy@chromium.org>
     2
     3        [Chromium] Fix OOP font loading to work on 10.6.6 and above.
     4        https://bugs.webkit.org/show_bug.cgi?id=65543
     5
     6        In 10.6.6 the function used to get the unique ID for an NSFont in the
     7        renderer was changed so it fails in the sandbox (it now tries to access
     8        the on-disk font file). In order to work around this, we get the font
     9        ID from the browser process.
     10
     11        To speed things up, we introduce 2 levels of caching in WebKit. A font
     12        name cache where we can perform a quick lookup without the need for the
     13        font id and a font id cache which we can only lookup in after getting
     14        the unique ID from the browser process.
     15
     16        Reviewed by Kenneth Russell.
     17
     18        No new tests since this is not readily testable.
     19
     20        * platform/chromium/PlatformBridge.h:
     21        * platform/graphics/chromium/CrossProcessFontLoading.h:
     22        * platform/graphics/chromium/CrossProcessFontLoading.mm:
     23        (WebCore::MemoryActivatedFont::create):
     24        (WebCore::MemoryActivatedFont::MemoryActivatedFont):
     25        (WebCore::MemoryActivatedFont::~MemoryActivatedFont):
     26
    1272011-08-03  Hayato Ito  <hayato@chromium.org>
    228
  • trunk/Source/WebCore/platform/chromium/PlatformBridge.h

    r91206 r92269  
    152152#endif
    153153#if OS(DARWIN)
    154     static bool loadFont(NSFont* srcFont, ATSFontContainerRef* out);
     154    static bool loadFont(NSFont* srcFont, ATSFontContainerRef*, uint32_t* fontID);
    155155#elif OS(UNIX)
    156156    static void getRenderStyleForStrike(const char* family, int sizeAndStyle, FontRenderStyle* result);
  • trunk/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.h

    r66574 r92269  
    3434#import <wtf/RefCounted.h>
    3535#import <wtf/RetainPtr.h>
     36#import <wtf/text/WTFString.h>
    3637
    3738typedef struct CGFont* CGFontRef;
     
    7475public:
    7576    // Use to create a new object, see docs on constructor below.
    76     static PassRefPtr<MemoryActivatedFont> create(ATSFontContainerRef srcFontContainerRef, ATSFontContainerRef container);
     77    static PassRefPtr<MemoryActivatedFont> create(uint32_t fontID, NSFont*, ATSFontContainerRef);
    7778    ~MemoryActivatedFont();
    7879   
     
    8889    // container - a font container corresponding to an identical font that
    8990    // we loaded cross-process.
    90     MemoryActivatedFont(ATSFontContainerRef srcFontContainerRef, ATSFontContainerRef container);
     91    MemoryActivatedFont(uint32_t fontID, NSFont*, ATSFontContainerRef);
    9192
    9293    ATSFontContainerRef m_fontContainer;
    9394    WTF::RetainPtr<CGFontRef> m_cgFont;
    9495    ATSFontRef m_atsFontRef;
    95     ATSFontContainerRef m_srcFontContainerRef;
     96    uint32_t m_fontID;
     97    WTF::String m_inSandboxHashKey;
    9698};
    9799
  • trunk/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm

    r82170 r92269  
    3939namespace {
    4040
    41 typedef HashMap<ATSFontContainerRef, MemoryActivatedFont*> FontContainerRefMemoryFontHash;
     41typedef HashMap<uint32, MemoryActivatedFont*> FontContainerRefMemoryFontHash;
     42typedef HashMap<WTF::String, MemoryActivatedFont*> FontNameMemoryFontHash;
    4243
    4344// On 10.5, font loading is not blocked by the sandbox and thus there is no
     
    5556}
    5657
    57 FontContainerRefMemoryFontHash& fontCacheBySrcFontContainerRef()
    58 {
    59     DEFINE_STATIC_LOCAL(FontContainerRefMemoryFontHash, srcFontRefCache, ());
    60     return srcFontRefCache;
     58// Caching:
     59//
     60// Requesting a font from the browser process is expensive and so is
     61// "activating" said font.  Caching of loaded fonts is complicated by the fact
     62// that it's impossible to get a unique identifier for the on-disk font file
     63// from inside the sandboxed renderer process.
     64// This means that when loading a font we need to round-trip through the browser
     65// process in order to get the unique font file identifer which we might already
     66// have activated and cached.
     67//
     68// In order to save as much work as we can, we maintain 2 levels of caching
     69// for the font data:
     70// 1. A dumb cache keyed by the font name/style (information we can determine
     71// from inside the sandbox).
     72// 2. A smarter cache keyed by the real "unique font id".
     73//
     74// In order to perform a lookup in #2 we need to consult with the browser to get
     75// us the lookup key.  While this doesn't save us the font load, it does save
     76// us font activation.
     77//
     78// It's important to remember that existing FontPlatformData objects are already
     79// cached, so a cache miss in the code in this file isn't necessarily so bad.
     80
     81FontContainerRefMemoryFontHash& fontCacheByFontID()
     82{
     83    DEFINE_STATIC_LOCAL(FontContainerRefMemoryFontHash, srcFontIDCache, ());
     84    return srcFontIDCache;
     85}
     86
     87
     88FontNameMemoryFontHash& fontCacheByFontName()
     89{
     90    DEFINE_STATIC_LOCAL(FontNameMemoryFontHash, srcFontNameCache, ());
     91    return srcFontNameCache;
     92}
     93
     94// Given a font specified by |srcFont|, use the information we can query in
     95// the sandbox to construct a key which we hope will be as unique as possible
     96// to the containing font file.
     97WTF::String hashKeyFromNSFont(NSFont* srcFont)
     98{
     99    NSFontDescriptor* desc = [srcFont fontDescriptor];
     100    NSFontSymbolicTraits traits = [desc symbolicTraits];
     101    return WTF::String::format("%s %x", [[srcFont fontName] UTF8String], traits);
    61102}
    62103
     
    86127PassRefPtr<MemoryActivatedFont> loadFontFromBrowserProcess(NSFont* nsFont)
    87128{
     129    // First try to lookup in our cache with the limited information we have.
     130    WTF::String hashKey = hashKeyFromNSFont(nsFont);
     131    RefPtr<MemoryActivatedFont> font(fontCacheByFontName().get(hashKey));
     132    if (font)
     133        return font;
     134
    88135    ATSFontContainerRef container;
     136    uint32_t fontID;
    89137    // Send cross-process request to load font.
    90     if (!PlatformBridge::loadFont(nsFont, &container))
     138    if (!PlatformBridge::loadFont(nsFont, &container, &fontID))
    91139        return 0;
    92    
    93     ATSFontContainerRef srcFontContainerRef = fontContainerRefFromNSFont(nsFont);
    94     if (!srcFontContainerRef) {
     140
     141    // Now that we have the fontID from the browser process, we can consult
     142    // the ID cache.
     143    font = fontCacheByFontID().get(fontID);
     144    if (font) {
     145        // We can safely discard the new container since we already have the
     146        // font in our cache.
     147        // FIXME: PlatformBridge::loadFont() should consult the id cache
     148        // before activating the font.  Then we can save this activate/deactive
     149        // dance altogether.
    95150        ATSFontDeactivate(container, 0, kATSOptionFlagsDefault);
    96         return 0;
    97     }
    98    
    99     PassRefPtr<MemoryActivatedFont> font = adoptRef(fontCacheBySrcFontContainerRef().get(srcFontContainerRef));
    100     if (font.get())
    101151        return font;
    102 
    103     return MemoryActivatedFont::create(srcFontContainerRef, container);
     152    }
     153
     154    return MemoryActivatedFont::create(fontID, nsFont, container);
    104155}
    105156
    106157} // namespace
    107158
    108 PassRefPtr<MemoryActivatedFont> MemoryActivatedFont::create(ATSFontContainerRef srcFontContainerRef, ATSFontContainerRef container)
    109 {
    110   MemoryActivatedFont* font = new MemoryActivatedFont(srcFontContainerRef, container);
     159PassRefPtr<MemoryActivatedFont> MemoryActivatedFont::create(uint32_t fontID, NSFont* nsFont, ATSFontContainerRef container)
     160{
     161  MemoryActivatedFont* font = new MemoryActivatedFont(fontID, nsFont, container);
    111162  if (!font->cgFont())  // Object construction failed.
    112163  {
     
    117168}
    118169
    119 MemoryActivatedFont::MemoryActivatedFont(ATSFontContainerRef srcFontContainerRef, ATSFontContainerRef container)
     170MemoryActivatedFont::MemoryActivatedFont(uint32_t fontID, NSFont* nsFont, ATSFontContainerRef container)
    120171    : m_fontContainer(container)
    121172    , m_atsFontRef(kATSFontRefUnspecified)
    122     , m_srcFontContainerRef(srcFontContainerRef)
     173    , m_fontID(fontID)
     174    , m_inSandboxHashKey(hashKeyFromNSFont(nsFont))
    123175{
    124176    if (!container)
     
    140192    m_cgFont.adoptCF(CGFontCreateWithPlatformFont(&m_atsFontRef));
    141193   
    142     if (!m_cgFont.get())
    143         return;
    144    
    145     // Add ourselves to cache.
    146     fontCacheBySrcFontContainerRef().add(m_srcFontContainerRef, this);
     194    if (!m_cgFont)
     195        return;
     196   
     197    // Add ourselves to caches.
     198    fontCacheByFontID().add(fontID, this);
     199    fontCacheByFontName().add(m_inSandboxHashKey, this);
    147200}
    148201
     
    151204MemoryActivatedFont::~MemoryActivatedFont()
    152205{
    153     if (m_cgFont.get()) {
     206    if (m_cgFont) {
    154207        // First remove ourselves from the caches.
    155         ASSERT(fontCacheBySrcFontContainerRef().contains(m_srcFontContainerRef));
     208        ASSERT(fontCacheByFontID().contains(m_fontID));
     209        ASSERT(fontCacheByFontName().contains(m_inSandboxHashKey));
    156210       
    157         fontCacheBySrcFontContainerRef().remove(m_srcFontContainerRef);
     211        fontCacheByFontID().remove(m_fontID);
     212        fontCacheByFontName().remove(m_inSandboxHashKey);
    158213       
    159214        // Make sure the CGFont is destroyed before its font container.
     
    193248        // Font loading was blocked by the Sandbox.
    194249        m_inMemoryFont = loadFontFromBrowserProcess(outNSFont);
    195         if (m_inMemoryFont.get()) {
     250        if (m_inMemoryFont) {
    196251            cgFont = m_inMemoryFont->cgFont();
    197252           
  • trunk/Source/WebKit/chromium/ChangeLog

    r92265 r92269  
     12011-08-03  Jeremy Moskovich  <jeremy@chromium.org>
     2
     3        [Chromium] Fix OOP font loading to work on 10.6.6 and above.
     4        https://bugs.webkit.org/show_bug.cgi?id=65543
     5
     6        In 10.6.6 the function used to get the unique ID for an NSFont in the
     7        renderer was changed so it fails in the sandbox (it now tries to access
     8        the on-disk font file). In order to work around this, we get the font
     9        ID from the browser process.
     10
     11        To speed things up, we introduce 2 levels of caching in WebKit. A font
     12        name cache where we can perform a quick lookup without the need for the
     13        font id and a font id cache which we can only lookup in after getting
     14        the unique ID from the browser process.
     15
     16        Reviewed by Kenneth Russell.
     17
     18        No new tests since this is not readily testable.
     19
     20        * public/mac/WebSandboxSupport.h: Plumb font ID parameter through.
     21        * src/PlatformBridge.cpp:
     22        (WebCore::PlatformBridge::loadFont): ditto.
     23
    1242011-08-03  Pavel Feldman  <pfeldman@chromium.org>
    225
  • trunk/Source/WebKit/chromium/public/mac/WebSandboxSupport.h

    r61361 r92269  
    4747    // Given an input font - |srcFont| [which can't be loaded due to sandbox
    4848    // restrictions].  Return a font container belonging to an equivalent
    49     // font file that can be used to access the font.
     49    // font file that can be used to access the font and a unique identifier
     50    // corresponding to the on-disk font file.
    5051    //
    5152    // Note that a font container may contain multiple fonts, the caller is
     
    5657    //
    5758    // Returns: true on success, false on error.
    58     virtual bool loadFont(NSFont* srcFont, ATSFontContainerRef* out) = 0;
     59    virtual bool loadFont(NSFont* srcFont, ATSFontContainerRef*, uint32_t* fontID) = 0;
    5960};
    6061
  • trunk/Source/WebKit/chromium/src/PlatformBridge.cpp

    r91206 r92269  
    445445
    446446#if OS(DARWIN)
    447 bool PlatformBridge::loadFont(NSFont* srcFont, ATSFontContainerRef* out)
     447bool PlatformBridge::loadFont(NSFont* srcFont, ATSFontContainerRef* container, uint32_t* fontID)
    448448{
    449449    WebSandboxSupport* ss = webKitClient()->sandboxSupport();
    450450    if (ss)
    451         return ss->loadFont(srcFont, out);
     451        return ss->loadFont(srcFont, container, fontID);
    452452
    453453    // This function should only be called in response to an error loading a
     
    455455    // This by definition shouldn't happen if there is no sandbox support.
    456456    ASSERT_NOT_REACHED();
    457     *out = 0;
     457    *container = 0;
     458    *fontID = 0;
    458459    return false;
    459460}
Note: See TracChangeset for help on using the changeset viewer.