WebCore:
[WebKit-https.git] / WebCore / html / HTMLEmbedElement.cpp
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) 2007 Trolltech ASA
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 "FrameView.h"
31 #include "HTMLDocument.h"
32 #include "HTMLObjectElement.h"
33 #include "HTMLNames.h"
34 #include "RenderPartObject.h"
35
36 #if USE(JAVASCRIPTCORE_BINDINGS)
37 #include "runtime.h"
38 #endif
39
40 namespace WebCore {
41
42 using namespace HTMLNames;
43
44 HTMLEmbedElement::HTMLEmbedElement(Document* doc)
45     : HTMLPlugInElement(embedTag, doc)
46     , m_needWidgetUpdate(false)
47 {
48 }
49
50 HTMLEmbedElement::~HTMLEmbedElement()
51 {
52 #if USE(JAVASCRIPTCORE_BINDINGS)
53     // m_instance should have been cleaned up in detach().
54     ASSERT(!m_instance);
55 #endif
56 }
57
58 #if USE(JAVASCRIPTCORE_BINDINGS)
59 static 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     return (n && n->renderer() && n->renderer()->isWidget()) 
67         ? static_cast<RenderWidget*>(n->renderer()) : 0;
68 }
69     
70 KJS::Bindings::Instance* HTMLEmbedElement::getInstance() const
71 {
72     Frame* frame = document()->frame();
73     if (!frame)
74         return 0;
75
76     if (m_instance)
77         return m_instance.get();
78     
79     RenderWidget* renderWidget = findWidgetRenderer(this);
80     if (renderWidget && !renderWidget->widget()) {
81         document()->updateLayoutIgnorePendingStylesheets();
82         renderWidget = findWidgetRenderer(this);
83     }
84     
85     if (renderWidget && renderWidget->widget()) 
86         m_instance = frame->createScriptInstanceForWidget(renderWidget->widget());
87     
88     return m_instance.get();
89 }
90 #endif
91
92 bool HTMLEmbedElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const
93 {
94     if (attrName == hiddenAttr) {
95         result = eUniversal;
96         return false;
97     }
98         
99     return HTMLPlugInElement::mapToEntry(attrName, result);
100 }
101
102 void HTMLEmbedElement::parseMappedAttribute(MappedAttribute* attr)
103 {
104     const AtomicString& value = attr->value();
105   
106     if (attr->name() == typeAttr) {
107         m_serviceType = value.string().lower();
108         int pos = m_serviceType.find(";");
109         if (pos != -1)
110             m_serviceType = m_serviceType.left(pos);
111     } else if (attr->name() == codeAttr || attr->name() == srcAttr)
112         m_url = parseURL(value.string());
113     else if (attr->name() == pluginpageAttr || attr->name() == pluginspageAttr)
114         m_pluginPage = value;
115     else if (attr->name() == hiddenAttr) {
116         if (equalIgnoringCase(value.string(), "yes") || equalIgnoringCase(value.string(), "true")) {
117             // FIXME: Not dynamic, since we add this but don't remove it, but it may be OK for now
118             // that this rarely-used attribute won't work properly if you remove it.
119             addCSSLength(attr, CSSPropertyWidth, "0");
120             addCSSLength(attr, CSSPropertyHeight, "0");
121         }
122     } else if (attr->name() == nameAttr) {
123         if (inDocument() && document()->isHTMLDocument()) {
124             HTMLDocument* document = static_cast<HTMLDocument*>(this->document());
125             document->removeNamedItem(m_name);
126             document->addNamedItem(value);
127         }
128         m_name = value;
129     } else
130         HTMLPlugInElement::parseMappedAttribute(attr);
131 }
132
133 bool HTMLEmbedElement::rendererIsNeeded(RenderStyle* style)
134 {
135     Frame* frame = document()->frame();
136     if (!frame)
137         return false;
138
139     Node* p = parentNode();
140     if (p && p->hasTagName(objectTag)) {
141         ASSERT(p->renderer());
142         return false;
143     }
144
145     return true;
146 }
147
148 RenderObject* HTMLEmbedElement::createRenderer(RenderArena* arena, RenderStyle* style)
149 {
150     return new (arena) RenderPartObject(this);
151 }
152
153 void HTMLEmbedElement::attach()
154 {
155     m_needWidgetUpdate = true;
156     queuePostAttachCallback(&HTMLPlugInElement::updateWidgetCallback, this);
157     HTMLPlugInElement::attach();
158 }
159
160 void HTMLEmbedElement::detach()
161 {
162 #if USE(JAVASCRIPTCORE_BINDINGS)
163     m_instance = 0;
164 #endif
165     HTMLPlugInElement::detach();
166 }
167
168 void HTMLEmbedElement::updateWidget()
169 {
170     document()->updateRendering();
171     if (m_needWidgetUpdate && renderer())
172         static_cast<RenderPartObject*>(renderer())->updateWidget(true);
173 }
174
175 void HTMLEmbedElement::insertedIntoDocument()
176 {
177     if (document()->isHTMLDocument())
178         static_cast<HTMLDocument*>(document())->addNamedItem(m_name);
179
180     String width = getAttribute(widthAttr);
181     String height = getAttribute(heightAttr);
182     if (!width.isEmpty() || !height.isEmpty()) {
183         Node* n = parent();
184         while (n && !n->hasTagName(objectTag))
185             n = n->parent();
186         if (n) {
187             if (!width.isEmpty())
188                 static_cast<HTMLObjectElement*>(n)->setAttribute(widthAttr, width);
189             if (!height.isEmpty())
190                 static_cast<HTMLObjectElement*>(n)->setAttribute(heightAttr, height);
191         }
192     }
193
194     HTMLPlugInElement::insertedIntoDocument();
195 }
196
197 void HTMLEmbedElement::removedFromDocument()
198 {
199     if (document()->isHTMLDocument())
200         static_cast<HTMLDocument*>(document())->removeNamedItem(m_name);
201
202     HTMLPlugInElement::removedFromDocument();
203 }
204
205 void HTMLEmbedElement::attributeChanged(Attribute* attr, bool preserveDecls)
206 {
207     HTMLPlugInElement::attributeChanged(attr, preserveDecls);
208
209     if ((attr->name() == widthAttr || attr->name() == heightAttr) && !attr->isEmpty()) {
210         Node* n = parent();
211         while (n && !n->hasTagName(objectTag))
212             n = n->parent();
213         if (n)
214             static_cast<HTMLObjectElement*>(n)->setAttribute(attr->name(), attr->value());
215     }
216 }
217
218 bool HTMLEmbedElement::isURLAttribute(Attribute* attr) const
219 {
220     return attr->name() == srcAttr;
221 }
222
223 String HTMLEmbedElement::src() const
224 {
225     return getAttribute(srcAttr);
226 }
227
228 void HTMLEmbedElement::setSrc(const String& value)
229 {
230     setAttribute(srcAttr, value);
231 }
232
233 String HTMLEmbedElement::type() const
234 {
235     return getAttribute(typeAttr);
236 }
237
238 void HTMLEmbedElement::setType(const String& value)
239 {
240     setAttribute(typeAttr, value);
241 }
242
243 void HTMLEmbedElement::getSubresourceAttributeStrings(Vector<String>& urls) const
244 {
245     urls.append(src());
246 }
247
248 }