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