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 |