1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 1999 Antti Koivisto (koivisto (at) kde.org) 4 * (C) 2000 Stefan Schimanski (1Stein (at) 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 "core/CSSPropertyNames.h" 28 #include "core/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 38 namespace WebCore { 39 40 using namespace HTMLNames; 41 42 inline HTMLEmbedElement::HTMLEmbedElement(Document& document, bool createdByParser) 43 : HTMLPlugInElement(embedTag, document, createdByParser, ShouldPreferPlugInsForImages) 44 { 45 ScriptWrappable::init(this); 46 } 47 48 PassRefPtrWillBeRawPtr<HTMLEmbedElement> HTMLEmbedElement::create(Document& document, bool createdByParser) 49 { 50 RefPtrWillBeRawPtr<HTMLEmbedElement> element = adoptRefWillBeNoop(new HTMLEmbedElement(document, createdByParser)); 51 element->ensureUserAgentShadowRoot(); 52 return element.release(); 53 } 54 55 static inline RenderWidget* findWidgetRenderer(const Node* n) 56 { 57 if (!n->renderer()) 58 n = Traversal<HTMLObjectElement>::firstAncestor(*n); 59 60 if (n && n->renderer() && n->renderer()->isWidget()) 61 return toRenderWidget(n->renderer()); 62 63 return 0; 64 } 65 66 RenderWidget* HTMLEmbedElement::existingRenderWidget() const 67 { 68 return findWidgetRenderer(this); 69 } 70 71 bool HTMLEmbedElement::isPresentationAttribute(const QualifiedName& name) const 72 { 73 if (name == hiddenAttr) 74 return true; 75 return HTMLPlugInElement::isPresentationAttribute(name); 76 } 77 78 void HTMLEmbedElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style) 79 { 80 if (name == hiddenAttr) { 81 if (equalIgnoringCase(value, "yes") || equalIgnoringCase(value, "true")) { 82 addPropertyToPresentationAttributeStyle(style, CSSPropertyWidth, 0, CSSPrimitiveValue::CSS_PX); 83 addPropertyToPresentationAttributeStyle(style, CSSPropertyHeight, 0, CSSPrimitiveValue::CSS_PX); 84 } 85 } else { 86 HTMLPlugInElement::collectStyleForPresentationAttribute(name, value, style); 87 } 88 } 89 90 void HTMLEmbedElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 91 { 92 if (name == typeAttr) { 93 m_serviceType = value.string().lower(); 94 size_t pos = m_serviceType.find(";"); 95 if (pos != kNotFound) 96 m_serviceType = m_serviceType.left(pos); 97 if (!renderer()) 98 requestPluginCreationWithoutRendererIfPossible(); 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 = HTMLImageLoader::create(this); 106 m_imageLoader->updateFromElementIgnoringPreviousError(); 107 } 108 } else { 109 HTMLPlugInElement::parseAttribute(name, value); 110 } 111 } 112 113 void HTMLEmbedElement::parametersForPlugin(Vector<String>& paramNames, Vector<String>& paramValues) 114 { 115 if (!hasAttributes()) 116 return; 117 118 AttributeCollection attributes = this->attributes(); 119 AttributeCollection::const_iterator end = attributes.end(); 120 for (AttributeCollection::const_iterator it = attributes.begin(); it != end; ++it) { 121 paramNames.append(it->localName().string()); 122 paramValues.append(it->value().string()); 123 } 124 } 125 126 // FIXME: This should be unified with HTMLObjectElement::updateWidget and 127 // moved down into HTMLPluginElement.cpp 128 void HTMLEmbedElement::updateWidgetInternal() 129 { 130 ASSERT(!renderEmbeddedObject()->showsUnavailablePluginIndicator()); 131 ASSERT(needsWidgetUpdate()); 132 setNeedsWidgetUpdate(false); 133 134 if (m_url.isEmpty() && m_serviceType.isEmpty()) 135 return; 136 137 // Note these pass m_url and m_serviceType to allow better code sharing with 138 // <object> which modifies url and serviceType before calling these. 139 if (!allowedToLoadFrameURL(m_url)) 140 return; 141 142 // FIXME: These should be joined into a PluginParameters class. 143 Vector<String> paramNames; 144 Vector<String> paramValues; 145 parametersForPlugin(paramNames, paramValues); 146 147 RefPtrWillBeRawPtr<HTMLEmbedElement> protect(this); // Loading the plugin might remove us from the document. 148 149 // FIXME: Can we not have renderer here now that beforeload events are gone? 150 if (!renderer()) 151 return; 152 153 requestObject(m_url, m_serviceType, paramNames, paramValues); 154 } 155 156 bool HTMLEmbedElement::rendererIsNeeded(const RenderStyle& style) 157 { 158 if (isImageType()) 159 return HTMLPlugInElement::rendererIsNeeded(style); 160 161 LocalFrame* frame = document().frame(); 162 if (!frame) 163 return false; 164 165 // If my parent is an <object> and is not set to use fallback content, I 166 // should be ignored and not get a renderer. 167 ContainerNode* p = parentNode(); 168 if (isHTMLObjectElement(p)) { 169 ASSERT(p->renderer()); 170 if (!toHTMLObjectElement(p)->useFallbackContent()) { 171 ASSERT(!p->renderer()->isEmbeddedObject()); 172 return false; 173 } 174 } 175 return HTMLPlugInElement::rendererIsNeeded(style); 176 } 177 178 bool HTMLEmbedElement::isURLAttribute(const Attribute& attribute) const 179 { 180 return attribute.name() == srcAttr || HTMLPlugInElement::isURLAttribute(attribute); 181 } 182 183 const QualifiedName& HTMLEmbedElement::subResourceAttributeName() const 184 { 185 return srcAttr; 186 } 187 188 const AtomicString HTMLEmbedElement::imageSourceURL() const 189 { 190 return getAttribute(srcAttr); 191 } 192 193 bool HTMLEmbedElement::isInteractiveContent() const 194 { 195 return true; 196 } 197 198 bool HTMLEmbedElement::isExposed() const 199 { 200 // http://www.whatwg.org/specs/web-apps/current-work/#exposed 201 for (HTMLObjectElement* object = Traversal<HTMLObjectElement>::firstAncestor(*this); object; object = Traversal<HTMLObjectElement>::firstAncestor(*object)) { 202 if (object->isExposed()) 203 return false; 204 } 205 return true; 206 } 207 208 } 209