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, 2011 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 "core/html/HTMLEmbedElement.h" 26 27#include "CSSPropertyNames.h" 28#include "HTMLNames.h" 29#include "core/dom/Attribute.h" 30#include "core/dom/shadow/ShadowRoot.h" 31#include "core/html/HTMLImageLoader.h" 32#include "core/html/HTMLObjectElement.h" 33#include "core/html/PluginDocument.h" 34#include "core/html/parser/HTMLParserIdioms.h" 35#include "core/rendering/RenderEmbeddedObject.h" 36#include "core/rendering/RenderWidget.h" 37 38namespace WebCore { 39 40using namespace HTMLNames; 41 42inline HTMLEmbedElement::HTMLEmbedElement(Document& document, bool createdByParser) 43 : HTMLPlugInElement(embedTag, document, createdByParser, ShouldPreferPlugInsForImages) 44{ 45 ScriptWrappable::init(this); 46} 47 48PassRefPtr<HTMLEmbedElement> HTMLEmbedElement::create(Document& document, bool createdByParser) 49{ 50 RefPtr<HTMLEmbedElement> element = adoptRef(new HTMLEmbedElement(document, createdByParser)); 51 element->ensureUserAgentShadowRoot(); 52 return element.release(); 53} 54 55static inline RenderWidget* findWidgetRenderer(const Node* n) 56{ 57 if (!n->renderer()) 58 do 59 n = n->parentNode(); 60 while (n && !n->hasTagName(objectTag)); 61 62 if (n && n->renderer() && n->renderer()->isWidget()) 63 return toRenderWidget(n->renderer()); 64 65 return 0; 66} 67 68RenderWidget* HTMLEmbedElement::existingRenderWidget() const 69{ 70 return findWidgetRenderer(this); 71} 72 73bool HTMLEmbedElement::isPresentationAttribute(const QualifiedName& name) const 74{ 75 if (name == hiddenAttr) 76 return true; 77 return HTMLPlugInElement::isPresentationAttribute(name); 78} 79 80void HTMLEmbedElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style) 81{ 82 if (name == hiddenAttr) { 83 if (equalIgnoringCase(value, "yes") || equalIgnoringCase(value, "true")) { 84 addPropertyToPresentationAttributeStyle(style, CSSPropertyWidth, 0, CSSPrimitiveValue::CSS_PX); 85 addPropertyToPresentationAttributeStyle(style, CSSPropertyHeight, 0, CSSPrimitiveValue::CSS_PX); 86 } 87 } else { 88 HTMLPlugInElement::collectStyleForPresentationAttribute(name, value, style); 89 } 90} 91 92void HTMLEmbedElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 93{ 94 if (name == typeAttr) { 95 m_serviceType = value.string().lower(); 96 size_t pos = m_serviceType.find(";"); 97 if (pos != kNotFound) 98 m_serviceType = m_serviceType.left(pos); 99 } else if (name == codeAttr) { 100 m_url = stripLeadingAndTrailingHTMLSpaces(value); 101 } else if (name == srcAttr) { 102 m_url = stripLeadingAndTrailingHTMLSpaces(value); 103 if (renderer() && isImageType()) { 104 if (!m_imageLoader) 105 m_imageLoader = adoptPtr(new HTMLImageLoader(this)); 106 m_imageLoader->updateFromElementIgnoringPreviousError(); 107 } 108 } else { 109 HTMLPlugInElement::parseAttribute(name, value); 110 } 111} 112 113void HTMLEmbedElement::parametersForPlugin(Vector<String>& paramNames, Vector<String>& paramValues) 114{ 115 if (!hasAttributes()) 116 return; 117 118 for (unsigned i = 0; i < attributeCount(); ++i) { 119 const Attribute* attribute = attributeItem(i); 120 paramNames.append(attribute->localName().string()); 121 paramValues.append(attribute->value().string()); 122 } 123} 124 125// FIXME: This should be unified with HTMLObjectElement::updateWidget and 126// moved down into HTMLPluginElement.cpp 127void HTMLEmbedElement::updateWidgetInternal() 128{ 129 ASSERT(!renderEmbeddedObject()->showsUnavailablePluginIndicator()); 130 ASSERT(needsWidgetUpdate()); 131 setNeedsWidgetUpdate(false); 132 133 if (m_url.isEmpty() && m_serviceType.isEmpty()) 134 return; 135 136 // Note these pass m_url and m_serviceType to allow better code sharing with 137 // <object> which modifies url and serviceType before calling these. 138 if (!allowedToLoadFrameURL(m_url)) 139 return; 140 141 // FIXME: These should be joined into a PluginParameters class. 142 Vector<String> paramNames; 143 Vector<String> paramValues; 144 parametersForPlugin(paramNames, paramValues); 145 146 RefPtr<HTMLEmbedElement> protect(this); // Loading the plugin might remove us from the document. 147 bool beforeLoadAllowedLoad = dispatchBeforeLoadEvent(m_url); 148 if (!beforeLoadAllowedLoad) { 149 if (document().isPluginDocument()) { 150 // Plugins inside plugin documents load differently than other plugins. By the time 151 // we are here in a plugin document, the load of the plugin (which is the plugin document's 152 // main resource) has already started. We need to explicitly cancel the main resource load here. 153 toPluginDocument(document()).cancelManualPluginLoad(); 154 } 155 return; 156 } 157 if (!renderer()) // Do not load the plugin if beforeload removed this element or its renderer. 158 return; 159 160 // FIXME: beforeLoad could have detached the renderer! Just like in the <object> case above. 161 requestObject(m_url, m_serviceType, paramNames, paramValues); 162} 163 164bool HTMLEmbedElement::rendererIsNeeded(const RenderStyle& style) 165{ 166 if (isImageType()) 167 return HTMLPlugInElement::rendererIsNeeded(style); 168 169 Frame* frame = document().frame(); 170 if (!frame) 171 return false; 172 173 // If my parent is an <object> and is not set to use fallback content, I 174 // should be ignored and not get a renderer. 175 ContainerNode* p = parentNode(); 176 if (p && p->hasTagName(objectTag)) { 177 ASSERT(p->renderer()); 178 if (!toHTMLObjectElement(p)->useFallbackContent()) { 179 ASSERT(!p->renderer()->isEmbeddedObject()); 180 return false; 181 } 182 } 183 return HTMLPlugInElement::rendererIsNeeded(style); 184} 185 186bool HTMLEmbedElement::isURLAttribute(const Attribute& attribute) const 187{ 188 return attribute.name() == srcAttr || HTMLPlugInElement::isURLAttribute(attribute); 189} 190 191const AtomicString HTMLEmbedElement::imageSourceURL() const 192{ 193 return getAttribute(srcAttr); 194} 195 196void HTMLEmbedElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const 197{ 198 HTMLPlugInElement::addSubresourceAttributeURLs(urls); 199 200 addSubresourceURL(urls, document().completeURL(getAttribute(srcAttr))); 201} 202 203bool HTMLEmbedElement::isInteractiveContent() const 204{ 205 return true; 206} 207 208bool HTMLEmbedElement::isExposed() const 209{ 210 // http://www.whatwg.org/specs/web-apps/current-work/#exposed 211 for (Node* ancestor = parentNode(); ancestor; ancestor = ancestor->parentNode()) { 212 if (ancestor->hasTagName(objectTag) && toHTMLObjectElement(ancestor)->isExposed()) 213 return false; 214 } 215 return true; 216} 217 218} 219