1/* 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 3 * (C) 2000 Simon Hausmann <hausmann@kde.org> 4 * (C) 2000 Stefan Schimanski (1Stein@gmx.de) 5 * Copyright (C) 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved. 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Library General Public 9 * License as published by the Free Software Foundation; either 10 * version 2 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Library General Public License for more details. 16 * 17 * You should have received a copy of the GNU Library General Public License 18 * along with this library; see the file COPYING.LIB. If not, write to 19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 * Boston, MA 02110-1301, USA. 21 * 22 */ 23 24#include "config.h" 25#include "RenderPartObject.h" 26 27#include "Frame.h" 28#include "FrameLoaderClient.h" 29#include "HTMLEmbedElement.h" 30#include "HTMLIFrameElement.h" 31#include "HTMLNames.h" 32#include "HTMLObjectElement.h" 33#include "HTMLParamElement.h" 34#include "MIMETypeRegistry.h" 35#include "Page.h" 36#include "RenderView.h" 37#include "RenderWidgetProtector.h" 38#include "Text.h" 39 40#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) 41#include "HTMLVideoElement.h" 42#endif 43 44namespace WebCore { 45 46using namespace HTMLNames; 47 48RenderPartObject::RenderPartObject(Element* element) 49 : RenderPart(element) 50{ 51} 52 53void RenderPartObject::layout() 54{ 55 ASSERT(needsLayout()); 56 57#ifdef FLATTEN_IFRAME 58 RenderPart::calcWidth(); 59 RenderPart::calcHeight(); 60 // Calculate the styled dimensions by subtracting the border and padding. 61 int extraWidth = paddingLeft() + paddingRight() + borderLeft() + borderRight(); 62 int extraHeight = paddingTop() + paddingBottom() + borderTop() + borderBottom(); 63 int styleWidth = width() - extraWidth; 64 int styleHeight = height() - extraHeight; 65 // Some IFrames have a width and/or height of 1 when they are meant to be 66 // hidden. If that is the case, do not try to expand. 67 if (node()->hasTagName(iframeTag) && widget() && widget()->isFrameView() && 68 styleWidth > 1 && styleHeight > 1) { 69 HTMLIFrameElement* element = static_cast<HTMLIFrameElement*>(node()); 70 bool scrolling = element->scrollingMode() != ScrollbarAlwaysOff; 71 bool widthIsFixed = style()->width().isFixed(); 72 bool heightIsFixed = style()->height().isFixed(); 73 // If an iframe has a fixed dimension and suppresses scrollbars, it 74 // will disrupt layout if we force it to expand. Plus on a desktop, 75 // the extra content is not accessible. 76 if (scrolling || !widthIsFixed || !heightIsFixed) { 77 FrameView* view = static_cast<FrameView*>(widget()); 78 RenderView* root = view ? view->frame()->contentRenderer() : NULL; 79 if (root && style()->visibility() != HIDDEN) { 80 // Update the dimensions to get the correct minimum preferred 81 // width 82 updateWidgetPosition(); 83 84 // Use the preferred width if it is larger and only if 85 // scrollbars are visible or the width style is not fixed. 86 if (scrolling || !widthIsFixed) 87 setWidth(max(width(), root->minPrefWidth()) + extraWidth); 88 89 // Resize the view to recalc the height. 90 int h = height() - extraHeight; 91 int w = width() - extraWidth; 92 if (w > view->width()) 93 h = 0; 94 if (w != view->width() || h != view->height()) { 95 view->resize(w, h); 96 } 97 98 // Layout the view. 99 do { 100 view->layout(); 101 } while (view->layoutPending() || root->needsLayout()); 102 103 int contentHeight = view->contentsHeight(); 104 int contentWidth = view->contentsWidth(); 105 // Only change the width or height if scrollbars are visible or 106 // if the style is not a fixed value. Use the maximum value so 107 // that iframes never shrink. 108 if (scrolling || !heightIsFixed) 109 setHeight(max(height(), contentHeight + extraHeight)); 110 if (scrolling || !widthIsFixed) 111 setWidth(max(width(), contentWidth + extraWidth)); 112 113 // Update one last time 114 updateWidgetPosition(); 115 116 // Layout one more time to ensure all objects have the correct 117 // height. 118 view->layout(); 119 120#if !ASSERT_DISABLED 121 ASSERT(!view->layoutPending()); 122 ASSERT(!root->needsLayout()); 123 // Sanity check when assertions are enabled. 124 RenderObject* c = root->nextInPreOrder(); 125 while (c) { 126 ASSERT(!c->needsLayout()); 127 c = c->nextInPreOrder(); 128 } 129#endif 130 } 131 } 132 } 133#else 134 calcWidth(); 135 calcHeight(); 136#endif 137 138 RenderPart::layout(); 139 140 m_overflow.clear(); 141 addShadowOverflow(); 142 143 setNeedsLayout(false); 144} 145 146#ifdef FLATTEN_IFRAME 147void RenderPartObject::calcWidth() { 148 RenderPart::calcWidth(); 149 if (!node()->hasTagName(iframeTag) || !widget() || !widget()->isFrameView()) 150 return; 151 FrameView* view = static_cast<FrameView*>(widget()); 152 RenderView* root = static_cast<RenderView*>(view->frame()->contentRenderer()); 153 if (!root) 154 return; 155 // Do not expand if the scrollbars are suppressed and the width is fixed. 156 bool scrolling = static_cast<HTMLIFrameElement*>(node())->scrollingMode() != ScrollbarAlwaysOff; 157 if (!scrolling && style()->width().isFixed()) 158 return; 159 // Update the dimensions to get the correct minimum preferred 160 // width 161 updateWidgetPosition(); 162 163 int extraWidth = paddingLeft() + paddingRight() + borderLeft() + borderRight(); 164 // Set the width 165 setWidth(max(width(), root->minPrefWidth()) + extraWidth); 166 167 // Update based on the new width 168 updateWidgetPosition(); 169 170 // Layout to get the content width 171 do { 172 view->layout(); 173 } while (view->layoutPending() || root->needsLayout()); 174 175 setWidth(max(width(), view->contentsWidth() + extraWidth)); 176 177 // Update one last time to ensure the dimensions. 178 updateWidgetPosition(); 179} 180 181void RenderPartObject::calcHeight() { 182 RenderPart::calcHeight(); 183 if (!node()->hasTagName(iframeTag) || !widget() || !widget()->isFrameView()) 184 return; 185 FrameView* view = static_cast<FrameView*>(widget()); 186 RenderView* root = static_cast<RenderView*>(view->frame()->contentRenderer()); 187 if (!root) 188 return; 189 // Do not expand if the scrollbars are suppressed and the height is fixed. 190 bool scrolling = static_cast<HTMLIFrameElement*>(node())->scrollingMode() != ScrollbarAlwaysOff; 191 if (!scrolling && style()->height().isFixed()) 192 return; 193 // Update the widget 194 updateWidgetPosition(); 195 196 // Layout to get the content height 197 do { 198 view->layout(); 199 } while (view->layoutPending() || root->needsLayout()); 200 201 int extraHeight = paddingTop() + paddingBottom() + borderTop() + borderBottom(); 202 setHeight(max(width(), view->contentsHeight() + extraHeight)); 203 204 // Update one last time to ensure the dimensions. 205 updateWidgetPosition(); 206} 207#endif 208 209void RenderPartObject::viewCleared() 210{ 211 if (node() && widget() && widget()->isFrameView()) { 212 FrameView* view = static_cast<FrameView*>(widget()); 213 int marginw = -1; 214 int marginh = -1; 215 if (node()->hasTagName(iframeTag)) { 216 HTMLIFrameElement* frame = static_cast<HTMLIFrameElement*>(node()); 217 marginw = frame->getMarginWidth(); 218 marginh = frame->getMarginHeight(); 219 } 220 if (marginw != -1) 221 view->setMarginWidth(marginw); 222 if (marginh != -1) 223 view->setMarginHeight(marginh); 224 } 225} 226 227} 228