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 "HTMLEmbedElement.h" 26 27#include "Attribute.h" 28#include "CSSPropertyNames.h" 29#include "DocumentLoader.h" 30#include "Frame.h" 31#include "FrameLoader.h" 32#include "FrameView.h" 33#include "HTMLDocument.h" 34#include "HTMLImageLoader.h" 35#include "HTMLNames.h" 36#include "HTMLObjectElement.h" 37#include "HTMLParserIdioms.h" 38#include "PluginDocument.h" 39#include "RenderEmbeddedObject.h" 40#include "RenderImage.h" 41#include "RenderWidget.h" 42#include "Settings.h" 43 44namespace WebCore { 45 46using namespace HTMLNames; 47 48inline HTMLEmbedElement::HTMLEmbedElement(const QualifiedName& tagName, Document* document, bool createdByParser) 49 : HTMLPlugInImageElement(tagName, document, createdByParser, ShouldPreferPlugInsForImages) 50{ 51 ASSERT(hasTagName(embedTag)); 52} 53 54PassRefPtr<HTMLEmbedElement> HTMLEmbedElement::create(const QualifiedName& tagName, Document* document, bool createdByParser) 55{ 56 return adoptRef(new HTMLEmbedElement(tagName, document, createdByParser)); 57} 58 59static inline RenderWidget* findWidgetRenderer(const Node* n) 60{ 61 if (!n->renderer()) 62 do 63 n = n->parentNode(); 64 while (n && !n->hasTagName(objectTag)); 65 66 if (n && n->renderer() && n->renderer()->isWidget()) 67 return toRenderWidget(n->renderer()); 68 69 return 0; 70} 71 72RenderWidget* HTMLEmbedElement::renderWidgetForJSBindings() const 73{ 74 FrameView* view = document()->view(); 75 if (!view || (!view->isInLayout() && !view->isPainting())) { 76 // Needs to load the plugin immediatedly because this function is called 77 // when JavaScript code accesses the plugin. 78 // FIXME: <rdar://16893708> Check if dispatching events here is safe. 79 document()->updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasksSynchronously); 80 } 81 return findWidgetRenderer(this); 82} 83 84bool HTMLEmbedElement::isPresentationAttribute(const QualifiedName& name) const 85{ 86 if (name == hiddenAttr) 87 return true; 88 return HTMLPlugInImageElement::isPresentationAttribute(name); 89} 90 91void HTMLEmbedElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style) 92{ 93 if (name == hiddenAttr) { 94 if (equalIgnoringCase(value, "yes") || equalIgnoringCase(value, "true")) { 95 addPropertyToPresentationAttributeStyle(style, CSSPropertyWidth, 0, CSSPrimitiveValue::CSS_PX); 96 addPropertyToPresentationAttributeStyle(style, CSSPropertyHeight, 0, CSSPrimitiveValue::CSS_PX); 97 } 98 } else 99 HTMLPlugInImageElement::collectStyleForPresentationAttribute(name, value, style); 100} 101 102void HTMLEmbedElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 103{ 104 if (name == typeAttr) { 105 m_serviceType = value.string().lower(); 106 size_t pos = m_serviceType.find(";"); 107 if (pos != notFound) 108 m_serviceType = m_serviceType.left(pos); 109 } else if (name == codeAttr) 110 m_url = stripLeadingAndTrailingHTMLSpaces(value); 111 else if (name == srcAttr) { 112 m_url = stripLeadingAndTrailingHTMLSpaces(value); 113 if (renderer() && isImageType()) { 114 if (!m_imageLoader) 115 m_imageLoader = adoptPtr(new HTMLImageLoader(this)); 116 m_imageLoader->updateFromElementIgnoringPreviousError(); 117 } 118 } else 119 HTMLPlugInImageElement::parseAttribute(name, value); 120} 121 122void HTMLEmbedElement::parametersForPlugin(Vector<String>& paramNames, Vector<String>& paramValues) 123{ 124 if (!hasAttributes()) 125 return; 126 127 for (unsigned i = 0; i < attributeCount(); ++i) { 128 const Attribute* attribute = attributeItem(i); 129 paramNames.append(attribute->localName().string()); 130 paramValues.append(attribute->value().string()); 131 } 132} 133 134// FIXME: This should be unified with HTMLObjectElement::updateWidget and 135// moved down into HTMLPluginImageElement.cpp 136void HTMLEmbedElement::updateWidget(PluginCreationOption pluginCreationOption) 137{ 138 ASSERT(!renderEmbeddedObject()->isPluginUnavailable()); 139 ASSERT(needsWidgetUpdate()); 140 setNeedsWidgetUpdate(false); 141 142 if (m_url.isEmpty() && m_serviceType.isEmpty()) 143 return; 144 145 // Note these pass m_url and m_serviceType to allow better code sharing with 146 // <object> which modifies url and serviceType before calling these. 147 if (!allowedToLoadFrameURL(m_url)) 148 return; 149 150 // FIXME: It's sadness that we have this special case here. 151 // See http://trac.webkit.org/changeset/25128 and 152 // plugins/netscape-plugin-setwindow-size.html 153 if (pluginCreationOption == CreateOnlyNonNetscapePlugins && wouldLoadAsNetscapePlugin(m_url, m_serviceType)) { 154 // Ensure updateWidget() is called again during layout to create the Netscape plug-in. 155 setNeedsWidgetUpdate(true); 156 return; 157 } 158 159 // FIXME: These should be joined into a PluginParameters class. 160 Vector<String> paramNames; 161 Vector<String> paramValues; 162 parametersForPlugin(paramNames, paramValues); 163 164 RefPtr<HTMLEmbedElement> protect(this); // Loading the plugin might remove us from the document. 165 bool beforeLoadAllowedLoad = guardedDispatchBeforeLoadEvent(m_url); 166 if (!beforeLoadAllowedLoad) { 167 if (document()->isPluginDocument()) { 168 // Plugins inside plugin documents load differently than other plugins. By the time 169 // we are here in a plugin document, the load of the plugin (which is the plugin document's 170 // main resource) has already started. We need to explicitly cancel the main resource load here. 171 toPluginDocument(document())->cancelManualPluginLoad(); 172 } 173 return; 174 } 175 if (!renderer()) // Do not load the plugin if beforeload removed this element or its renderer. 176 return; 177 178 SubframeLoader* loader = document()->frame()->loader()->subframeLoader(); 179 // FIXME: beforeLoad could have detached the renderer! Just like in the <object> case above. 180 loader->requestObject(this, m_url, getNameAttribute(), m_serviceType, paramNames, paramValues); 181} 182 183bool HTMLEmbedElement::rendererIsNeeded(const NodeRenderingContext& context) 184{ 185 if (isImageType()) 186 return HTMLPlugInImageElement::rendererIsNeeded(context); 187 188 Frame* frame = document()->frame(); 189 if (!frame) 190 return false; 191 192 // If my parent is an <object> and is not set to use fallback content, I 193 // should be ignored and not get a renderer. 194 ContainerNode* p = parentNode(); 195 if (p && p->hasTagName(objectTag)) { 196 ASSERT(p->renderer()); 197 if (!static_cast<HTMLObjectElement*>(p)->useFallbackContent()) { 198 ASSERT(!p->renderer()->isEmbeddedObject()); 199 return false; 200 } 201 } 202 203#if ENABLE(DASHBOARD_SUPPORT) 204 // Workaround for <rdar://problem/6642221>. 205 if (Settings* settings = frame->settings()) { 206 if (settings->usesDashboardBackwardCompatibilityMode()) 207 return true; 208 } 209#endif 210 211 return HTMLPlugInImageElement::rendererIsNeeded(context); 212} 213 214bool HTMLEmbedElement::isURLAttribute(const Attribute& attribute) const 215{ 216 return attribute.name() == srcAttr || HTMLPlugInImageElement::isURLAttribute(attribute); 217} 218 219const AtomicString& HTMLEmbedElement::imageSourceURL() const 220{ 221 return getAttribute(srcAttr); 222} 223 224void HTMLEmbedElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const 225{ 226 HTMLPlugInImageElement::addSubresourceAttributeURLs(urls); 227 228 addSubresourceURL(urls, document()->completeURL(getAttribute(srcAttr))); 229} 230 231#if ENABLE(MICRODATA) 232String HTMLEmbedElement::itemValueText() const 233{ 234 return getURLAttribute(srcAttr); 235} 236 237void HTMLEmbedElement::setItemValueText(const String& value, ExceptionCode&) 238{ 239 setAttribute(srcAttr, value); 240} 241#endif 242 243} 244