Title: [145934] trunk/Source/WebCore
Revision
145934
Author
[email protected]
Date
2013-03-15 13:33:50 -0700 (Fri, 15 Mar 2013)

Log Message

RenderSnapshottedPlugIn can't be a RenderBlock (what if it's display: inline?)
https://bugs.webkit.org/show_bug.cgi?id=112432
<rdar://problem/13187211>

Reviewed by Simon Fraser and Dean Jackson.

Re-use code from PLUGIN_PROXY_FOR_VIDEO to allow RenderEmbeddedObject to lay out its children,
and make RenderSnapshottedPlugIn a RenderEmbeddedObject subclass once again. This will ensure that
RenderSnapshottedPlugIn lays itself out in the page the same as the RenderEmbeddedObject it replaces did,
preventing snapshotted plug-ins from breaking the layout when they are display: inline.

* html/HTMLPlugInElement.cpp:
(WebCore::HTMLPlugInElement::defaultEventHandler):
RenderSnapshottedPlugIn is a RenderEmbeddedObject subclass again, so we need to check
for it when we have a RenderEmbeddedObject, instead of when we don't.

* page/FrameView.cpp:
(WebCore::FrameView::updateWidget):
Ditto.

* rendering/RenderEmbeddedObject.cpp:
(WebCore::RenderEmbeddedObject::layout):
(WebCore::RenderEmbeddedObject::canHaveChildren):
Allow RenderEmbeddedObject to have and lay out children if it is a RenderSnapshottedPlugIn.
Also, preserve the code that allows children if it is a media element and PLUGIN_PROXY_FOR_VIDEO is enabled.
Don't call addWidgetToUpdate for instances which will never have a widget, like RenderSnapshottedPlugIn.

* rendering/RenderEmbeddedObject.h:
(RenderEmbeddedObject):
We need canHaveChildren() and children() and m_children now.
Add canHaveWidget(), which returns true. Subclasses can override if need be.

* rendering/RenderSnapshottedPlugIn.h: Add canHaveWidget(), which is false for RenderSnapshottedPlugIn.
* rendering/RenderSnapshottedPlugIn.cpp:
(WebCore::RenderSnapshottedPlugIn::RenderSnapshottedPlugIn):
(WebCore::RenderSnapshottedPlugIn::layout):
(WebCore::RenderSnapshottedPlugIn::getCursor):
Make RenderSnapshottedPlugIn a RenderEmbeddedObject.

(WebCore::RenderSnapshottedPlugIn::paint):
Paint our children.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (145933 => 145934)


--- trunk/Source/WebCore/ChangeLog	2013-03-15 20:24:39 UTC (rev 145933)
+++ trunk/Source/WebCore/ChangeLog	2013-03-15 20:33:50 UTC (rev 145934)
@@ -1,3 +1,47 @@
+2013-03-15  Tim Horton  <[email protected]>
+
+        RenderSnapshottedPlugIn can't be a RenderBlock (what if it's display: inline?)
+        https://bugs.webkit.org/show_bug.cgi?id=112432
+        <rdar://problem/13187211>
+
+        Reviewed by Simon Fraser and Dean Jackson.
+
+        Re-use code from PLUGIN_PROXY_FOR_VIDEO to allow RenderEmbeddedObject to lay out its children,
+        and make RenderSnapshottedPlugIn a RenderEmbeddedObject subclass once again. This will ensure that
+        RenderSnapshottedPlugIn lays itself out in the page the same as the RenderEmbeddedObject it replaces did,
+        preventing snapshotted plug-ins from breaking the layout when they are display: inline.
+
+        * html/HTMLPlugInElement.cpp:
+        (WebCore::HTMLPlugInElement::defaultEventHandler):
+        RenderSnapshottedPlugIn is a RenderEmbeddedObject subclass again, so we need to check
+        for it when we have a RenderEmbeddedObject, instead of when we don't.
+
+        * page/FrameView.cpp:
+        (WebCore::FrameView::updateWidget):
+        Ditto.
+
+        * rendering/RenderEmbeddedObject.cpp:
+        (WebCore::RenderEmbeddedObject::layout):
+        (WebCore::RenderEmbeddedObject::canHaveChildren):
+        Allow RenderEmbeddedObject to have and lay out children if it is a RenderSnapshottedPlugIn.
+        Also, preserve the code that allows children if it is a media element and PLUGIN_PROXY_FOR_VIDEO is enabled.
+        Don't call addWidgetToUpdate for instances which will never have a widget, like RenderSnapshottedPlugIn.
+
+        * rendering/RenderEmbeddedObject.h:
+        (RenderEmbeddedObject):
+        We need canHaveChildren() and children() and m_children now.
+        Add canHaveWidget(), which returns true. Subclasses can override if need be.
+
+        * rendering/RenderSnapshottedPlugIn.h: Add canHaveWidget(), which is false for RenderSnapshottedPlugIn.
+        * rendering/RenderSnapshottedPlugIn.cpp:
+        (WebCore::RenderSnapshottedPlugIn::RenderSnapshottedPlugIn):
+        (WebCore::RenderSnapshottedPlugIn::layout):
+        (WebCore::RenderSnapshottedPlugIn::getCursor):
+        Make RenderSnapshottedPlugIn a RenderEmbeddedObject.
+
+        (WebCore::RenderSnapshottedPlugIn::paint):
+        Paint our children.
+
 2013-03-15  Hajime Morrita  <[email protected]>
 
         [Custom Elements] Any HTMLElement subclass should become a superclass of custom element

Modified: trunk/Source/WebCore/html/HTMLPlugInElement.cpp (145933 => 145934)


--- trunk/Source/WebCore/html/HTMLPlugInElement.cpp	2013-03-15 20:24:39 UTC (rev 145933)
+++ trunk/Source/WebCore/html/HTMLPlugInElement.cpp	2013-03-15 20:33:50 UTC (rev 145934)
@@ -202,12 +202,15 @@
             toRenderEmbeddedObject(r)->handleUnavailablePluginIndicatorEvent(event);
             return;
         }
-        if (displayState() < HTMLPlugInElement::Playing)
+
+        if (r->isSnapshottedPlugIn() && displayState() < PlayingWithPendingMouseClick) {
+            toRenderSnapshottedPlugIn(r)->handleEvent(event);
+            HTMLFrameOwnerElement::defaultEventHandler(event);
             return;
-    } else if (r && r->isSnapshottedPlugIn() && displayState() < PlayingWithPendingMouseClick) {
-        toRenderSnapshottedPlugIn(r)->handleEvent(event);
-        HTMLFrameOwnerElement::defaultEventHandler(event);
-        return;
+        }
+
+        if (displayState() < Playing)
+            return;
     }
 
     if (!r || !r->isWidget())

Modified: trunk/Source/WebCore/page/FrameView.cpp (145933 => 145934)


--- trunk/Source/WebCore/page/FrameView.cpp	2013-03-15 20:24:39 UTC (rev 145933)
+++ trunk/Source/WebCore/page/FrameView.cpp	2013-03-15 20:33:50 UTC (rev 145934)
@@ -1388,7 +1388,7 @@
     // Tell the DOM element that it needs a widget update.
     Node* node = object->node();
     if (node->hasTagName(objectTag) || node->hasTagName(embedTag)) {
-        HTMLPlugInImageElement* pluginElement = static_cast<HTMLPlugInImageElement*>(node);
+        HTMLPlugInImageElement* pluginElement = toHTMLPlugInImageElement(node);
         pluginElement->setNeedsWidgetUpdate(true);
     }
 
@@ -2527,10 +2527,18 @@
         if (embeddedObject->showsUnavailablePluginIndicator())
             return;
 
+        if (object->isSnapshottedPlugIn()) {
+            if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag)) {
+                HTMLPlugInImageElement* pluginElement = toHTMLPlugInImageElement(ownerElement);
+                pluginElement->updateSnapshotInfo();
+            }
+            return;
+        }
+
         // FIXME: This could turn into a real virtual dispatch if we defined
         // updateWidget(PluginCreationOption) on HTMLElement.
         if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag) || ownerElement->hasTagName(appletTag)) {
-            HTMLPlugInImageElement* pluginElement = static_cast<HTMLPlugInImageElement*>(ownerElement);
+            HTMLPlugInImageElement* pluginElement = toHTMLPlugInImageElement(ownerElement);
             if (pluginElement->needsWidgetUpdate())
                 pluginElement->updateWidget(CreateAnyWidgetType);
         }
@@ -2545,11 +2553,6 @@
         // Caution: it's possible the object was destroyed again, since loading a
         // plugin may run any arbitrary _javascript_.
         embeddedObject->updateWidgetPosition();
-    } else if (object->isSnapshottedPlugIn()) {
-        if (ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag)) {
-            HTMLPlugInImageElement* pluginElement = static_cast<HTMLPlugInImageElement*>(ownerElement);
-            pluginElement->updateSnapshotInfo();
-        }
     }
 }
 

Modified: trunk/Source/WebCore/rendering/RenderEmbeddedObject.cpp (145933 => 145934)


--- trunk/Source/WebCore/rendering/RenderEmbeddedObject.cpp	2013-03-15 20:24:39 UTC (rev 145933)
+++ trunk/Source/WebCore/rendering/RenderEmbeddedObject.cpp	2013-03-15 20:33:50 UTC (rev 145934)
@@ -38,6 +38,7 @@
 #include "HTMLNames.h"
 #include "HTMLObjectElement.h"
 #include "HTMLParamElement.h"
+#include "HTMLPlugInElement.h"
 #include "HitTestResult.h"
 #include "LocalizedStrings.h"
 #include "MIMETypeRegistry.h"
@@ -278,9 +279,7 @@
     StackStats::LayoutCheckPoint layoutCheckPoint;
     ASSERT(needsLayout());
 
-#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
     LayoutSize oldSize = contentBoxRect().size();
-#endif
 
     updateLogicalWidth();
     updateLogicalHeight();
@@ -292,19 +291,27 @@
 
     updateLayerTransform();
 
-    if (!widget() && frameView())
+    if (!widget() && frameView() && canHaveWidget())
         frameView()->addWidgetToUpdate(this);
 
     setNeedsLayout(false);
 
-#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+    if (!canHaveChildren())
+        return;
+
     // This code copied from RenderMedia::layout().
-    RenderBox* controlsRenderer = toRenderBox(m_children.firstChild());
-    if (!controlsRenderer)
+    RenderObject* child = m_children.firstChild();
+
+    if (!child)
         return;
+
+    RenderBox* childBox = toRenderBox(child);
+
+    if (!childBox)
+        return;
     
     LayoutSize newSize = contentBoxRect().size();
-    if (newSize == oldSize && !controlsRenderer->needsLayout())
+    if (newSize == oldSize && !childBox->needsLayout())
         return;
     
     // When calling layout() on a child node, a parent must either push a LayoutStateMaintainter, or
@@ -312,15 +319,14 @@
     // and this method will be called many times per second during playback, use a LayoutStateMaintainer:
     LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
     
-    controlsRenderer->setLocation(LayoutPoint(borderLeft(), borderTop()) + LayoutSize(paddingLeft(), paddingTop()));
-    controlsRenderer->style()->setHeight(Length(newSize.height(), Fixed));
-    controlsRenderer->style()->setWidth(Length(newSize.width(), Fixed));
-    controlsRenderer->setNeedsLayout(true, MarkOnlyThis);
-    controlsRenderer->layout();
+    childBox->setLocation(LayoutPoint(borderLeft(), borderTop()) + LayoutSize(paddingLeft(), paddingTop()));
+    childBox->style()->setHeight(Length(newSize.height(), Fixed));
+    childBox->style()->setWidth(Length(newSize.width(), Fixed));
+    childBox->setNeedsLayout(true, MarkOnlyThis);
+    childBox->layout();
     setChildNeedsLayout(false);
     
     statePusher.pop();
-#endif
 }
 
 void RenderEmbeddedObject::viewCleared()
@@ -459,4 +465,20 @@
     return RenderPart::getCursor(point, cursor);
 }
 
+bool RenderEmbeddedObject::canHaveChildren() const
+{
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+    if (!node())
+        return false;
+
+    if (toElement(node())->isMediaElement())
+        return true;
+#endif
+
+    if (isSnapshottedPlugIn())
+        return true;
+
+    return false;
 }
+
+}

Modified: trunk/Source/WebCore/rendering/RenderEmbeddedObject.h (145933 => 145934)


--- trunk/Source/WebCore/rendering/RenderEmbeddedObject.h	2013-03-15 20:24:39 UTC (rev 145933)
+++ trunk/Source/WebCore/rendering/RenderEmbeddedObject.h	2013-03-15 20:33:50 UTC (rev 145934)
@@ -63,10 +63,8 @@
 
     virtual CursorDirective getCursor(const LayoutPoint&, Cursor&) const;
 
-#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
     const RenderObjectChildList* children() const { return &m_children; }
     RenderObjectChildList* children() { return &m_children; }
-#endif
 
 protected:
     virtual void layout() OVERRIDE;
@@ -94,11 +92,11 @@
     bool isInUnavailablePluginIndicator(const LayoutPoint&) const;
     bool getReplacementTextGeometry(const LayoutPoint& accumulatedOffset, FloatRect& contentRect, Path&, FloatRect& replacementTextRect, Font&, TextRun&, float& textWidth) const;
 
-#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
-    virtual bool canHaveChildren() const { return node() && toElement(node())->isMediaElement(); }
+    virtual bool canHaveChildren() const;
     virtual RenderObjectChildList* virtualChildren() { return children(); }
     virtual const RenderObjectChildList* virtualChildren() const { return children(); }
-#endif
+    
+    virtual bool canHaveWidget() const { return true; }
 
     bool m_hasFallbackContent; // FIXME: This belongs on HTMLObjectElement.
 
@@ -107,9 +105,7 @@
     String m_unavailablePluginReplacementText;
     bool m_unavailablePluginIndicatorIsPressed;
     bool m_mouseDownWasInUnavailablePluginIndicator;
-#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
     RenderObjectChildList m_children;
-#endif
 };
 
 inline RenderEmbeddedObject* toRenderEmbeddedObject(RenderObject* object)

Modified: trunk/Source/WebCore/rendering/RenderSnapshottedPlugIn.cpp (145933 => 145934)


--- trunk/Source/WebCore/rendering/RenderSnapshottedPlugIn.cpp	2013-03-15 20:24:39 UTC (rev 145933)
+++ trunk/Source/WebCore/rendering/RenderSnapshottedPlugIn.cpp	2013-03-15 20:33:50 UTC (rev 145934)
@@ -44,7 +44,7 @@
 namespace WebCore {
 
 RenderSnapshottedPlugIn::RenderSnapshottedPlugIn(HTMLPlugInImageElement* element)
-    : RenderBlock(element)
+    : RenderEmbeddedObject(element)
     , m_snapshotResource(RenderImageResource::create())
 {
     m_snapshotResource->initialize(this);
@@ -66,7 +66,7 @@
     StackStats::LayoutCheckPoint layoutCheckPoint;
     LayoutSize oldSize = contentBoxRect().size();
 
-    RenderBlock::layout();
+    RenderEmbeddedObject::layout();
 
     LayoutSize newSize = contentBoxRect().size();
     if (newSize == oldSize)
@@ -92,7 +92,20 @@
         paintSnapshot(paintInfo, paintOffset);
     }
 
-    RenderBlock::paint(paintInfo, paintOffset);
+    PaintPhase newPhase = (paintInfo.phase == PaintPhaseChildOutlines) ? PaintPhaseOutline : paintInfo.phase;
+    newPhase = (newPhase == PaintPhaseChildBlockBackgrounds) ? PaintPhaseChildBlockBackground : newPhase;
+
+    PaintInfo paintInfoForChild(paintInfo);
+    paintInfoForChild.phase = newPhase;
+    paintInfoForChild.updatePaintingRootForChildren(this);
+
+    for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
+        LayoutPoint childPoint = flipForWritingModeForChild(child, paintOffset);
+        if (!child->hasSelfPaintingLayer() && !child->isFloating())
+            child->paint(paintInfoForChild, childPoint);
+    }
+
+    RenderEmbeddedObject::paint(paintInfo, paintOffset);
 }
 
 void RenderSnapshottedPlugIn::paintSnapshot(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
@@ -131,7 +144,7 @@
         overrideCursor = handCursor();
         return SetCursor;
     }
-    return RenderBlock::getCursor(point, overrideCursor);
+    return RenderEmbeddedObject::getCursor(point, overrideCursor);
 }
 
 void RenderSnapshottedPlugIn::handleEvent(Event* event)

Modified: trunk/Source/WebCore/rendering/RenderSnapshottedPlugIn.h (145933 => 145934)


--- trunk/Source/WebCore/rendering/RenderSnapshottedPlugIn.h	2013-03-15 20:24:39 UTC (rev 145933)
+++ trunk/Source/WebCore/rendering/RenderSnapshottedPlugIn.h	2013-03-15 20:33:50 UTC (rev 145934)
@@ -26,7 +26,7 @@
 #ifndef RenderSnapshottedPlugIn_h
 #define RenderSnapshottedPlugIn_h
 
-#include "RenderBlock.h"
+#include "RenderEmbeddedObject.h"
 #include "RenderImageResource.h"
 #include "Timer.h"
 
@@ -34,7 +34,7 @@
 
 class HTMLPlugInImageElement;
 
-class RenderSnapshottedPlugIn : public RenderBlock {
+class RenderSnapshottedPlugIn : public RenderEmbeddedObject {
 public:
     explicit RenderSnapshottedPlugIn(HTMLPlugInImageElement*);
     virtual ~RenderSnapshottedPlugIn();
@@ -50,6 +50,8 @@
     virtual CursorDirective getCursor(const LayoutPoint&, Cursor&) const OVERRIDE;
     virtual bool isSnapshottedPlugIn() const OVERRIDE { return true; }
     virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
+    
+    virtual bool canHaveWidget() const OVERRIDE { return false; }
 
     void paintSnapshot(PaintInfo&, const LayoutPoint&);
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to