1 /*
2 * Copyright 2009, The Android Open Source Project
3 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #define LOG_TAG "WebCore"
28
29 #include "config.h"
30 #include "PluginView.h"
31
32 #include "Document.h"
33 #include "Element.h"
34 #include "EventNames.h"
35 #include "FocusController.h"
36 #include "FrameLoader.h"
37 #include "FrameLoadRequest.h"
38 #include "FrameTree.h"
39 #include "Frame.h"
40 #include "FrameView.h"
41 #include "GraphicsContext.h"
42 #include "HTMLNames.h"
43 #include "HTMLPlugInElement.h"
44 #include "Image.h"
45 #include "KeyboardEvent.h"
46 #include "MIMETypeRegistry.h"
47 #include "MouseEvent.h"
48 #include "NetworkStateNotifier.h"
49 #include "NotImplemented.h"
50 #include "Page.h"
51 #include "PlatformGraphicsContext.h"
52 #include "PlatformKeyboardEvent.h"
53 #include "PluginMainThreadScheduler.h"
54 #include "PluginPackage.h"
55 #include "Touch.h"
56 #include "TouchEvent.h"
57 #include "TouchList.h"
58 #include "SkCanvas.h"
59 #include "npruntime_impl.h"
60 // #include "runtime_root.h"
61 #include "utils/SystemClock.h"
62 #include "ScriptController.h"
63 #include "Settings.h"
64
65 #include <wtf/ASCIICType.h>
66 // #include "runtime.h"
67 #include "WebViewCore.h"
68
69 /* Controls the printing of log messages in this file. This must be defined
70 before PluginDebugAndroid.h is included.
71 */
72 // #define PLUGIN_DEBUG_LOCAL
73 #define TRACE_KEY_EVENTS 0
74
75 #include "PluginDebug.h"
76 #include "PluginDebugAndroid.h"
77 #include "PluginViewBridgeAndroid.h"
78 #include "PluginWidgetAndroid.h"
79
80 #include "android_npapi.h"
81 #include "ANPNativeWindow_npapi.h"
82 #include "ANPSurface_npapi.h"
83 #include "ANPSystem_npapi.h"
84 #include "ANPVideo_npapi.h"
85 #include "SkANP.h"
86 #include "SkFlipPixelRef.h"
87
88 ///////////////////////////////////////////////////////////////////////////////
89
90 extern void ANPAudioTrackInterfaceV0_Init(ANPInterface* value);
91 extern void ANPAudioTrackInterfaceV1_Init(ANPInterface* value);
92 extern void ANPBitmapInterfaceV0_Init(ANPInterface* value);
93 extern void ANPCanvasInterfaceV0_Init(ANPInterface* value);
94 extern void ANPEventInterfaceV0_Init(ANPInterface* value);
95 extern void ANPLogInterfaceV0_Init(ANPInterface* value);
96 extern void ANPMatrixInterfaceV0_Init(ANPInterface* value);
97 extern void ANPOffscreenInterfaceV0_Init(ANPInterface* value);
98 extern void ANPPaintInterfaceV0_Init(ANPInterface* value);
99 extern void ANPPathInterfaceV0_Init(ANPInterface* value);
100 extern void ANPSurfaceInterfaceV0_Init(ANPInterface* value);
101 extern void ANPTypefaceInterfaceV0_Init(ANPInterface* value);
102 extern void ANPWindowInterfaceV0_Init(ANPInterface* value);
103 extern void ANPWindowInterfaceV1_Init(ANPInterface* value);
104 extern void ANPWindowInterfaceV2_Init(ANPInterface* value);
105 extern void ANPSystemInterfaceV0_Init(ANPInterface* value);
106 extern void ANPSystemInterfaceV1_Init(ANPInterface* value);
107 extern void ANPSystemInterfaceV2_Init(ANPInterface* value);
108 extern void ANPNativeWindowInterfaceV0_Init(ANPInterface* value);
109 extern void ANPVideoInterfaceV0_Init(ANPInterface* value);
110 extern void ANPVideoInterfaceV1_Init(ANPInterface* value);
111
112 struct VarProcPair {
113 int enumValue;
114 size_t size;
115 void (*proc)(ANPInterface*);
116 };
117
118 #define VARPROCLINE(name) \
119 k##name##_ANPGetValue, sizeof(ANP##name), ANP##name##_Init
120
121 static const VarProcPair gVarProcs[] = {
122 { VARPROCLINE(AudioTrackInterfaceV0) },
123 { VARPROCLINE(AudioTrackInterfaceV1) },
124 { VARPROCLINE(BitmapInterfaceV0) },
125 { VARPROCLINE(CanvasInterfaceV0) },
126 { VARPROCLINE(EventInterfaceV0) },
127 { VARPROCLINE(LogInterfaceV0) },
128 { VARPROCLINE(MatrixInterfaceV0) },
129 { VARPROCLINE(PaintInterfaceV0) },
130 { VARPROCLINE(PathInterfaceV0) },
131 { VARPROCLINE(SurfaceInterfaceV0) },
132 { VARPROCLINE(TypefaceInterfaceV0) },
133 { VARPROCLINE(WindowInterfaceV0) },
134 { VARPROCLINE(WindowInterfaceV1) },
135 { VARPROCLINE(WindowInterfaceV2) },
136 { VARPROCLINE(SystemInterfaceV0) },
137 { VARPROCLINE(SystemInterfaceV1) },
138 { VARPROCLINE(SystemInterfaceV2) },
139 { VARPROCLINE(NativeWindowInterfaceV0) },
140 { VARPROCLINE(VideoInterfaceV0) },
141 { VARPROCLINE(VideoInterfaceV1) },
142 };
143
144 /* return true if var was an interface request (error will be set accordingly)
145 return false if var is not a recognized interface (and ignore error param)
146 */
anp_getInterface(NPNVariable var,void * value,NPError * error)147 static bool anp_getInterface(NPNVariable var, void* value, NPError* error) {
148 const VarProcPair* iter = gVarProcs;
149 const VarProcPair* stop = gVarProcs + SK_ARRAY_COUNT(gVarProcs);
150 while (iter < stop) {
151 if (iter->enumValue == var) {
152 ANPInterface* i = reinterpret_cast<ANPInterface*>(value);
153 if (i->inSize < iter->size) {
154 SkDebugf("------- interface %d, expected size %d, allocated %d\n",
155 var, iter->size, i->inSize);
156 *error = NPERR_INCOMPATIBLE_VERSION_ERROR;
157 } else {
158 iter->proc(i);
159 *error = NPERR_NO_ERROR;
160 }
161 return true;
162 }
163 iter += 1;
164 }
165 SkDebugf("------ unknown NPNVariable %d\n", var);
166 return false;
167 }
168
169 ///////////////////////////////////////////////////////////////////////////////
170
171 using std::min;
172
173 using namespace WTF;
174
175 namespace WebCore {
176
177 using namespace HTMLNames;
178
platformInit()179 void PluginView::platformInit()
180 {
181 setPlatformWidget(new PluginViewBridgeAndroid());
182
183 m_isWindowed = false; // we don't support windowed yet
184
185 m_window = new PluginWidgetAndroid(this);
186
187 m_npWindow.type = NPWindowTypeDrawable;
188 m_npWindow.window = 0;
189 }
190
platformStart()191 bool PluginView::platformStart()
192 {
193 return true;
194 }
195
platformDestroy()196 void PluginView::platformDestroy()
197 {
198 delete m_window;
199 }
200
platformLayer() const201 PlatformLayer* PluginView::platformLayer() const
202 {
203 return (PlatformLayer*) m_window->getLayer();
204 }
205
206 #if ENABLE(TOUCH_EVENTS)
handleTouchEvent(TouchEvent * event)207 void PluginView::handleTouchEvent(TouchEvent* event)
208 {
209 if (!m_window->isAcceptingEvent(kTouch_ANPEventFlag))
210 return;
211
212 if (!m_window->inFullScreen() && m_parentFrame->document()->focusedNode() != m_element)
213 return;
214
215 ANPEvent evt;
216 SkANP::InitEvent(&evt, kMultiTouch_ANPEventType);
217
218 const AtomicString& type = event->type();
219 if (eventNames().touchstartEvent == type)
220 evt.data.multiTouch.action = kDown_ANPTouchAction;
221 else if (eventNames().touchendEvent == type)
222 evt.data.multiTouch.action = kUp_ANPTouchAction;
223 else if (eventNames().touchmoveEvent == type)
224 evt.data.multiTouch.action = kMove_ANPTouchAction;
225 else if (eventNames().touchcancelEvent == type)
226 evt.data.multiTouch.action = kCancel_ANPTouchAction;
227 else if (eventNames().touchlongpressEvent == type)
228 evt.data.multiTouch.action = kLongPress_ANPTouchAction;
229 else if (eventNames().touchdoubletapEvent == type)
230 evt.data.multiTouch.action = kDoubleTap_ANPTouchAction;
231 else
232 return;
233
234 // set the id and timestamp
235 evt.data.multiTouch.id = 0; // TODO
236 evt.data.multiTouch.timestamp = 0; // TODO
237
238 // In the event of a touchend (up) or touchcancel event, we must ask the changedTouch for the
239 // co-ordinates as there is no touch in touches anymore.
240 TouchList* touches = (evt.data.multiTouch.action == kUp_ANPTouchAction
241 || evt.data.multiTouch.action == kCancel_ANPTouchAction) ? event->changedTouches() : event->touches();
242
243 // set each touchPoint
244 int pointerCount = touches->length();
245 evt.data.multiTouch.pointerCount = pointerCount;
246 evt.data.multiTouch.touchPoint = new TouchPoint[pointerCount];
247
248 for (int x = 0; x < evt.data.multiTouch.pointerCount; x++) {
249 Touch* touch = touches->item(x);
250 // Convert to coordinates that are relative to the plugin.
251 IntPoint localPos = roundedIntPoint(m_element->renderer()->absoluteToLocal(IntPoint(touch->pageX(), touch->pageY())));
252
253 evt.data.multiTouch.touchPoint[x].id = touch->identifier();
254 evt.data.multiTouch.touchPoint[x].x = localPos.x();
255 evt.data.multiTouch.touchPoint[x].y = localPos.y();
256 evt.data.multiTouch.touchPoint[x].pressure = 1; // TODO
257 evt.data.multiTouch.touchPoint[x].size = 1; // TODO
258 }
259
260 if (m_window->sendEvent(evt))
261 event->preventDefault();
262
263 // cleanup the touch points we allocated
264 delete[] evt.data.multiTouch.touchPoint;
265 }
266 #endif
267
handleMouseEvent(MouseEvent * event)268 void PluginView::handleMouseEvent(MouseEvent* event)
269 {
270 const AtomicString& type = event->type();
271 bool isUp = (eventNames().mouseupEvent == type);
272 bool isDown = (eventNames().mousedownEvent == type);
273
274 ANPEvent evt;
275
276 if (isUp || isDown) {
277 SkANP::InitEvent(&evt, kMouse_ANPEventType);
278 evt.data.mouse.action = isUp ? kUp_ANPMouseAction : kDown_ANPMouseAction;
279
280 // Convert to coordinates that are relative to the plugin.
281 IntPoint localPos = roundedIntPoint(m_element->renderer()->absoluteToLocal(event->absoluteLocation()));
282 evt.data.mouse.x = localPos.x();
283 evt.data.mouse.y = localPos.y();
284
285 if (isDown) {
286 // The plugin needs focus to receive keyboard and touch events
287 m_element->focus();
288 event->setDefaultHandled();
289 }
290 }
291 else {
292 return;
293 }
294
295 if (m_window->sendEvent(evt)) {
296 event->setDefaultHandled();
297 }
298 }
299
make_modifiers(bool shift,bool alt)300 static ANPKeyModifier make_modifiers(bool shift, bool alt) {
301 ANPKeyModifier mod = 0;
302 if (shift) {
303 mod |= kShift_ANPKeyModifier;
304 }
305 if (alt) {
306 mod |= kAlt_ANPKeyModifier;
307 }
308 return mod;
309 }
310
handleFocusEvent(bool hasFocus)311 void PluginView::handleFocusEvent(bool hasFocus)
312 {
313 ANPEvent evt;
314 SkANP::InitEvent(&evt, kLifecycle_ANPEventType);
315 evt.data.lifecycle.action = hasFocus ? kGainFocus_ANPLifecycleAction :
316 kLoseFocus_ANPLifecycleAction;
317 m_window->sendEvent(evt);
318
319 // redraw the plugin which subsequently invalidates the nav cache
320 IntRect rect = IntRect(m_npWindow.x, m_npWindow.y,
321 m_npWindow.width, m_npWindow.height);
322 m_window->webViewCore()->contentInvalidate(rect);
323 }
324
handleKeyboardEvent(KeyboardEvent * event)325 void PluginView::handleKeyboardEvent(KeyboardEvent* event)
326 {
327 if (!m_window->isAcceptingEvent(kKey_ANPEventFlag))
328 return;
329
330 const PlatformKeyboardEvent* pke = event->keyEvent();
331 if (NULL == pke) {
332 return;
333 }
334
335 bool ignoreEvent = false;
336
337 ANPEvent evt;
338 SkANP::InitEvent(&evt, kKey_ANPEventType);
339
340 switch (pke->type()) {
341 case PlatformKeyboardEvent::KeyDown:
342 #if TRACE_KEY_EVENTS
343 PLUGIN_LOG("--------- KeyDown, ignore\n");
344 #endif
345 ignoreEvent = true;
346 break;
347 case PlatformKeyboardEvent::RawKeyDown:
348 evt.data.key.action = kDown_ANPKeyAction;
349 break;
350 case PlatformKeyboardEvent::Char:
351 #if TRACE_KEY_EVENTS
352 PLUGIN_LOG("--------- Char, ignore\n");
353 #endif
354 ignoreEvent = true;
355 break;
356 case PlatformKeyboardEvent::KeyUp:
357 evt.data.key.action = kUp_ANPKeyAction;
358 break;
359 default:
360 #if TRACE_KEY_EVENTS
361 PLUGIN_LOG("------ unexpected keyevent type %d\n", pke->type());
362 #endif
363 ignoreEvent = true;
364 break;
365 }
366
367 /* the plugin should be the only party able to return nav control to the
368 * browser UI. Therefore, if we discard an event on behalf of the plugin
369 * we should mark the event as being handled.
370 */
371 if (ignoreEvent) {
372 int keyCode = pke->nativeVirtualKeyCode();
373 if (keyCode >= kDpadUp_ANPKeyCode && keyCode <= kDpadCenter_ANPKeyCode)
374 event->setDefaultHandled();
375 return;
376 }
377
378 evt.data.key.nativeCode = pke->nativeVirtualKeyCode();
379 evt.data.key.virtualCode = pke->windowsVirtualKeyCode();
380 evt.data.key.repeatCount = pke->repeatCount();
381 evt.data.key.modifiers = make_modifiers(pke->shiftKey(), pke->altKey());
382 evt.data.key.unichar = pke->unichar();
383
384 if (m_window->sendEvent(evt)) {
385 event->setDefaultHandled();
386 } else if (m_window->inFullScreen()){
387 // while in the full screen mode, always consumes the key events and
388 // keeps the document focus
389 event->setDefaultHandled();
390 } else {
391 // remove the plugin from the document's focus
392 m_parentFrame->document()->focusedNodeRemoved();
393 }
394 }
395
handlePostReadFile(Vector<char> & buffer,uint32_t len,const char * buf)396 NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32_t len, const char* buf)
397 {
398 notImplemented();
399 return NPERR_GENERIC_ERROR;
400 }
401
platformGetValueStatic(NPNVariable variable,void * value,NPError * result)402 bool PluginView::platformGetValueStatic(NPNVariable variable, void* value, NPError* result)
403 {
404 // our interface query is valid with no NPP instance
405 *result = NPERR_GENERIC_ERROR;
406
407 switch ((int)variable) {
408 case NPNVisOfflineBool: {
409 if (value != NULL) {
410 bool* retValue = static_cast<bool*>(value);
411 *retValue = !networkStateNotifier().onLine();
412 *result = NPERR_NO_ERROR;
413 return true;
414 }
415 break;
416 }
417 case kJavaContext_ANPGetValue: {
418 jobject* retObject = static_cast<jobject*>(value);
419 *retObject = android::WebViewCore::getApplicationContext();
420 *result = NPERR_NO_ERROR;
421 return true;
422 }
423 default:
424 break; // do nothing
425 }
426
427 (void)anp_getInterface(variable, value, result);
428 return true;
429 }
430
setParent(ScrollView * parent)431 void PluginView::setParent(ScrollView* parent)
432 {
433 PLUGIN_LOG("--%p SetParent old=[%p], new=[%p] \n", instance(), this->parent(), parent);
434
435 Widget::setParent(parent);
436
437 if (parent) {
438 // the widget needs initialized now so that the plugin has access to
439 // WebViewCore when NPP_New is called
440 if (m_window && !m_window->webViewCore()) {
441 android::WebViewCore* c = android::WebViewCore::getWebViewCore(this->parent());
442 m_window->init(c);
443 }
444 init();
445
446 /* Our widget needs to recompute its m_windowRect which then sets
447 the NPWindowRect if necessary. This ensures that if NPWindowRect
448 is set prior to parent() being set that we still (1) notify the
449 plugin of its current rect and (2) that we execute our logic in
450 PluginWidgetAndroid in response to changes to NPWindowRect.
451 */
452 updatePluginWidget();
453 }
454 }
455
setNPWindowRect(const IntRect &)456 void PluginView::setNPWindowRect(const IntRect&)
457 {
458 setNPWindowIfNeeded();
459 }
460
setNPWindowIfNeeded()461 void PluginView::setNPWindowIfNeeded()
462 {
463 PLUGIN_LOG("--%p SetWindow isStarted=[%d] \n", instance(), m_isStarted);
464
465 if (!m_isStarted || !parent())
466 return;
467
468 // in Android, plugin always get the setwindow() in the page coordinate.
469
470 // the m_npWindow is relative to the page
471 m_npWindow.x = m_pageRect.x();
472 m_npWindow.y = m_pageRect.y();
473 m_npWindow.width = m_pageRect.width();
474 m_npWindow.height = m_pageRect.height();
475
476 m_npWindow.clipRect.left = m_pageRect.x();
477 m_npWindow.clipRect.top = m_pageRect.y();
478 m_npWindow.clipRect.right = m_pageRect.x() + m_pageRect.width();
479 m_npWindow.clipRect.bottom = m_pageRect.y() + m_pageRect.height();
480
481 if (m_plugin->pluginFuncs()->setwindow) {
482 setCallingPlugin(true);
483 m_plugin->pluginFuncs()->setwindow(m_instance, &m_npWindow);
484 setCallingPlugin(false);
485 }
486
487 m_window->setWindow(&m_npWindow, m_isTransparent);
488 }
489
platformGetValue(NPNVariable variable,void * value,NPError * result)490 bool PluginView::platformGetValue(NPNVariable variable, void* value, NPError* result)
491 {
492 switch ((int)variable) {
493 case NPNVWindowNPObject: {
494 NPObject* windowScriptObject =
495 m_parentFrame->script()->windowScriptNPObject();
496
497 // Return value is expected to be retained, as described
498 // here:
499 // <http://www.mozilla.org/projects/plugin/npruntime.html>
500 if (windowScriptObject)
501 _NPN_RetainObject(windowScriptObject);
502
503 void** v = (void**)value;
504 *v = windowScriptObject;
505
506 *result = NPERR_NO_ERROR;
507 return true;
508 }
509
510 case NPNVPluginElementNPObject: {
511 NPObject* pluginScriptObject = 0;
512
513 if (m_element->hasTagName(appletTag) ||
514 m_element->hasTagName(embedTag) ||
515 m_element->hasTagName(objectTag)) {
516 HTMLPlugInElement* pluginElement =
517 static_cast<HTMLPlugInElement*>(m_element);
518 pluginScriptObject = pluginElement->getNPObject();
519 }
520
521 // Return value is expected to be retained, as described
522 // here:
523 // <http://www.mozilla.org/projects/plugin/npruntime.html>
524 if (pluginScriptObject)
525 _NPN_RetainObject(pluginScriptObject);
526
527 void** v = (void**)value;
528 *v = pluginScriptObject;
529
530 *result = NPERR_NO_ERROR;
531 return true;
532 }
533
534 case NPNVnetscapeWindow: {
535 // Return the top level WebView Java object associated
536 // with this instance.
537 jobject *retObject = static_cast<jobject*>(value);
538 // TODO: Is it safe for this to be NULL? It looks from the NPNVWindowNPObject case that it is.
539 *retObject = android::WebViewCore::getWebViewCore(parent())->getWebViewJavaObject();
540 *result = NPERR_NO_ERROR;
541 return true;
542 }
543
544 case NPNVisOfflineBool: {
545 if (value == NULL) {
546 *result = NPERR_GENERIC_ERROR;
547 return true;
548 }
549 bool* retValue = static_cast<bool*>(value);
550 *retValue = !networkStateNotifier().onLine();
551 *result = NPERR_NO_ERROR;
552 return true;
553 }
554
555 case kSupportedDrawingModel_ANPGetValue: {
556 uint32_t* bits = reinterpret_cast<uint32_t*>(value);
557 *bits = kBitmap_ANPDrawingModel & kSurface_ANPDrawingModel;
558 *result = NPERR_NO_ERROR;
559 return true;
560 }
561
562 case kJavaContext_ANPGetValue: {
563 jobject* retObject = static_cast<jobject*>(value);
564 // TODO: Is it safe for this to be NULL? It looks from the NPNVWindowNPObject case that it is.
565 *retObject = android::WebViewCore::getWebViewCore(parent())->getContext();
566 *result = NPERR_NO_ERROR;
567 return true;
568 }
569
570 default: {
571 NPError error = NPERR_GENERIC_ERROR;
572 (void)anp_getInterface(variable, value, &error);
573 *result = error;
574 return true;
575 }
576 }
577 }
578
platformSetValue(NPPVariable variable,void * value)579 NPError PluginView::platformSetValue(NPPVariable variable, void* value)
580 {
581 NPError error = NPERR_GENERIC_ERROR;
582
583 switch ((int)variable) {
584 case kRequestDrawingModel_ANPSetValue: {
585 ANPDrawingModel model = reinterpret_cast<ANPDrawingModel>(value);
586 if (m_window->setDrawingModel(model))
587 error = NPERR_NO_ERROR;
588 break;
589 }
590 case kAcceptEvents_ANPSetValue : {
591 if(value) {
592 ANPEventFlags flags = *reinterpret_cast<ANPEventFlags*>(value);
593 m_window->updateEventFlags(flags);
594 error = NPERR_NO_ERROR;
595 }
596 break;
597 }
598 default:
599 break;
600 }
601 return error;
602 }
603
invalidateRect(const IntRect & r)604 void PluginView::invalidateRect(const IntRect& r)
605 {
606 m_window->inval(r, true);
607 }
608
invalidateRect(NPRect * rect)609 void PluginView::invalidateRect(NPRect* rect)
610 {
611 IntRect r;
612
613 if (rect) {
614 r = IntRect(rect->left, rect->top,
615 rect->right - rect->left, rect->bottom - rect->top);
616 } else {
617 r = IntRect(0, 0, m_npWindow.width, m_npWindow.height);
618 }
619
620 m_window->inval(r, true);
621 }
622
invalidateRegion(NPRegion region)623 void PluginView::invalidateRegion(NPRegion region)
624 {
625 // we don't support/define regions (yet), so do nothing
626 }
627
forceRedraw()628 void PluginView::forceRedraw()
629 {
630 this->invalidateRect(0);
631 }
632
setFocus(bool focused)633 void PluginView::setFocus(bool focused)
634 {
635 Widget::setFocus(focused);
636 // SkDebugf("------------- setFocus %p\n", this);
637 }
638
show()639 void PluginView::show()
640 {
641 setSelfVisible(true);
642 Widget::show();
643
644 if (platformPluginWidget())
645 platformPluginWidget()->layoutSurface();
646
647 }
648
hide()649 void PluginView::hide()
650 {
651 setSelfVisible(false);
652 Widget::hide();
653
654 if (platformPluginWidget())
655 platformPluginWidget()->layoutSurface();
656 }
657
setParentVisible(bool visible)658 void PluginView::setParentVisible(bool visible) {
659
660 if (isParentVisible() == visible)
661 return;
662
663 Widget::setParentVisible(visible);
664
665 if (platformPluginWidget())
666 platformPluginWidget()->layoutSurface();
667
668 }
669
paint(GraphicsContext * context,const IntRect & rect)670 void PluginView::paint(GraphicsContext* context, const IntRect& rect)
671 {
672 if (!m_isStarted) {
673 // Draw the "missing plugin" image
674 paintMissingPluginIcon(context, rect);
675 return;
676 }
677
678 IntRect frame = frameRect();
679 if (!frame.width() || !frame.height()) {
680 PLUGIN_LOG("--%p FrameRect Dimensions are (0,0).\n", instance());
681 return;
682 }
683
684 if (m_window->isSurfaceDrawingModel()) {
685 /* the document position of the frame (e.g. iFrame) containing the
686 surface may have changed, which requires us to to update the global
687 coordinates of the surface. This is necessary because the plugin has
688 not moved within its parent frame and therefore will not get any
689 notification of its global position change.
690 */
691 updatePluginWidget();
692 m_window->setSurfaceClip(context->platformContext()->getTotalClipBounds());
693 } else {
694 m_window->inval(rect, false);
695 context->save();
696 context->translate(frame.x(), frame.y());
697 m_window->draw(context->platformContext());
698 context->restore();
699 }
700
701
702 }
703
updatePluginWidget()704 void PluginView::updatePluginWidget()
705 {
706 FrameView* frameView = static_cast<FrameView*>(parent());
707 PLUGIN_LOG("--%p UpdatePluginWidget frame=[%p] \n", instance(), frameView);
708 if (frameView) {
709 m_windowRect = frameView->contentsToWindow(frameRect());
710
711 IntRect oldPageRect = m_pageRect;
712
713 // only the top ScrollView can have the offset
714 m_pageRect = m_windowRect;
715 ScrollView* top = parent();
716 while (top->parent())
717 top = top->parent();
718 m_pageRect.move(top->scrollOffset());
719
720 if (m_pageRect != oldPageRect)
721 setNPWindowIfNeeded();
722 }
723 }
724
halt()725 void PluginView::halt() {
726 notImplemented();
727 }
728
restart()729 void PluginView::restart() {
730 notImplemented();
731 }
732
733 } // namespace WebCore
734