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 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 "RenderImage.h"
36 #include "RenderPartObject.h"
37 #include "RenderWidget.h"
38 #include "ScriptController.h"
39 #include "Settings.h"
40
41 namespace WebCore {
42
43 using namespace HTMLNames;
44
HTMLEmbedElement(const QualifiedName & tagName,Document * doc)45 HTMLEmbedElement::HTMLEmbedElement(const QualifiedName& tagName, Document* doc)
46 : HTMLPlugInImageElement(tagName, doc)
47 , m_needWidgetUpdate(false)
48 {
49 ASSERT(hasTagName(embedTag));
50 }
51
~HTMLEmbedElement()52 HTMLEmbedElement::~HTMLEmbedElement()
53 {
54 }
55
findWidgetRenderer(const Node * n)56 static inline RenderWidget* findWidgetRenderer(const Node* n)
57 {
58 if (!n->renderer())
59 do
60 n = n->parentNode();
61 while (n && !n->hasTagName(objectTag));
62
63 if (n && n->renderer() && n->renderer()->isWidget())
64 return toRenderWidget(n->renderer());
65
66 return 0;
67 }
68
renderWidgetForJSBindings() const69 RenderWidget* HTMLEmbedElement::renderWidgetForJSBindings() const
70 {
71 RenderWidget* renderWidget = findWidgetRenderer(this);
72 if (renderWidget && !renderWidget->widget()) {
73 document()->updateLayoutIgnorePendingStylesheets();
74 renderWidget = findWidgetRenderer(this);
75 }
76 return renderWidget;
77 }
78
mapToEntry(const QualifiedName & attrName,MappedAttributeEntry & result) const79 bool HTMLEmbedElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const
80 {
81 if (attrName == hiddenAttr) {
82 result = eUniversal;
83 return false;
84 }
85
86 return HTMLPlugInElement::mapToEntry(attrName, result);
87 }
88
parseMappedAttribute(MappedAttribute * attr)89 void HTMLEmbedElement::parseMappedAttribute(MappedAttribute* attr)
90 {
91 const AtomicString& value = attr->value();
92
93 if (attr->name() == typeAttr) {
94 m_serviceType = value.string().lower();
95 int pos = m_serviceType.find(";");
96 if (pos != -1)
97 m_serviceType = m_serviceType.left(pos);
98 if (!isImageType() && m_imageLoader)
99 m_imageLoader.clear();
100 } else if (attr->name() == codeAttr)
101 m_url = deprecatedParseURL(value.string());
102 else if (attr->name() == srcAttr) {
103 m_url = deprecatedParseURL(value.string());
104 if (renderer() && isImageType()) {
105 if (!m_imageLoader)
106 m_imageLoader.set(new HTMLImageLoader(this));
107 m_imageLoader->updateFromElementIgnoringPreviousError();
108 }
109 } else if (attr->name() == hiddenAttr) {
110 if (equalIgnoringCase(value.string(), "yes") || equalIgnoringCase(value.string(), "true")) {
111 // FIXME: Not dynamic, since we add this but don't remove it, but it may be OK for now
112 // that this rarely-used attribute won't work properly if you remove it.
113 addCSSLength(attr, CSSPropertyWidth, "0");
114 addCSSLength(attr, CSSPropertyHeight, "0");
115 }
116 } else if (attr->name() == nameAttr) {
117 if (inDocument() && document()->isHTMLDocument()) {
118 HTMLDocument* document = static_cast<HTMLDocument*>(this->document());
119 document->removeNamedItem(m_name);
120 document->addNamedItem(value);
121 }
122 m_name = value;
123 } else
124 HTMLPlugInElement::parseMappedAttribute(attr);
125 }
126
rendererIsNeeded(RenderStyle * style)127 bool HTMLEmbedElement::rendererIsNeeded(RenderStyle* style)
128 {
129 if (isImageType())
130 return HTMLPlugInElement::rendererIsNeeded(style);
131
132 Frame* frame = document()->frame();
133 if (!frame)
134 return false;
135
136 Node* p = parentNode();
137 if (p && p->hasTagName(objectTag)) {
138 ASSERT(p->renderer());
139 return false;
140 }
141
142 #if ENABLE(DASHBOARD_SUPPORT)
143 // Workaround for <rdar://problem/6642221>.
144 if (Settings* settings = frame->settings()) {
145 if (settings->usesDashboardBackwardCompatibilityMode())
146 return true;
147 }
148 #endif
149
150 return HTMLPlugInElement::rendererIsNeeded(style);
151 }
152
createRenderer(RenderArena * arena,RenderStyle *)153 RenderObject* HTMLEmbedElement::createRenderer(RenderArena* arena, RenderStyle*)
154 {
155 if (isImageType())
156 return new (arena) RenderImage(this);
157 return new (arena) RenderPartObject(this);
158 }
159
attach()160 void HTMLEmbedElement::attach()
161 {
162 m_needWidgetUpdate = true;
163
164 bool isImage = isImageType();
165
166 if (!isImage)
167 queuePostAttachCallback(&HTMLPlugInElement::updateWidgetCallback, this);
168
169 HTMLPlugInElement::attach();
170
171 if (isImage && renderer()) {
172 if (!m_imageLoader)
173 m_imageLoader.set(new HTMLImageLoader(this));
174 m_imageLoader->updateFromElement();
175
176 if (renderer())
177 toRenderImage(renderer())->setCachedImage(m_imageLoader->image());
178 }
179 }
180
updateWidget()181 void HTMLEmbedElement::updateWidget()
182 {
183 document()->updateStyleIfNeeded();
184 if (m_needWidgetUpdate && renderer() && !isImageType())
185 toRenderPartObject(renderer())->updateWidget(true);
186 }
187
insertedIntoDocument()188 void HTMLEmbedElement::insertedIntoDocument()
189 {
190 if (document()->isHTMLDocument())
191 static_cast<HTMLDocument*>(document())->addNamedItem(m_name);
192
193 String width = getAttribute(widthAttr);
194 String height = getAttribute(heightAttr);
195 if (!width.isEmpty() || !height.isEmpty()) {
196 Node* n = parent();
197 while (n && !n->hasTagName(objectTag))
198 n = n->parent();
199 if (n) {
200 if (!width.isEmpty())
201 static_cast<HTMLObjectElement*>(n)->setAttribute(widthAttr, width);
202 if (!height.isEmpty())
203 static_cast<HTMLObjectElement*>(n)->setAttribute(heightAttr, height);
204 }
205 }
206
207 HTMLPlugInElement::insertedIntoDocument();
208 }
209
removedFromDocument()210 void HTMLEmbedElement::removedFromDocument()
211 {
212 if (document()->isHTMLDocument())
213 static_cast<HTMLDocument*>(document())->removeNamedItem(m_name);
214
215 HTMLPlugInElement::removedFromDocument();
216 }
217
attributeChanged(Attribute * attr,bool preserveDecls)218 void HTMLEmbedElement::attributeChanged(Attribute* attr, bool preserveDecls)
219 {
220 HTMLPlugInElement::attributeChanged(attr, preserveDecls);
221
222 if ((attr->name() == widthAttr || attr->name() == heightAttr) && !attr->isEmpty()) {
223 Node* n = parent();
224 while (n && !n->hasTagName(objectTag))
225 n = n->parent();
226 if (n)
227 static_cast<HTMLObjectElement*>(n)->setAttribute(attr->name(), attr->value());
228 }
229 }
230
isURLAttribute(Attribute * attr) const231 bool HTMLEmbedElement::isURLAttribute(Attribute* attr) const
232 {
233 return attr->name() == srcAttr;
234 }
235
imageSourceAttributeName() const236 const QualifiedName& HTMLEmbedElement::imageSourceAttributeName() const
237 {
238 return srcAttr;
239 }
240
src() const241 String HTMLEmbedElement::src() const
242 {
243 return getAttribute(srcAttr);
244 }
245
setSrc(const String & value)246 void HTMLEmbedElement::setSrc(const String& value)
247 {
248 setAttribute(srcAttr, value);
249 }
250
type() const251 String HTMLEmbedElement::type() const
252 {
253 return getAttribute(typeAttr);
254 }
255
setType(const String & value)256 void HTMLEmbedElement::setType(const String& value)
257 {
258 setAttribute(typeAttr, value);
259 }
260
addSubresourceAttributeURLs(ListHashSet<KURL> & urls) const261 void HTMLEmbedElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
262 {
263 HTMLPlugInImageElement::addSubresourceAttributeURLs(urls);
264
265 addSubresourceURL(urls, document()->completeURL(src()));
266 }
267
268 }
269