[BlackBerry] Remove skia code from PluginViewBlackBerry
[WebKit-https.git] / Source / WebCore / plugins / blackberry / PluginViewBlackBerry.cpp
1 /*
2  * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
3  * Copyright (C) 2008 Collabora Ltd. All rights reserved.
4  * Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in>
5  * Copyright (C) 2011 Research In Motion Limited. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
27  */
28
29 #include "config.h"
30 #include "PluginView.h"
31
32 #include "DocumentLoader.h"
33 #include "Event.h"
34 #include "EventNames.h"
35 #include "Frame.h"
36 #include "FrameView.h"
37 #include "HTMLNames.h"
38 #include "HTMLPlugInElement.h"
39 #include "HostWindow.h"
40 #include "JSDOMBinding.h"
41 #include "KeyboardEvent.h"
42 #include "MouseEvent.h"
43 #include "NPCallbacksBlackBerry.h"
44 #include "NotImplemented.h"
45 #include "Page.h"
46 #include "PlatformKeyboardEvent.h"
47 #include "PluginDebug.h"
48 #include "PluginMainThreadScheduler.h"
49 #include "PluginPackage.h"
50 #include "PluginViewPrivateBlackBerry.h"
51 #include "RenderLayer.h"
52 #include "Settings.h"
53 #include "TouchEvent.h"
54 #include "TouchList.h"
55 #include "WheelEvent.h"
56 #include "npruntime_impl.h"
57 #include "runtime_root.h"
58
59 #if USE(ACCELERATED_COMPOSITING)
60 #include "Chrome.h"
61 #include "ChromeClient.h"
62 #include "PluginLayerWebKitThread.h"
63 #endif
64
65 #include <BlackBerryPlatformGraphics.h>
66 #include <BlackBerryPlatformIntRectRegion.h>
67 #include <BlackBerryPlatformWindow.h>
68
69 #include <runtime/JSCJSValue.h>
70 #include <runtime/JSLock.h>
71 #include <sys/keycodes.h>
72 #include <vector>
73
74 const unsigned UninitializedCoordinate = 0xffffffff;
75
76 namespace WebCore {
77
78 template<class T> static NPRect toNPRect(const T& rect)
79 {
80     NPRect npRect;
81     npRect.top = rect.y();
82     npRect.left = rect.x();
83     npRect.bottom = rect.y() + rect.height();
84     npRect.right = rect.x() + rect.width();
85     return npRect;
86 }
87
88 using JSC::ExecState;
89 using JSC::Interpreter;
90 using JSC::JSLock;
91 using JSC::JSObject;
92
93 using namespace std;
94 using namespace WTF;
95 using namespace HTMLNames;
96
97 void PluginView::updatePluginWidget()
98 {
99     if (!parent() || !m_private)
100         return;
101
102     ASSERT(parent()->isFrameView());
103     FrameView* frameView = toFrameView(parent());
104
105     IntRect oldWindowRect = m_windowRect;
106     IntRect oldClipRect = m_clipRect;
107
108     m_windowRect = IntRect(frameView->contentsToWindow(frameRect().location()), frameRect().size());
109
110     ScrollView* theRoot = root();
111     if (!theRoot)
112         return; // ASSERT(parent()->isFrameView()) should prevent this but check just in case
113     // Map rect to content coordinate space of main frame.
114     m_windowRect.move(theRoot->scrollOffset());
115
116     m_clipRect = calculateClipRect();
117
118     // Notify the plugin if it may or may not be on/offscreen.
119     handleScrollEvent();
120
121     bool zoomFactorChanged = ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->zoomFactor
122         != frameView->hostWindow()->platformPageClient()->currentZoomFactor();
123
124     if (!zoomFactorChanged && m_windowRect == oldWindowRect && m_clipRect == oldClipRect)
125         return;
126
127     // Do not call setNPWindowIfNeeded immediately, will be called on paint().
128     m_private->m_hasPendingGeometryChange = true;
129
130     // (i) In order to move/resize the plugin window at the same time as the
131     // rest of frame during e.g. scrolling, we set the window geometry
132     // in the paint() function, but as paint() isn't called when the
133     // plugin window is outside the frame which can be caused by a
134     // scroll, we need to move/resize immediately.
135     // (ii) If we are running layout tests from DRT, paint() won't ever get called
136     // so we need to call setNPWindowIfNeeded() if window geometry has changed.
137     if (m_clipRect.isEmpty() || (platformPluginWidget() && (m_windowRect != oldWindowRect || m_clipRect != oldClipRect || zoomFactorChanged)))
138         setNPWindowIfNeeded();
139
140     // Make sure we get repainted afterwards. This is necessary for downward
141     // scrolling to move the plugin widget properly.
142     invalidate();
143 }
144
145 void PluginView::setFocus(bool focused)
146 {
147     if (!m_private || m_private->m_isFocused == focused)
148         return;
149
150     ASSERT(platformPluginWidget() == platformWidget());
151     Widget::setFocus(focused);
152
153     if (focused)
154         handleFocusInEvent();
155     else
156         handleFocusOutEvent();
157 }
158
159 void PluginView::show()
160 {
161     setSelfVisible(true);
162     Widget::show();
163     updatePluginWidget();
164 }
165
166 void PluginView::hide()
167 {
168     setSelfVisible(false);
169     Widget::hide();
170     updatePluginWidget();
171 }
172
173 void PluginView::updateBuffer(const IntRect& bufferRect)
174 {
175     if (!m_private)
176         return;
177
178     // Update the zoom factor here, it happens right before setNPWindowIfNeeded
179     // ensuring that the plugin has every opportunity to get the zoom factor before
180     // it paints anything.
181     if (FrameView* frameView = toFrameView(parent()))
182         m_private->setZoomFactor(frameView->hostWindow()->platformPageClient()->currentZoomFactor());
183
184     setNPWindowIfNeeded();
185
186     // Build and dispatch an event to the plugin to notify it we are about to draw whatever
187     // is in the front buffer. This is it's opportunity to do a swap.
188     IntRect exposedRect(bufferRect);
189     exposedRect.intersect(IntRect(IntPoint(0, 0), frameRect().size()));
190
191     // Only ask the plugin to draw if the exposed rect was explicitly invalidated
192     // by the plugin.
193     BlackBerry::Platform::IntRectRegion exposedRegion = BlackBerry::Platform::IntRectRegion::intersectRegions(m_private->m_invalidateRegion, BlackBerry::Platform::IntRect(exposedRect));
194     if (!exposedRegion.isEmpty()) {
195         m_private->m_invalidateRegion = BlackBerry::Platform::IntRectRegion::subtractRegions(m_private->m_invalidateRegion, exposedRegion);
196         std::vector<BlackBerry::Platform::IntRect> exposedRects = exposedRegion.rects();
197         for (unsigned i = 0; i < exposedRects.size(); ++i) {
198             NPDrawEvent draw;
199             NPRect tempRect = toNPRect(exposedRects.at(i));
200             draw.pluginRect = toNPRect(m_windowRect);
201             draw.clipRect = toNPRect(m_clipRect);
202             draw.drawRect = &tempRect;
203             draw.drawRectCount = 1;
204             draw.zoomFactor = ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->zoomFactor;
205
206             NPEvent npEvent;
207             npEvent.type = NP_DrawEvent;
208             npEvent.data = &draw;
209
210             // FIXME: Return early if this fails? Or just repaint?
211             dispatchNPEvent(npEvent);
212         }
213     }
214 }
215
216 void PluginView::paint(GraphicsContext* context, const IntRect& rect)
217 {
218     if (!m_private || !m_isStarted) {
219         paintMissingPluginIcon(context, rect);
220         return;
221     }
222
223     // Update the zoom factor here, it happens right before setNPWindowIfNeeded
224     // ensuring that the plugin has every opportunity to get the zoom factor before
225     // it paints anything.
226     if (FrameView* frameView = toFrameView(parent()))
227         m_private->setZoomFactor(frameView->hostWindow()->platformPageClient()->currentZoomFactor());
228
229     if (context->paintingDisabled())
230         return;
231
232     setNPWindowIfNeeded();
233
234 #if USE(ACCELERATED_COMPOSITING)
235     if (m_private->m_platformLayer)
236         return;
237 #endif
238
239     // Build and dispatch an event to the plugin to notify it we are about to draw whatever
240     // is in the front buffer. This is it's opportunity to do a swap.
241     IntRect rectClip(rect);
242     rectClip.intersect(frameRect());
243
244     IntRect exposedRect(rectClip);
245     exposedRect.move(-frameRect().x(), -frameRect().y());
246
247     updateBuffer(exposedRect);
248 }
249
250
251 bool PluginView::dispatchFullScreenNPEvent(NPEvent& event)
252 {
253     if (!m_private)
254         return false;
255
256     ASSERT(m_private->m_isFullScreen);
257     return dispatchNPEvent(event);
258 }
259
260 // FIXME: Unify across ports.
261 bool PluginView::dispatchNPEvent(NPEvent& event)
262 {
263     if (!m_plugin || !m_plugin->pluginFuncs()->event)
264         return false;
265
266     PluginView::setCurrentPluginView(this);
267     JSC::JSLock::DropAllLocks dropAllLocks(JSDOMWindowBase::commonJSGlobalData());
268     setCallingPlugin(true);
269
270     bool accepted = m_plugin->pluginFuncs()->event(m_instance, &event);
271
272     setCallingPlugin(false);
273     PluginView::setCurrentPluginView(0);
274
275     return accepted;
276 }
277
278 void PluginView::handleKeyboardEvent(KeyboardEvent* event)
279 {
280     NPEvent npEvent;
281     NPKeyboardEvent keyEvent;
282     const PlatformKeyboardEvent *platformKeyEvent = event->keyEvent();
283
284     keyEvent.modifiers = 0;
285
286     if (platformKeyEvent->shiftKey())
287         keyEvent.modifiers |= KEYMOD_SHIFT;
288
289     if (platformKeyEvent->ctrlKey())
290         keyEvent.modifiers |= KEYMOD_CTRL;
291
292     if (platformKeyEvent->altKey())
293         keyEvent.modifiers |= KEYMOD_ALT;
294
295     if (platformKeyEvent->metaKey())
296         keyEvent.modifiers |= KEYMOD_ALTGR;
297
298     keyEvent.cap = platformKeyEvent->unmodifiedCharacter();
299     keyEvent.sym = keyEvent.cap;
300     keyEvent.scan = 0;
301     keyEvent.flags = 0;
302
303     if (platformKeyEvent->type() == PlatformKeyboardEvent::RawKeyDown
304         || platformKeyEvent->type() == PlatformKeyboardEvent::KeyDown) {
305         keyEvent.flags = KEY_DOWN | KEY_SYM_VALID | KEY_CAP_VALID;
306     } else if (platformKeyEvent->type() == PlatformKeyboardEvent::KeyUp)
307         keyEvent.flags = KEY_SYM_VALID | KEY_CAP_VALID;
308
309     npEvent.type = NP_KeyEvent;
310     npEvent.data = &keyEvent;
311     if (dispatchNPEvent(npEvent))
312         event->setDefaultHandled();
313 }
314
315 void PluginView::handleWheelEvent(WheelEvent* event)
316 {
317     if (!m_private)
318         return;
319
320     if (!m_private->m_isFocused)
321         focusPluginElement();
322
323     NPEvent npEvent;
324     NPWheelEvent wheelEvent;
325
326     wheelEvent.x = event->offsetX();
327     wheelEvent.y = event->offsetY();
328
329     wheelEvent.flags = 0;
330
331     wheelEvent.xDelta = event->rawDeltaX();
332     wheelEvent.yDelta = event->rawDeltaY();
333
334     npEvent.type = NP_WheelEvent;
335     npEvent.data = &wheelEvent;
336
337     if (dispatchNPEvent(npEvent))
338         event->setDefaultHandled();
339 }
340
341 void PluginView::handleTouchEvent(TouchEvent* event)
342 {
343     if (!m_private)
344         return;
345
346     if (!m_private->m_isFocused)
347         focusPluginElement();
348
349     NPTouchEvent npTouchEvent;
350
351     if (event->isDoubleTap())
352         npTouchEvent.type = TOUCH_EVENT_DOUBLETAP;
353     else if (event->isTouchHold())
354         npTouchEvent.type = TOUCH_EVENT_TOUCHHOLD;
355     else if (event->type() == eventNames().touchcancelEvent)
356         npTouchEvent.type = TOUCH_EVENT_CANCEL;
357     else
358         return;
359
360     TouchList* touchList;
361     // The touches list is empty if in a touch end event.
362     // Since DoubleTap is ususally a TouchEnd Use changedTouches instead.
363     if (npTouchEvent.type == TOUCH_EVENT_DOUBLETAP)
364         touchList = event->changedTouches();
365     else
366         touchList = event->touches();
367
368     npTouchEvent.points = 0;
369     npTouchEvent.size = touchList->length();
370
371     OwnArrayPtr<NPTouchPoint> touchPoints;
372     if (touchList->length()) {
373         touchPoints = adoptArrayPtr(new NPTouchPoint[touchList->length()]);
374         npTouchEvent.points = touchPoints.get();
375         for (unsigned i = 0; i < touchList->length(); i++) {
376             Touch* touchItem = touchList->item(i);
377             touchPoints[i].touchId = touchItem->identifier();
378             touchPoints[i].clientX = touchItem->pageX() - frameRect().x();
379             touchPoints[i].clientY = touchItem->pageY() - frameRect().y();
380             touchPoints[i].screenX = touchItem->screenX();
381             touchPoints[i].screenY = touchItem->screenY();
382             touchPoints[i].pageX = touchItem->pageX();
383             touchPoints[i].pageY = touchItem->pageY();
384
385         }
386     }
387
388     NPEvent npEvent;
389     npEvent.type = NP_TouchEvent;
390     npEvent.data = &npTouchEvent;
391
392     if (dispatchNPEvent(npEvent))
393         event->setDefaultHandled();
394 }
395
396 void PluginView::handleMouseEvent(MouseEvent* event)
397 {
398     if (!m_private)
399         return;
400
401     if (!m_private->m_isFocused)
402         focusPluginElement();
403
404     NPEvent npEvent;
405     NPMouseEvent mouseEvent;
406
407     mouseEvent.x = event->offsetX();
408     mouseEvent.y = event->offsetY();
409
410     if (event->type() == eventNames().mousedownEvent)
411         mouseEvent.type = MOUSE_BUTTON_DOWN;
412     else if (event->type() == eventNames().mousemoveEvent)
413         mouseEvent.type = MOUSE_MOTION;
414     else if (event->type() == eventNames().mouseoutEvent)
415         mouseEvent.type = MOUSE_OUTBOUND;
416     else if (event->type() == eventNames().mouseoverEvent)
417         mouseEvent.type = MOUSE_OVER;
418     else if (event->type() == eventNames().mouseupEvent)
419         mouseEvent.type = MOUSE_BUTTON_UP;
420     else
421         return;
422
423     mouseEvent.button = event->button();
424     mouseEvent.flags = 0;
425
426     npEvent.type = NP_MouseEvent;
427     npEvent.data = &mouseEvent;
428
429     if (dispatchNPEvent(npEvent))
430         event->setDefaultHandled();
431 }
432
433 void PluginView::handleFocusInEvent()
434 {
435     if (!m_private)
436         return;
437
438     if (m_private->m_isFocused)
439         return;
440
441     m_private->m_isFocused = true;
442
443     NPEvent npEvent;
444     npEvent.type = NP_FocusGainedEvent;
445     npEvent.data = 0;
446     dispatchNPEvent(npEvent);
447 }
448
449 void PluginView::handleFocusOutEvent()
450 {
451     if (!m_private)
452         return;
453
454     if (!m_private->m_isFocused)
455         return;
456
457     m_private->m_isFocused = false;
458
459     NPEvent npEvent;
460     npEvent.type = NP_FocusLostEvent;
461     npEvent.data = 0;
462     dispatchNPEvent(npEvent);
463 }
464
465 void PluginView::handlePauseEvent()
466 {
467     NPEvent npEvent;
468     npEvent.type = NP_PauseEvent;
469     npEvent.data = 0;
470     dispatchNPEvent(npEvent);
471 }
472
473 void PluginView::handleResumeEvent()
474 {
475     NPEvent npEvent;
476     npEvent.type = NP_ResumeEvent;
477     npEvent.data = 0;
478     dispatchNPEvent(npEvent);
479 }
480
481 void PluginView::handleScrollEvent()
482 {
483     FrameView* frameView = toFrameView(parent());
484
485     // As a special case, if the frameView extent in either dimension is
486     // empty, then send an on screen event. This is important for sites like
487     // picnik.com which use a hidden iframe (read: width = 0 and height = 0)
488     // with an embedded swf to execute some javascript. Unless we send an
489     // on screen event the swf will not execute the javascript and the real
490     // site will never load.
491     bool onScreenEvent = frameView && (!frameView->width() || !frameView->height());
492
493     NPEvent npEvent;
494     npEvent.type = m_clipRect.isEmpty() && !onScreenEvent ? NP_OffScreenEvent : NP_OnScreenEvent;
495     npEvent.data = 0;
496     dispatchNPEvent(npEvent);
497 }
498
499 IntRect PluginView::calculateClipRect() const
500 {
501     FrameView* frameView = toFrameView(parent());
502     bool visible = frameView && isVisible();
503
504     if (visible && frameView->width() && frameView->height()) {
505         IntSize windowSize = frameView->hostWindow()->platformPageClient()->viewportSize();
506
507         // Get the clipped rectangle for this player within the current frame.
508         IntRect visibleContentRect;
509         IntRect contentRect = m_element->renderer()->absoluteClippedOverflowRect();
510         FloatPoint contentLocal = m_element->renderer()->absoluteToLocal(FloatPoint(contentRect.location()));
511
512         contentRect.setLocation(roundedIntPoint(contentLocal));
513         contentRect.move(frameRect().x(), frameRect().y());
514
515         // Clip against any frames that the widget is inside. Note that if the frames are also clipped
516         // by a div, that will not be included in this calculation. That is an improvement that still
517         // needs to be made.
518         const Widget* current = this;
519         while (current->parent() && visible) {
520             // Determine if it is visible in this scrollview.
521             visibleContentRect = current->parent()->visibleContentRect();
522
523             // Special case for the root ScrollView. Its size does not match the actual window size.
524             if (current->parent() == root())
525                 visibleContentRect.setSize(windowSize);
526
527             contentRect.intersect(visibleContentRect);
528             visible = !contentRect.isEmpty();
529
530             // Offset to visible coordinates in scrollview widget's coordinate system (except in the case of
531             // the top scroll view).
532             if (current->parent()->parent())
533                 contentRect.move(-visibleContentRect.x(), -visibleContentRect.y());
534
535             current = current->parent();
536
537             // Don't include the offset for the root window or we get the wrong coordinates.
538             if (current->parent()) {
539                 // Move content rect into the parent scrollview's coordinates.
540                 IntRect curFrameRect = current->frameRect();
541                 contentRect.move(curFrameRect.x(), curFrameRect.y());
542             }
543         }
544
545         return contentRect;
546     }
547
548     return IntRect();
549 }
550
551 void PluginView::handleOnLoadEvent()
552 {
553     if (!m_private)
554         return;
555
556     if (m_private->m_sentOnLoad)
557         return;
558
559     m_private->m_sentOnLoad = true;
560
561     NPEvent npEvent;
562     npEvent.type = NP_OnLoadEvent;
563     npEvent.data = 0;
564
565     dispatchNPEvent(npEvent);
566
567     // Send an initial OnScreen/OffScreen event. It must always come after onLoad is sent.
568     handleScrollEvent();
569 }
570
571 void PluginView::handleFreeMemoryEvent()
572 {
573     NPEvent npEvent;
574     npEvent.type = NP_FreeMemoryEvent;
575     npEvent.data = 0;
576
577     dispatchNPEvent(npEvent);
578 }
579
580 void PluginView::handleBackgroundEvent()
581 {
582     NPEvent npEvent;
583     npEvent.type = NP_BackgroundEvent;
584     npEvent.data = 0;
585
586     dispatchNPEvent(npEvent);
587 }
588
589 void PluginView::handleForegroundEvent()
590 {
591     setNPWindowIfNeeded();
592
593     NPEvent npEvent;
594     npEvent.type = NP_ForegroundEvent;
595     npEvent.data = 0;
596
597     dispatchNPEvent(npEvent);
598 }
599
600 void PluginView::handleFullScreenAllowedEvent()
601 {
602     if (!m_private)
603         return;
604
605     NPEvent npEvent;
606     npEvent.type = NP_FullScreenReadyEvent;
607     npEvent.data = 0;
608
609     if (FrameView* frameView = toFrameView(parent())) {
610         frameView->hostWindow()->platformPageClient()->didPluginEnterFullScreen(this, m_private->m_pluginUniquePrefix.c_str());
611
612         if (!dispatchNPEvent(npEvent))
613             frameView->hostWindow()->platformPageClient()->didPluginExitFullScreen(this, m_private->m_pluginUniquePrefix.c_str());
614         else
615             m_private->m_isFullScreen = true;
616     }
617 }
618
619 void PluginView::handleFullScreenExitEvent()
620 {
621     if (!m_private)
622         return;
623
624     NPEvent npEvent;
625     npEvent.type = NP_FullScreenExitEvent;
626     npEvent.data = 0;
627
628     dispatchNPEvent(npEvent);
629
630     if (FrameView* frameView = toFrameView(parent()))
631         frameView->hostWindow()->platformPageClient()->didPluginExitFullScreen(this, m_private->m_pluginUniquePrefix.c_str());
632
633     m_private->m_isFullScreen = false;
634     invalidate();
635 }
636
637 void PluginView::handleIdleEvent(bool enterIdle)
638 {
639     NPEvent npEvent;
640     npEvent.data = 0;
641
642     if (enterIdle)
643         npEvent.type = NP_EnterIdleEvent;
644     else
645         npEvent.type = NP_ExitIdleEvent;
646
647     dispatchNPEvent(npEvent);
648 }
649
650
651 void PluginView::handleAppActivatedEvent()
652 {
653     NPEvent npEvent;
654     npEvent.data = 0;
655     npEvent.type = NP_AppActivatedEvent;
656
657     dispatchNPEvent(npEvent);
658 }
659
660 void PluginView::handleAppDeactivatedEvent()
661 {
662     if (!m_private)
663         return;
664
665     // Plugin wants to know that it has to exit fullscreen on deactivation.
666     if (m_private->m_isFullScreen)
667         handleFullScreenExitEvent();
668
669     NPEvent npEvent;
670     npEvent.data = 0;
671     npEvent.type = NP_AppDeactivatedEvent;
672
673     dispatchNPEvent(npEvent);
674 }
675
676 void PluginView::handleAppStandbyEvent()
677 {
678     // FIXME: This should send an QNP_AppStandbyEvent
679     NPEvent npEvent;
680     npEvent.data = 0;
681     npEvent.type = NP_AppStandByEvent;
682
683     dispatchNPEvent(npEvent);
684 }
685
686 void PluginView::handleOrientationEvent(int angle)
687 {
688     NPEvent npEvent;
689     npEvent.type = NP_OrientationEvent;
690     npEvent.data = (void*)angle;
691
692     dispatchNPEvent(npEvent);
693 }
694
695 void PluginView::handleSwipeEvent()
696 {
697     if (!m_private)
698         return;
699
700     // Plugin only wants to know that it has to exit fullscreen.
701     if (m_private->m_isFullScreen)
702         handleFullScreenExitEvent();
703 }
704
705 void PluginView::handleScreenPowerEvent(bool powered)
706 {
707     NPEvent npEvent;
708     npEvent.data = 0;
709
710     if (powered)
711         npEvent.type = NP_ScreenPowerUpEvent;
712     else
713         npEvent.type = NP_ScreenPowerDownEvent;
714
715     dispatchNPEvent(npEvent);
716 }
717
718 void PluginView::setParent(ScrollView* parentWidget)
719 {
720     // If parentWidget is 0, lets unregister the plugin with the current parent.
721     if (m_private && (!parentWidget || parentWidget != parent())) {
722         if (FrameView* frameView = toFrameView(parent())) {
723             if (m_private->m_isBackgroundPlaying)
724                 frameView->hostWindow()->platformPageClient()->onPluginStopBackgroundPlay(this, m_private->m_pluginUniquePrefix.c_str());
725
726             if (m_private->m_isFullScreen)
727                 handleFullScreenExitEvent();
728
729             // This will unlock the idle (if we have locked it).
730             m_private->preventIdle(false);
731
732             // This will release any keepVisibleRects if they were set.
733             m_private->clearVisibleRects();
734
735 #if USE(ACCELERATED_COMPOSITING)
736             // If we had a hole punch rect set, clear it.
737             if (m_private->m_platformLayer && !m_private->m_holePunchRect.isEmpty())
738                 m_private->m_platformLayer->setHolePunchRect(IntRect());
739 #endif
740             frameView->hostWindow()->platformPageClient()->registerPlugin(this, false /*shouldRegister*/);
741         }
742     }
743
744     Widget::setParent(parentWidget);
745
746     if (parentWidget) {
747         init();
748
749         FrameView* frameView = toFrameView(parentWidget);
750
751         if (frameView && m_private) {
752             frameView->hostWindow()->platformPageClient()->registerPlugin(this, true /*shouldRegister*/);
753             if (frameView->frame()
754                && frameView->frame()->loader()
755                && frameView->frame()->loader()->frameHasLoaded())
756                 handleOnLoadEvent();
757
758             if (m_private->m_isBackgroundPlaying)
759                 frameView->hostWindow()->platformPageClient()->onPluginStartBackgroundPlay(this, m_private->m_pluginUniquePrefix.c_str());
760         }
761     }
762 }
763
764 void PluginView::setNPWindowRect(const IntRect&)
765 {
766     setNPWindowIfNeeded();
767 }
768
769 void PluginView::setNPWindowIfNeeded()
770 {
771     if (!m_private || !m_isStarted || !parent() || !m_plugin->pluginFuncs()->setwindow)
772         return;
773
774     FrameView* frameView = toFrameView(parent());
775     if (!frameView->hostWindow()->platformPageClient()->isActive())
776         return;
777
778     // If the plugin didn't load sucessfully, no point in calling setwindow
779     if (m_status != PluginStatusLoadedSuccessfully)
780         return;
781
782     if (m_private->m_isFullScreen)
783         return;
784
785     if (!m_private->m_hasPendingGeometryChange)
786         return;
787
788     m_private->m_hasPendingGeometryChange = false;
789
790     m_npWindow.x = m_windowRect.x();
791     m_npWindow.y = m_windowRect.y();
792
793     m_npWindow.clipRect.left = max(0, m_clipRect.x());
794     m_npWindow.clipRect.top = max(0, m_clipRect.y());
795     m_npWindow.clipRect.right = max(0, m_clipRect.maxX());
796     m_npWindow.clipRect.bottom = max(0, m_clipRect.maxY());
797
798     if (m_plugin->quirks().contains(PluginQuirkDontCallSetWindowMoreThanOnce)) {
799         // Only set the width and height of the plugin content the first time setNPWindow() is called
800         // so as to workaround an issue in Flash where multiple calls to setNPWindow() cause the plugin
801         // to crash in windowed mode.
802         if (!m_isWindowed || m_npWindow.width == UninitializedCoordinate || m_npWindow.height == UninitializedCoordinate) {
803             m_npWindow.width = m_windowRect.width();
804             m_npWindow.height = m_windowRect.height();
805         }
806     } else {
807         m_npWindow.width = m_windowRect.width();
808         m_npWindow.height = m_windowRect.height();
809     }
810
811     m_npWindow.type = NPWindowTypeDrawable;
812
813     BlackBerry::Platform::Graphics::Window* window = frameView->hostWindow()->platformPageClient()->platformWindow();
814     if (window)
815         ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->windowGroup = window->windowGroup();
816
817     PluginView::setCurrentPluginView(this);
818     JSC::JSLock::DropAllLocks dropAllLocks(JSDOMWindowBase::commonJSGlobalData());
819     setCallingPlugin(true);
820
821     // FIXME: Passing zoomFactor to setwindow make windowed plugin scale incorrectly.
822     // Handling the zoom factor properly in the plugin side may be a better solution.
823     double oldZoomFactor = ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->zoomFactor;
824     ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->zoomFactor = 1.;
825     m_plugin->pluginFuncs()->setwindow(m_instance, &m_npWindow);
826     ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->zoomFactor = oldZoomFactor;
827
828     setCallingPlugin(false);
829     PluginView::setCurrentPluginView(0);
830 }
831
832 void PluginView::setParentVisible(bool visible)
833 {
834     if (isParentVisible() == visible)
835         return;
836
837     Widget::setParentVisible(visible);
838
839     // FIXME: We might want to tell the plugin to hide it's window here, but it doesn't matter
840     // since the window manager should take care of that for us.
841 }
842
843 NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32_t len, const char* buf)
844 {
845     String filename(buf, len);
846
847     if (filename.startsWith("file:///"))
848         filename = filename.substring(8);
849
850     long long size;
851     if (!getFileSize(filename, size))
852         return NPERR_FILE_NOT_FOUND;
853
854     FILE* fileHandle = fopen(filename.utf8().data(), "r");
855     if (!fileHandle)
856         return NPERR_FILE_NOT_FOUND;
857
858     buffer.resize(size);
859     int bytesRead = fread(buffer.data(), 1, size, fileHandle);
860
861     fclose(fileHandle);
862
863     if (bytesRead <= 0)
864         return NPERR_FILE_NOT_FOUND;
865
866     return NPERR_NO_ERROR;
867 }
868
869 bool PluginView::platformGetValueStatic(NPNVariable variable, void* value, NPError* result)
870 {
871     switch (variable) {
872     case NPNVToolkit:
873         *static_cast<uint32_t*>(value) = 0;
874         *result = NPERR_NO_ERROR;
875         return true;
876
877     case NPNVSupportsXEmbedBool:
878         *static_cast<NPBool*>(value) = true;
879         *result = NPERR_NO_ERROR;
880         return true;
881
882     case NPNVjavascriptEnabledBool:
883         *static_cast<NPBool*>(value) = true;
884         *result = NPERR_NO_ERROR;
885         return true;
886
887     case NPNVSupportsWindowless:
888         *static_cast<NPBool*>(value) = true;
889         *result = NPERR_NO_ERROR;
890         return true;
891
892     case NPNVNPCallbacksPtr:
893         *((void **) value) = (void*)&s_NpCallbacks;
894         *result = NPERR_NO_ERROR;
895         return true;
896
897     case NPNVxDisplay:
898     case NPNVxtAppContext:
899     case NPNVnetscapeWindow:
900     case NPNVasdEnabledBool:
901     case NPNVisOfflineBool:
902     case NPNVserviceManager:
903     case NPNVDOMElement:
904     case NPNVDOMWindow:
905     case NPNVWindowNPObject:
906     case NPNVPluginElementNPObject:
907     case NPNVprivateModeBool:
908     case NPNVZoomFactor:
909     case NPNVRootWindowGroup:
910     case NPNVBrowserWindowGroup:
911     case NPNVBrowserDisplayContext:
912     case NPNVPluginWindowPrefix:
913         return false;
914
915     default:
916         ASSERT_NOT_REACHED();
917         return false;
918     }
919 }
920
921 bool PluginView::platformGetValue(NPNVariable variable, void* value, NPError* result)
922 {
923     switch (variable) {
924     case NPNVZoomFactor:
925         *(static_cast<void**>(value)) = static_cast<void*>(&((static_cast<NPSetWindowCallbackStruct*>(m_npWindow.ws_info)))->zoomFactor);
926         *result = NPERR_NO_ERROR;
927         return true;
928
929     case NPNVRootWindowGroup: {
930         FrameView* frameView = toFrameView(parent());
931         if (frameView) {
932             BlackBerry::Platform::Graphics::Window *window = frameView->hostWindow()->platformPageClient()->platformWindow();
933             if (window) {
934                 void** tempValue = static_cast<void**>(value);
935                 *tempValue = (void*)window->rootGroup();
936
937                 if (*tempValue) {
938                     *result = NPERR_NO_ERROR;
939                     return true;
940                 }
941             }
942         }
943         *result = NPERR_GENERIC_ERROR;
944         return false;
945     }
946
947     case NPNVBrowserWindowGroup: {
948         FrameView* frameView = toFrameView(parent());
949         if (frameView) {
950             BlackBerry::Platform::Graphics::Window* window = frameView->hostWindow()->platformPageClient()->platformWindow();
951             if (window) {
952                 void** tempValue = static_cast<void**>(value);
953                 *tempValue = reinterpret_cast<void*>(const_cast<char*>(window->windowGroup()));
954
955                 if (*tempValue) {
956                     *result = NPERR_NO_ERROR;
957                     return true;
958                 }
959             }
960         }
961         *result = NPERR_GENERIC_ERROR;
962         return false;
963     }
964
965     case NPNVBrowserDisplayContext: {
966         FrameView* frameView = toFrameView(parent());
967         if (frameView) {
968             BlackBerry::Platform::Graphics::PlatformDisplayContextHandle context = BlackBerry::Platform::Graphics::platformDisplayContext();
969             if (context) {
970                 void** tempValue = static_cast<void**>(value);
971                 *tempValue = static_cast<void*>(context);
972
973                 if (*tempValue) {
974                     *result = NPERR_NO_ERROR;
975                     return true;
976                 }
977             }
978         }
979         *result = NPERR_GENERIC_ERROR;
980         return false;
981     }
982
983     case NPNVPluginWindowPrefix: {
984         void** tempValue = static_cast<void**>(value);
985         *tempValue = static_cast<void*>(const_cast<char*>(m_private->m_pluginUniquePrefix.c_str()));
986
987         if (*tempValue) {
988             *result = NPERR_NO_ERROR;
989             return true;
990         }
991         *result = NPERR_GENERIC_ERROR;
992         return false;
993     }
994
995     case NPNVxDisplay:
996     case NPNVxtAppContext:
997     case NPNVnetscapeWindow:
998     case NPNVjavascriptEnabledBool:
999     case NPNVasdEnabledBool:
1000     case NPNVisOfflineBool:
1001     case NPNVserviceManager:
1002     case NPNVDOMElement:
1003     case NPNVDOMWindow:
1004     case NPNVToolkit:
1005     case NPNVSupportsXEmbedBool:
1006     case NPNVWindowNPObject:
1007     case NPNVPluginElementNPObject:
1008     case NPNVSupportsWindowless:
1009     case NPNVprivateModeBool:
1010     case NPNVNPCallbacksPtr:
1011         return platformGetValueStatic(variable, value, result);
1012
1013     default:
1014         ASSERT_NOT_REACHED();
1015         return false;
1016     }
1017 }
1018
1019 // This is a pure virtual inherited from Widget class and all invalidates
1020 // are funneled through this method. We forward them on to either the
1021 // compositing layer or the PluginView::invalidateWindowlessPluginRect method.
1022 void PluginView::invalidateRect(const IntRect& rect)
1023 {
1024     if (!m_private)
1025         return;
1026
1027     // Record the region that we've been asked to invalidate
1028     m_private->m_invalidateRegion = BlackBerry::Platform::IntRectRegion::unionRegions(BlackBerry::Platform::IntRect(rect), m_private->m_invalidateRegion);
1029
1030 #if USE(ACCELERATED_COMPOSITING)
1031     if (m_private->m_platformLayer) {
1032         m_private->m_platformLayer->setNeedsDisplay();
1033         return;
1034     }
1035 #endif
1036
1037     invalidateWindowlessPluginRect(rect);
1038 }
1039
1040 void PluginView::invalidateRect(NPRect* rect)
1041 {
1042     if (!rect) {
1043         invalidate();
1044         return;
1045     }
1046     invalidateRect(IntRect(rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top));
1047 }
1048
1049 void PluginView::invalidateRegion(NPRegion region)
1050 {
1051     invalidate();
1052 }
1053
1054 void PluginView::forceRedraw()
1055 {
1056     invalidate();
1057 }
1058
1059 bool PluginView::platformStart()
1060 {
1061     ASSERT(m_isStarted);
1062     ASSERT(m_status == PluginStatusLoadedSuccessfully);
1063
1064     m_private = new PluginViewPrivate(this);
1065
1066     if (m_plugin->pluginFuncs()->getvalue) {
1067         PluginView::setCurrentPluginView(this);
1068         JSC::JSLock::DropAllLocks dropAllLocks(JSDOMWindowBase::commonJSGlobalData());
1069         setCallingPlugin(true);
1070         m_plugin->pluginFuncs()->getvalue(m_instance, NPPVpluginNeedsXEmbed, &m_needsXEmbed);
1071         setCallingPlugin(false);
1072         PluginView::setCurrentPluginView(0);
1073     }
1074
1075 #if USE(ACCELERATED_COMPOSITING)
1076     if (m_parentFrame->page()->chrome()->client()->allowsAcceleratedCompositing()
1077         && m_parentFrame->page()->settings()
1078         && m_parentFrame->page()->settings()->acceleratedCompositingEnabled()) {
1079         m_private->m_platformLayer = PluginLayerWebKitThread::create(this);
1080         // Trigger layer computation in RenderLayerCompositor
1081         m_element->setNeedsStyleRecalc(SyntheticStyleChange);
1082     }
1083 #endif
1084
1085     m_npWindow.type = NPWindowTypeDrawable;
1086     m_npWindow.window = 0; // Not used?
1087     m_npWindow.x = 0;
1088     m_npWindow.y = 0;
1089     m_npWindow.width = UninitializedCoordinate;
1090     m_npWindow.height = UninitializedCoordinate;
1091     m_npWindow.ws_info = new NPSetWindowCallbackStruct;
1092     ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->zoomFactor = 1.;
1093     ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->windowGroup = 0;
1094
1095     show();
1096
1097     if (FrameView* frameView = toFrameView(parent()))
1098         handleOrientationEvent(frameView->hostWindow()->platformPageClient()->orientation());
1099
1100     if (!(m_plugin->quirks().contains(PluginQuirkDeferFirstSetWindowCall))) {
1101         updatePluginWidget();
1102         setNPWindowIfNeeded();
1103     }
1104
1105     return true;
1106 }
1107
1108 void PluginView::platformDestroy()
1109 {
1110     if (!m_private)
1111         return;
1112
1113     // This will unlock the idle (if we have locked it).
1114     m_private->preventIdle(false);
1115
1116     // This will release any keepVisibleRects if they were set.
1117     m_private->clearVisibleRects();
1118
1119     // This will ensure that we unregistered the plugin.
1120     if (FrameView* frameView = toFrameView(parent())) {
1121         if (m_private->m_isBackgroundPlaying)
1122             frameView->hostWindow()->platformPageClient()->onPluginStopBackgroundPlay(this, m_private->m_pluginUniquePrefix.c_str());
1123
1124         // If we were still fullscreen, ensure we notify everyone we're not.
1125         if (m_private->m_isFullScreen)
1126             frameView->hostWindow()->platformPageClient()->didPluginExitFullScreen(this, m_private->m_pluginUniquePrefix.c_str());
1127
1128         if (m_private->m_orientationLocked)
1129             frameView->hostWindow()->platformPageClient()->unlockOrientation();
1130
1131         frameView->hostWindow()->platformPageClient()->registerPlugin(this, false /*shouldRegister*/);
1132     }
1133
1134     m_private->m_isBackgroundPlaying = false;
1135     m_private->m_isFullScreen = false;
1136
1137     delete m_private;
1138     m_private = 0;
1139 }
1140
1141 void PluginView::getWindowInfo(Vector<PluginWindowInfo>& windowList)
1142 {
1143     if (!m_plugin->pluginFuncs()->getvalue)
1144         return;
1145
1146     void* valPtr = 0;
1147
1148     PluginView::setCurrentPluginView(this);
1149     JSC::JSLock::DropAllLocks dropAllLocks(JSDOMWindowBase::commonJSGlobalData());
1150     setCallingPlugin(true);
1151     m_plugin->pluginFuncs()->getvalue(m_instance, NPPVpluginScreenWindow, &valPtr);
1152     setCallingPlugin(false);
1153     PluginView::setCurrentPluginView(0);
1154
1155     if (!valPtr)
1156         return;
1157
1158     NPScreenWindowHandles* screenWinHandles = static_cast<NPScreenWindowHandles*>(valPtr);
1159
1160     for (int i = 0; i < screenWinHandles->numOfWindows; i++) {
1161         PluginWindowInfo info;
1162         info.windowPtr = screenWinHandles->windowHandles[i];
1163
1164         NPRect* rc = screenWinHandles->windowRects[i];
1165         info.windowRect = IntRect(rc->left, rc->top, rc->right - rc->left, rc->bottom - rc->top);
1166
1167         windowList.append(info);
1168     }
1169 }
1170
1171 BlackBerry::Platform::Graphics::Buffer* PluginView::lockFrontBufferForRead() const
1172 {
1173     if (!m_private)
1174         return 0;
1175
1176     BlackBerry::Platform::Graphics::Buffer* buffer = m_private->lockReadFrontBufferInternal();
1177
1178     if (!buffer)
1179         m_private->unlockReadFrontBuffer();
1180
1181     return buffer;
1182 }
1183
1184 void PluginView::unlockFrontBuffer() const
1185 {
1186     if (!m_private)
1187         return;
1188     m_private->unlockReadFrontBuffer();
1189 }
1190
1191 #if USE(ACCELERATED_COMPOSITING)
1192 PlatformLayer* PluginView::platformLayer() const
1193 {
1194     if (!m_private)
1195         return 0;
1196     return m_private->m_platformLayer.get();
1197 }
1198 #endif
1199
1200 IntRect PluginView::ensureVisibleRect()
1201 {
1202     if (!m_private)
1203         return IntRect();
1204     return m_private->m_keepVisibleRect;
1205 }
1206
1207 void PluginView::setBackgroundPlay(bool value)
1208 {
1209     if (!m_private || m_private->m_isBackgroundPlaying == value)
1210         return;
1211
1212     FrameView* frameView = toFrameView(m_private->m_view->parent());
1213     m_private->m_isBackgroundPlaying = value;
1214     if (m_private->m_isBackgroundPlaying)
1215         frameView->hostWindow()->platformPageClient()->onPluginStartBackgroundPlay(this, m_private->m_pluginUniquePrefix.c_str());
1216     else
1217         frameView->hostWindow()->platformPageClient()->onPluginStopBackgroundPlay(this, m_private->m_pluginUniquePrefix.c_str());
1218 }
1219
1220 } // namespace WebCore
1221
1222