1 /* 2 * Copyright (C) 2010 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "core/rendering/RenderIFrame.h" 28 29 #include "HTMLNames.h" 30 #include "core/html/HTMLIFrameElement.h" 31 #include "core/frame/Frame.h" 32 #include "core/frame/FrameView.h" 33 #include "core/rendering/LayoutRectRecorder.h" 34 #include "core/rendering/RenderView.h" 35 36 namespace WebCore { 37 38 using namespace HTMLNames; 39 40 RenderIFrame::RenderIFrame(Element* element) 41 : RenderPart(element) 42 { 43 } 44 45 bool RenderIFrame::shouldComputeSizeAsReplaced() const 46 { 47 // When we're seamless, we use normal block/box sizing code except when inline. 48 return !isSeamless(); 49 } 50 51 bool RenderIFrame::isInlineBlockOrInlineTable() const 52 { 53 return isSeamless() && isInline(); 54 } 55 56 LayoutUnit RenderIFrame::minPreferredLogicalWidth() const 57 { 58 if (!isSeamless()) 59 return RenderPart::minPreferredLogicalWidth(); 60 61 RenderView* childRoot = contentRootRenderer(); 62 if (!childRoot) 63 return 0; 64 65 return childRoot->minPreferredLogicalWidth() + borderAndPaddingLogicalWidth(); 66 } 67 68 LayoutUnit RenderIFrame::maxPreferredLogicalWidth() const 69 { 70 if (!isSeamless()) 71 return RenderPart::maxPreferredLogicalWidth(); 72 73 RenderView* childRoot = contentRootRenderer(); 74 if (!childRoot) 75 return 0; 76 77 return childRoot->maxPreferredLogicalWidth() + borderAndPaddingLogicalWidth(); 78 } 79 80 bool RenderIFrame::isSeamless() const 81 { 82 return node() && node()->hasTagName(iframeTag) && toHTMLIFrameElement(node())->shouldDisplaySeamlessly(); 83 } 84 85 bool RenderIFrame::requiresLayer() const 86 { 87 return RenderPart::requiresLayer() || style()->resize() != RESIZE_NONE; 88 } 89 90 RenderView* RenderIFrame::contentRootRenderer() const 91 { 92 // FIXME: Is this always a valid cast? What about plugins? 93 ASSERT(!widget() || widget()->isFrameView()); 94 FrameView* childFrameView = toFrameView(widget()); 95 return childFrameView ? childFrameView->frame().contentRenderer() : 0; 96 } 97 98 void RenderIFrame::layoutSeamlessly() 99 { 100 updateLogicalWidth(); 101 // FIXME: Containers set their height to 0 before laying out their kids (as we're doing here) 102 // however, this causes FrameView::layout() to add vertical scrollbars, incorrectly inflating 103 // the resulting contentHeight(). We'll need to make FrameView::layout() smarter. 104 setLogicalHeight(0); 105 updateWidgetPosition(); // Tell the Widget about our new width/height (it will also layout the child document). 106 107 // Laying out our kids is normally responsible for adjusting our height, so we set it here. 108 // Replaced elements normally do not respect padding, but seamless elements should: we'll add 109 // both padding and border to the child's logical height here. 110 FrameView* childFrameView = toFrameView(widget()); 111 if (childFrameView) // Widget should never be null during layout(), but just in case. 112 setLogicalHeight(childFrameView->contentsHeight() + borderTop() + borderBottom() + paddingTop() + paddingBottom()); 113 updateLogicalHeight(); 114 115 updateWidgetPosition(); // Notify the Widget of our final height. 116 117 // Assert that the child document did a complete layout. 118 RenderView* childRoot = childFrameView ? childFrameView->frame().contentRenderer() : 0; 119 ASSERT(!childFrameView || !childFrameView->layoutPending()); 120 ASSERT_UNUSED(childRoot, !childRoot || !childRoot->needsLayout()); 121 } 122 123 void RenderIFrame::layout() 124 { 125 ASSERT(needsLayout()); 126 127 LayoutRectRecorder recorder(*this); 128 if (isSeamless()) { 129 layoutSeamlessly(); 130 // Do not return so as to share the layer and overflow updates below. 131 } else { 132 updateLogicalWidth(); 133 // No kids to layout as a replaced element. 134 updateLogicalHeight(); 135 } 136 137 m_overflow.clear(); 138 addVisualEffectOverflow(); 139 updateLayerTransform(); 140 141 clearNeedsLayout(); 142 } 143 144 } 145