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/renderer/webplugin_delegate_proxy.h" | 5 #include "content/renderer/webplugin_delegate_proxy.h" |
6 | 6 |
7 #if defined(TOOLKIT_GTK) | 7 #if defined(TOOLKIT_GTK) |
8 #include <gtk/gtk.h> | 8 #include <gtk/gtk.h> |
9 #elif defined(USE_X11) | 9 #elif defined(USE_X11) |
10 #include <cairo/cairo.h> | 10 #include <cairo/cairo.h> |
(...skipping 30 matching lines...) Expand all Loading... |
41 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h" | 41 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h" |
42 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" | 42 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" |
43 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 43 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
44 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" | 44 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" |
45 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebDragData.
h" | 45 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebDragData.
h" |
46 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" | 46 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" |
47 #include "ui/gfx/blit.h" | 47 #include "ui/gfx/blit.h" |
48 #include "ui/gfx/canvas.h" | 48 #include "ui/gfx/canvas.h" |
49 #include "ui/gfx/native_widget_types.h" | 49 #include "ui/gfx/native_widget_types.h" |
50 #include "ui/gfx/size.h" | 50 #include "ui/gfx/size.h" |
| 51 #include "ui/gfx/skia_util.h" |
51 #include "webkit/glue/webkit_glue.h" | 52 #include "webkit/glue/webkit_glue.h" |
52 #include "webkit/plugins/npapi/webplugin.h" | 53 #include "webkit/plugins/npapi/webplugin.h" |
53 #include "webkit/plugins/plugin_constants.h" | 54 #include "webkit/plugins/plugin_constants.h" |
54 #include "webkit/plugins/sad_plugin.h" | 55 #include "webkit/plugins/sad_plugin.h" |
55 | 56 |
56 #if defined(OS_POSIX) | 57 #if defined(OS_POSIX) |
57 #include "ipc/ipc_channel_posix.h" | 58 #include "ipc/ipc_channel_posix.h" |
58 #endif | 59 #endif |
59 | 60 |
60 #if defined(OS_MACOSX) | 61 #if defined(OS_MACOSX) |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 uses_compositor_(false), | 205 uses_compositor_(false), |
205 #elif defined(OS_WIN) | 206 #elif defined(OS_WIN) |
206 dummy_activation_window_(NULL), | 207 dummy_activation_window_(NULL), |
207 #endif | 208 #endif |
208 window_(gfx::kNullPluginWindow), | 209 window_(gfx::kNullPluginWindow), |
209 mime_type_(mime_type), | 210 mime_type_(mime_type), |
210 instance_id_(MSG_ROUTING_NONE), | 211 instance_id_(MSG_ROUTING_NONE), |
211 npobject_(NULL), | 212 npobject_(NULL), |
212 sad_plugin_(NULL), | 213 sad_plugin_(NULL), |
213 invalidate_pending_(false), | 214 invalidate_pending_(false), |
214 transparent_(false), | |
215 front_buffer_index_(0), | 215 front_buffer_index_(0), |
216 page_url_(render_view_->webview()->mainFrame()->document().url()) { | 216 page_url_(render_view_->webview()->mainFrame()->document().url()) { |
217 } | 217 } |
218 | 218 |
219 WebPluginDelegateProxy::~WebPluginDelegateProxy() { | 219 WebPluginDelegateProxy::~WebPluginDelegateProxy() { |
220 if (npobject_) | 220 if (npobject_) |
221 WebBindings::releaseObject(npobject_); | 221 WebBindings::releaseObject(npobject_); |
222 } | 222 } |
223 | 223 |
224 WebPluginDelegateProxy::SharedBitmap::SharedBitmap() {} | 224 WebPluginDelegateProxy::SharedBitmap::SharedBitmap() {} |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 // the window script object. The window script object stub is unique to the | 272 // the window script object. The window script object stub is unique to the |
273 // plugin instance, so this won't affect other instances. | 273 // plugin instance, so this won't affect other instances. |
274 window_script_object_->DeleteSoon(); | 274 window_script_object_->DeleteSoon(); |
275 } | 275 } |
276 | 276 |
277 plugin_ = NULL; | 277 plugin_ = NULL; |
278 | 278 |
279 MessageLoop::current()->DeleteSoon(FROM_HERE, this); | 279 MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
280 } | 280 } |
281 | 281 |
282 // Returns true if the given Silverlight 'background' value corresponds to | |
283 // one that should make the plugin transparent. See: | |
284 // http://msdn.microsoft.com/en-us/library/cc838148(VS.95).aspx | |
285 // for possible values. | |
286 static bool SilverlightColorIsTransparent(const std::string& color) { | |
287 if (StartsWithASCII(color, "#", false)) { | |
288 // If it's #ARGB or #AARRGGBB check the alpha; if not it's an RGB form and | |
289 // it's not transparent. | |
290 if ((color.length() == 5 && !StartsWithASCII(color, "#F", false)) || | |
291 (color.length() == 9 && !StartsWithASCII(color, "#FF", false))) | |
292 return true; | |
293 } else if (StartsWithASCII(color, "sc#", false)) { | |
294 // It's either sc#A,R,G,B or sc#R,G,B; if the former, check the alpha. | |
295 if (color.length() < 4) | |
296 return false; | |
297 std::string value_string = color.substr(3, std::string::npos); | |
298 std::vector<std::string> components; | |
299 base::SplitString(value_string, ',', &components); | |
300 if (components.size() == 4 && !StartsWithASCII(components[0], "1", false)) | |
301 return true; | |
302 } else if (LowerCaseEqualsASCII(color, "transparent")) { | |
303 return true; | |
304 } | |
305 // Anything else is a named, opaque color or an RGB form with no alpha. | |
306 return false; | |
307 } | |
308 | |
309 bool WebPluginDelegateProxy::Initialize( | 282 bool WebPluginDelegateProxy::Initialize( |
310 const GURL& url, | 283 const GURL& url, |
311 const std::vector<std::string>& arg_names, | 284 const std::vector<std::string>& arg_names, |
312 const std::vector<std::string>& arg_values, | 285 const std::vector<std::string>& arg_values, |
313 webkit::npapi::WebPlugin* plugin, | 286 webkit::npapi::WebPlugin* plugin, |
314 bool load_manually) { | 287 bool load_manually) { |
315 // TODO(shess): Attempt to work around http://crbug.com/97285 and | 288 // TODO(shess): Attempt to work around http://crbug.com/97285 and |
316 // http://crbug.com/141055 by retrying the connection. Reports seem | 289 // http://crbug.com/141055 by retrying the connection. Reports seem |
317 // to indicate that the plugin hasn't crashed, and that the problem | 290 // to indicate that the plugin hasn't crashed, and that the problem |
318 // is not 100% persistent. | 291 // is not 100% persistent. |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 | 358 |
386 channel_host_->AddRoute(instance_id_, this, NULL); | 359 channel_host_->AddRoute(instance_id_, this, NULL); |
387 | 360 |
388 // Now tell the PluginInstance in the plugin process to initialize. | 361 // Now tell the PluginInstance in the plugin process to initialize. |
389 PluginMsg_Init_Params params; | 362 PluginMsg_Init_Params params; |
390 params.url = url; | 363 params.url = url; |
391 params.page_url = page_url_; | 364 params.page_url = page_url_; |
392 params.arg_names = arg_names; | 365 params.arg_names = arg_names; |
393 params.arg_values = arg_values; | 366 params.arg_values = arg_values; |
394 params.host_render_view_routing_id = render_view_->routing_id(); | 367 params.host_render_view_routing_id = render_view_->routing_id(); |
395 | |
396 bool flash = LowerCaseEqualsASCII(mime_type_, kFlashPluginSwfMimeType); | |
397 bool silverlight = | |
398 StartsWithASCII(mime_type_, "application/x-silverlight", false); | |
399 for (size_t i = 0; i < arg_names.size(); ++i) { | |
400 if ((flash && LowerCaseEqualsASCII(arg_names[i], "wmode") && | |
401 LowerCaseEqualsASCII(arg_values[i], "transparent")) || | |
402 (silverlight && LowerCaseEqualsASCII(arg_names[i], "background") && | |
403 SilverlightColorIsTransparent(arg_values[i]))) { | |
404 transparent_ = true; | |
405 } | |
406 } | |
407 params.load_manually = load_manually; | 368 params.load_manually = load_manually; |
408 | 369 |
409 plugin_ = plugin; | 370 plugin_ = plugin; |
410 | 371 |
411 result = false; | 372 result = false; |
412 IPC::Message* msg = new PluginMsg_Init(instance_id_, params, &result); | 373 Send(new PluginMsg_Init(instance_id_, params, &result)); |
413 Send(msg); | |
414 | 374 |
415 if (!result) | 375 if (!result) |
416 LOG(ERROR) << "PluginMsg_Init returned false"; | 376 LOG(ERROR) << "PluginMsg_Init returned false"; |
417 | 377 |
418 render_view_->RegisterPluginDelegate(this); | 378 render_view_->RegisterPluginDelegate(this); |
419 | 379 |
420 return result; | 380 return result; |
421 } | 381 } |
422 | 382 |
423 bool WebPluginDelegateProxy::Send(IPC::Message* msg) { | 383 bool WebPluginDelegateProxy::Send(IPC::Message* msg) { |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
573 } | 533 } |
574 | 534 |
575 void WebPluginDelegateProxy::SendUpdateGeometry( | 535 void WebPluginDelegateProxy::SendUpdateGeometry( |
576 bool bitmaps_changed) { | 536 bool bitmaps_changed) { |
577 PluginMsg_UpdateGeometry_Param param; | 537 PluginMsg_UpdateGeometry_Param param; |
578 param.window_rect = plugin_rect_; | 538 param.window_rect = plugin_rect_; |
579 param.clip_rect = clip_rect_; | 539 param.clip_rect = clip_rect_; |
580 param.windowless_buffer0 = TransportDIB::DefaultHandleValue(); | 540 param.windowless_buffer0 = TransportDIB::DefaultHandleValue(); |
581 param.windowless_buffer1 = TransportDIB::DefaultHandleValue(); | 541 param.windowless_buffer1 = TransportDIB::DefaultHandleValue(); |
582 param.windowless_buffer_index = back_buffer_index(); | 542 param.windowless_buffer_index = back_buffer_index(); |
583 param.background_buffer = TransportDIB::DefaultHandleValue(); | |
584 param.transparent = transparent_; | |
585 | 543 |
586 #if defined(OS_POSIX) | 544 #if defined(OS_POSIX) |
587 // If we're using POSIX mmap'd TransportDIBs, sending the handle across | 545 // If we're using POSIX mmap'd TransportDIBs, sending the handle across |
588 // IPC establishes a new mapping rather than just sending a window ID, | 546 // IPC establishes a new mapping rather than just sending a window ID, |
589 // so only do so if we've actually changed the shared memory bitmaps. | 547 // so only do so if we've actually changed the shared memory bitmaps. |
590 if (bitmaps_changed) | 548 if (bitmaps_changed) |
591 #endif | 549 #endif |
592 { | 550 { |
593 if (transport_stores_[0].dib.get()) | 551 if (transport_stores_[0].dib.get()) |
594 CopyTransportDIBHandleForMessage(transport_stores_[0].dib->handle(), | 552 CopyTransportDIBHandleForMessage(transport_stores_[0].dib->handle(), |
595 ¶m.windowless_buffer0, | 553 ¶m.windowless_buffer0, |
596 channel_host_->peer_pid()); | 554 channel_host_->peer_pid()); |
597 | 555 |
598 if (transport_stores_[1].dib.get()) | 556 if (transport_stores_[1].dib.get()) |
599 CopyTransportDIBHandleForMessage(transport_stores_[1].dib->handle(), | 557 CopyTransportDIBHandleForMessage(transport_stores_[1].dib->handle(), |
600 ¶m.windowless_buffer1, | 558 ¶m.windowless_buffer1, |
601 channel_host_->peer_pid()); | 559 channel_host_->peer_pid()); |
602 | |
603 if (background_store_.dib.get()) | |
604 CopyTransportDIBHandleForMessage(background_store_.dib->handle(), | |
605 ¶m.background_buffer, | |
606 channel_host_->peer_pid()); | |
607 } | 560 } |
608 | 561 |
609 IPC::Message* msg; | 562 IPC::Message* msg; |
610 #if defined(OS_WIN) | 563 #if defined(OS_WIN) |
611 if (UseSynchronousGeometryUpdates()) { | 564 if (UseSynchronousGeometryUpdates()) { |
612 msg = new PluginMsg_UpdateGeometrySync(instance_id_, param); | 565 msg = new PluginMsg_UpdateGeometrySync(instance_id_, param); |
613 } else // NOLINT | 566 } else // NOLINT |
614 #endif | 567 #endif |
615 { | 568 { |
616 msg = new PluginMsg_UpdateGeometry(instance_id_, param); | 569 msg = new PluginMsg_UpdateGeometry(instance_id_, param); |
(...skipping 21 matching lines...) Expand all Loading... |
638 | 591 |
639 bool bitmaps_changed = false; | 592 bool bitmaps_changed = false; |
640 | 593 |
641 if (uses_shared_bitmaps_) { | 594 if (uses_shared_bitmaps_) { |
642 if (!front_buffer_canvas() || | 595 if (!front_buffer_canvas() || |
643 (window_rect.width() != front_buffer_canvas()->getDevice()->width() || | 596 (window_rect.width() != front_buffer_canvas()->getDevice()->width() || |
644 window_rect.height() != front_buffer_canvas()->getDevice()->height())) | 597 window_rect.height() != front_buffer_canvas()->getDevice()->height())) |
645 { | 598 { |
646 bitmaps_changed = true; | 599 bitmaps_changed = true; |
647 | 600 |
648 bool needs_background_store = transparent_; | |
649 #if defined(OS_MACOSX) | |
650 // We don't support transparency under QuickDraw, and CoreGraphics | |
651 // preserves transparency information (and does the compositing itself) | |
652 // so plugins don't need access to the page background. | |
653 needs_background_store = false; | |
654 #endif | |
655 | |
656 // Create a shared memory section that the plugin paints into | 601 // Create a shared memory section that the plugin paints into |
657 // asynchronously. | 602 // asynchronously. |
658 ResetWindowlessBitmaps(); | 603 ResetWindowlessBitmaps(); |
659 if (!window_rect.IsEmpty()) { | 604 if (!window_rect.IsEmpty()) { |
660 if (!CreateSharedBitmap(&transport_stores_[0].dib, | 605 if (!CreateSharedBitmap(&transport_stores_[0].dib, |
661 &transport_stores_[0].canvas) || | 606 &transport_stores_[0].canvas) || |
662 !CreateSharedBitmap(&transport_stores_[1].dib, | 607 !CreateSharedBitmap(&transport_stores_[1].dib, |
663 &transport_stores_[1].canvas) || | 608 &transport_stores_[1].canvas)) { |
664 (needs_background_store && | |
665 !CreateSharedBitmap(&background_store_.dib, | |
666 &background_store_.canvas))) { | |
667 DCHECK(false); | 609 DCHECK(false); |
668 ResetWindowlessBitmaps(); | 610 ResetWindowlessBitmaps(); |
669 return; | 611 return; |
670 } | 612 } |
671 } | 613 } |
672 } | 614 } |
673 } | 615 } |
674 | 616 |
675 SendUpdateGeometry(bitmaps_changed); | 617 SendUpdateGeometry(bitmaps_changed); |
676 } | 618 } |
677 | 619 |
678 void WebPluginDelegateProxy::ResetWindowlessBitmaps() { | 620 void WebPluginDelegateProxy::ResetWindowlessBitmaps() { |
679 transport_stores_[0].dib.reset(); | 621 transport_stores_[0].dib.reset(); |
680 transport_stores_[1].dib.reset(); | 622 transport_stores_[1].dib.reset(); |
681 background_store_.dib.reset(); | |
682 | 623 |
683 transport_stores_[0].canvas.reset(); | 624 transport_stores_[0].canvas.reset(); |
684 transport_stores_[1].canvas.reset(); | 625 transport_stores_[1].canvas.reset(); |
685 background_store_.canvas.reset(); | |
686 transport_store_painted_ = gfx::Rect(); | 626 transport_store_painted_ = gfx::Rect(); |
687 front_buffer_diff_ = gfx::Rect(); | 627 front_buffer_diff_ = gfx::Rect(); |
688 } | 628 } |
689 | 629 |
690 static size_t BitmapSizeForPluginRect(const gfx::Rect& plugin_rect) { | 630 static size_t BitmapSizeForPluginRect(const gfx::Rect& plugin_rect) { |
691 const size_t stride = | 631 const size_t stride = |
692 skia::PlatformCanvas::StrideForWidth(plugin_rect.width()); | 632 skia::PlatformCanvas::StrideForWidth(plugin_rect.width()); |
693 return stride * plugin_rect.height(); | 633 return stride * plugin_rect.height(); |
694 } | 634 } |
695 | 635 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
755 } | 695 } |
756 | 696 |
757 if (!uses_shared_bitmaps_) | 697 if (!uses_shared_bitmaps_) |
758 return; | 698 return; |
759 | 699 |
760 // We got a paint before the plugin's coordinates, so there's no buffer to | 700 // We got a paint before the plugin's coordinates, so there's no buffer to |
761 // copy from. | 701 // copy from. |
762 if (!front_buffer_canvas()) | 702 if (!front_buffer_canvas()) |
763 return; | 703 return; |
764 | 704 |
765 // We're using the native OS APIs from here on out. | |
766 if (!skia::SupportsPlatformPaint(canvas)) { | |
767 // TODO(alokp): Implement this path. | |
768 // This block will only get hit with --enable-accelerated-drawing flag. | |
769 // With accelerated canvas, we do not have a bitmap that can be provided | |
770 // to the plugin for compositing. We may have to implement a solution | |
771 // described in crbug.com/12586. | |
772 DLOG(WARNING) << "Could not paint plugin"; | |
773 return; | |
774 } | |
775 skia::ScopedPlatformPaint scoped_platform_paint(canvas); | |
776 gfx::NativeDrawingContext context = | |
777 scoped_platform_paint.GetPlatformSurface(); | |
778 | |
779 gfx::Rect offset_rect = rect; | 705 gfx::Rect offset_rect = rect; |
780 offset_rect.Offset(-plugin_rect_.x(), -plugin_rect_.y()); | 706 offset_rect.Offset(-plugin_rect_.x(), -plugin_rect_.y()); |
781 gfx::Rect canvas_rect = offset_rect; | |
782 #if defined(OS_MACOSX) | |
783 // The canvases are flipped relative to the context, so flip the rect too. | |
784 FlipRectVerticallyWithHeight(&canvas_rect, plugin_rect_.height()); | |
785 #endif | |
786 | |
787 bool background_changed = false; | |
788 if (background_store_.canvas.get() && BackgroundChanged(context, rect)) { | |
789 background_changed = true; | |
790 BlitContextToCanvas(background_store_.canvas.get(), canvas_rect, | |
791 context, rect.origin()); | |
792 } | |
793 | 707 |
794 // transport_store_painted_ is really a bounding box, so in principle this | 708 // transport_store_painted_ is really a bounding box, so in principle this |
795 // check could falsely indicate that we don't need to paint offset_rect, but | 709 // check could falsely indicate that we don't need to paint offset_rect, but |
796 // in practice it works fine. | 710 // in practice it works fine. |
797 if (background_changed || | 711 if (!transport_store_painted_.Contains(offset_rect)) { |
798 !transport_store_painted_.Contains(offset_rect)) { | |
799 Send(new PluginMsg_Paint(instance_id_, offset_rect)); | 712 Send(new PluginMsg_Paint(instance_id_, offset_rect)); |
800 // Since the plugin is not blocked on the renderer in this context, there is | 713 // Since the plugin is not blocked on the renderer in this context, there is |
801 // a chance that it will begin repainting the back-buffer before we complete | 714 // a chance that it will begin repainting the back-buffer before we complete |
802 // capturing the data. Buffer flipping would increase that risk because | 715 // capturing the data. Buffer flipping would increase that risk because |
803 // geometry update is asynchronous, so we don't want to use buffer flipping | 716 // geometry update is asynchronous, so we don't want to use buffer flipping |
804 // here. | 717 // here. |
805 UpdateFrontBuffer(offset_rect, false); | 718 UpdateFrontBuffer(offset_rect, false); |
806 } | 719 } |
807 | 720 |
808 #if defined(OS_MACOSX) | 721 const SkBitmap& bitmap = |
809 // The canvases are flipped relative to the context, so flip the context's | 722 front_buffer_canvas()->getDevice()->accessBitmap(false); |
810 // coordinate space so that the blit unflips the content. | 723 SkPaint paint; |
811 CGContextSaveGState(context); | 724 paint.setXfermodeMode(SkXfermode::kSrcATop_Mode); |
812 CGContextScaleCTM(context, 1, -1); | 725 SkIRect src_rect = gfx::RectToSkIRect(offset_rect); |
813 rect.set_y(-rect.bottom()); | 726 canvas->drawBitmapRect(bitmap, |
814 #endif | 727 &src_rect, |
815 BlitCanvasToContext(context, | 728 gfx::RectToSkRect(rect), |
816 rect, | 729 &paint); |
817 front_buffer_canvas(), | |
818 offset_rect.origin()); | |
819 #if defined(OS_MACOSX) | |
820 CGContextRestoreGState(context); | |
821 #endif | |
822 | 730 |
823 if (invalidate_pending_) { | 731 if (invalidate_pending_) { |
824 // Only send the PaintAck message if this paint is in response to an | 732 // Only send the PaintAck message if this paint is in response to an |
825 // invalidate from the plugin, since this message acts as an access token | 733 // invalidate from the plugin, since this message acts as an access token |
826 // to ensure only one process is using the transport dib at a time. | 734 // to ensure only one process is using the transport dib at a time. |
827 invalidate_pending_ = false; | 735 invalidate_pending_ = false; |
828 Send(new PluginMsg_DidPaint(instance_id_)); | 736 Send(new PluginMsg_DidPaint(instance_id_)); |
829 } | 737 } |
830 } | 738 } |
831 | 739 |
832 bool WebPluginDelegateProxy::BackgroundChanged( | |
833 gfx::NativeDrawingContext context, | |
834 const gfx::Rect& rect) { | |
835 #if defined(OS_ANDROID) | |
836 NOTIMPLEMENTED(); | |
837 #else | |
838 #if defined(OS_WIN) | |
839 HBITMAP hbitmap = static_cast<HBITMAP>(GetCurrentObject(context, OBJ_BITMAP)); | |
840 if (hbitmap == NULL) { | |
841 NOTREACHED(); | |
842 return true; | |
843 } | |
844 | |
845 BITMAP bitmap = { 0 }; | |
846 int result = GetObject(hbitmap, sizeof(bitmap), &bitmap); | |
847 if (!result) { | |
848 NOTREACHED(); | |
849 return true; | |
850 } | |
851 | |
852 XFORM xf; | |
853 if (!GetWorldTransform(context, &xf)) { | |
854 NOTREACHED(); | |
855 return true; | |
856 } | |
857 | |
858 // The damaged rect that we're given can be larger than the bitmap, so | |
859 // intersect their rects first. | |
860 gfx::Rect bitmap_rect(static_cast<int>(-xf.eDx), static_cast<int>(-xf.eDy), | |
861 bitmap.bmWidth, bitmap.bmHeight); | |
862 gfx::Rect check_rect = gfx::IntersectRects(rect, bitmap_rect); | |
863 int row_byte_size = check_rect.width() * (bitmap.bmBitsPixel / 8); | |
864 for (int y = check_rect.y(); y < check_rect.bottom(); y++) { | |
865 char* hdc_row_start = static_cast<char*>(bitmap.bmBits) + | |
866 (y + static_cast<int>(xf.eDy)) * bitmap.bmWidthBytes + | |
867 (check_rect.x() + static_cast<int>(xf.eDx)) * (bitmap.bmBitsPixel / 8); | |
868 | |
869 // getAddr32 doesn't use the translation units, so we have to subtract | |
870 // the plugin origin from the coordinates. | |
871 uint32_t* canvas_row_start = | |
872 background_store_.canvas->getDevice()->accessBitmap(true).getAddr32( | |
873 check_rect.x() - plugin_rect_.x(), y - plugin_rect_.y()); | |
874 if (memcmp(hdc_row_start, canvas_row_start, row_byte_size) != 0) | |
875 return true; | |
876 } | |
877 #else | |
878 #if defined(OS_MACOSX) | |
879 // If there is a translation on the content area context, we need to account | |
880 // for it; the context may be a subset of the full content area with a | |
881 // transform that makes the coordinates work out. | |
882 CGAffineTransform transform = CGContextGetCTM(context); | |
883 bool flipped = fabs(transform.d + 1) < 0.0001; | |
884 CGFloat context_offset_x = -transform.tx; | |
885 CGFloat context_offset_y = flipped ? transform.ty - | |
886 CGBitmapContextGetHeight(context) | |
887 : -transform.ty; | |
888 gfx::Rect full_content_rect(context_offset_x, context_offset_y, | |
889 CGBitmapContextGetWidth(context), | |
890 CGBitmapContextGetHeight(context)); | |
891 #else | |
892 cairo_surface_t* page_surface = cairo_get_target(context); | |
893 DCHECK_EQ(cairo_surface_get_type(page_surface), CAIRO_SURFACE_TYPE_IMAGE); | |
894 DCHECK_EQ(cairo_image_surface_get_format(page_surface), CAIRO_FORMAT_ARGB32); | |
895 | |
896 // Transform context coordinates into surface coordinates. | |
897 double page_x_double = 0; | |
898 double page_y_double = 0; | |
899 cairo_device_to_user(context, &page_x_double, &page_y_double); | |
900 gfx::Rect full_content_rect(static_cast<int>(page_x_double), | |
901 static_cast<int>(page_y_double), | |
902 cairo_image_surface_get_width(page_surface), | |
903 cairo_image_surface_get_height(page_surface)); | |
904 #endif | |
905 // According to comments in the Windows code, the damage rect that we're given | |
906 // may project outside the image, so intersect their rects. | |
907 gfx::Rect content_rect = gfx::IntersectRects(rect, full_content_rect); | |
908 | |
909 #if defined(OS_MACOSX) | |
910 const unsigned char* page_bytes = static_cast<const unsigned char*>( | |
911 CGBitmapContextGetData(context)); | |
912 int page_stride = CGBitmapContextGetBytesPerRow(context); | |
913 int page_start_x = content_rect.x() - context_offset_x; | |
914 int page_start_y = content_rect.y() - context_offset_y; | |
915 | |
916 skia::ScopedPlatformPaint scoped_platform_paint( | |
917 background_store_.canvas.get()); | |
918 CGContextRef bg_context = scoped_platform_paint.GetPlatformSurface(); | |
919 | |
920 DCHECK_EQ(CGBitmapContextGetBitsPerPixel(context), | |
921 CGBitmapContextGetBitsPerPixel(bg_context)); | |
922 const unsigned char* bg_bytes = static_cast<const unsigned char*>( | |
923 CGBitmapContextGetData(bg_context)); | |
924 int full_bg_width = CGBitmapContextGetWidth(bg_context); | |
925 int full_bg_height = CGBitmapContextGetHeight(bg_context); | |
926 int bg_stride = CGBitmapContextGetBytesPerRow(bg_context); | |
927 int bg_last_row = CGBitmapContextGetHeight(bg_context) - 1; | |
928 | |
929 int bytes_per_pixel = CGBitmapContextGetBitsPerPixel(context) / 8; | |
930 #else | |
931 cairo_surface_flush(page_surface); | |
932 const unsigned char* page_bytes = cairo_image_surface_get_data(page_surface); | |
933 int page_stride = cairo_image_surface_get_stride(page_surface); | |
934 int page_start_x = content_rect.x() - static_cast<int>(page_x_double); | |
935 int page_start_y = content_rect.y() - static_cast<int>(page_y_double); | |
936 | |
937 skia::ScopedPlatformPaint scoped_platform_paint( | |
938 background_store_.canvas.get()); | |
939 cairo_surface_t* bg_surface =cairo_get_target( | |
940 scoped_platform_paint.GetPlatformSurface()); | |
941 DCHECK_EQ(cairo_surface_get_type(bg_surface), CAIRO_SURFACE_TYPE_IMAGE); | |
942 DCHECK_EQ(cairo_image_surface_get_format(bg_surface), CAIRO_FORMAT_ARGB32); | |
943 cairo_surface_flush(bg_surface); | |
944 const unsigned char* bg_bytes = cairo_image_surface_get_data(bg_surface); | |
945 int full_bg_width = cairo_image_surface_get_width(bg_surface); | |
946 int full_bg_height = cairo_image_surface_get_height(bg_surface); | |
947 int bg_stride = cairo_image_surface_get_stride(bg_surface); | |
948 | |
949 int bytes_per_pixel = 4; // ARGB32 = 4 bytes per pixel. | |
950 #endif | |
951 | |
952 int damage_width = content_rect.width(); | |
953 int damage_height = content_rect.height(); | |
954 | |
955 int bg_start_x = rect.x() - plugin_rect_.x(); | |
956 int bg_start_y = rect.y() - plugin_rect_.y(); | |
957 // The damage rect is supposed to have been intersected with the plugin rect; | |
958 // double-check, since if it hasn't we'll walk off the end of the buffer. | |
959 DCHECK_LE(bg_start_x + damage_width, full_bg_width); | |
960 DCHECK_LE(bg_start_y + damage_height, full_bg_height); | |
961 | |
962 int bg_x_byte_offset = bg_start_x * bytes_per_pixel; | |
963 int page_x_byte_offset = page_start_x * bytes_per_pixel; | |
964 for (int row = 0; row < damage_height; ++row) { | |
965 int page_offset = page_stride * (page_start_y + row) + page_x_byte_offset; | |
966 int bg_y = bg_start_y + row; | |
967 #if defined(OS_MACOSX) | |
968 // The background buffer is upside down relative to the content. | |
969 bg_y = bg_last_row - bg_y; | |
970 #endif | |
971 int bg_offset = bg_stride * bg_y + bg_x_byte_offset; | |
972 if (memcmp(page_bytes + page_offset, | |
973 bg_bytes + bg_offset, | |
974 damage_width * bytes_per_pixel) != 0) | |
975 return true; | |
976 } | |
977 #endif | |
978 #endif // OS_ANDROID | |
979 | |
980 return false; | |
981 } | |
982 | |
983 NPObject* WebPluginDelegateProxy::GetPluginScriptableObject() { | 740 NPObject* WebPluginDelegateProxy::GetPluginScriptableObject() { |
984 if (npobject_) | 741 if (npobject_) |
985 return WebBindings::retainObject(npobject_); | 742 return WebBindings::retainObject(npobject_); |
986 | 743 |
987 int route_id = MSG_ROUTING_NONE; | 744 int route_id = MSG_ROUTING_NONE; |
988 Send(new PluginMsg_GetPluginScriptableObject(instance_id_, &route_id)); | 745 Send(new PluginMsg_GetPluginScriptableObject(instance_id_, &route_id)); |
989 if (route_id == MSG_ROUTING_NONE) | 746 if (route_id == MSG_ROUTING_NONE) |
990 return NULL; | 747 return NULL; |
991 | 748 |
992 npobject_ = NPObjectProxy::Create( | 749 npobject_ = NPObjectProxy::Create( |
(...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1542 | 1299 |
1543 void WebPluginDelegateProxy::OnURLRedirectResponse(bool allow, | 1300 void WebPluginDelegateProxy::OnURLRedirectResponse(bool allow, |
1544 int resource_id) { | 1301 int resource_id) { |
1545 if (!plugin_) | 1302 if (!plugin_) |
1546 return; | 1303 return; |
1547 | 1304 |
1548 plugin_->URLRedirectResponse(allow, resource_id); | 1305 plugin_->URLRedirectResponse(allow, resource_id); |
1549 } | 1306 } |
1550 | 1307 |
1551 } // namespace content | 1308 } // namespace content |
OLD | NEW |