WebCore:
[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     , m_needWidgetUpdate(false)
49 {
50 }
51
52 HTMLEmbedElement::~HTMLEmbedElement()
53 {
54 #if USE(JAVASCRIPTCORE_BINDINGS)
55     // m_instance should have been cleaned up in detach().
56     ASSERT(!m_instance);
57 #endif
58 }
59
60 #if USE(JAVASCRIPTCORE_BINDINGS)
61 static inline RenderWidget* findWidgetRenderer(const Node* n) 
62 {
63     if (!n->renderer())
64         do
65             n = n->parentNode();
66         while (n && !n->hasTagName(objectTag));
67     
68     return (n && n->renderer() && n->renderer()->isWidget()) 
69         ? static_cast<RenderWidget*>(n->renderer()) : 0;
70 }
71     
72 KJS::Bindings::Instance *HTMLEmbedElement::getInstance() const
73 {
74     Frame* frame = document()->frame();
75     if (!frame)
76         return 0;
77
78     if (m_instance)
79         return m_instance.get();
80     
81     RenderWidget* renderWidget = findWidgetRenderer(this);
82     if (renderWidget && !renderWidget->widget()) {
83         document()->updateLayoutIgnorePendingStylesheets();
84         renderWidget = findWidgetRenderer(this);
85     }
86     
87     if (renderWidget && renderWidget->widget()) 
88         m_instance = frame->createScriptInstanceForWidget(renderWidget->widget());
89     
90     return m_instance.get();
91 }
92 #endif
93
94 bool HTMLEmbedElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const
95 {
96     if (attrName == hiddenAttr) {
97         result = eUniversal;
98         return false;
99     }
100         
101     return HTMLPlugInElement::mapToEntry(attrName, result);
102 }
103
104 void HTMLEmbedElement::parseMappedAttribute(MappedAttribute* attr)
105 {
106     String val = attr->value();
107   
108     if (attr->name() == typeAttr) {
109         m_serviceType = val.lower();
110         int pos = m_serviceType.find(";");
111         if (pos != -1)
112             m_serviceType = m_serviceType.left(pos);
113     } else if (attr->name() == codeAttr || attr->name() == srcAttr)
114          url = parseURL(val).deprecatedString();
115     else if (attr->name() == pluginpageAttr || attr->name() == pluginspageAttr)
116         m_pluginPage = val;
117     else if (attr->name() == hiddenAttr) {
118         if (val.lower() == "yes" || val.lower() == "true") {
119             // FIXME: Not dynamic, but it's not really important that such a rarely-used
120             // feature work dynamically.
121             addCSSLength(attr, CSS_PROP_WIDTH, "0");
122             addCSSLength(attr, CSS_PROP_HEIGHT, "0");
123         }
124     } else if (attr->name() == nameAttr) {
125         if (inDocument() && document()->isHTMLDocument()) {
126             HTMLDocument* doc = static_cast<HTMLDocument*>(document());
127             doc->removeNamedItem(oldNameAttr);
128             doc->addNamedItem(val);
129         }
130         oldNameAttr = val;
131     } else
132         HTMLPlugInElement::parseMappedAttribute(attr);
133 }
134
135 bool HTMLEmbedElement::rendererIsNeeded(RenderStyle *style)
136 {
137     Frame *frame = document()->frame();
138     if (!frame)
139         return false;
140
141     Node *p = parentNode();
142     if (p && p->hasTagName(objectTag)) {
143         ASSERT(p->renderer());
144         return false;
145     }
146
147     return true;
148 }
149
150 RenderObject *HTMLEmbedElement::createRenderer(RenderArena *arena, RenderStyle *style)
151 {
152     return new (arena) RenderPartObject(this);
153 }
154
155 void HTMLEmbedElement::attach()
156 {
157     m_needWidgetUpdate = true;
158     queuePostAttachCallback(&HTMLPlugInElement::updateWidgetCallback, this);
159     HTMLPlugInElement::attach();
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::updateWidget()
171 {
172     if (m_needWidgetUpdate && renderer())
173         static_cast<RenderPartObject*>(renderer())->updateWidget(true);
174 }
175
176 void HTMLEmbedElement::insertedIntoDocument()
177 {
178     if (document()->isHTMLDocument()) {
179         HTMLDocument *doc = static_cast<HTMLDocument *>(document());
180         doc->addNamedItem(oldNameAttr);
181     }
182
183     String width = getAttribute(widthAttr);
184     String height = getAttribute(heightAttr);
185     if (!width.isEmpty() || !height.isEmpty()) {
186         Node* n = parent();
187         while (n && !n->hasTagName(objectTag))
188             n = n->parent();
189         if (n) {
190             if (!width.isEmpty())
191                 static_cast<HTMLObjectElement*>(n)->setAttribute(widthAttr, width);
192             if (!height.isEmpty())
193                 static_cast<HTMLObjectElement*>(n)->setAttribute(heightAttr, height);
194         }
195     }
196
197     HTMLPlugInElement::insertedIntoDocument();
198 }
199
200 void HTMLEmbedElement::removedFromDocument()
201 {
202     if (document()->isHTMLDocument()) {
203         HTMLDocument *doc = static_cast<HTMLDocument *>(document());
204         doc->removeNamedItem(oldNameAttr);
205     }
206
207     HTMLPlugInElement::removedFromDocument();
208 }
209
210 void HTMLEmbedElement::attributeChanged(Attribute* attr, bool preserveDecls)
211 {
212     HTMLPlugInElement::attributeChanged(attr, preserveDecls);
213
214     if ((attr->name() == widthAttr || attr->name() == heightAttr) && !attr->isEmpty()) {
215         Node* n = parent();
216         while (n && !n->hasTagName(objectTag))
217             n = n->parent();
218         if (n)
219             static_cast<HTMLObjectElement*>(n)->setAttribute(attr->name(), attr->value());
220     }
221 }
222
223 bool HTMLEmbedElement::isURLAttribute(Attribute *attr) const
224 {
225     return attr->name() == srcAttr;
226 }
227
228 String HTMLEmbedElement::src() const
229 {
230     return getAttribute(srcAttr);
231 }
232
233 void HTMLEmbedElement::setSrc(const String& value)
234 {
235     setAttribute(srcAttr, value);
236 }
237
238 String HTMLEmbedElement::type() const
239 {
240     return getAttribute(typeAttr);
241 }
242
243 void HTMLEmbedElement::setType(const String& value)
244 {
245     setAttribute(typeAttr, value);
246 }
247
248 #if ENABLE(SVG)
249 SVGDocument* HTMLEmbedElement::getSVGDocument(ExceptionCode& ec) const
250 {
251     Document* doc = contentDocument();
252     if (doc && doc->isSVGDocument())
253         return static_cast<SVGDocument*>(doc);
254     // Spec: http://www.w3.org/TR/SVG/struct.html#InterfaceGetSVGDocument
255     ec = NOT_SUPPORTED_ERR;
256     return 0;
257 }
258 #endif
259
260 }