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 Apple Computer, Inc.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 */
22
23 #include "config.h"
24 #include "HTMLPlugInElement.h"
25
26 #include "Attribute.h"
27 #include "Chrome.h"
28 #include "ChromeClient.h"
29 #include "CSSPropertyNames.h"
30 #include "Document.h"
31 #include "Frame.h"
32 #include "FrameLoader.h"
33 #include "FrameTree.h"
34 #include "HTMLNames.h"
35 #include "Page.h"
36 #include "RenderEmbeddedObject.h"
37 #include "RenderWidget.h"
38 #include "ScriptController.h"
39 #include "Settings.h"
40 #include "Widget.h"
41
42 #if ENABLE(NETSCAPE_PLUGIN_API)
43 #include "npruntime_impl.h"
44 #endif
45
46 namespace WebCore {
47
48 using namespace HTMLNames;
49
HTMLPlugInElement(const QualifiedName & tagName,Document * doc)50 HTMLPlugInElement::HTMLPlugInElement(const QualifiedName& tagName, Document* doc)
51 : HTMLFrameOwnerElement(tagName, doc)
52 , m_inBeforeLoadEventHandler(false)
53 #if ENABLE(NETSCAPE_PLUGIN_API)
54 , m_NPObject(0)
55 #endif
56 , m_isCapturingMouseEvents(false)
57 {
58 }
59
~HTMLPlugInElement()60 HTMLPlugInElement::~HTMLPlugInElement()
61 {
62 ASSERT(!m_instance); // cleared in detach()
63
64 #if ENABLE(NETSCAPE_PLUGIN_API)
65 if (m_NPObject) {
66 _NPN_ReleaseObject(m_NPObject);
67 m_NPObject = 0;
68 }
69 #endif
70 }
71
detach()72 void HTMLPlugInElement::detach()
73 {
74 m_instance.clear();
75
76 if (m_isCapturingMouseEvents) {
77 if (Frame* frame = document()->frame())
78 frame->eventHandler()->setCapturingMouseEventsNode(0);
79 m_isCapturingMouseEvents = false;
80 }
81
82 HTMLFrameOwnerElement::detach();
83 }
84
getInstance() const85 PassScriptInstance HTMLPlugInElement::getInstance() const
86 {
87 Frame* frame = document()->frame();
88 if (!frame)
89 return 0;
90
91 // If the host dynamically turns off JavaScript (or Java) we will still return
92 // the cached allocated Bindings::Instance. Not supporting this edge-case is OK.
93 if (m_instance)
94 return m_instance;
95
96 if (Widget* widget = pluginWidget())
97 m_instance = frame->script()->createScriptInstanceForWidget(widget);
98
99 return m_instance;
100 }
101
pluginWidget() const102 Widget* HTMLPlugInElement::pluginWidget() const
103 {
104 if (m_inBeforeLoadEventHandler) {
105 // The plug-in hasn't loaded yet, and it makes no sense to try to load if beforeload handler happened to touch the plug-in element.
106 // That would recursively call beforeload for the same element.
107 return 0;
108 }
109
110 RenderWidget* renderWidget = renderWidgetForJSBindings();
111 if (!renderWidget)
112 return 0;
113
114 return renderWidget->widget();
115 }
116
mapToEntry(const QualifiedName & attrName,MappedAttributeEntry & result) const117 bool HTMLPlugInElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const
118 {
119 if (attrName == widthAttr ||
120 attrName == heightAttr ||
121 attrName == vspaceAttr ||
122 attrName == hspaceAttr) {
123 result = eUniversal;
124 return false;
125 }
126
127 if (attrName == alignAttr) {
128 result = eReplaced; // Share with <img> since the alignment behavior is the same.
129 return false;
130 }
131
132 return HTMLFrameOwnerElement::mapToEntry(attrName, result);
133 }
134
parseMappedAttribute(Attribute * attr)135 void HTMLPlugInElement::parseMappedAttribute(Attribute* attr)
136 {
137 if (attr->name() == widthAttr)
138 addCSSLength(attr, CSSPropertyWidth, attr->value());
139 else if (attr->name() == heightAttr)
140 addCSSLength(attr, CSSPropertyHeight, attr->value());
141 else if (attr->name() == vspaceAttr) {
142 addCSSLength(attr, CSSPropertyMarginTop, attr->value());
143 addCSSLength(attr, CSSPropertyMarginBottom, attr->value());
144 } else if (attr->name() == hspaceAttr) {
145 addCSSLength(attr, CSSPropertyMarginLeft, attr->value());
146 addCSSLength(attr, CSSPropertyMarginRight, attr->value());
147 } else if (attr->name() == alignAttr)
148 addHTMLAlignment(attr);
149 else
150 HTMLFrameOwnerElement::parseMappedAttribute(attr);
151 }
152
defaultEventHandler(Event * event)153 void HTMLPlugInElement::defaultEventHandler(Event* event)
154 {
155 // Firefox seems to use a fake event listener to dispatch events to plug-in (tested with mouse events only).
156 // This is observable via different order of events - in Firefox, event listeners specified in HTML attributes fires first, then an event
157 // gets dispatched to plug-in, and only then other event listeners fire. Hopefully, this difference does not matter in practice.
158
159 // FIXME: Mouse down and scroll events are passed down to plug-in via custom code in EventHandler; these code paths should be united.
160
161 RenderObject* r = renderer();
162 if (r && r->isEmbeddedObject() && toRenderEmbeddedObject(r)->showsMissingPluginIndicator()) {
163 toRenderEmbeddedObject(r)->handleMissingPluginIndicatorEvent(event);
164 return;
165 }
166
167 if (!r || !r->isWidget())
168 return;
169 RefPtr<Widget> widget = toRenderWidget(r)->widget();
170 if (!widget)
171 return;
172 widget->handleEvent(event);
173 }
174
175 #if ENABLE(NETSCAPE_PLUGIN_API)
176
getNPObject()177 NPObject* HTMLPlugInElement::getNPObject()
178 {
179 ASSERT(document()->frame());
180 if (!m_NPObject)
181 m_NPObject = document()->frame()->script()->createScriptObjectForPluginElement(this);
182 return m_NPObject;
183 }
184
185 #endif /* ENABLE(NETSCAPE_PLUGIN_API) */
186
187 #if PLATFORM(ANDROID)
supportsFocus() const188 bool HTMLPlugInElement::supportsFocus() const
189 {
190 return true;
191 }
192 #endif
193
194 }
195