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/ElementTraversal.h" 31 #include "core/dom/shadow/ShadowRoot.h" 32 #include "core/html/HTMLImageLoader.h" 33 #include "core/html/HTMLObjectElement.h" 34 #include "core/html/PluginDocument.h" 35 #include "core/html/parser/HTMLParserIdioms.h" 36 #include "core/rendering/RenderEmbeddedObject.h" 37 #include "core/rendering/RenderWidget.h" 38 39 namespace blink { 40 41 using namespace HTMLNames; 42 43 inline HTMLEmbedElement::HTMLEmbedElement(Document& document, bool createdByParser) 44 : HTMLPlugInElement(embedTag, document, createdByParser, ShouldPreferPlugInsForImages) 45 { 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.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->updateFromElement(ImageLoader::UpdateIgnorePreviousError); 107 } 108 } else { 109 HTMLPlugInElement::parseAttribute(name, value); 110 } 111 } 112 113 void HTMLEmbedElement::parametersForPlugin(Vector<String>& paramNames, Vector<String>& paramValues) 114 { 115 AttributeCollection attributes = this->attributes(); 116 AttributeCollection::iterator end = attributes.end(); 117 for (AttributeCollection::iterator it = attributes.begin(); it != end; ++it) { 118 paramNames.append(it->localName().string()); 119 paramValues.append(it->value().string()); 120 } 121 } 122 123 // FIXME: This should be unified with HTMLObjectElement::updateWidget and 124 // moved down into HTMLPluginElement.cpp 125 void HTMLEmbedElement::updateWidgetInternal() 126 { 127 ASSERT(!renderEmbeddedObject()->showsUnavailablePluginIndicator()); 128 ASSERT(needsWidgetUpdate()); 129 setNeedsWidgetUpdate(false); 130 131 if (m_url.isEmpty() && m_serviceType.isEmpty()) 132 return; 133 134 // Note these pass m_url and m_serviceType to allow better code sharing with 135 // <object> which modifies url and serviceType before calling these. 136 if (!allowedToLoadFrameURL(m_url)) 137 return; 138 139 // FIXME: These should be joined into a PluginParameters class. 140 Vector<String> paramNames; 141 Vector<String> paramValues; 142 parametersForPlugin(paramNames, paramValues); 143 144 RefPtrWillBeRawPtr<HTMLEmbedElement> protect(this); // Loading the plugin might remove us from the document. 145 146 // FIXME: Can we not have renderer here now that beforeload events are gone? 147 if (!renderer()) 148 return; 149 150 requestObject(m_url, m_serviceType, paramNames, paramValues); 151 } 152 153 bool HTMLEmbedElement::rendererIsNeeded(const RenderStyle& style) 154 { 155 if (isImageType()) 156 return HTMLPlugInElement::rendererIsNeeded(style); 157 158 LocalFrame* frame = document().frame(); 159 if (!frame) 160 return false; 161 162 // If my parent is an <object> and is not set to use fallback content, I 163 // should be ignored and not get a renderer. 164 ContainerNode* p = parentNode(); 165 if (isHTMLObjectElement(p)) { 166 ASSERT(p->renderer()); 167 if (!toHTMLObjectElement(p)->useFallbackContent()) { 168 ASSERT(!p->renderer()->isEmbeddedObject()); 169 return false; 170 } 171 } 172 return HTMLPlugInElement::rendererIsNeeded(style); 173 } 174 175 bool HTMLEmbedElement::isURLAttribute(const Attribute& attribute) const 176 { 177 return attribute.name() == srcAttr || HTMLPlugInElement::isURLAttribute(attribute); 178 } 179 180 const QualifiedName& HTMLEmbedElement::subResourceAttributeName() const 181 { 182 return srcAttr; 183 } 184 185 bool HTMLEmbedElement::isInteractiveContent() const 186 { 187 return true; 188 } 189 190 bool HTMLEmbedElement::isExposed() const 191 { 192 // http://www.whatwg.org/specs/web-apps/current-work/#exposed 193 for (HTMLObjectElement* object = Traversal<HTMLObjectElement>::firstAncestor(*this); object; object = Traversal<HTMLObjectElement>::firstAncestor(*object)) { 194 if (object->isExposed()) 195 return false; 196 } 197 return true; 198 } 199 200 } 201