| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/plugin/webplugin_proxy.h" | 5 #include "content/plugin/webplugin_proxy.h" |
| 6 | 6 |
| 7 #include "build/build_config.h" | 7 #include "build/build_config.h" |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 int route_id, | 60 int route_id, |
| 61 const GURL& page_url, | 61 const GURL& page_url, |
| 62 int host_render_view_routing_id) | 62 int host_render_view_routing_id) |
| 63 : channel_(channel), | 63 : channel_(channel), |
| 64 route_id_(route_id), | 64 route_id_(route_id), |
| 65 window_npobject_(NULL), | 65 window_npobject_(NULL), |
| 66 plugin_element_(NULL), | 66 plugin_element_(NULL), |
| 67 delegate_(NULL), | 67 delegate_(NULL), |
| 68 waiting_for_paint_(false), | 68 waiting_for_paint_(false), |
| 69 page_url_(page_url), | 69 page_url_(page_url), |
| 70 transparent_(false), | |
| 71 windowless_buffer_index_(0), | 70 windowless_buffer_index_(0), |
| 72 host_render_view_routing_id_(host_render_view_routing_id), | 71 host_render_view_routing_id_(host_render_view_routing_id), |
| 73 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { | 72 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { |
| 74 #if defined(USE_X11) | 73 #if defined(USE_X11) |
| 75 windowless_shm_pixmaps_[0] = None; | 74 windowless_shm_pixmaps_[0] = None; |
| 76 windowless_shm_pixmaps_[1] = None; | 75 windowless_shm_pixmaps_[1] = None; |
| 77 use_shm_pixmap_ = false; | 76 use_shm_pixmap_ = false; |
| 78 | 77 |
| 79 // If the X server supports SHM pixmaps | 78 // If the X server supports SHM pixmaps |
| 80 // and the color depth and masks match, | 79 // and the color depth and masks match, |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 355 // (since the plugin can make a synchronous call during paint event handling), | 354 // (since the plugin can make a synchronous call during paint event handling), |
| 356 // in which case we don't want to try to restore later. Not an owning ref | 355 // in which case we don't want to try to restore later. Not an owning ref |
| 357 // since owning the ref without owning the shared backing memory doesn't make | 356 // since owning the ref without owning the shared backing memory doesn't make |
| 358 // sense, so this should only be used for pointer comparisons. | 357 // sense, so this should only be used for pointer comparisons. |
| 359 CGContextRef saved_context_weak = windowless_context(); | 358 CGContextRef saved_context_weak = windowless_context(); |
| 360 // We also save the buffer index for the comparison because if we flip buffers | 359 // We also save the buffer index for the comparison because if we flip buffers |
| 361 // but haven't reallocated them then we do need to restore the context because | 360 // but haven't reallocated them then we do need to restore the context because |
| 362 // it is going to continue to be used. | 361 // it is going to continue to be used. |
| 363 int saved_index = windowless_buffer_index_; | 362 int saved_index = windowless_buffer_index_; |
| 364 | 363 |
| 365 if (background_context_.get()) { | |
| 366 base::mac::ScopedCFTypeRef<CGImageRef> image( | |
| 367 CGBitmapContextCreateImage(background_context_)); | |
| 368 CGRect source_rect = rect.ToCGRect(); | |
| 369 // Flip the rect we use to pull from the canvas, since it's upside-down. | |
| 370 source_rect.origin.y = CGImageGetHeight(image) - rect.y() - rect.height(); | |
| 371 base::mac::ScopedCFTypeRef<CGImageRef> sub_image( | |
| 372 CGImageCreateWithImageInRect(image, source_rect)); | |
| 373 CGContextDrawImage(windowless_context(), rect.ToCGRect(), sub_image); | |
| 374 } else if (transparent_) { | |
| 375 CGContextClearRect(windowless_context(), rect.ToCGRect()); | |
| 376 } | |
| 377 CGContextClipToRect(windowless_context(), rect.ToCGRect()); | 364 CGContextClipToRect(windowless_context(), rect.ToCGRect()); |
| 378 // TODO(caryclark): This is a temporary workaround to allow the Darwin / Skia | 365 // TODO(caryclark): This is a temporary workaround to allow the Darwin / Skia |
| 379 // port to share code with the Darwin / CG port. All ports will eventually use | 366 // port to share code with the Darwin / CG port. All ports will eventually use |
| 380 // the common code below. | 367 // the common code below. |
| 381 delegate_->CGPaint(windowless_context(), rect); | 368 delegate_->CGPaint(windowless_context(), rect); |
| 382 if (windowless_contexts_[saved_index].get() == saved_context_weak) | 369 if (windowless_contexts_[saved_index].get() == saved_context_weak) |
| 383 CGContextRestoreGState(windowless_contexts_[saved_index]); | 370 CGContextRestoreGState(windowless_contexts_[saved_index]); |
| 384 #else | 371 #else |
| 385 // See above comment about windowless_context_ changing. | 372 // See above comment about windowless_context_ changing. |
| 386 // http::/crbug.com/139462 | 373 // http::/crbug.com/139462 |
| 387 skia::PlatformCanvas* saved_canvas = windowless_canvas(); | 374 skia::PlatformCanvas* saved_canvas = windowless_canvas(); |
| 388 SkAutoRef local_ref(saved_canvas); | 375 SkAutoRef local_ref(saved_canvas); |
| 389 #if defined(USE_X11) | 376 #if defined(USE_X11) |
| 390 scoped_refptr<SharedTransportDIB> local_dib_ref( | 377 scoped_refptr<SharedTransportDIB> local_dib_ref( |
| 391 windowless_dibs_[windowless_buffer_index_]); | 378 windowless_dibs_[windowless_buffer_index_]); |
| 392 #endif | 379 #endif |
| 393 | 380 |
| 394 saved_canvas->save(); | 381 saved_canvas->save(); |
| 395 | 382 |
| 396 // The given clip rect is relative to the plugin coordinate system. | 383 // The given clip rect is relative to the plugin coordinate system. |
| 397 SkRect sk_rect = { SkIntToScalar(rect.x()), | 384 SkRect sk_rect = { SkIntToScalar(rect.x()), |
| 398 SkIntToScalar(rect.y()), | 385 SkIntToScalar(rect.y()), |
| 399 SkIntToScalar(rect.right()), | 386 SkIntToScalar(rect.right()), |
| 400 SkIntToScalar(rect.bottom()) }; | 387 SkIntToScalar(rect.bottom()) }; |
| 401 saved_canvas->clipRect(sk_rect); | 388 saved_canvas->clipRect(sk_rect); |
| 402 | 389 |
| 403 // Setup the background. | 390 // Fill a transparent value so that if the plugin supports transparency that |
| 404 if (background_canvas_.get() && background_canvas_.get()->getDevice()) { | 391 // will work. |
| 405 // When a background canvas is given, we're in transparent mode. This means | 392 saved_canvas->drawColor(SkColorSetARGB(0, 0, 0, 0), SkXfermode::kSrc_Mode); |
| 406 // the plugin wants to have the image of the page in the canvas it's drawing | |
| 407 // into (which is windowless_canvases_) so it can do blending. So we copy | |
| 408 // the background bitmap into the windowless canvas. | |
| 409 const SkBitmap& background_bitmap = | |
| 410 skia::GetTopDevice(*background_canvas_)->accessBitmap(false); | |
| 411 saved_canvas->drawBitmap(background_bitmap, 0, 0); | |
| 412 } else { | |
| 413 // In non-transparent mode, the plugin doesn't care what's underneath, so we | |
| 414 // can just give it black. | |
| 415 SkPaint black_fill_paint; | |
| 416 black_fill_paint.setARGB(0xFF, 0x00, 0x00, 0x00); | |
| 417 saved_canvas->drawPaint(black_fill_paint); | |
| 418 } | |
| 419 | 393 |
| 420 // Bring the windowless canvas into the window coordinate system, which is | 394 // Bring the windowless canvas into the window coordinate system, which is |
| 421 // how the plugin expects to draw (since the windowless API was originally | 395 // how the plugin expects to draw (since the windowless API was originally |
| 422 // designed just for scribbling over the web page). | 396 // designed just for scribbling over the web page). |
| 423 saved_canvas->translate(SkIntToScalar(-delegate_->GetRect().x()), | 397 saved_canvas->translate(SkIntToScalar(-delegate_->GetRect().x()), |
| 424 SkIntToScalar(-delegate_->GetRect().y())); | 398 SkIntToScalar(-delegate_->GetRect().y())); |
| 425 | 399 |
| 426 // Before we send the invalidate, paint so that renderer uses the updated | 400 // Before we send the invalidate, paint so that renderer uses the updated |
| 427 // bitmap. | 401 // bitmap. |
| 428 delegate_->Paint(saved_canvas, offset_rect); | 402 delegate_->Paint(saved_canvas, offset_rect); |
| 429 | 403 |
| 430 saved_canvas->restore(); | 404 saved_canvas->restore(); |
| 431 #endif | 405 #endif |
| 432 } | 406 } |
| 433 | 407 |
| 434 void WebPluginProxy::UpdateGeometry( | 408 void WebPluginProxy::UpdateGeometry( |
| 435 const gfx::Rect& window_rect, | 409 const gfx::Rect& window_rect, |
| 436 const gfx::Rect& clip_rect, | 410 const gfx::Rect& clip_rect, |
| 437 const TransportDIB::Handle& windowless_buffer0, | 411 const TransportDIB::Handle& windowless_buffer0, |
| 438 const TransportDIB::Handle& windowless_buffer1, | 412 const TransportDIB::Handle& windowless_buffer1, |
| 439 int windowless_buffer_index, | 413 int windowless_buffer_index) { |
| 440 const TransportDIB::Handle& background_buffer, | |
| 441 bool transparent) { | |
| 442 gfx::Rect old = delegate_->GetRect(); | 414 gfx::Rect old = delegate_->GetRect(); |
| 443 gfx::Rect old_clip_rect = delegate_->GetClipRect(); | 415 gfx::Rect old_clip_rect = delegate_->GetClipRect(); |
| 444 transparent_ = transparent; | |
| 445 | 416 |
| 446 // Update the buffers before doing anything that could call into plugin code, | 417 // Update the buffers before doing anything that could call into plugin code, |
| 447 // so that we don't process buffer changes out of order if plugins make | 418 // so that we don't process buffer changes out of order if plugins make |
| 448 // synchronous calls that lead to nested UpdateGeometry calls. | 419 // synchronous calls that lead to nested UpdateGeometry calls. |
| 449 if (TransportDIB::is_valid_handle(windowless_buffer0)) { | 420 if (TransportDIB::is_valid_handle(windowless_buffer0)) { |
| 450 // The plugin's rect changed, so now we have new buffers to draw into. | 421 // The plugin's rect changed, so now we have new buffers to draw into. |
| 451 SetWindowlessBuffers(windowless_buffer0, | 422 SetWindowlessBuffers(windowless_buffer0, |
| 452 windowless_buffer1, | 423 windowless_buffer1, |
| 453 background_buffer, | |
| 454 window_rect); | 424 window_rect); |
| 455 } | 425 } |
| 456 | 426 |
| 457 DCHECK(0 <= windowless_buffer_index && windowless_buffer_index <= 1); | 427 DCHECK(0 <= windowless_buffer_index && windowless_buffer_index <= 1); |
| 458 windowless_buffer_index_ = windowless_buffer_index; | 428 windowless_buffer_index_ = windowless_buffer_index; |
| 459 #if defined(USE_X11) | 429 #if defined(USE_X11) |
| 460 delegate_->SetWindowlessShmPixmap(windowless_shm_pixmap()); | 430 delegate_->SetWindowlessShmPixmap(windowless_shm_pixmap()); |
| 461 #endif | 431 #endif |
| 462 | 432 |
| 463 #if defined(OS_MACOSX) | 433 #if defined(OS_MACOSX) |
| (...skipping 25 matching lines...) Expand all Loading... |
| 489 dib_handle)) { | 459 dib_handle)) { |
| 490 canvas->reset(NULL); | 460 canvas->reset(NULL); |
| 491 } | 461 } |
| 492 // The canvas does not own the section so we need to close it now. | 462 // The canvas does not own the section so we need to close it now. |
| 493 CloseHandle(dib_handle); | 463 CloseHandle(dib_handle); |
| 494 } | 464 } |
| 495 | 465 |
| 496 void WebPluginProxy::SetWindowlessBuffers( | 466 void WebPluginProxy::SetWindowlessBuffers( |
| 497 const TransportDIB::Handle& windowless_buffer0, | 467 const TransportDIB::Handle& windowless_buffer0, |
| 498 const TransportDIB::Handle& windowless_buffer1, | 468 const TransportDIB::Handle& windowless_buffer1, |
| 499 const TransportDIB::Handle& background_buffer, | |
| 500 const gfx::Rect& window_rect) { | 469 const gfx::Rect& window_rect) { |
| 501 CreateCanvasFromHandle(windowless_buffer0, | 470 CreateCanvasFromHandle(windowless_buffer0, |
| 502 window_rect, | 471 window_rect, |
| 503 &windowless_canvases_[0]); | 472 &windowless_canvases_[0]); |
| 504 if (!windowless_canvases_[0].get()) { | 473 if (!windowless_canvases_[0].get()) { |
| 505 windowless_canvases_[1].reset(NULL); | 474 windowless_canvases_[1].reset(NULL); |
| 506 background_canvas_.reset(NULL); | |
| 507 return; | 475 return; |
| 508 } | 476 } |
| 509 CreateCanvasFromHandle(windowless_buffer1, | 477 CreateCanvasFromHandle(windowless_buffer1, |
| 510 window_rect, | 478 window_rect, |
| 511 &windowless_canvases_[1]); | 479 &windowless_canvases_[1]); |
| 512 if (!windowless_canvases_[1].get()) { | 480 if (!windowless_canvases_[1].get()) { |
| 513 windowless_canvases_[0].reset(NULL); | 481 windowless_canvases_[0].reset(NULL); |
| 514 background_canvas_.reset(NULL); | |
| 515 return; | 482 return; |
| 516 } | 483 } |
| 517 | |
| 518 if (background_buffer) { | |
| 519 CreateCanvasFromHandle(background_buffer, | |
| 520 window_rect, | |
| 521 &background_canvas_); | |
| 522 if (!background_canvas_.get()) { | |
| 523 windowless_canvases_[0].reset(NULL); | |
| 524 windowless_canvases_[1].reset(NULL); | |
| 525 return; | |
| 526 } | |
| 527 } | |
| 528 } | 484 } |
| 529 | 485 |
| 530 #elif defined(OS_MACOSX) | 486 #elif defined(OS_MACOSX) |
| 531 | 487 |
| 532 void WebPluginProxy::CreateDIBAndCGContextFromHandle( | 488 void WebPluginProxy::CreateDIBAndCGContextFromHandle( |
| 533 const TransportDIB::Handle& dib_handle, | 489 const TransportDIB::Handle& dib_handle, |
| 534 const gfx::Rect& window_rect, | 490 const gfx::Rect& window_rect, |
| 535 scoped_ptr<TransportDIB>* dib_out, | 491 scoped_ptr<TransportDIB>* dib_out, |
| 536 base::mac::ScopedCFTypeRef<CGContextRef>* cg_context_out) { | 492 base::mac::ScopedCFTypeRef<CGContextRef>* cg_context_out) { |
| 537 // Convert the shared memory handle to a handle that works in our process, | 493 // Convert the shared memory handle to a handle that works in our process, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 550 CGContextTranslateCTM(cg_context, 0, window_rect.height()); | 506 CGContextTranslateCTM(cg_context, 0, window_rect.height()); |
| 551 CGContextScaleCTM(cg_context, 1, -1); | 507 CGContextScaleCTM(cg_context, 1, -1); |
| 552 } | 508 } |
| 553 dib_out->reset(dib); | 509 dib_out->reset(dib); |
| 554 cg_context_out->reset(cg_context); | 510 cg_context_out->reset(cg_context); |
| 555 } | 511 } |
| 556 | 512 |
| 557 void WebPluginProxy::SetWindowlessBuffers( | 513 void WebPluginProxy::SetWindowlessBuffers( |
| 558 const TransportDIB::Handle& windowless_buffer0, | 514 const TransportDIB::Handle& windowless_buffer0, |
| 559 const TransportDIB::Handle& windowless_buffer1, | 515 const TransportDIB::Handle& windowless_buffer1, |
| 560 const TransportDIB::Handle& background_buffer, | |
| 561 const gfx::Rect& window_rect) { | 516 const gfx::Rect& window_rect) { |
| 562 CreateDIBAndCGContextFromHandle(windowless_buffer0, | 517 CreateDIBAndCGContextFromHandle(windowless_buffer0, |
| 563 window_rect, | 518 window_rect, |
| 564 &windowless_dibs_[0], | 519 &windowless_dibs_[0], |
| 565 &windowless_contexts_[0]); | 520 &windowless_contexts_[0]); |
| 566 CreateDIBAndCGContextFromHandle(windowless_buffer1, | 521 CreateDIBAndCGContextFromHandle(windowless_buffer1, |
| 567 window_rect, | 522 window_rect, |
| 568 &windowless_dibs_[1], | 523 &windowless_dibs_[1], |
| 569 &windowless_contexts_[1]); | 524 &windowless_contexts_[1]); |
| 570 CreateDIBAndCGContextFromHandle(background_buffer, | |
| 571 window_rect, | |
| 572 &background_dib_, | |
| 573 &background_context_); | |
| 574 } | 525 } |
| 575 | 526 |
| 576 #elif defined(USE_X11) | 527 #elif defined(USE_X11) |
| 577 | 528 |
| 578 void WebPluginProxy::CreateDIBAndCanvasFromHandle( | 529 void WebPluginProxy::CreateDIBAndCanvasFromHandle( |
| 579 const TransportDIB::Handle& dib_handle, | 530 const TransportDIB::Handle& dib_handle, |
| 580 const gfx::Rect& window_rect, | 531 const gfx::Rect& window_rect, |
| 581 scoped_refptr<SharedTransportDIB>* dib_out, | 532 scoped_refptr<SharedTransportDIB>* dib_out, |
| 582 SkAutoTUnref<skia::PlatformCanvas>* canvas) { | 533 SkAutoTUnref<skia::PlatformCanvas>* canvas) { |
| 583 TransportDIB* dib = TransportDIB::Map(dib_handle); | 534 TransportDIB* dib = TransportDIB::Map(dib_handle); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 610 NULL, &shminfo, | 561 NULL, &shminfo, |
| 611 window_rect.width(), window_rect.height(), | 562 window_rect.width(), window_rect.height(), |
| 612 DefaultDepth(display, | 563 DefaultDepth(display, |
| 613 DefaultScreen(display))); | 564 DefaultScreen(display))); |
| 614 } | 565 } |
| 615 } | 566 } |
| 616 | 567 |
| 617 void WebPluginProxy::SetWindowlessBuffers( | 568 void WebPluginProxy::SetWindowlessBuffers( |
| 618 const TransportDIB::Handle& windowless_buffer0, | 569 const TransportDIB::Handle& windowless_buffer0, |
| 619 const TransportDIB::Handle& windowless_buffer1, | 570 const TransportDIB::Handle& windowless_buffer1, |
| 620 const TransportDIB::Handle& background_buffer, | |
| 621 const gfx::Rect& window_rect) { | 571 const gfx::Rect& window_rect) { |
| 622 CreateDIBAndCanvasFromHandle(windowless_buffer0, | 572 CreateDIBAndCanvasFromHandle(windowless_buffer0, |
| 623 window_rect, | 573 window_rect, |
| 624 &windowless_dibs_[0], | 574 &windowless_dibs_[0], |
| 625 &windowless_canvases_[0]); | 575 &windowless_canvases_[0]); |
| 626 CreateDIBAndCanvasFromHandle(windowless_buffer1, | 576 CreateDIBAndCanvasFromHandle(windowless_buffer1, |
| 627 window_rect, | 577 window_rect, |
| 628 &windowless_dibs_[1], | 578 &windowless_dibs_[1], |
| 629 &windowless_canvases_[1]); | 579 &windowless_canvases_[1]); |
| 630 CreateDIBAndCanvasFromHandle(background_buffer, | |
| 631 window_rect, | |
| 632 &background_dib_, | |
| 633 &background_canvas_); | |
| 634 | 580 |
| 635 // If SHM pixmaps support is available, create SHM pixmaps to pass to the | 581 // If SHM pixmaps support is available, create SHM pixmaps to pass to the |
| 636 // delegate for windowless plugin painting. | 582 // delegate for windowless plugin painting. |
| 637 if (delegate_->IsWindowless() && use_shm_pixmap_) { | 583 if (delegate_->IsWindowless() && use_shm_pixmap_) { |
| 638 CreateShmPixmapFromDIB(windowless_dibs_[0]->dib(), | 584 CreateShmPixmapFromDIB(windowless_dibs_[0]->dib(), |
| 639 window_rect, | 585 window_rect, |
| 640 &windowless_shm_pixmaps_[0]); | 586 &windowless_shm_pixmaps_[0]); |
| 641 CreateShmPixmapFromDIB(windowless_dibs_[1]->dib(), | 587 CreateShmPixmapFromDIB(windowless_dibs_[1]->dib(), |
| 642 window_rect, | 588 window_rect, |
| 643 &windowless_shm_pixmaps_[1]); | 589 &windowless_shm_pixmaps_[1]); |
| 644 } | 590 } |
| 645 } | 591 } |
| 646 | 592 |
| 647 #elif defined(OS_ANDROID) | 593 #elif defined(OS_ANDROID) |
| 648 | 594 |
| 649 void WebPluginProxy::SetWindowlessBuffers( | 595 void WebPluginProxy::SetWindowlessBuffers( |
| 650 const TransportDIB::Handle& windowless_buffer0, | 596 const TransportDIB::Handle& windowless_buffer0, |
| 651 const TransportDIB::Handle& windowless_buffer1, | 597 const TransportDIB::Handle& windowless_buffer1, |
| 652 const TransportDIB::Handle& background_buffer, | |
| 653 const gfx::Rect& window_rect) { | 598 const gfx::Rect& window_rect) { |
| 654 NOTIMPLEMENTED(); | 599 NOTIMPLEMENTED(); |
| 655 } | 600 } |
| 656 | 601 |
| 657 #endif | 602 #endif |
| 658 | 603 |
| 659 void WebPluginProxy::CancelDocumentLoad() { | 604 void WebPluginProxy::CancelDocumentLoad() { |
| 660 Send(new PluginHostMsg_CancelDocumentLoad(route_id_)); | 605 Send(new PluginHostMsg_CancelDocumentLoad(route_id_)); |
| 661 } | 606 } |
| 662 | 607 |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 782 int input_type; | 727 int input_type; |
| 783 gfx::Rect caret_rect; | 728 gfx::Rect caret_rect; |
| 784 if (!delegate_->GetIMEStatus(&input_type, &caret_rect)) | 729 if (!delegate_->GetIMEStatus(&input_type, &caret_rect)) |
| 785 return; | 730 return; |
| 786 | 731 |
| 787 Send(new PluginHostMsg_NotifyIMEStatus(route_id_, input_type, caret_rect)); | 732 Send(new PluginHostMsg_NotifyIMEStatus(route_id_, input_type, caret_rect)); |
| 788 } | 733 } |
| 789 #endif | 734 #endif |
| 790 | 735 |
| 791 } // namespace content | 736 } // namespace content |
| OLD | NEW |