| 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; | 50 iat_patch::IATPatchFunction WebPluginDelegateImpl::iat_patch_track_popup_menu_; |
| 51 iat_patch::IATPatchFunction WebPluginDelegateImpl::iat_patch_helper_; | 51 iat_patch::IATPatchFunction WebPluginDelegateImpl::iat_patch_set_cursor_; |
| 52 | 52 |
| 53 WebPluginDelegateImpl* WebPluginDelegateImpl::Create( | 53 WebPluginDelegateImpl* WebPluginDelegateImpl::Create( |
| 54 const FilePath& filename, | 54 const FilePath& filename, |
| 55 const std::string& mime_type, | 55 const std::string& mime_type, |
| 56 gfx::NativeView containing_view) { | 56 gfx::NativeView containing_view) { |
| 57 scoped_refptr<NPAPI::PluginLib> plugin = | 57 scoped_refptr<NPAPI::PluginLib> plugin = |
| 58 NPAPI::PluginLib::CreatePluginLib(filename); | 58 NPAPI::PluginLib::CreatePluginLib(filename); |
| 59 if (plugin.get() == NULL) | 59 if (plugin.get() == NULL) |
| 60 return NULL; | 60 return NULL; |
| 61 | 61 |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 | 146 |
| 147 const WebPluginInfo& plugin_info = instance_->plugin_lib()->plugin_info(); | 147 const WebPluginInfo& plugin_info = instance_->plugin_lib()->plugin_info(); |
| 148 std::wstring filename = plugin_info.file.BaseName().value(); | 148 std::wstring filename = plugin_info.file.BaseName().value(); |
| 149 | 149 |
| 150 if (instance_->mime_type() == "application/x-shockwave-flash" || | 150 if (instance_->mime_type() == "application/x-shockwave-flash" || |
| 151 filename == L"npswf32.dll") { | 151 filename == L"npswf32.dll") { |
| 152 // Flash only requests windowless plugins if we return a Mozilla user | 152 // Flash only requests windowless plugins if we return a Mozilla user |
| 153 // agent. | 153 // agent. |
| 154 instance_->set_use_mozilla_user_agent(); | 154 instance_->set_use_mozilla_user_agent(); |
| 155 quirks_ |= PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE; | 155 quirks_ |= PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE; |
| 156 quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR; |
| 156 } else if (filename == L"nppdf32.dll") { | 157 } else if (filename == L"nppdf32.dll") { |
| 157 // Check for the version number above or equal 9. | 158 // Check for the version number above or equal 9. |
| 158 std::vector<std::wstring> version; | 159 std::vector<std::wstring> version; |
| 159 SplitString(plugin_info.version, L'.', &version); | 160 SplitString(plugin_info.version, L'.', &version); |
| 160 if (version.size() > 0) { | 161 if (version.size() > 0) { |
| 161 int major = static_cast<int>(StringToInt64(version[0])); | 162 int major = static_cast<int>(StringToInt64(version[0])); |
| 162 if (major >= 9) { | 163 if (major >= 9) { |
| 163 quirks_ |= PLUGIN_QUIRK_DIE_AFTER_UNLOAD; | 164 quirks_ |= PLUGIN_QUIRK_DIE_AFTER_UNLOAD; |
| 164 } | 165 } |
| 165 } | 166 } |
| 166 } else if (plugin_info.name.find(L"Windows Media Player") != | 167 } else if (plugin_info.name.find(L"Windows Media Player") != |
| 167 std::wstring::npos) { | 168 std::wstring::npos) { |
| 168 // Windows Media Player needs two NPP_SetWindow calls. | 169 // Windows Media Player needs two NPP_SetWindow calls. |
| 169 quirks_ |= PLUGIN_QUIRK_SETWINDOW_TWICE; | 170 quirks_ |= PLUGIN_QUIRK_SETWINDOW_TWICE; |
| 170 } else if (instance_->mime_type() == "audio/x-pn-realaudio-plugin" || | 171 } else if (instance_->mime_type() == "audio/x-pn-realaudio-plugin" || |
| 171 filename == L"nppl3260.dll") { | 172 filename == L"nppl3260.dll") { |
| 172 quirks_ |= PLUGIN_QUIRK_DONT_CALL_WND_PROC_RECURSIVELY; | 173 quirks_ |= PLUGIN_QUIRK_DONT_CALL_WND_PROC_RECURSIVELY; |
| 173 } else if (plugin_info.name.find(L"VLC Multimedia Plugin") != | 174 } else if (plugin_info.name.find(L"VLC Multimedia Plugin") != |
| 174 std::wstring::npos) { | 175 std::wstring::npos) { |
| 175 // VLC hangs on NPP_Destroy if we call NPP_SetWindow with a null window | 176 // VLC hangs on NPP_Destroy if we call NPP_SetWindow with a null window |
| 176 // handle | 177 // handle |
| 177 quirks_ |= PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY; | 178 quirks_ |= PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY; |
| 178 // VLC 0.8.6d and 0.8.6e crash if multiple instances are created. | 179 // VLC 0.8.6d and 0.8.6e crash if multiple instances are created. |
| 179 quirks_ |= PLUGIN_QUIRK_DONT_ALLOW_MULTIPLE_INSTANCES; | 180 quirks_ |= PLUGIN_QUIRK_DONT_ALLOW_MULTIPLE_INSTANCES; |
| 180 } else if (filename == L"npctrl.dll") { | 181 } else if (filename == L"npctrl.dll") { |
| 181 // Explanation for this quirk can be found in | 182 // Explanation for this quirk can be found in |
| 182 // WebPluginDelegateImpl::Initialize. | 183 // WebPluginDelegateImpl::Initialize. |
| 183 quirks_ |= PLUGIN_QUIRK_PATCH_TRACKPOPUP_MENU; | 184 quirks_ |= PLUGIN_QUIRK_PATCH_TRACKPOPUP_MENU; |
| 185 quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR; |
| 184 } | 186 } |
| 185 | 187 |
| 186 plugin_module_handle_ = ::GetModuleHandle(filename.c_str()); | 188 plugin_module_handle_ = ::GetModuleHandle(filename.c_str()); |
| 187 } | 189 } |
| 188 | 190 |
| 189 WebPluginDelegateImpl::~WebPluginDelegateImpl() { | 191 WebPluginDelegateImpl::~WebPluginDelegateImpl() { |
| 190 if (::IsWindow(dummy_window_for_activation_)) { | 192 if (::IsWindow(dummy_window_for_activation_)) { |
| 191 ::DestroyWindow(dummy_window_for_activation_); | 193 ::DestroyWindow(dummy_window_for_activation_); |
| 192 } | 194 } |
| 193 | 195 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 plugin_url_ = url.spec(); | 255 plugin_url_ = url.spec(); |
| 254 | 256 |
| 255 // The windowless version of the Silverlight plugin calls the | 257 // The windowless version of the Silverlight plugin calls the |
| 256 // WindowFromPoint API and passes the result of that to the | 258 // WindowFromPoint API and passes the result of that to the |
| 257 // TrackPopupMenu API call as the owner window. This causes the API | 259 // 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 | 260 // 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 | 261 // 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 | 262 // lives on the browser thread. Our workaround is to intercept the |
| 261 // TrackPopupMenu API for Silverlight and replace the window handle | 263 // TrackPopupMenu API for Silverlight and replace the window handle |
| 262 // with the dummy activation window. | 264 // with the dummy activation window. |
| 263 if (windowless_ && !track_popup_menu_patched_ && | 265 if (windowless_ && !iat_patch_track_popup_menu_.is_patched() && |
| 264 (quirks_ & PLUGIN_QUIRK_PATCH_TRACKPOPUP_MENU)) { | 266 (quirks_ & PLUGIN_QUIRK_PATCH_TRACKPOPUP_MENU)) { |
| 265 iat_patch_helper_.Patch(plugin_module_handle_, "user32.dll", | 267 iat_patch_track_popup_menu_.Patch( |
| 266 "TrackPopupMenu", | 268 plugin_module_handle_, "user32.dll", "TrackPopupMenu", |
| 267 WebPluginDelegateImpl::TrackPopupMenuPatch); | 269 WebPluginDelegateImpl::TrackPopupMenuPatch); |
| 268 track_popup_menu_patched_ = true; | 270 } |
| 271 |
| 272 // Windowless plugins can set cursors by calling the SetCursor API. This |
| 273 // works because the thread inputs of the browser UI thread and the plugin |
| 274 // thread are attached. We intercept the SetCursor API for windowless plugins |
| 275 // and remember the cursor being set. This is shipped over to the browser |
| 276 // in the HandleEvent call, which ensures that the cursor does not change |
| 277 // when a windowless plugin instance changes the cursor in a background tab. |
| 278 if (windowless_ && !iat_patch_set_cursor_.is_patched() && |
| 279 (quirks_ & PLUGIN_QUIRK_PATCH_SETCURSOR)) { |
| 280 iat_patch_set_cursor_.Patch(plugin_module_handle_, "user32.dll", |
| 281 "SetCursor", |
| 282 WebPluginDelegateImpl::SetCursorPatch); |
| 269 } | 283 } |
| 270 return true; | 284 return true; |
| 271 } | 285 } |
| 272 | 286 |
| 273 void WebPluginDelegateImpl::DestroyInstance() { | 287 void WebPluginDelegateImpl::DestroyInstance() { |
| 274 if (instance_ && (instance_->npp()->ndata != NULL)) { | 288 if (instance_ && (instance_->npp()->ndata != NULL)) { |
| 275 // Shutdown all streams before destroying so that | 289 // Shutdown all streams before destroying so that |
| 276 // no streams are left "in progress". Need to do | 290 // no streams are left "in progress". Need to do |
| 277 // this before calling set_web_plugin(NULL) because the | 291 // this before calling set_web_plugin(NULL) because the |
| 278 // instance uses the helper to do the download. | 292 // instance uses the helper to do the download. |
| 279 instance_->CloseStreams(); | 293 instance_->CloseStreams(); |
| 280 | 294 |
| 281 window_.window = NULL; | 295 window_.window = NULL; |
| 282 if (!(quirks_ & PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY)) { | 296 if (!(quirks_ & PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY)) { |
| 283 instance_->NPP_SetWindow(&window_); | 297 instance_->NPP_SetWindow(&window_); |
| 284 } | 298 } |
| 285 | 299 |
| 286 instance_->NPP_Destroy(); | 300 instance_->NPP_Destroy(); |
| 287 | 301 |
| 288 instance_->set_web_plugin(NULL); | 302 instance_->set_web_plugin(NULL); |
| 289 | 303 |
| 304 if (instance_->plugin_lib()) { |
| 305 // Unpatch if this is the last plugin instance. |
| 306 if (instance_->plugin_lib()->instance_count() == 1) { |
| 307 if (iat_patch_set_cursor_.is_patched()) { |
| 308 iat_patch_set_cursor_.Unpatch(); |
| 309 } |
| 310 |
| 311 if (iat_patch_track_popup_menu_.is_patched()) { |
| 312 iat_patch_track_popup_menu_.Unpatch(); |
| 313 } |
| 314 } |
| 315 } |
| 316 |
| 290 instance_ = 0; | 317 instance_ = 0; |
| 291 } | 318 } |
| 292 } | 319 } |
| 293 | 320 |
| 294 void WebPluginDelegateImpl::UpdateGeometry( | 321 void WebPluginDelegateImpl::UpdateGeometry( |
| 295 const gfx::Rect& window_rect, | 322 const gfx::Rect& window_rect, |
| 296 const gfx::Rect& clip_rect, | 323 const gfx::Rect& clip_rect, |
| 297 const std::vector<gfx::Rect>& cutout_rects, | 324 const std::vector<gfx::Rect>& cutout_rects, |
| 298 bool visible) { | 325 bool visible) { |
| 299 if (windowless_) { | 326 if (windowless_) { |
| (...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 794 delegate->quirks() & PLUGIN_QUIRK_DONT_CALL_WND_PROC_RECURSIVELY && | 821 delegate->quirks() & PLUGIN_QUIRK_DONT_CALL_WND_PROC_RECURSIVELY && |
| 795 delegate->is_calling_wndproc) { | 822 delegate->is_calling_wndproc) { |
| 796 // Real may go into a state where it recursively dispatches the same event | 823 // Real may go into a state where it recursively dispatches the same event |
| 797 // when subclassed. See https://bugzilla.mozilla.org/show_bug.cgi?id=192914 | 824 // when subclassed. See https://bugzilla.mozilla.org/show_bug.cgi?id=192914 |
| 798 // We only do the recursive check for Real because it's possible and valid | 825 // We only do the recursive check for Real because it's possible and valid |
| 799 // for a plugin to synchronously dispatch a message to itself such that it | 826 // for a plugin to synchronously dispatch a message to itself such that it |
| 800 // looks like it's in recursion. | 827 // looks like it's in recursion. |
| 801 return TRUE; | 828 return TRUE; |
| 802 } | 829 } |
| 803 | 830 |
| 831 current_plugin_instance_ = delegate; |
| 832 |
| 804 switch (message) { | 833 switch (message) { |
| 805 case WM_NCDESTROY: { | 834 case WM_NCDESTROY: { |
| 806 RemoveProp(hwnd, kWebPluginDelegateProperty); | 835 RemoveProp(hwnd, kWebPluginDelegateProperty); |
| 807 ATOM plugin_name_atom = reinterpret_cast <ATOM>( | 836 ATOM plugin_name_atom = reinterpret_cast <ATOM>( |
| 808 RemoveProp(hwnd, kPluginNameAtomProperty)); | 837 RemoveProp(hwnd, kPluginNameAtomProperty)); |
| 809 if (plugin_name_atom != 0) | 838 if (plugin_name_atom != 0) |
| 810 GlobalDeleteAtom(plugin_name_atom); | 839 GlobalDeleteAtom(plugin_name_atom); |
| 811 ClearThrottleQueueForWindow(hwnd); | 840 ClearThrottleQueueForWindow(hwnd); |
| 812 break; | 841 break; |
| 813 } | 842 } |
| 814 // Flash may flood the message queue with WM_USER+1 message causing 100% CPU | 843 // Flash may flood the message queue with WM_USER+1 message causing 100% CPU |
| 815 // usage. See https://bugzilla.mozilla.org/show_bug.cgi?id=132759. We | 844 // usage. See https://bugzilla.mozilla.org/show_bug.cgi?id=132759. We |
| 816 // prevent this by throttling the messages. | 845 // prevent this by throttling the messages. |
| 817 case WM_USER + 1: { | 846 case WM_USER + 1: { |
| 818 if (delegate->quirks() & PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE) { | 847 if (delegate->quirks() & PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE) { |
| 819 WebPluginDelegateImpl::ThrottleMessage(delegate->plugin_wnd_proc_, hwnd, | 848 WebPluginDelegateImpl::ThrottleMessage(delegate->plugin_wnd_proc_, hwnd, |
| 820 message, wparam, lparam); | 849 message, wparam, lparam); |
| 850 current_plugin_instance_ = NULL; |
| 821 return FALSE; | 851 return FALSE; |
| 822 } | 852 } |
| 823 break; | 853 break; |
| 824 } | 854 } |
| 825 default: { | 855 default: { |
| 826 break; | 856 break; |
| 827 } | 857 } |
| 828 } | 858 } |
| 829 | 859 |
| 830 delegate->last_message_ = message; | 860 delegate->last_message_ = message; |
| 831 delegate->is_calling_wndproc = true; | 861 delegate->is_calling_wndproc = true; |
| 832 | 862 |
| 833 if (!delegate->user_gesture_message_posted_ && | 863 if (!delegate->user_gesture_message_posted_ && |
| 834 IsUserGestureMessage(message)) { | 864 IsUserGestureMessage(message)) { |
| 835 delegate->user_gesture_message_posted_ = true; | 865 delegate->user_gesture_message_posted_ = true; |
| 836 | 866 |
| 837 delegate->instance()->PushPopupsEnabledState(true); | 867 delegate->instance()->PushPopupsEnabledState(true); |
| 838 | 868 |
| 839 MessageLoop::current()->PostTask(FROM_HERE, | 869 MessageLoop::current()->PostTask(FROM_HERE, |
| 840 delegate->user_gesture_msg_factory_.NewRunnableMethod( | 870 delegate->user_gesture_msg_factory_.NewRunnableMethod( |
| 841 &WebPluginDelegateImpl::OnUserGestureEnd)); | 871 &WebPluginDelegateImpl::OnUserGestureEnd)); |
| 842 } | 872 } |
| 843 | 873 |
| 844 LRESULT result = CallWindowProc(delegate->plugin_wnd_proc_, hwnd, message, | 874 LRESULT result = CallWindowProc(delegate->plugin_wnd_proc_, hwnd, message, |
| 845 wparam, lparam); | 875 wparam, lparam); |
| 846 delegate->is_calling_wndproc = false; | 876 delegate->is_calling_wndproc = false; |
| 877 current_plugin_instance_ = NULL; |
| 847 return result; | 878 return result; |
| 848 } | 879 } |
| 849 | 880 |
| 850 void WebPluginDelegateImpl::WindowlessUpdateGeometry( | 881 void WebPluginDelegateImpl::WindowlessUpdateGeometry( |
| 851 const gfx::Rect& window_rect, | 882 const gfx::Rect& window_rect, |
| 852 const gfx::Rect& clip_rect) { | 883 const gfx::Rect& clip_rect) { |
| 853 // Only resend to the instance if the geometry has changed. | 884 // Only resend to the instance if the geometry has changed. |
| 854 if (window_rect == window_rect_ && clip_rect == clip_rect_) | 885 if (window_rect == window_rect_ && clip_rect == clip_rect_) |
| 855 return; | 886 return; |
| 856 | 887 |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 991 | 1022 |
| 992 bool pop_user_gesture = false; | 1023 bool pop_user_gesture = false; |
| 993 | 1024 |
| 994 if (IsUserGestureMessage(event->event)) { | 1025 if (IsUserGestureMessage(event->event)) { |
| 995 pop_user_gesture = true; | 1026 pop_user_gesture = true; |
| 996 instance()->PushPopupsEnabledState(true); | 1027 instance()->PushPopupsEnabledState(true); |
| 997 } | 1028 } |
| 998 | 1029 |
| 999 bool ret = instance()->NPP_HandleEvent(event) != 0; | 1030 bool ret = instance()->NPP_HandleEvent(event) != 0; |
| 1000 | 1031 |
| 1001 // Snag a reference to the current cursor ASAP in case the plugin modified | 1032 if (event->event == WM_MOUSEMOVE) { |
| 1002 // it. There is a nasty race condition here with the multiprocess browser | 1033 // Snag a reference to the current cursor ASAP in case the plugin modified |
| 1003 // as someone might be setting the cursor in the main process as well. | 1034 // it. There is a nasty race condition here with the multiprocess browser |
| 1004 HCURSOR last_cursor; | 1035 // as someone might be setting the cursor in the main process as well. |
| 1005 if (WM_MOUSEMOVE == event->event) { | 1036 *cursor = current_windowless_cursor_; |
| 1006 last_cursor = ::GetCursor(); | |
| 1007 } | 1037 } |
| 1008 | 1038 |
| 1009 if (pop_user_gesture) { | 1039 if (pop_user_gesture) { |
| 1010 instance()->PopPopupsEnabledState(); | 1040 instance()->PopPopupsEnabledState(); |
| 1011 } | 1041 } |
| 1012 | 1042 |
| 1013 handle_event_depth_--; | 1043 handle_event_depth_--; |
| 1014 | 1044 |
| 1015 current_plugin_instance_ = NULL; | 1045 current_plugin_instance_ = NULL; |
| 1016 | 1046 |
| 1017 MessageLoop::current()->SetNestableTasksAllowed(old_task_reentrancy_state); | 1047 MessageLoop::current()->SetNestableTasksAllowed(old_task_reentrancy_state); |
| 1018 | 1048 |
| 1019 if (handle_event_message_filter_hook_) { | 1049 if (handle_event_message_filter_hook_) { |
| 1020 UnhookWindowsHookEx(handle_event_message_filter_hook_); | 1050 UnhookWindowsHookEx(handle_event_message_filter_hook_); |
| 1021 handle_event_message_filter_hook_ = NULL; | 1051 handle_event_message_filter_hook_ = NULL; |
| 1022 } | 1052 } |
| 1023 | 1053 |
| 1024 // We could have multiple NPP_HandleEvent calls nested together in case | 1054 // We could have multiple NPP_HandleEvent calls nested together in case |
| 1025 // the plugin enters a modal loop. Reset the pump messages event when | 1055 // the plugin enters a modal loop. Reset the pump messages event when |
| 1026 // the outermost NPP_HandleEvent call unwinds. | 1056 // the outermost NPP_HandleEvent call unwinds. |
| 1027 if (handle_event_depth_ == 0) { | 1057 if (handle_event_depth_ == 0) { |
| 1028 ResetEvent(handle_event_pump_messages_event_); | 1058 ResetEvent(handle_event_pump_messages_event_); |
| 1029 } | 1059 } |
| 1030 | 1060 |
| 1031 if (event->event == WM_RBUTTONUP && ::IsWindow(prev_focus_window)) { | 1061 if (event->event == WM_RBUTTONUP && ::IsWindow(prev_focus_window)) { |
| 1032 ::SetFocus(prev_focus_window); | 1062 ::SetFocus(prev_focus_window); |
| 1033 } | 1063 } |
| 1034 | 1064 |
| 1035 if (WM_MOUSEMOVE == event->event) { | |
| 1036 cursor->InitFromCursor(last_cursor); | |
| 1037 } | |
| 1038 | |
| 1039 return ret; | 1065 return ret; |
| 1040 } | 1066 } |
| 1041 | 1067 |
| 1042 WebPluginResourceClient* WebPluginDelegateImpl::CreateResourceClient( | 1068 WebPluginResourceClient* WebPluginDelegateImpl::CreateResourceClient( |
| 1043 int resource_id, const std::string &url, bool notify_needed, | 1069 int resource_id, const std::string &url, bool notify_needed, |
| 1044 void *notify_data, void* existing_stream) { | 1070 void *notify_data, void* existing_stream) { |
| 1045 // Stream already exists. This typically happens for range requests | 1071 // Stream already exists. This typically happens for range requests |
| 1046 // initiated via NPN_RequestRead. | 1072 // initiated via NPN_RequestRead. |
| 1047 if (existing_stream) { | 1073 if (existing_stream) { |
| 1048 NPAPI::PluginStream* plugin_stream = | 1074 NPAPI::PluginStream* plugin_stream = |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1117 unsigned long window_thread_id = | 1143 unsigned long window_thread_id = |
| 1118 GetWindowThreadProcessId(window, &window_process_id); | 1144 GetWindowThreadProcessId(window, &window_process_id); |
| 1119 // TrackPopupMenu fails if the window passed in belongs to a different | 1145 // TrackPopupMenu fails if the window passed in belongs to a different |
| 1120 // thread. | 1146 // thread. |
| 1121 if (::GetCurrentThreadId() != window_thread_id) { | 1147 if (::GetCurrentThreadId() != window_thread_id) { |
| 1122 window = current_plugin_instance_->dummy_window_for_activation_; | 1148 window = current_plugin_instance_->dummy_window_for_activation_; |
| 1123 } | 1149 } |
| 1124 } | 1150 } |
| 1125 return TrackPopupMenu(menu, flags, x, y, reserved, window, rect); | 1151 return TrackPopupMenu(menu, flags, x, y, reserved, window, rect); |
| 1126 } | 1152 } |
| 1153 |
| 1154 HCURSOR WINAPI WebPluginDelegateImpl::SetCursorPatch(HCURSOR cursor) { |
| 1155 // The windowless flash plugin periodically calls SetCursor in a wndproc |
| 1156 // instantiated on the plugin thread. This causes annoying cursor flicker |
| 1157 // when the mouse is moved on a foreground tab, with a windowless plugin |
| 1158 // instance in a background tab. We just ignore the call here. |
| 1159 if (!current_plugin_instance_) |
| 1160 return GetCursor(); |
| 1161 |
| 1162 if (!current_plugin_instance_->windowless()) { |
| 1163 return SetCursor(cursor); |
| 1164 } |
| 1165 |
| 1166 // It is ok to pass NULL here to GetCursor as we are not looking for cursor |
| 1167 // types defined by Webkit. |
| 1168 HCURSOR previous_cursor = |
| 1169 current_plugin_instance_->current_windowless_cursor_.GetCursor(NULL); |
| 1170 |
| 1171 current_plugin_instance_->current_windowless_cursor_.InitFromExternalCursor( |
| 1172 cursor); |
| 1173 return previous_cursor; |
| 1174 } |
| OLD | NEW |