Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(162)

Side by Side Diff: webkit/glue/plugins/webplugin_delegate_impl.cc

Issue 12626: Ensure that the context menu shows up in a windowless Silverlight plugin... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « webkit/glue/plugins/webplugin_delegate_impl.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 29 matching lines...) Expand all
40 // I'd like to make the throttle delay variable, based on the amount of 40 // I'd like to make the throttle delay variable, based on the amount of
41 // time currently required to paint Flash plugins. There isn't a good 41 // time currently required to paint Flash plugins. There isn't a good
42 // way to count the time spent in aggregate plugin painting, however, so 42 // way to count the time spent in aggregate plugin painting, however, so
43 // this seems to work well enough. 43 // this seems to work well enough.
44 static const int kFlashWMUSERMessageThrottleDelayMs = 5; 44 static const int kFlashWMUSERMessageThrottleDelayMs = 5;
45 45
46 std::list<MSG> WebPluginDelegateImpl::throttle_queue_; 46 std::list<MSG> WebPluginDelegateImpl::throttle_queue_;
47 47
48 WebPluginDelegateImpl* WebPluginDelegateImpl::current_plugin_instance_ = NULL; 48 WebPluginDelegateImpl* WebPluginDelegateImpl::current_plugin_instance_ = NULL;
49 49
50 bool WebPluginDelegateImpl::track_popup_menu_patched_ = false;
51 iat_patch::IATPatchFunction WebPluginDelegateImpl::iat_patch_helper_;
52
50 WebPluginDelegateImpl* WebPluginDelegateImpl::Create( 53 WebPluginDelegateImpl* WebPluginDelegateImpl::Create(
51 const std::wstring& filename, 54 const std::wstring& filename,
52 const std::string& mime_type, 55 const std::string& mime_type,
53 HWND containing_window) { 56 HWND containing_window) {
54 scoped_refptr<NPAPI::PluginLib> plugin = 57 scoped_refptr<NPAPI::PluginLib> plugin =
55 NPAPI::PluginLib::CreatePluginLib(filename); 58 NPAPI::PluginLib::CreatePluginLib(filename);
56 if (plugin.get() == NULL) 59 if (plugin.get() == NULL)
57 return NULL; 60 return NULL;
58 61
59 NPError err = plugin->NP_Initialize(); 62 NPError err = plugin->NP_Initialize();
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 plugin_wnd_proc_(NULL), 133 plugin_wnd_proc_(NULL),
131 last_message_(0), 134 last_message_(0),
132 is_calling_wndproc(false), 135 is_calling_wndproc(false),
133 initial_plugin_resize_done_(false), 136 initial_plugin_resize_done_(false),
134 dummy_window_for_activation_(NULL), 137 dummy_window_for_activation_(NULL),
135 handle_event_message_filter_hook_(NULL), 138 handle_event_message_filter_hook_(NULL),
136 handle_event_pump_messages_event_(NULL), 139 handle_event_pump_messages_event_(NULL),
137 handle_event_depth_(0), 140 handle_event_depth_(0),
138 user_gesture_message_posted_(false), 141 user_gesture_message_posted_(false),
139 #pragma warning(suppress: 4355) // can use this 142 #pragma warning(suppress: 4355) // can use this
140 user_gesture_msg_factory_(this) { 143 user_gesture_msg_factory_(this),
144 plugin_module_handle_(NULL) {
141 memset(&window_, 0, sizeof(window_)); 145 memset(&window_, 0, sizeof(window_));
142 146
143 const WebPluginInfo& plugin_info = instance_->plugin_lib()->plugin_info(); 147 const WebPluginInfo& plugin_info = instance_->plugin_lib()->plugin_info();
144 std::wstring filename = file_util::GetFilenameFromPath(plugin_info.file); 148 std::wstring filename = file_util::GetFilenameFromPath(plugin_info.file);
145 149
146 if (instance_->mime_type() == "application/x-shockwave-flash" || 150 if (instance_->mime_type() == "application/x-shockwave-flash" ||
147 filename == L"npswf32.dll") { 151 filename == L"npswf32.dll") {
148 // Flash only requests windowless plugins if we return a Mozilla user 152 // Flash only requests windowless plugins if we return a Mozilla user
149 // agent. 153 // agent.
150 instance_->set_use_mozilla_user_agent(); 154 instance_->set_use_mozilla_user_agent();
(...skipping 15 matching lines...) Expand all
166 } else if (instance_->mime_type() == "audio/x-pn-realaudio-plugin" || 170 } else if (instance_->mime_type() == "audio/x-pn-realaudio-plugin" ||
167 filename == L"nppl3260.dll") { 171 filename == L"nppl3260.dll") {
168 quirks_ |= PLUGIN_QUIRK_DONT_CALL_WND_PROC_RECURSIVELY; 172 quirks_ |= PLUGIN_QUIRK_DONT_CALL_WND_PROC_RECURSIVELY;
169 } else if (plugin_info.name.find(L"VLC Multimedia Plugin") != 173 } else if (plugin_info.name.find(L"VLC Multimedia Plugin") !=
170 std::wstring::npos) { 174 std::wstring::npos) {
171 // VLC hangs on NPP_Destroy if we call NPP_SetWindow with a null window 175 // VLC hangs on NPP_Destroy if we call NPP_SetWindow with a null window
172 // handle 176 // handle
173 quirks_ |= PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY; 177 quirks_ |= PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY;
174 // VLC 0.8.6d and 0.8.6e crash if multiple instances are created. 178 // VLC 0.8.6d and 0.8.6e crash if multiple instances are created.
175 quirks_ |= PLUGIN_QUIRK_DONT_ALLOW_MULTIPLE_INSTANCES; 179 quirks_ |= PLUGIN_QUIRK_DONT_ALLOW_MULTIPLE_INSTANCES;
180 } else if (filename == L"npctrl.dll") {
181 // Explanation for this quirk can be found in
182 // WebPluginDelegateImpl::Initialize.
183 quirks_ |= PLUGIN_QUIRK_PATCH_TRACKPOPUP_MENU;
176 } 184 }
185
186 plugin_module_handle_ = ::GetModuleHandle(filename.c_str());
177 } 187 }
178 188
179 WebPluginDelegateImpl::~WebPluginDelegateImpl() { 189 WebPluginDelegateImpl::~WebPluginDelegateImpl() {
180 if (::IsWindow(dummy_window_for_activation_)) { 190 if (::IsWindow(dummy_window_for_activation_)) {
181 ::DestroyWindow(dummy_window_for_activation_); 191 ::DestroyWindow(dummy_window_for_activation_);
182 } 192 }
183 193
184 DestroyInstance(); 194 DestroyInstance();
185 195
186 if (!windowless_) 196 if (!windowless_)
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 // retreived via NPN_GetValue of NPNVnetscapeWindow. 243 // retreived via NPN_GetValue of NPNVnetscapeWindow.
234 instance_->set_window_handle(parent_); 244 instance_->set_window_handle(parent_);
235 CreateDummyWindowForActivation(); 245 CreateDummyWindowForActivation();
236 handle_event_pump_messages_event_ = CreateEvent(NULL, TRUE, FALSE, NULL); 246 handle_event_pump_messages_event_ = CreateEvent(NULL, TRUE, FALSE, NULL);
237 } else { 247 } else {
238 if (!WindowedCreatePlugin()) 248 if (!WindowedCreatePlugin())
239 return false; 249 return false;
240 } 250 }
241 251
242 plugin->SetWindow(windowed_handle_, handle_event_pump_messages_event_); 252 plugin->SetWindow(windowed_handle_, handle_event_pump_messages_event_);
253 plugin_url_ = url.spec();
243 254
244 plugin_url_ = url.spec(); 255 // The windowless version of the Silverlight plugin calls the
256 // WindowFromPoint API and passes the result of that to the
257 // TrackPopupMenu API call as the owner window. This causes the API
258 // to fail as the API expects the window handle to live on the same
259 // thread as the caller. It works in the other browsers as the plugin
260 // lives on the browser thread. Our workaround is to intercept the
261 // TrackPopupMenu API for Silverlight and replace the window handle
262 // with the dummy activation window.
263 if (windowless_ && !track_popup_menu_patched_ &&
264 (quirks_ & PLUGIN_QUIRK_PATCH_TRACKPOPUP_MENU)) {
265 iat_patch_helper_.Patch(plugin_module_handle_, "user32.dll",
266 "TrackPopupMenu",
267 WebPluginDelegateImpl::TrackPopupMenuPatch);
268 track_popup_menu_patched_ = true;
269 }
245 return true; 270 return true;
246 } 271 }
247 272
248 void WebPluginDelegateImpl::DestroyInstance() { 273 void WebPluginDelegateImpl::DestroyInstance() {
249 if (instance_ && (instance_->npp()->ndata != NULL)) { 274 if (instance_ && (instance_->npp()->ndata != NULL)) {
250 // Shutdown all streams before destroying so that 275 // Shutdown all streams before destroying so that
251 // no streams are left "in progress". Need to do 276 // no streams are left "in progress". Need to do
252 // this before calling set_web_plugin(NULL) because the 277 // this before calling set_web_plugin(NULL) because the
253 // instance uses the helper to do the download. 278 // instance uses the helper to do the download.
254 instance_->CloseStreams(); 279 instance_->CloseStreams();
(...skipping 741 matching lines...) Expand 10 before | Expand all | Expand 10 after
996 handle_event_message_filter_hook_ = NULL; 1021 handle_event_message_filter_hook_ = NULL;
997 } 1022 }
998 1023
999 // We could have multiple NPP_HandleEvent calls nested together in case 1024 // We could have multiple NPP_HandleEvent calls nested together in case
1000 // the plugin enters a modal loop. Reset the pump messages event when 1025 // the plugin enters a modal loop. Reset the pump messages event when
1001 // the outermost NPP_HandleEvent call unwinds. 1026 // the outermost NPP_HandleEvent call unwinds.
1002 if (handle_event_depth_ == 0) { 1027 if (handle_event_depth_ == 0) {
1003 ResetEvent(handle_event_pump_messages_event_); 1028 ResetEvent(handle_event_pump_messages_event_);
1004 } 1029 }
1005 1030
1006 if (::IsWindow(prev_focus_window)) { 1031 if (event->event == WM_RBUTTONUP && ::IsWindow(prev_focus_window)) {
1007 ::SetFocus(prev_focus_window); 1032 ::SetFocus(prev_focus_window);
1008 } 1033 }
1009 1034
1010 if (WM_MOUSEMOVE == event->event) { 1035 if (WM_MOUSEMOVE == event->event) {
1011 cursor->InitFromCursor(last_cursor); 1036 cursor->InitFromCursor(last_cursor);
1012 } 1037 }
1013 1038
1014 return ret; 1039 return ret;
1015 } 1040 }
1016 1041
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1076 break; 1101 break;
1077 } 1102 }
1078 1103
1079 return false; 1104 return false;
1080 } 1105 }
1081 1106
1082 void WebPluginDelegateImpl::OnUserGestureEnd() { 1107 void WebPluginDelegateImpl::OnUserGestureEnd() {
1083 user_gesture_message_posted_ = false; 1108 user_gesture_message_posted_ = false;
1084 instance()->PopPopupsEnabledState(); 1109 instance()->PopPopupsEnabledState();
1085 } 1110 }
1111
1112 BOOL WINAPI WebPluginDelegateImpl::TrackPopupMenuPatch(
1113 HMENU menu, unsigned int flags, int x, int y, int reserved,
1114 HWND window, const RECT* rect) {
1115 if (current_plugin_instance_) {
1116 unsigned long window_process_id = 0;
1117 unsigned long window_thread_id =
1118 GetWindowThreadProcessId(window, &window_process_id);
1119 // TrackPopupMenu fails if the window passed in belongs to a different
1120 // thread.
1121 if (::GetCurrentThreadId() != window_thread_id) {
1122 window = current_plugin_instance_->dummy_window_for_activation_;
1123 }
1124 }
1125 return TrackPopupMenu(menu, flags, x, y, reserved, window, rect);
1126 }
OLDNEW
« no previous file with comments | « webkit/glue/plugins/webplugin_delegate_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698