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 "Settings.h"
39 #include "Widget.h"
40
41 #if ENABLE(NETSCAPE_PLUGIN_API)
42 #include "npruntime_impl.h"
43 #endif
44
45 namespace WebCore {
46
47 using namespace HTMLNames;
48
HTMLPlugInElement(const QualifiedName & tagName,Document * doc)49 HTMLPlugInElement::HTMLPlugInElement(const QualifiedName& tagName, Document* doc)
50 : HTMLFrameOwnerElement(tagName, doc)
51 , m_inBeforeLoadEventHandler(false)
52 #if ENABLE(NETSCAPE_PLUGIN_API)
53 , m_NPObject(0)
54 #endif
55 , m_isCapturingMouseEvents(false)
56 {
57 }
58
~HTMLPlugInElement()59 HTMLPlugInElement::~HTMLPlugInElement()
60 {
61 ASSERT(!m_instance); // cleared in detach()
62
63 #if ENABLE(NETSCAPE_PLUGIN_API)
64 if (m_NPObject) {
65 _NPN_ReleaseObject(m_NPObject);
66 m_NPObject = 0;
67 }
68 #endif
69 }
70
detach()71 void HTMLPlugInElement::detach()
72 {
73 m_instance.clear();
74
75 if (m_isCapturingMouseEvents) {
76 if (Frame* frame = document()->frame())
77 frame->eventHandler()->setCapturingMouseEventsNode(0);
78 m_isCapturingMouseEvents = false;
79 }
80
81 HTMLFrameOwnerElement::detach();
82 }
83
getInstance() const84 PassScriptInstance HTMLPlugInElement::getInstance() const
85 {
86 Frame* frame = document()->frame();
87 if (!frame)
88 return 0;
89
90 // If the host dynamically turns off JavaScript (or Java) we will still return
91 // the cached allocated Bindings::Instance. Not supporting this edge-case is OK.
92 if (m_instance)
93 return m_instance;
94
95 if (Widget* widget = pluginWidget())
96 m_instance = frame->script()->createScriptInstanceForWidget(widget);
97
98 return m_instance;
99 }
100
pluginWidget() const101 Widget* HTMLPlugInElement::pluginWidget() const
102 {
103 if (m_inBeforeLoadEventHandler) {
104 // 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.
105 // That would recursively call beforeload for the same element.
106 return 0;
107 }
108
109 RenderWidget* renderWidget = renderWidgetForJSBindings();
110 if (!renderWidget)
111 return 0;
112
113 return renderWidget->widget();
114 }
115
mapToEntry(const QualifiedName & attrName,MappedAttributeEntry & result) const116 bool HTMLPlugInElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const
117 {
118 if (attrName == widthAttr ||
119 attrName == heightAttr ||
120 attrName == vspaceAttr ||
121 attrName == hspaceAttr) {
122 result = eUniversal;
123 return false;
124 }
125
126 if (attrName == alignAttr) {
127 result = eReplaced; // Share with <img> since the alignment behavior is the same.
128 return false;
129 }
130
131 return HTMLFrameOwnerElement::mapToEntry(attrName, result);
132 }
133
parseMappedAttribute(Attribute * attr)134 void HTMLPlugInElement::parseMappedAttribute(Attribute* attr)
135 {
136 if (attr->name() == widthAttr)
137 addCSSLength(attr, CSSPropertyWidth, attr->value());
138 else if (attr->name() == heightAttr)
139 addCSSLength(attr, CSSPropertyHeight, attr->value());
140 else if (attr->name() == vspaceAttr) {
141 addCSSLength(attr, CSSPropertyMarginTop, attr->value());
142 addCSSLength(attr, CSSPropertyMarginBottom, attr->value());
143 } else if (attr->name() == hspaceAttr) {
144 addCSSLength(attr, CSSPropertyMarginLeft, attr->value());
145 addCSSLength(attr, CSSPropertyMarginRight, attr->value());
146 } else if (attr->name() == alignAttr)
147 addHTMLAlignment(attr);
148 else
149 HTMLFrameOwnerElement::parseMappedAttribute(attr);
150 }
151
defaultEventHandler(Event * event)152 void HTMLPlugInElement::defaultEventHandler(Event* event)
153 {
154 // Firefox seems to use a fake event listener to dispatch events to plug-in (tested with mouse events only).
155 // This is observable via different order of events - in Firefox, event listeners specified in HTML attributes fires first, then an event
156 // gets dispatched to plug-in, and only then other event listeners fire. Hopefully, this difference does not matter in practice.
157
158 // FIXME: Mouse down and scroll events are passed down to plug-in via custom code in EventHandler; these code paths should be united.
159
160 RenderObject* r = renderer();
161 if (r && r->isEmbeddedObject() && toRenderEmbeddedObject(r)->showsMissingPluginIndicator()) {
162 toRenderEmbeddedObject(r)->handleMissingPluginIndicatorEvent(event);
163 return;
164 }
165
166 if (!r || !r->isWidget())
167 return;
168 RefPtr<Widget> widget = toRenderWidget(r)->widget();
169 if (!widget)
170 return;
171 widget->handleEvent(event);
172 }
173
174 #if ENABLE(NETSCAPE_PLUGIN_API)
175
getNPObject()176 NPObject* HTMLPlugInElement::getNPObject()
177 {
178 ASSERT(document()->frame());
179 if (!m_NPObject)
180 m_NPObject = document()->frame()->script()->createScriptObjectForPluginElement(this);
181 return m_NPObject;
182 }
183
184 #endif /* ENABLE(NETSCAPE_PLUGIN_API) */
185
186 }
187