| 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 29 matching lines...) Expand all Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |