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