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