• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2     Copyright (C) 2009, 2010 Nokia Corporation and/or its subsidiary(-ies)
3 
4     This library is free software; you can redistribute it and/or
5     modify it under the terms of the GNU Library General Public
6     License as published by the Free Software Foundation; either
7     version 2 of the License, or (at your option) any later version.
8 
9     This library is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12     Library General Public License for more details.
13 
14     You should have received a copy of the GNU Library General Public License
15     along with this library; see the file COPYING.LIB.  If not, write to
16     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17     Boston, MA 02110-1301, USA.
18 */
19 #include "config.h"
20 #include "PluginView.h"
21 
22 #include "BridgeJSC.h"
23 #include "Document.h"
24 #include "DocumentLoader.h"
25 #include "Element.h"
26 #include "FocusController.h"
27 #include "Frame.h"
28 #include "FrameLoadRequest.h"
29 #include "FrameLoader.h"
30 #include "FrameTree.h"
31 #include "FrameView.h"
32 #include "GraphicsContext.h"
33 #include "HTMLNames.h"
34 #include "HTMLPlugInElement.h"
35 #include "HostWindow.h"
36 #include "Image.h"
37 #include "JSDOMBinding.h"
38 #include "KeyboardEvent.h"
39 #include "MouseEvent.h"
40 #include "NotImplemented.h"
41 #include "Page.h"
42 #include "PlatformKeyboardEvent.h"
43 #include "PlatformMouseEvent.h"
44 #include "PluginContainerSymbian.h"
45 #include "PluginDebug.h"
46 #include "PluginMainThreadScheduler.h"
47 #include "PluginPackage.h"
48 #include "QWebPageClient.h"
49 #include "RenderLayer.h"
50 #include "ScriptController.h"
51 #include "Settings.h"
52 #include "npfunctions.h"
53 #include "npinterface.h"
54 #include "npruntime_impl.h"
55 #include "qgraphicswebview.h"
56 #include "qwebframe.h"
57 #include "qwebframe_p.h"
58 #include "runtime_root.h"
59 #include <QGraphicsProxyWidget>
60 #include <QKeyEvent>
61 #include <QPixmap>
62 #include <QRegion>
63 #include <QVector>
64 #include <QWidget>
65 #include <runtime/JSLock.h>
66 #include <runtime/JSValue.h>
67 
68 typedef void (*_qtwebkit_page_plugin_created)(QWebFrame*, void*, void*); // frame, plugin instance, plugin functions
69 static _qtwebkit_page_plugin_created qtwebkit_page_plugin_created = 0;
qtwebkit_setPluginCreatedCallback(_qtwebkit_page_plugin_created cb)70 QWEBKIT_EXPORT void qtwebkit_setPluginCreatedCallback(_qtwebkit_page_plugin_created cb)
71 {
72     qtwebkit_page_plugin_created = cb;
73 }
74 
75 using JSC::ExecState;
76 using JSC::Interpreter;
77 using JSC::JSLock;
78 using JSC::JSObject;
79 using JSC::UString;
80 
81 using namespace std;
82 
83 using namespace WTF;
84 
85 namespace WebCore {
86 
87 using namespace HTMLNames;
88 
updatePluginWidget()89 void PluginView::updatePluginWidget()
90 {
91     if (!parent())
92         return;
93     ASSERT(parent()->isFrameView());
94     FrameView* frameView = static_cast<FrameView*>(parent());
95     IntRect oldWindowRect = m_windowRect;
96     IntRect oldClipRect = m_clipRect;
97 
98     m_windowRect = IntRect(frameView->contentsToWindow(frameRect().location()), frameRect().size());
99 
100     m_clipRect = windowClipRect();
101     m_clipRect.move(-m_windowRect.x(), -m_windowRect.y());
102     if (m_windowRect == oldWindowRect && m_clipRect == oldClipRect)
103         return;
104 
105     setNPWindowIfNeeded();
106 }
107 
setFocus(bool focused)108 void PluginView::setFocus(bool focused)
109 {
110     if (platformPluginWidget()) {
111         if (focused)
112             platformPluginWidget()->setFocus(Qt::OtherFocusReason);
113     } else {
114         Widget::setFocus(focused);
115     }
116 }
117 
show()118 void PluginView::show()
119 {
120     setSelfVisible(true);
121 
122     if (isParentVisible() && platformPluginWidget())
123         platformPluginWidget()->setVisible(true);
124 }
125 
hide()126 void PluginView::hide()
127 {
128     setSelfVisible(false);
129 
130     if (isParentVisible() && platformPluginWidget())
131         platformPluginWidget()->setVisible(false);
132 }
133 
paint(GraphicsContext * context,const IntRect & rect)134 void PluginView::paint(GraphicsContext* context, const IntRect& rect)
135 {
136     if (!m_isStarted) {
137         paintMissingPluginIcon(context, rect);
138         return;
139     }
140 
141     if (context->paintingDisabled())
142         return;
143     m_npWindow.ws_info = (void*)(context->platformContext());
144     setNPWindowIfNeeded();
145 
146     if (m_isWindowed && platformPluginWidget())
147         static_cast<PluginContainerSymbian*>(platformPluginWidget())->adjustGeometry();
148 
149     if (m_isWindowed)
150         return;
151 
152     context->save();
153     IntRect clipRect(rect);
154     clipRect.intersect(frameRect());
155     context->clip(clipRect);
156     context->translate(frameRect().location().x(), frameRect().location().y());
157 
158     QPaintEvent ev(rect);
159     QEvent& npEvent = ev;
160     dispatchNPEvent(npEvent);
161 
162     context->restore();
163 }
164 
165 // TODO: Unify across ports.
dispatchNPEvent(NPEvent & event)166 bool PluginView::dispatchNPEvent(NPEvent& event)
167 {
168     if (!m_plugin->pluginFuncs()->event)
169         return false;
170 
171     PluginView::setCurrentPluginView(this);
172     JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
173 
174     setCallingPlugin(true);
175     bool accepted = m_plugin->pluginFuncs()->event(m_instance, &event);
176     setCallingPlugin(false);
177     PluginView::setCurrentPluginView(0);
178 
179     return accepted;
180 }
181 
handleKeyboardEvent(KeyboardEvent * event)182 void PluginView::handleKeyboardEvent(KeyboardEvent* event)
183 {
184     if (m_isWindowed)
185         return;
186 
187     ASSERT(event->keyEvent()->qtEvent());
188     QEvent& npEvent = *(event->keyEvent()->qtEvent());
189     if (!dispatchNPEvent(npEvent))
190         event->setDefaultHandled();
191 }
192 
handleMouseEvent(MouseEvent * event)193 void PluginView::handleMouseEvent(MouseEvent* event)
194 {
195     if (m_isWindowed)
196         return;
197 
198     if (event->type() == eventNames().mousedownEvent) {
199         // Give focus to the plugin on click
200         if (Page* page = m_parentFrame->page())
201             page->focusController()->setActive(true);
202 
203         focusPluginElement();
204     }
205 
206     QEvent::Type type;
207     if (event->type() == eventNames().mousedownEvent)
208         type = QEvent::MouseButtonPress;
209     else if (event->type() == eventNames().mousemoveEvent)
210         type = QEvent::MouseMove;
211     else if (event->type() == eventNames().mouseupEvent)
212         type = QEvent::MouseButtonRelease;
213     else
214         return;
215 
216     QPoint position(event->offsetX(), event->offsetY());
217     Qt::MouseButton button;
218     switch (event->which()) {
219     case 1:
220         button = Qt::LeftButton;
221         break;
222     case 2:
223         button = Qt::MidButton;
224         break;
225     case 3:
226         button = Qt::RightButton;
227         break;
228     default:
229         button = Qt::NoButton;
230     }
231     Qt::KeyboardModifiers modifiers = 0;
232     if (event->ctrlKey())
233         modifiers |= Qt::ControlModifier;
234     if (event->altKey())
235         modifiers |= Qt::AltModifier;
236     if (event->shiftKey())
237         modifiers |= Qt::ShiftModifier;
238     if (event->metaKey())
239         modifiers |= Qt::MetaModifier;
240     QMouseEvent mouseEvent(type, position, button, button, modifiers);
241     QEvent& npEvent = mouseEvent;
242     if (!dispatchNPEvent(npEvent))
243         event->setDefaultHandled();
244 }
245 
setParent(ScrollView * parent)246 void PluginView::setParent(ScrollView* parent)
247 {
248     Widget::setParent(parent);
249 
250     if (parent) {
251         init();
252         if (m_status == PluginStatusLoadedSuccessfully)
253             updatePluginWidget();
254     }
255 }
256 
setNPWindowRect(const IntRect &)257 void PluginView::setNPWindowRect(const IntRect&)
258 {
259     if (!m_isWindowed)
260         setNPWindowIfNeeded();
261 }
262 
setNPWindowIfNeeded()263 void PluginView::setNPWindowIfNeeded()
264 {
265     if (!m_isStarted || !parent() || !m_plugin->pluginFuncs()->setwindow)
266         return;
267     if (m_isWindowed) {
268         ASSERT(platformPluginWidget());
269         platformPluginWidget()->setGeometry(m_windowRect);
270         // if setMask is set with an empty QRegion, no clipping will
271         // be performed, so in that case we hide the plugin view
272         platformPluginWidget()->setVisible(!m_clipRect.isEmpty());
273         platformPluginWidget()->setMask(QRegion(m_clipRect));
274 
275         m_npWindow.x = m_windowRect.x();
276         m_npWindow.y = m_windowRect.y();
277 
278         m_npWindow.clipRect.left = max(0, m_clipRect.x());
279         m_npWindow.clipRect.top = max(0, m_clipRect.y());
280         m_npWindow.clipRect.right = m_clipRect.x() + m_clipRect.width();
281         m_npWindow.clipRect.bottom = m_clipRect.y() + m_clipRect.height();
282 
283     } else {
284         // always call this method before painting.
285         m_npWindow.x = m_windowRect.x();
286         m_npWindow.y = m_windowRect.y();
287 
288         m_npWindow.clipRect.left = 0;
289         m_npWindow.clipRect.top = 0;
290         m_npWindow.clipRect.right = m_windowRect.width();
291         m_npWindow.clipRect.bottom = m_windowRect.height();
292         m_npWindow.window = 0;
293     }
294 
295     m_npWindow.width = m_windowRect.width();
296     m_npWindow.height = m_windowRect.height();
297 
298     PluginView::setCurrentPluginView(this);
299     JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
300     setCallingPlugin(true);
301     m_plugin->pluginFuncs()->setwindow(m_instance, &m_npWindow);
302     setCallingPlugin(false);
303     PluginView::setCurrentPluginView(0);
304 }
305 
setParentVisible(bool visible)306 void PluginView::setParentVisible(bool visible)
307 {
308     if (isParentVisible() == visible)
309         return;
310 
311     Widget::setParentVisible(visible);
312 
313     if (isSelfVisible() && platformPluginWidget())
314         platformPluginWidget()->setVisible(visible);
315 }
316 
handlePostReadFile(Vector<char> & buffer,uint32_t len,const char * buf)317 NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32_t len, const char* buf)
318 {
319     notImplemented();
320     return NPERR_NO_ERROR;
321 }
322 
platformGetValueStatic(NPNVariable variable,void * value,NPError * result)323 bool PluginView::platformGetValueStatic(NPNVariable variable, void* value, NPError* result)
324 {
325     switch (variable) {
326     case NPNVjavascriptEnabledBool:
327         *static_cast<NPBool*>(value) = true;
328         *result = NPERR_NO_ERROR;
329         return true;
330 
331     case NPNVSupportsWindowless:
332         *static_cast<NPBool*>(value) = true;
333         *result = NPERR_NO_ERROR;
334         return true;
335 
336     default:
337         return false;
338     }
339 }
340 
platformGetValue(NPNVariable,void *,NPError *)341 bool PluginView::platformGetValue(NPNVariable, void*, NPError*)
342 {
343     return false;
344 }
345 
invalidateRect(const IntRect & rect)346 void PluginView::invalidateRect(const IntRect& rect)
347 {
348     if (m_isWindowed) {
349         platformWidget()->update(rect);
350         return;
351     }
352 
353     invalidateWindowlessPluginRect(rect);
354 }
355 
invalidateRect(NPRect * rect)356 void PluginView::invalidateRect(NPRect* rect)
357 {
358     if (m_isWindowed)
359         return;
360     if (!rect) {
361         invalidate();
362         return;
363     }
364     IntRect r(rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top);
365     m_invalidRects.append(r);
366     if (!m_invalidateTimer.isActive())
367         m_invalidateTimer.startOneShot(0.001);
368 }
369 
invalidateRegion(NPRegion region)370 void PluginView::invalidateRegion(NPRegion region)
371 {
372     if (m_isWindowed)
373         return;
374 
375     if (!region)
376         return;
377 
378     QVector<QRect> rects = region->rects();
379     for (int i = 0; i < rects.size(); ++i) {
380         const QRect& qRect = rects.at(i);
381         m_invalidRects.append(qRect);
382         if (!m_invalidateTimer.isActive())
383             m_invalidateTimer.startOneShot(0.001);
384     }
385 }
386 
forceRedraw()387 void PluginView::forceRedraw()
388 {
389     if (m_isWindowed)
390         return;
391     invalidate();
392 }
393 
platformStart()394 bool PluginView::platformStart()
395 {
396     ASSERT(m_isStarted);
397     ASSERT(m_status == PluginStatusLoadedSuccessfully);
398 
399     show();
400 
401     if (m_isWindowed) {
402         QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient();
403         QGraphicsProxyWidget* proxy = 0;
404         if (QGraphicsWebView *webView = qobject_cast<QGraphicsWebView*>(client->pluginParent()))
405             proxy = new QGraphicsProxyWidget(webView);
406 
407         PluginContainerSymbian* container = new PluginContainerSymbian(this, proxy ? 0 : client->ownerWidget(), proxy);
408         setPlatformWidget(container);
409         if (proxy)
410             proxy->setWidget(container);
411 
412         m_npWindow.type = NPWindowTypeWindow;
413         m_npWindow.window = (void*)platformPluginWidget();
414 
415     } else {
416         setPlatformWidget(0);
417         m_npWindow.type = NPWindowTypeDrawable;
418         m_npWindow.window = 0; // Not used?
419     }
420     updatePluginWidget();
421     setNPWindowIfNeeded();
422 
423     if (qtwebkit_page_plugin_created)
424         qtwebkit_page_plugin_created(QWebFramePrivate::kit(m_parentFrame.get()), m_instance, (void*)(m_plugin->pluginFuncs()));
425 
426     return true;
427 }
428 
platformDestroy()429 void PluginView::platformDestroy()
430 {
431     if (platformPluginWidget()) {
432         PluginContainerSymbian* container = static_cast<PluginContainerSymbian*>(platformPluginWidget());
433         if (container && container->proxy())
434             delete container->proxy();
435         else
436             delete container;
437     }
438 }
439 
halt()440 void PluginView::halt()
441 {
442 }
443 
restart()444 void PluginView::restart()
445 {
446 }
447 
448 } // namespace WebCore
449