b76c2a900c4735b2bf7eb63b01ac256f28302ab8
[WebKit-https.git] / WebCore / html / HTMLEmbedElement.cpp
1 /**
2  * This file is part of the DOM implementation for KDE.
3  *
4  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
5  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
6  *           (C) 2000 Stefan Schimanski (1Stein@gmx.de)
7  * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
8  * Copyright (C) 2007 Trolltech ASA
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public License
21  * along with this library; see the file COPYING.LIB.  If not, write to
22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  */
25 #include "config.h"
26 #include "HTMLEmbedElement.h"
27
28 #include "CSSHelper.h"
29 #include "CSSPropertyNames.h"
30 #include "Frame.h"
31 #include "FrameView.h"
32 #include "HTMLDocument.h"
33 #include "HTMLObjectElement.h"
34 #include "HTMLNames.h"
35 #include "RenderPartObject.h"
36
37 #if ENABLE(SVG)
38 #include "ExceptionCode.h"
39 #include "SVGDocument.h"
40 #endif
41
42 namespace WebCore {
43
44 using namespace HTMLNames;
45
46 HTMLEmbedElement::HTMLEmbedElement(Document* doc)
47     : HTMLPlugInElement(embedTag, doc)
48 {
49 }
50
51 HTMLEmbedElement::~HTMLEmbedElement()
52 {
53 #if USE(JAVASCRIPTCORE_BINDINGS)
54     // m_instance should have been cleaned up in detach().
55     ASSERT(!m_instance);
56 #endif
57 }
58
59 #if USE(JAVASCRIPTCORE_BINDINGS)
60 static inline RenderWidget* findWidgetRenderer(const Node* n) 
61 {
62     if (!n->renderer())
63         do
64             n = n->parentNode();
65         while (n && !n->hasTagName(objectTag));
66     
67     return (n && n->renderer() && n->renderer()->isWidget()) 
68         ? static_cast<RenderWidget*>(n->renderer()) : 0;
69 }
70     
71 KJS::Bindings::Instance *HTMLEmbedElement::getInstance() const
72 {
73     Frame* frame = document()->frame();
74     if (!frame)
75         return 0;
76
77     if (m_instance)
78         return m_instance.get();
79     
80     RenderWidget* renderWidget = findWidgetRenderer(this);
81     if (renderWidget && !renderWidget->widget()) {
82         document()->updateLayoutIgnorePendingStylesheets();
83         renderWidget = findWidgetRenderer(this);
84     }
85     
86     if (renderWidget && renderWidget->widget()) 
87         m_instance = frame->createScriptInstanceForWidget(renderWidget->widget());
88     
89     return m_instance.get();
90 }
91 #endif
92
93 bool HTMLEmbedElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const
94 {
95     if (attrName == hiddenAttr) {
96         result = eUniversal;
97         return false;
98     }
99         
100     return HTMLPlugInElement::mapToEntry(attrName, result);
101 }
102
103 void HTMLEmbedElement::parseMappedAttribute(MappedAttribute* attr)
104 {
105     String val = attr->value();
106   
107     if (attr->name() == typeAttr) {
108         m_serviceType = val.lower();
109         int pos = m_serviceType.find(";");
110         if (pos != -1)
111             m_serviceType = m_serviceType.left(pos);
112     } else if (attr->name() == codeAttr || attr->name() == srcAttr)
113          url = parseURL(val).deprecatedString();
114     else if (attr->name() == pluginpageAttr || attr->name() == pluginspageAttr)
115         m_pluginPage = val;
116     else if (attr->name() == hiddenAttr) {
117         if (val.lower() == "yes" || val.lower() == "true") {
118             // FIXME: Not dynamic, but it's not really important that such a rarely-used
119             // feature work dynamically.
120             addCSSLength(attr, CSS_PROP_WIDTH, "0");
121             addCSSLength(attr, CSS_PROP_HEIGHT, "0");
122         }
123     } else if (attr->name() == nameAttr) {
124         if (inDocument() && document()->isHTMLDocument()) {
125             HTMLDocument* doc = static_cast<HTMLDocument*>(document());
126             doc->removeNamedItem(oldNameAttr);
127             doc->addNamedItem(val);
128         }
129         oldNameAttr = val;
130     } else
131         HTMLPlugInElement::parseMappedAttribute(attr);
132 }
133
134 bool HTMLEmbedElement::rendererIsNeeded(RenderStyle *style)
135 {
136     Frame *frame = document()->frame();
137     if (!frame)
138         return false;
139
140     Node *p = parentNode();
141     if (p && p->hasTagName(objectTag)) {
142         ASSERT(p->renderer());
143         return false;
144     }
145
146     return true;
147 }
148
149 RenderObject *HTMLEmbedElement::createRenderer(RenderArena *arena, RenderStyle *style)
150 {
151     return new (arena) RenderPartObject(this);
152 }
153
154 void HTMLEmbedElement::attach()
155 {
156     HTMLPlugInElement::attach();
157
158     if (renderer())
159         static_cast<RenderPartObject*>(renderer())->updateWidget(true);
160 }
161
162 void HTMLEmbedElement::detach()
163 {
164 #if USE(JAVASCRIPTCORE_BINDINGS)
165     m_instance = 0;
166 #endif
167     HTMLPlugInElement::detach();
168 }
169
170 void HTMLEmbedElement::insertedIntoDocument()
171 {
172     if (document()->isHTMLDocument()) {
173         HTMLDocument *doc = static_cast<HTMLDocument *>(document());
174         doc->addNamedItem(oldNameAttr);
175     }
176
177     String width = getAttribute(widthAttr);
178     String height = getAttribute(heightAttr);
179     if (!width.isEmpty() || !height.isEmpty()) {
180         Node* n = parent();
181         while (n && !n->hasTagName(objectTag))
182             n = n->parent();
183         if (n) {
184             if (!width.isEmpty())
185                 static_cast<HTMLObjectElement*>(n)->setAttribute(widthAttr, width);
186             if (!height.isEmpty())
187                 static_cast<HTMLObjectElement*>(n)->setAttribute(heightAttr, height);
188         }
189     }
190
191     HTMLPlugInElement::insertedIntoDocument();
192 }
193
194 void HTMLEmbedElement::removedFromDocument()
195 {
196     if (document()->isHTMLDocument()) {
197         HTMLDocument *doc = static_cast<HTMLDocument *>(document());
198         doc->removeNamedItem(oldNameAttr);
199     }
200
201     HTMLPlugInElement::removedFromDocument();
202 }
203
204 void HTMLEmbedElement::attributeChanged(Attribute* attr, bool preserveDecls)
205 {
206     HTMLPlugInElement::attributeChanged(attr, preserveDecls);
207
208     if ((attr->name() == widthAttr || attr->name() == heightAttr) && !attr->isEmpty()) {
209         Node* n = parent();
210         while (n && !n->hasTagName(objectTag))
211             n = n->parent();
212         if (n)
213             static_cast<HTMLObjectElement*>(n)->setAttribute(attr->name(), attr->value());
214     }
215 }
216
217 bool HTMLEmbedElement::isURLAttribute(Attribute *attr) const
218 {
219     return attr->name() == srcAttr;
220 }
221
222 String HTMLEmbedElement::src() const
223 {
224     return getAttribute(srcAttr);
225 }
226
227 void HTMLEmbedElement::setSrc(const String& value)
228 {
229     setAttribute(srcAttr, value);
230 }
231
232 String HTMLEmbedElement::type() const
233 {
234     return getAttribute(typeAttr);
235 }
236
237 void HTMLEmbedElement::setType(const String& value)
238 {
239     setAttribute(typeAttr, value);
240 }
241
242 #if ENABLE(SVG)
243 SVGDocument* HTMLEmbedElement::getSVGDocument(ExceptionCode& ec) const
244 {
245     Document* doc = contentDocument();
246     if (doc && doc->isSVGDocument())
247         return static_cast<SVGDocument*>(doc);
248     // Spec: http://www.w3.org/TR/SVG/struct.html#InterfaceGetSVGDocument
249     ec = NOT_SUPPORTED_ERR;
250     return 0;
251 }
252 #endif
253
254 }