OSDN Git Service

Do not merge - pulled from master
authorPatrick Scott <phanna@android.com>
Fri, 14 Aug 2009 12:21:09 +0000 (08:21 -0400)
committerPatrick Scott <phanna@android.com>
Mon, 17 Aug 2009 19:05:06 +0000 (15:05 -0400)
Be more restrictive when expanding iframes.

If an iframe has no scrollbars and a fixed dimension, it serves no purpose to
try and expand the contents. Some sites like to use hidden iframes for
asynchronous loading and showing or expanding those iframes causes layout
problems.

Change the expansion logic slightly to only expand iframes and not contract
them. Also update calcWidth and calcHeight to check for scrollbars or a
non-fixed dimension.

BUG=2039520,2004093

WebCore/rendering/RenderPartObject.cpp
WebKit/android/jni/WebViewCore.cpp

index 2964e39..0e7655b 100644 (file)
@@ -332,46 +332,58 @@ void RenderPartObject::layout()
     RenderPart::calcWidth();
     RenderPart::calcHeight();
     // Some IFrames have a width and/or height of 1 when they are meant to be
-    // hidden. If that is the case, don't try to expand.
-    int w = width();
-    int h = height();
-    if (widget() && widget()->isFrameView() &&
-            w > 1 && h > 1) {
-        FrameView* view = static_cast<FrameView*>(widget());
-        RenderView* root = NULL;
-        if (view->frame() && view->frame()->document() &&
-            view->frame()->document()->renderer() && view->frame()->document()->renderer()->isRenderView())
-            root = static_cast<RenderView*>(view->frame()->document()->renderer());
-        if (root) {
-            // Update the dimensions to get the correct minimum preferred width
-            updateWidgetPosition();
-
-            int extraWidth = paddingLeft() + paddingRight() + borderLeft() + borderRight();
-            int extraHeight = paddingTop() + paddingBottom() + borderTop() + borderBottom();
-            // Use the preferred width if it is larger.
-            setWidth(max(w, root->minPrefWidth()) + extraWidth);
-
-            // Resize the view to recalc the height.
-            int height = h - extraHeight;
-            int width = w - extraWidth;
-            if (width > view->width())
-                height = 0;
-            if (width != view->width() || height != view->height()) {
-                view->resize(width, height);
-                root->setNeedsLayout(true, false);
+    // hidden. If that is the case, do not try to expand.
+    if (node()->hasTagName(iframeTag) && widget() && widget()->isFrameView()
+            && width() > 1 && height() > 1) {
+        HTMLIFrameElement* element = static_cast<HTMLIFrameElement*>(node());
+        bool scrolling = element->scrollingMode() != ScrollbarAlwaysOff;
+        bool widthIsFixed = style()->width().isFixed();
+        bool heightIsFixed = style()->height().isFixed();
+        // If an iframe has a fixed dimension and suppresses scrollbars, it
+        // will disrupt layout if we force it to expand. Plus on a desktop,
+        // the extra content is not accessible.
+        if (scrolling || !widthIsFixed || !heightIsFixed) {
+            FrameView* view = static_cast<FrameView*>(widget());
+            RenderView* root = view ? view->frame()->contentRenderer() : NULL;
+            RenderPart* owner = view->frame()->ownerRenderer();
+            if (root && style()->visibility() != HIDDEN
+                    && (!owner || owner->style()->visibility() != HIDDEN)) {
+                // Update the dimensions to get the correct minimum preferred
+                // width
+                updateWidgetPosition();
+
+                int extraWidth = paddingLeft() + paddingRight() + borderLeft() + borderRight();
+                int extraHeight = paddingTop() + paddingBottom() + borderTop() + borderBottom();
+                // Use the preferred width if it is larger and only if
+                // scrollbars are visible or the width style is not fixed.
+                if (scrolling || !widthIsFixed)
+                    setWidth(max(width(), root->minPrefWidth()) + extraWidth);
+
+                // Resize the view to recalc the height.
+                int h = height() - extraHeight;
+                int w = width() - extraWidth;
+                if (w > view->width())
+                    h = 0;
+                if (w != view->width() || h != view->height()) {
+                    view->resize(w, h);
+                    root->setNeedsLayout(true, false);
+                }
+                // Layout the view.
+                if (view->needsLayout())
+                    view->layout();
+                int contentHeight = view->contentsHeight();
+                int contentWidth = view->contentsWidth();
+                // Only change the width or height if scrollbars are visible or
+                // if the style is not a fixed value. Use the maximum value so
+                // that iframes never shrink.
+                if (scrolling || !heightIsFixed)
+                    setHeight(max(height(), contentHeight + extraHeight));
+                if (scrolling || !widthIsFixed)
+                    setWidth(max(width(), contentWidth + extraWidth));
+
+                // Update one last time
+                updateWidgetPosition();
             }
-            // Layout the view.
-            if (view->needsLayout())
-                view->layout();
-            int contentHeight = view->contentsHeight();
-            int contentWidth = view->contentsWidth();
-            // Do not shrink iframes with a specified height.
-            if (contentHeight > (h - extraHeight)  || style()->height().isAuto())
-                setHeight(contentHeight + extraHeight);
-            setWidth(contentWidth + extraWidth);
-
-            // Update one last time
-            updateWidgetPosition();
         }
     }
 #else
@@ -392,12 +404,16 @@ void RenderPartObject::layout()
 #ifdef FLATTEN_IFRAME
 void RenderPartObject::calcWidth() {
     RenderPart::calcWidth();
-    if (!widget() || !widget()->isFrameView())
+    if (!node()->hasTagName(iframeTag) || !widget() || !widget()->isFrameView())
         return;
     FrameView* view = static_cast<FrameView*>(widget());
     RenderView* root = static_cast<RenderView*>(view->frame()->contentRenderer());
     if (!root)
         return;
+    // Do not expand if the scrollbars are suppressed and the width is fixed.
+    bool scrolling = static_cast<HTMLIFrameElement*>(node())->scrollingMode() != ScrollbarAlwaysOff;
+    if (!scrolling && style()->width().isFixed())
+        return;
     // Update the dimensions to get the correct minimum preferred
     // width
     updateWidgetPosition();
@@ -413,7 +429,7 @@ void RenderPartObject::calcWidth() {
     while (view->needsLayout())
         view->layout();
 
-    setWidth(view->contentsWidth() + extraWidth);
+    setWidth(max(width(), view->contentsWidth() + extraWidth));
 
     // Update one last time to ensure the dimensions.
     updateWidgetPosition();
@@ -421,12 +437,16 @@ void RenderPartObject::calcWidth() {
 
 void RenderPartObject::calcHeight() {
     RenderPart::calcHeight();
-    if (!widget() || !widget()->isFrameView())
+    if (!node()->hasTagName(iframeTag) || !widget() || !widget()->isFrameView())
         return;
     FrameView* view = static_cast<FrameView*>(widget());
     RenderView* root = static_cast<RenderView*>(view->frame()->contentRenderer());
     if (!root)
         return;
+    // Do not expand if the scrollbars are suppressed and the height is fixed.
+    bool scrolling = static_cast<HTMLIFrameElement*>(node())->scrollingMode() != ScrollbarAlwaysOff;
+    if (!scrolling && style()->height().isFixed())
+        return;
     // Update the widget
     updateWidgetPosition();
 
@@ -434,11 +454,8 @@ void RenderPartObject::calcHeight() {
     while (view->needsLayout())
         view->layout();
 
-    // Do not shrink the height if the size is specified
-    int h = view->contentsHeight();
     int extraHeight = paddingTop() + paddingBottom() + borderTop() + borderBottom();
-    if (h > height() - extraHeight || style()->height().isAuto())
-        setHeight(h + extraHeight);
+    setHeight(max(width(), view->contentsHeight() + extraHeight));
 
     // Update one last time to ensure the dimensions.
     updateWidgetPosition();
index c16d0a3..aa96b18 100644 (file)
@@ -440,7 +440,7 @@ void WebViewCore::recordPictureSet(PictureSet* content)
         // If the frame doesn't have an owner then it is the top frame and the
         // view size is the frame size.
         WebCore::RenderPart* owner = frame->ownerRenderer();
-        if (owner) {
+        if (owner && owner->style()->visibility() == VISIBLE) {
             int x = owner->x();
             int y = owner->y();