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 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
395 | 396 |
396 bool flash = LowerCaseEqualsASCII(mime_type_, kFlashPluginSwfMimeType); | 397 bool flash = LowerCaseEqualsASCII(mime_type_, kFlashPluginSwfMimeType); |
397 bool silverlight = | 398 bool silverlight = |
398 StartsWithASCII(mime_type_, "application/x-silverlight", false); | 399 StartsWithASCII(mime_type_, "application/x-silverlight", false); |
399 for (size_t i = 0; i < arg_names.size(); ++i) { | 400 for (size_t i = 0; i < arg_names.size(); ++i) { |
400 if ((flash && LowerCaseEqualsASCII(arg_names[i], "wmode") && | 401 if ((flash && LowerCaseEqualsASCII(arg_names[i], "wmode") && |
401 LowerCaseEqualsASCII(arg_values[i], "transparent")) || | 402 LowerCaseEqualsASCII(arg_values[i], "transparent")) || |
402 (silverlight && LowerCaseEqualsASCII(arg_names[i], "background") && | 403 (silverlight && LowerCaseEqualsASCII(arg_names[i], "background") && |
403 SilverlightColorIsTransparent(arg_values[i]))) { | 404 SilverlightColorIsTransparent(arg_values[i]))) { |
404 transparent_ = true; | 405 transparent_ = true; |
406 RenderThread::Get()->RecordUserMetrics("Plugin_Transparent"); | |
405 } | 407 } |
406 } | 408 } |
407 params.load_manually = load_manually; | 409 params.load_manually = load_manually; |
408 | 410 |
409 plugin_ = plugin; | 411 plugin_ = plugin; |
410 | 412 |
411 result = false; | 413 result = false; |
412 IPC::Message* msg = new PluginMsg_Init(instance_id_, params, &result); | 414 Send(new PluginMsg_Init(instance_id_, params, &result)); |
413 Send(msg); | |
414 | 415 |
415 if (!result) | 416 if (!result) |
416 LOG(ERROR) << "PluginMsg_Init returned false"; | 417 LOG(ERROR) << "PluginMsg_Init returned false"; |
417 | 418 |
418 render_view_->RegisterPluginDelegate(this); | 419 render_view_->RegisterPluginDelegate(this); |
419 | 420 |
420 return result; | 421 return result; |
421 } | 422 } |
422 | 423 |
423 bool WebPluginDelegateProxy::Send(IPC::Message* msg) { | 424 bool WebPluginDelegateProxy::Send(IPC::Message* msg) { |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
661 &transport_stores_[0].canvas) || | 662 &transport_stores_[0].canvas) || |
662 !CreateSharedBitmap(&transport_stores_[1].dib, | 663 !CreateSharedBitmap(&transport_stores_[1].dib, |
663 &transport_stores_[1].canvas) || | 664 &transport_stores_[1].canvas) || |
664 (needs_background_store && | 665 (needs_background_store && |
665 !CreateSharedBitmap(&background_store_.dib, | 666 !CreateSharedBitmap(&background_store_.dib, |
666 &background_store_.canvas))) { | 667 &background_store_.canvas))) { |
667 DCHECK(false); | 668 DCHECK(false); |
668 ResetWindowlessBitmaps(); | 669 ResetWindowlessBitmaps(); |
669 return; | 670 return; |
670 } | 671 } |
672 | |
673 if (needs_background_store && | |
674 render_view_->is_accelerated_compositing_active()) { | |
675 // Better than grabage... | |
676 background_store_.canvas->drawColor(SK_ColorWHITE); | |
piman
2012/11/09 19:27:03
How about writing transparent pixels? If the plugi
jam
2012/11/09 22:50:24
Thanks, actually trying this out shows that NPAPI
| |
677 } | |
671 } | 678 } |
672 } | 679 } |
673 } | 680 } |
674 | 681 |
675 SendUpdateGeometry(bitmaps_changed); | 682 SendUpdateGeometry(bitmaps_changed); |
676 } | 683 } |
677 | 684 |
678 void WebPluginDelegateProxy::ResetWindowlessBitmaps() { | 685 void WebPluginDelegateProxy::ResetWindowlessBitmaps() { |
679 transport_stores_[0].dib.reset(); | 686 transport_stores_[0].dib.reset(); |
680 transport_stores_[1].dib.reset(); | 687 transport_stores_[1].dib.reset(); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
755 } | 762 } |
756 | 763 |
757 if (!uses_shared_bitmaps_) | 764 if (!uses_shared_bitmaps_) |
758 return; | 765 return; |
759 | 766 |
760 // We got a paint before the plugin's coordinates, so there's no buffer to | 767 // We got a paint before the plugin's coordinates, so there's no buffer to |
761 // copy from. | 768 // copy from. |
762 if (!front_buffer_canvas()) | 769 if (!front_buffer_canvas()) |
763 return; | 770 return; |
764 | 771 |
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; | 772 gfx::Rect offset_rect = rect; |
780 offset_rect.Offset(-plugin_rect_.x(), -plugin_rect_.y()); | 773 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 | 774 |
787 bool background_changed = false; | 775 bool background_changed = false; |
788 if (background_store_.canvas.get() && BackgroundChanged(context, rect)) { | 776 if (background_store_.canvas.get() && BackgroundChanged(canvas, rect) && |
777 // When accelerated compositing is used we don't have access to the | |
778 // page data under the plugin. This might result in painting glitches, | |
779 // but there's nothing we can do about that. This is mostly mitigiated | |
piman
2012/11/09 19:27:03
typo: mitigated
| |
780 // by the fact that this is only for NPAPI plugins, and for Flash we use | |
781 // Pepper. | |
782 !render_view_->is_accelerated_compositing_active()) { | |
789 background_changed = true; | 783 background_changed = true; |
790 BlitContextToCanvas(background_store_.canvas.get(), canvas_rect, | 784 SkIRect src_rect = gfx::RectToSkIRect(rect); |
791 context, rect.origin()); | 785 background_store_.canvas->drawBitmapRect( |
786 canvas->getDevice()->accessBitmap(false), | |
787 &src_rect, gfx::RectToSkRect(offset_rect)); | |
jam
2012/11/09 19:02:25
btw I found that somehow this isn't working on Lin
piman
2012/11/09 19:27:03
I'm not sure specifically, but I was going to ment
| |
792 } | 788 } |
793 | 789 |
794 // transport_store_painted_ is really a bounding box, so in principle this | 790 // 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 | 791 // check could falsely indicate that we don't need to paint offset_rect, but |
796 // in practice it works fine. | 792 // in practice it works fine. |
797 if (background_changed || | 793 if (background_changed || !transport_store_painted_.Contains(offset_rect)) { |
798 !transport_store_painted_.Contains(offset_rect)) { | |
799 Send(new PluginMsg_Paint(instance_id_, offset_rect)); | 794 Send(new PluginMsg_Paint(instance_id_, offset_rect)); |
800 // Since the plugin is not blocked on the renderer in this context, there is | 795 // 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 | 796 // a chance that it will begin repainting the back-buffer before we complete |
802 // capturing the data. Buffer flipping would increase that risk because | 797 // capturing the data. Buffer flipping would increase that risk because |
803 // geometry update is asynchronous, so we don't want to use buffer flipping | 798 // geometry update is asynchronous, so we don't want to use buffer flipping |
804 // here. | 799 // here. |
805 UpdateFrontBuffer(offset_rect, false); | 800 UpdateFrontBuffer(offset_rect, false); |
806 } | 801 } |
807 | 802 |
808 #if defined(OS_MACOSX) | 803 const SkBitmap& bitmap = |
809 // The canvases are flipped relative to the context, so flip the context's | 804 front_buffer_canvas()->getDevice()->accessBitmap(false); |
810 // coordinate space so that the blit unflips the content. | 805 SkPaint paint; |
811 CGContextSaveGState(context); | 806 paint.setXfermodeMode(SkXfermode::kSrcATop_Mode); |
812 CGContextScaleCTM(context, 1, -1); | 807 SkIRect src_rect = gfx::RectToSkIRect(offset_rect); |
813 rect.set_y(-rect.bottom()); | 808 canvas->drawBitmapRect(bitmap, |
814 #endif | 809 &src_rect, |
815 BlitCanvasToContext(context, | 810 gfx::RectToSkRect(rect), |
816 rect, | 811 &paint); |
817 front_buffer_canvas(), | |
818 offset_rect.origin()); | |
819 #if defined(OS_MACOSX) | |
820 CGContextRestoreGState(context); | |
821 #endif | |
822 | 812 |
823 if (invalidate_pending_) { | 813 if (invalidate_pending_) { |
824 // Only send the PaintAck message if this paint is in response to an | 814 // 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 | 815 // 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. | 816 // to ensure only one process is using the transport dib at a time. |
827 invalidate_pending_ = false; | 817 invalidate_pending_ = false; |
828 Send(new PluginMsg_DidPaint(instance_id_)); | 818 Send(new PluginMsg_DidPaint(instance_id_)); |
829 } | 819 } |
830 } | 820 } |
831 | 821 |
832 bool WebPluginDelegateProxy::BackgroundChanged( | 822 bool WebPluginDelegateProxy::BackgroundChanged(SkCanvas* canvas, |
833 gfx::NativeDrawingContext context, | 823 const gfx::Rect& rect) { |
834 const gfx::Rect& rect) { | 824 const SkMatrix& matrix = canvas->getTotalMatrix(); |
835 #if defined(OS_ANDROID) | 825 const SkBitmap& page = canvas->getDevice()->accessBitmap(false); |
836 NOTIMPLEMENTED(); | 826 const SkBitmap& background = |
837 #else | 827 background_store_.canvas->getDevice()->accessBitmap(false); |
838 #if defined(OS_WIN) | 828 CHECK(page.bytesPerPixel() == background.bytesPerPixel()); |
piman
2012/11/09 19:27:03
Awesome thanks for removing this horrible per-plat
| |
839 HBITMAP hbitmap = static_cast<HBITMAP>(GetCurrentObject(context, OBJ_BITMAP)); | 829 int row_byte_size = rect.width() * page.bytesPerPixel(); |
piman
2012/11/09 19:27:03
This can get tricky with CSS transforms, in partic
| |
840 if (hbitmap == NULL) { | 830 for (int y = rect.y(); y < rect.bottom(); y++) { |
841 NOTREACHED(); | 831 SkPoint result; |
842 return true; | 832 matrix.mapXY(SkIntToScalar(rect.x()), SkIntToScalar(y), &result); |
843 } | 833 uint32_t* page_row_start = page.getAddr32(result.x(), result.y()); |
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 | 834 |
869 // getAddr32 doesn't use the translation units, so we have to subtract | 835 // getAddr32 doesn't use the translation units, so we have to subtract |
870 // the plugin origin from the coordinates. | 836 // the plugin origin from the coordinates. |
871 uint32_t* canvas_row_start = | 837 uint32_t* background_row_start = background.getAddr32( |
872 background_store_.canvas->getDevice()->accessBitmap(true).getAddr32( | 838 rect.x() - plugin_rect_.x(), y - plugin_rect_.y()); |
873 check_rect.x() - plugin_rect_.x(), y - plugin_rect_.y()); | 839 if (memcmp(page_row_start, background_row_start, row_byte_size) != 0) |
874 if (memcmp(hdc_row_start, canvas_row_start, row_byte_size) != 0) | |
875 return true; | 840 return true; |
876 } | 841 } |
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; | 842 return false; |
981 } | 843 } |
982 | 844 |
983 NPObject* WebPluginDelegateProxy::GetPluginScriptableObject() { | 845 NPObject* WebPluginDelegateProxy::GetPluginScriptableObject() { |
984 if (npobject_) | 846 if (npobject_) |
985 return WebBindings::retainObject(npobject_); | 847 return WebBindings::retainObject(npobject_); |
986 | 848 |
987 int route_id = MSG_ROUTING_NONE; | 849 int route_id = MSG_ROUTING_NONE; |
988 Send(new PluginMsg_GetPluginScriptableObject(instance_id_, &route_id)); | 850 Send(new PluginMsg_GetPluginScriptableObject(instance_id_, &route_id)); |
989 if (route_id == MSG_ROUTING_NONE) | 851 if (route_id == MSG_ROUTING_NONE) |
(...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1542 | 1404 |
1543 void WebPluginDelegateProxy::OnURLRedirectResponse(bool allow, | 1405 void WebPluginDelegateProxy::OnURLRedirectResponse(bool allow, |
1544 int resource_id) { | 1406 int resource_id) { |
1545 if (!plugin_) | 1407 if (!plugin_) |
1546 return; | 1408 return; |
1547 | 1409 |
1548 plugin_->URLRedirectResponse(allow, resource_id); | 1410 plugin_->URLRedirectResponse(allow, resource_id); |
1549 } | 1411 } |
1550 | 1412 |
1551 } // namespace content | 1413 } // namespace content |
OLD | NEW |