1/* 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 4 * (C) 2000 Stefan Schimanski (1Stein@gmx.de) 5 * Copyright (C) 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved. 6 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Library General Public 10 * License as published by the Free Software Foundation; either 11 * version 2 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Library General Public License for more details. 17 * 18 * You should have received a copy of the GNU Library General Public License 19 * along with this library; see the file COPYING.LIB. If not, write to 20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 * Boston, MA 02110-1301, USA. 22 */ 23 24#include "config.h" 25#include "HTMLEmbedElement.h" 26 27#include "CSSHelper.h" 28#include "CSSPropertyNames.h" 29#include "Frame.h" 30#include "HTMLDocument.h" 31#include "HTMLImageLoader.h" 32#include "HTMLNames.h" 33#include "HTMLObjectElement.h" 34#include "MappedAttribute.h" 35#include "RenderEmbeddedObject.h" 36#include "RenderImage.h" 37#include "RenderWidget.h" 38#include "ScriptController.h" 39#include "Settings.h" 40 41namespace WebCore { 42 43using namespace HTMLNames; 44 45inline HTMLEmbedElement::HTMLEmbedElement(const QualifiedName& tagName, Document* document) 46 : HTMLPlugInImageElement(tagName, document) 47 , m_needWidgetUpdate(false) 48{ 49 ASSERT(hasTagName(embedTag)); 50} 51 52PassRefPtr<HTMLEmbedElement> HTMLEmbedElement::create(const QualifiedName& tagName, Document* document) 53{ 54 return adoptRef(new HTMLEmbedElement(tagName, document)); 55} 56 57static inline RenderWidget* findWidgetRenderer(const Node* n) 58{ 59 if (!n->renderer()) 60 do 61 n = n->parentNode(); 62 while (n && !n->hasTagName(objectTag)); 63 64 if (n && n->renderer() && n->renderer()->isWidget()) 65 return toRenderWidget(n->renderer()); 66 67 return 0; 68} 69 70RenderWidget* HTMLEmbedElement::renderWidgetForJSBindings() const 71{ 72 document()->updateLayoutIgnorePendingStylesheets(); 73 return findWidgetRenderer(this); 74} 75 76bool HTMLEmbedElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const 77{ 78 if (attrName == hiddenAttr) { 79 result = eUniversal; 80 return false; 81 } 82 83 return HTMLPlugInElement::mapToEntry(attrName, result); 84} 85 86void HTMLEmbedElement::parseMappedAttribute(MappedAttribute* attr) 87{ 88 const AtomicString& value = attr->value(); 89 90 if (attr->name() == typeAttr) { 91 m_serviceType = value.string().lower(); 92 int pos = m_serviceType.find(";"); 93 if (pos != -1) 94 m_serviceType = m_serviceType.left(pos); 95 if (!isImageType() && m_imageLoader) 96 m_imageLoader.clear(); 97 } else if (attr->name() == codeAttr) 98 m_url = deprecatedParseURL(value.string()); 99 else if (attr->name() == srcAttr) { 100 m_url = deprecatedParseURL(value.string()); 101 if (renderer() && isImageType()) { 102 if (!m_imageLoader) 103 m_imageLoader.set(new HTMLImageLoader(this)); 104 m_imageLoader->updateFromElementIgnoringPreviousError(); 105 } 106 } else if (attr->name() == hiddenAttr) { 107 if (equalIgnoringCase(value.string(), "yes") || equalIgnoringCase(value.string(), "true")) { 108 // FIXME: Not dynamic, since we add this but don't remove it, but it may be OK for now 109 // that this rarely-used attribute won't work properly if you remove it. 110 addCSSLength(attr, CSSPropertyWidth, "0"); 111 addCSSLength(attr, CSSPropertyHeight, "0"); 112 } 113 } else if (attr->name() == nameAttr) { 114 if (inDocument() && document()->isHTMLDocument()) { 115 HTMLDocument* document = static_cast<HTMLDocument*>(this->document()); 116 document->removeNamedItem(m_name); 117 document->addNamedItem(value); 118 } 119 m_name = value; 120 } else 121 HTMLPlugInElement::parseMappedAttribute(attr); 122} 123 124bool HTMLEmbedElement::rendererIsNeeded(RenderStyle* style) 125{ 126 if (isImageType()) 127 return HTMLPlugInElement::rendererIsNeeded(style); 128 129 Frame* frame = document()->frame(); 130 if (!frame) 131 return false; 132 133 Node* p = parentNode(); 134 if (p && p->hasTagName(objectTag)) { 135 ASSERT(p->renderer()); 136 return false; 137 } 138 139#if ENABLE(DASHBOARD_SUPPORT) 140 // Workaround for <rdar://problem/6642221>. 141 if (Settings* settings = frame->settings()) { 142 if (settings->usesDashboardBackwardCompatibilityMode()) 143 return true; 144 } 145#endif 146 147 return HTMLPlugInElement::rendererIsNeeded(style); 148} 149 150RenderObject* HTMLEmbedElement::createRenderer(RenderArena* arena, RenderStyle*) 151{ 152 if (isImageType()) 153 return new (arena) RenderImage(this); 154 return new (arena) RenderEmbeddedObject(this); 155} 156 157void HTMLEmbedElement::attach() 158{ 159 m_needWidgetUpdate = true; 160 161 bool isImage = isImageType(); 162 163 if (!isImage) 164 queuePostAttachCallback(&HTMLPlugInElement::updateWidgetCallback, this); 165 166 HTMLPlugInElement::attach(); 167 168 if (isImage && renderer()) { 169 if (!m_imageLoader) 170 m_imageLoader.set(new HTMLImageLoader(this)); 171 m_imageLoader->updateFromElement(); 172 173 if (renderer()) 174 toRenderImage(renderer())->setCachedImage(m_imageLoader->image()); 175 } 176} 177 178void HTMLEmbedElement::updateWidget() 179{ 180 document()->updateStyleIfNeeded(); 181 if (m_needWidgetUpdate && renderer() && !isImageType()) 182 toRenderEmbeddedObject(renderer())->updateWidget(true); 183} 184 185void HTMLEmbedElement::insertedIntoDocument() 186{ 187 if (document()->isHTMLDocument()) 188 static_cast<HTMLDocument*>(document())->addNamedItem(m_name); 189 190 String width = getAttribute(widthAttr); 191 String height = getAttribute(heightAttr); 192 if (!width.isEmpty() || !height.isEmpty()) { 193 Node* n = parent(); 194 while (n && !n->hasTagName(objectTag)) 195 n = n->parent(); 196 if (n) { 197 if (!width.isEmpty()) 198 static_cast<HTMLObjectElement*>(n)->setAttribute(widthAttr, width); 199 if (!height.isEmpty()) 200 static_cast<HTMLObjectElement*>(n)->setAttribute(heightAttr, height); 201 } 202 } 203 204 HTMLPlugInElement::insertedIntoDocument(); 205} 206 207void HTMLEmbedElement::removedFromDocument() 208{ 209 if (document()->isHTMLDocument()) 210 static_cast<HTMLDocument*>(document())->removeNamedItem(m_name); 211 212 HTMLPlugInElement::removedFromDocument(); 213} 214 215void HTMLEmbedElement::attributeChanged(Attribute* attr, bool preserveDecls) 216{ 217 HTMLPlugInElement::attributeChanged(attr, preserveDecls); 218 219 if ((attr->name() == widthAttr || attr->name() == heightAttr) && !attr->isEmpty()) { 220 Node* n = parent(); 221 while (n && !n->hasTagName(objectTag)) 222 n = n->parent(); 223 if (n) 224 static_cast<HTMLObjectElement*>(n)->setAttribute(attr->name(), attr->value()); 225 } 226} 227 228bool HTMLEmbedElement::isURLAttribute(Attribute* attr) const 229{ 230 return attr->name() == srcAttr; 231} 232 233const QualifiedName& HTMLEmbedElement::imageSourceAttributeName() const 234{ 235 return srcAttr; 236} 237 238void HTMLEmbedElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const 239{ 240 HTMLPlugInImageElement::addSubresourceAttributeURLs(urls); 241 242 addSubresourceURL(urls, document()->completeURL(getAttribute(srcAttr))); 243} 244 245} 246