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 89extern void ANPAudioTrackInterfaceV0_Init(ANPInterface* value); 90extern void ANPAudioTrackInterfaceV1_Init(ANPInterface* value); 91extern void ANPBitmapInterfaceV0_Init(ANPInterface* value); 92extern void ANPCanvasInterfaceV0_Init(ANPInterface* value); 93extern void ANPEventInterfaceV0_Init(ANPInterface* value); 94extern void ANPLogInterfaceV0_Init(ANPInterface* value); 95extern void ANPMatrixInterfaceV0_Init(ANPInterface* value); 96extern void ANPOffscreenInterfaceV0_Init(ANPInterface* value); 97extern void ANPPaintInterfaceV0_Init(ANPInterface* value); 98extern void ANPPathInterfaceV0_Init(ANPInterface* value); 99extern void ANPSurfaceInterfaceV0_Init(ANPInterface* value); 100extern void ANPTypefaceInterfaceV0_Init(ANPInterface* value); 101extern void ANPWindowInterfaceV0_Init(ANPInterface* value); 102extern void ANPWindowInterfaceV1_Init(ANPInterface* value); 103extern void ANPWindowInterfaceV2_Init(ANPInterface* value); 104extern void ANPSystemInterfaceV0_Init(ANPInterface* value); 105extern void ANPSystemInterfaceV1_Init(ANPInterface* value); 106extern void ANPSystemInterfaceV2_Init(ANPInterface* value); 107extern void ANPNativeWindowInterfaceV0_Init(ANPInterface* value); 108extern void ANPVideoInterfaceV0_Init(ANPInterface* value); 109extern void ANPVideoInterfaceV1_Init(ANPInterface* value); 110 111struct 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 120static 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 */ 146static 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 170using std::min; 171 172using namespace WTF; 173 174namespace WebCore { 175 176using namespace HTMLNames; 177 178void 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 190bool PluginView::platformStart() 191{ 192 return true; 193} 194 195void PluginView::platformDestroy() 196{ 197 delete m_window; 198} 199 200PlatformLayer* PluginView::platformLayer() const 201{ 202 return (PlatformLayer*) m_window->getLayer(); 203} 204 205#if ENABLE(TOUCH_EVENTS) 206void 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 267void 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 299static 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 310void 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 324void 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 395NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32_t len, const char* buf) 396{ 397 notImplemented(); 398 return NPERR_GENERIC_ERROR; 399} 400 401bool 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 430void 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 455void PluginView::setNPWindowRect(const IntRect&) 456{ 457 setNPWindowIfNeeded(); 458} 459 460void 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 489bool 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 578NPError 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 603void PluginView::invalidateRect(const IntRect& r) 604{ 605 m_window->inval(r, true); 606} 607 608void 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 622void PluginView::invalidateRegion(NPRegion region) 623{ 624 // we don't support/define regions (yet), so do nothing 625} 626 627void PluginView::forceRedraw() 628{ 629 this->invalidateRect(0); 630} 631 632void PluginView::setFocus(bool focused) 633{ 634 Widget::setFocus(focused); 635// SkDebugf("------------- setFocus %p\n", this); 636} 637 638void PluginView::show() 639{ 640 setSelfVisible(true); 641 Widget::show(); 642 643 if (platformPluginWidget()) 644 platformPluginWidget()->layoutSurface(); 645 646} 647 648void PluginView::hide() 649{ 650 setSelfVisible(false); 651 Widget::hide(); 652 653 if (platformPluginWidget()) 654 platformPluginWidget()->layoutSurface(); 655} 656 657void 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 669void 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 703void 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 724void PluginView::halt() { 725 notImplemented(); 726} 727 728void PluginView::restart() { 729 notImplemented(); 730} 731 732} // namespace WebCore 733