OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 "webkit/glue/plugins/webplugin_delegate_impl.h" | 5 #include "webkit/glue/plugins/webplugin_delegate_impl.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 base::LazyInstance<std::list<MSG> > g_throttle_queue(base::LINKER_INITIALIZED); | 60 base::LazyInstance<std::list<MSG> > g_throttle_queue(base::LINKER_INITIALIZED); |
61 | 61 |
62 // Helper object for patching the TrackPopupMenu API. | 62 // Helper object for patching the TrackPopupMenu API. |
63 base::LazyInstance<iat_patch::IATPatchFunction> g_iat_patch_track_popup_menu( | 63 base::LazyInstance<iat_patch::IATPatchFunction> g_iat_patch_track_popup_menu( |
64 base::LINKER_INITIALIZED); | 64 base::LINKER_INITIALIZED); |
65 | 65 |
66 // Helper object for patching the SetCursor API. | 66 // Helper object for patching the SetCursor API. |
67 base::LazyInstance<iat_patch::IATPatchFunction> g_iat_patch_set_cursor( | 67 base::LazyInstance<iat_patch::IATPatchFunction> g_iat_patch_set_cursor( |
68 base::LINKER_INITIALIZED); | 68 base::LINKER_INITIALIZED); |
69 | 69 |
| 70 // http://crbug.com/16114 |
| 71 // Enforces providing a valid device context in NPWindow, so that NPP_SetWindow |
| 72 // is never called with NPNWindoTypeDrawable and NPWindow set to NULL. |
| 73 // Doing so allows removing NPP_SetWindow call during painting a windowless |
| 74 // plugin, which otherwise could trigger layout change while painting by |
| 75 // invoking NPN_Evaluate. Which would cause bad, bad crashes. Bad crashes. |
| 76 // TODO(dglazkov): If this approach doesn't produce regressions, move class to |
| 77 // webplugin_delegate_impl.h and implement for other platforms. |
| 78 class DrawableContextEnforcer { |
| 79 public: |
| 80 explicit DrawableContextEnforcer(NPWindow* window) |
| 81 : window_(window), |
| 82 disposable_dc_(window && !window->window) { |
| 83 // If NPWindow is NULL, create a device context with monochrome 1x1 surface |
| 84 // and stuff it to NPWindow. |
| 85 if (disposable_dc_) |
| 86 window_->window = CreateCompatibleDC(NULL); |
| 87 } |
| 88 |
| 89 ~DrawableContextEnforcer() { |
| 90 if (!disposable_dc_) |
| 91 return; |
| 92 |
| 93 DeleteDC(static_cast<HDC>(window_->window)); |
| 94 window_->window = NULL; |
| 95 } |
| 96 |
| 97 private: |
| 98 NPWindow* window_; |
| 99 bool disposable_dc_; |
| 100 }; |
| 101 |
70 } // namespace | 102 } // namespace |
71 | 103 |
72 WebPluginDelegate* WebPluginDelegate::Create( | 104 WebPluginDelegate* WebPluginDelegate::Create( |
73 const FilePath& filename, | 105 const FilePath& filename, |
74 const std::string& mime_type, | 106 const std::string& mime_type, |
75 gfx::PluginWindowHandle containing_view) { | 107 gfx::PluginWindowHandle containing_view) { |
76 scoped_refptr<NPAPI::PluginLib> plugin = | 108 scoped_refptr<NPAPI::PluginLib> plugin = |
77 NPAPI::PluginLib::CreatePluginLib(filename); | 109 NPAPI::PluginLib::CreatePluginLib(filename); |
78 if (plugin.get() == NULL) | 110 if (plugin.get() == NULL) |
79 return NULL; | 111 return NULL; |
(...skipping 819 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
899 return result; | 931 return result; |
900 } | 932 } |
901 | 933 |
902 void WebPluginDelegateImpl::WindowlessUpdateGeometry( | 934 void WebPluginDelegateImpl::WindowlessUpdateGeometry( |
903 const gfx::Rect& window_rect, | 935 const gfx::Rect& window_rect, |
904 const gfx::Rect& clip_rect) { | 936 const gfx::Rect& clip_rect) { |
905 // Only resend to the instance if the geometry has changed. | 937 // Only resend to the instance if the geometry has changed. |
906 if (window_rect == window_rect_ && clip_rect == clip_rect_) | 938 if (window_rect == window_rect_ && clip_rect == clip_rect_) |
907 return; | 939 return; |
908 | 940 |
909 // Set this flag before entering the instance in case of side-effects. | |
910 windowless_needs_set_window_ = true; | |
911 | |
912 // We will inform the instance of this change when we call NPP_SetWindow. | 941 // We will inform the instance of this change when we call NPP_SetWindow. |
913 clip_rect_ = clip_rect; | 942 clip_rect_ = clip_rect; |
914 cutout_rects_.clear(); | 943 cutout_rects_.clear(); |
915 | 944 |
916 if (window_rect_ != window_rect) { | 945 if (window_rect_ != window_rect) { |
917 window_rect_ = window_rect; | 946 window_rect_ = window_rect; |
918 | 947 |
919 WindowlessSetWindow(true); | 948 WindowlessSetWindow(true); |
920 | 949 |
921 WINDOWPOS win_pos = {0}; | 950 WINDOWPOS win_pos = {0}; |
(...skipping 14 matching lines...) Expand all Loading... |
936 void WebPluginDelegateImpl::WindowlessPaint(HDC hdc, | 965 void WebPluginDelegateImpl::WindowlessPaint(HDC hdc, |
937 const gfx::Rect& damage_rect) { | 966 const gfx::Rect& damage_rect) { |
938 DCHECK(hdc); | 967 DCHECK(hdc); |
939 | 968 |
940 RECT damage_rect_win; | 969 RECT damage_rect_win; |
941 damage_rect_win.left = damage_rect.x(); // + window_rect_.x(); | 970 damage_rect_win.left = damage_rect.x(); // + window_rect_.x(); |
942 damage_rect_win.top = damage_rect.y(); // + window_rect_.y(); | 971 damage_rect_win.top = damage_rect.y(); // + window_rect_.y(); |
943 damage_rect_win.right = damage_rect_win.left + damage_rect.width(); | 972 damage_rect_win.right = damage_rect_win.left + damage_rect.width(); |
944 damage_rect_win.bottom = damage_rect_win.top + damage_rect.height(); | 973 damage_rect_win.bottom = damage_rect_win.top + damage_rect.height(); |
945 | 974 |
946 // We need to pass the HDC to the plugin via NPP_SetWindow in the | |
947 // first paint to ensure that it initiates rect invalidations. | |
948 if (window_.window == NULL) | |
949 windowless_needs_set_window_ = true; | |
950 | |
951 window_.window = hdc; | 975 window_.window = hdc; |
952 // TODO(darin): we should avoid calling NPP_SetWindow here since it may | |
953 // cause page layout to be invalidated. | |
954 | |
955 // We really don't need to continually call SetWindow. | |
956 // m_needsSetWindow flags when the geometry has changed. | |
957 if (windowless_needs_set_window_) | |
958 WindowlessSetWindow(false); | |
959 | 976 |
960 NPEvent paint_event; | 977 NPEvent paint_event; |
961 paint_event.event = WM_PAINT; | 978 paint_event.event = WM_PAINT; |
962 // NOTE: NPAPI is not 64bit safe. It puts pointers into 32bit values. | 979 // NOTE: NPAPI is not 64bit safe. It puts pointers into 32bit values. |
963 paint_event.wParam = PtrToUlong(hdc); | 980 paint_event.wParam = PtrToUlong(hdc); |
964 paint_event.lParam = PtrToUlong(&damage_rect_win); | 981 paint_event.lParam = PtrToUlong(&damage_rect_win); |
965 static StatsRate plugin_paint("Plugin.Paint"); | 982 static StatsRate plugin_paint("Plugin.Paint"); |
966 StatsScope<StatsRate> scope(plugin_paint); | 983 StatsScope<StatsRate> scope(plugin_paint); |
967 instance()->NPP_HandleEvent(&paint_event); | 984 instance()->NPP_HandleEvent(&paint_event); |
968 } | 985 } |
969 | 986 |
970 void WebPluginDelegateImpl::WindowlessSetWindow(bool force_set_window) { | 987 void WebPluginDelegateImpl::WindowlessSetWindow(bool force_set_window) { |
971 if (!instance()) | 988 if (!instance()) |
972 return; | 989 return; |
973 | 990 |
974 if (window_rect_.IsEmpty()) // wait for geometry to be set. | 991 if (window_rect_.IsEmpty()) // wait for geometry to be set. |
975 return; | 992 return; |
976 | 993 |
977 DCHECK(instance()->windowless()); | 994 DCHECK(instance()->windowless()); |
978 | 995 |
979 window_.clipRect.top = clip_rect_.y(); | 996 window_.clipRect.top = clip_rect_.y(); |
980 window_.clipRect.left = clip_rect_.x(); | 997 window_.clipRect.left = clip_rect_.x(); |
981 window_.clipRect.bottom = clip_rect_.y() + clip_rect_.height(); | 998 window_.clipRect.bottom = clip_rect_.y() + clip_rect_.height(); |
982 window_.clipRect.right = clip_rect_.x() + clip_rect_.width(); | 999 window_.clipRect.right = clip_rect_.x() + clip_rect_.width(); |
983 window_.height = window_rect_.height(); | 1000 window_.height = window_rect_.height(); |
984 window_.width = window_rect_.width(); | 1001 window_.width = window_rect_.width(); |
985 window_.x = window_rect_.x(); | 1002 window_.x = window_rect_.x(); |
986 window_.y = window_rect_.y(); | 1003 window_.y = window_rect_.y(); |
987 window_.type = NPWindowTypeDrawable; | 1004 window_.type = NPWindowTypeDrawable; |
988 | 1005 DrawableContextEnforcer enforcer(&window_); |
989 if (!force_set_window) | |
990 // Reset this flag before entering the instance in case of side-effects. | |
991 windowless_needs_set_window_ = false; | |
992 | 1006 |
993 NPError err = instance()->NPP_SetWindow(&window_); | 1007 NPError err = instance()->NPP_SetWindow(&window_); |
994 DCHECK(err == NPERR_NO_ERROR); | 1008 DCHECK(err == NPERR_NO_ERROR); |
995 } | 1009 } |
996 | 1010 |
997 void WebPluginDelegateImpl::SetFocus() { | 1011 void WebPluginDelegateImpl::SetFocus() { |
998 DCHECK(instance()->windowless()); | 1012 DCHECK(instance()->windowless()); |
999 | 1013 |
1000 NPEvent focus_event; | 1014 NPEvent focus_event; |
1001 focus_event.event = WM_SETFOCUS; | 1015 focus_event.event = WM_SETFOCUS; |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1314 | 1328 |
1315 // It is ok to pass NULL here to GetCursor as we are not looking for cursor | 1329 // It is ok to pass NULL here to GetCursor as we are not looking for cursor |
1316 // types defined by Webkit. | 1330 // types defined by Webkit. |
1317 HCURSOR previous_cursor = | 1331 HCURSOR previous_cursor = |
1318 g_current_plugin_instance->current_windowless_cursor_.GetCursor(NULL); | 1332 g_current_plugin_instance->current_windowless_cursor_.GetCursor(NULL); |
1319 | 1333 |
1320 g_current_plugin_instance->current_windowless_cursor_.InitFromExternalCursor( | 1334 g_current_plugin_instance->current_windowless_cursor_.InitFromExternalCursor( |
1321 cursor); | 1335 cursor); |
1322 return previous_cursor; | 1336 return previous_cursor; |
1323 } | 1337 } |
OLD | NEW |