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/page/Frame.h" 32 #include "core/page/FrameView.h" 33 #include "core/rendering/RenderView.h" 34 35 namespace WebCore { 36 37 using namespace HTMLNames; 38 39 RenderIFrame::RenderIFrame(Element* element) 40 : RenderPart(element) 41 { 42 } 43 44 bool RenderIFrame::shouldComputeSizeAsReplaced() const 45 { 46 // When we're seamless, we use normal block/box sizing code except when inline. 47 return !isSeamless(); 48 } 49 50 bool RenderIFrame::isInlineBlockOrInlineTable() const 51 { 52 return isSeamless() && isInline(); 53 } 54 55 LayoutUnit RenderIFrame::minPreferredLogicalWidth() const 56 { 57 if (!isSeamless()) 58 return RenderPart::minPreferredLogicalWidth(); 59 60 RenderView* childRoot = contentRootRenderer(); 61 if (!childRoot) 62 return 0; 63 64 return childRoot->minPreferredLogicalWidth() + borderAndPaddingLogicalWidth(); 65 } 66 67 LayoutUnit RenderIFrame::maxPreferredLogicalWidth() const 68 { 69 if (!isSeamless()) 70 return RenderPart::maxPreferredLogicalWidth(); 71 72 RenderView* childRoot = contentRootRenderer(); 73 if (!childRoot) 74 return 0; 75 76 return childRoot->maxPreferredLogicalWidth() + borderAndPaddingLogicalWidth(); 77 } 78 79 bool RenderIFrame::isSeamless() const 80 { 81 return node() && node()->hasTagName(iframeTag) && toHTMLIFrameElement(node())->shouldDisplaySeamlessly(); 82 } 83 84 bool RenderIFrame::requiresLayer() const 85 { 86 return RenderPart::requiresLayer() || style()->resize() != RESIZE_NONE; 87 } 88 89 RenderView* RenderIFrame::contentRootRenderer() const 90 { 91 // FIXME: Is this always a valid cast? What about plugins? 92 ASSERT(!widget() || widget()->isFrameView()); 93 FrameView* childFrameView = toFrameView(widget()); 94 return childFrameView ? childFrameView->frame()->contentRenderer() : 0; 95 } 96 97 void RenderIFrame::layoutSeamlessly() 98 { 99 updateLogicalWidth(); 100 // FIXME: Containers set their height to 0 before laying out their kids (as we're doing here) 101 // however, this causes FrameView::layout() to add vertical scrollbars, incorrectly inflating 102 // the resulting contentHeight(). We'll need to make FrameView::layout() smarter. 103 setLogicalHeight(0); 104 updateWidgetPosition(); // Tell the Widget about our new width/height (it will also layout the child document). 105 106 // Laying out our kids is normally responsible for adjusting our height, so we set it here. 107 // Replaced elements normally do not respect padding, but seamless elements should: we'll add 108 // both padding and border to the child's logical height here. 109 FrameView* childFrameView = toFrameView(widget()); 110 if (childFrameView) // Widget should never be null during layout(), but just in case. 111 setLogicalHeight(childFrameView->contentsHeight() + borderTop() + borderBottom() + paddingTop() + paddingBottom()); 112 updateLogicalHeight(); 113 114 updateWidgetPosition(); // Notify the Widget of our final height. 115 116 // Assert that the child document did a complete layout. 117 RenderView* childRoot = childFrameView ? childFrameView->frame()->contentRenderer() : 0; 118 ASSERT(!childFrameView || !childFrameView->layoutPending()); 119 ASSERT_UNUSED(childRoot, !childRoot || !childRoot->needsLayout()); 120 } 121 122 void RenderIFrame::layout() 123 { 124 StackStats::LayoutCheckPoint layoutCheckPoint; 125 ASSERT(needsLayout()); 126 127 if (isSeamless()) { 128 layoutSeamlessly(); 129 // Do not return so as to share the layer and overflow updates below. 130 } else { 131 updateLogicalWidth(); 132 // No kids to layout as a replaced element. 133 updateLogicalHeight(); 134 } 135 136 m_overflow.clear(); 137 addVisualEffectOverflow(); 138 updateLayerTransform(); 139 140 clearNeedsLayout(); 141 } 142 143 } 144