Skip to content
  • simon.fraser@apple.com's avatar
    2010-12-22 Simon Fraser <simon.fraser@apple.com> · a892004c
    simon.fraser@apple.com authored
            Reviewed by Darin Adler.
    
            Cache snapshots of plug-ins before painting, to avoid script running during painting
            https://bugs.webkit.org/show_bug.cgi?id=51493
    
            When FrameView is asked to do a flattening paint (e.g. when Safari snapshots,
            or when printing), plug-ins which otherwise use the CA rendering model
            are sent a paint event. Some plug-ins may run script while handling this event,
            or out of process plug-ins may process queued requests at this time. Running
            script while inside layout or painting can have bad consequences, because it
            can result in arbitrary changes to the render tree.
    
            This patch avoids sending plug-ins paint events inside of painting. Instead,
            we ask the plug-ins to cache a snapshot before we paint, and then the software
            paint simply draws that snapshot.
    
            Requires manual test, because the bug happens when Safari does
            a page snapshot. It's not possible to tell the Test Netscape Plug-in
            to paint without laying out, making an automated test impossible.
    
            * manual-tests/plugins/plugin-paint-causes-layout.html: Added.
    
            * page/FrameView.h:
            * page/FrameView.cpp:
            (WebCore::FrameView::paintContents): Notify all enclosed widgets
            that a flattening paint is going to happen.
            (WebCore::FrameView::notifyWidgetsInAllFrames): Utility method
            that tells the RenderView in all subframes to notify their widgets.
    
            * platform/Widget.h:
            (WebCore::Widget::notifyWidget): Generic method that can be used
            to send messages to widgets. Current messages are just 'before flattening paint'
            and 'after flattening paint'. Message has no payload.
    
            * rendering/RenderView.h:
            * rendering/RenderView.cpp:
            (WebCore::RenderView::getRetainedWidgets):
            (WebCore::RenderView::releaseWidgets): Factor code out of updateWidgetPositions(),
            since we use it in two places now.
    
            (WebCore::RenderView::updateWidgetPositions): Use getRetainedWidgets() etc.
            (WebCore::RenderView::notifyWidgets): Retain all the widgets, then send
            them all the message.
    
            * rendering/RenderWidget.h:
            * rendering/RenderWidget.cpp:
            (WebCore::RenderWidget::notifyWidget): Pass the message to the widget.
    
            * Plugins/Hosted/WebHostedNetscapePluginView.mm:
            (-[WebHostedNetscapePluginView drawRect:]): If we have a cached snapshot,
            draw it. Also only send the snapshot message to the plugin proxy if we
            know we're snapshotting, since even if creating the snapshot image failed,
            we still don't want to call to the plug-in.
    
            * Plugins/WebBaseNetscapePluginView.h: Add a retained NSImage member for the snapshot.
            * Plugins/WebBaseNetscapePluginView.mm:
            (-[WebBaseNetscapePluginView cacheSnapshot]): Create an image and draw the snapshot into it.
            (-[WebBaseNetscapePluginView clearCachedSnapshot]): Clear the snapshot.
    
            * Plugins/WebNetscapePluginView.mm:
            (-[WebNetscapePluginView drawRect:]): If we have a cached snapshot, use it.
            * WebCoreSupport/WebFrameLoaderClient.mm:
            (NetscapePluginWidget::notifyWidget): Implement notifyWidget() and use it
            to cache and clear the snapshots.
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@74524 268f45cc-cd09-0410-ab3c-d52691b4dbfc
    a892004c