OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/plugins/npapi/webplugin_delegate_impl.h" | 5 #include "webkit/plugins/npapi/webplugin_delegate_impl.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 base::LINKER_INITIALIZED); | 79 base::LINKER_INITIALIZED); |
80 | 80 |
81 // Helper object for patching the SetCursor API. | 81 // Helper object for patching the SetCursor API. |
82 base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_set_cursor( | 82 base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_set_cursor( |
83 base::LINKER_INITIALIZED); | 83 base::LINKER_INITIALIZED); |
84 | 84 |
85 // Helper object for patching the RegEnumKeyExW API. | 85 // Helper object for patching the RegEnumKeyExW API. |
86 base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_reg_enum_key_ex_w( | 86 base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_reg_enum_key_ex_w( |
87 base::LINKER_INITIALIZED); | 87 base::LINKER_INITIALIZED); |
88 | 88 |
| 89 // Helper object for patching the GetKeyState API. |
| 90 base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_get_key_state( |
| 91 base::LINKER_INITIALIZED); |
| 92 |
| 93 // Saved key state globals and helper access functions. |
| 94 SHORT (WINAPI *g_iat_orig_get_key_state)(int vkey); |
| 95 typedef size_t SavedStateType; |
| 96 const size_t kBitsPerType = sizeof(SavedStateType) * 8; |
| 97 // Bit array of key state corresponding to virtual key index (0=up, 1=down). |
| 98 SavedStateType g_saved_key_state[256 / kBitsPerType]; |
| 99 |
| 100 bool GetSavedKeyState(WPARAM vkey) { |
| 101 CHECK_LT(vkey, kBitsPerType * sizeof(g_saved_key_state)); |
| 102 if (g_saved_key_state[vkey / kBitsPerType] & 1 << (vkey % kBitsPerType)) |
| 103 return true; |
| 104 return false; |
| 105 } |
| 106 |
| 107 void SetSavedKeyState(WPARAM vkey) { |
| 108 CHECK_LT(vkey, kBitsPerType * sizeof(g_saved_key_state)); |
| 109 g_saved_key_state[vkey / kBitsPerType] |= 1 << (vkey % kBitsPerType); |
| 110 } |
| 111 |
| 112 void UnsetSavedKeyState(WPARAM vkey) { |
| 113 CHECK_LT(vkey, kBitsPerType * sizeof(g_saved_key_state)); |
| 114 g_saved_key_state[vkey / kBitsPerType] &= ~(1 << (vkey % kBitsPerType)); |
| 115 } |
| 116 |
| 117 void ClearSavedKeyState() { |
| 118 memset(g_saved_key_state, 0, sizeof(g_saved_key_state)); |
| 119 } |
| 120 |
| 121 |
89 // http://crbug.com/16114 | 122 // http://crbug.com/16114 |
90 // Enforces providing a valid device context in NPWindow, so that NPP_SetWindow | 123 // Enforces providing a valid device context in NPWindow, so that NPP_SetWindow |
91 // is never called with NPNWindoTypeDrawable and NPWindow set to NULL. | 124 // is never called with NPNWindoTypeDrawable and NPWindow set to NULL. |
92 // Doing so allows removing NPP_SetWindow call during painting a windowless | 125 // Doing so allows removing NPP_SetWindow call during painting a windowless |
93 // plugin, which otherwise could trigger layout change while painting by | 126 // plugin, which otherwise could trigger layout change while painting by |
94 // invoking NPN_Evaluate. Which would cause bad, bad crashes. Bad crashes. | 127 // invoking NPN_Evaluate. Which would cause bad, bad crashes. Bad crashes. |
95 // TODO(dglazkov): If this approach doesn't produce regressions, move class to | 128 // TODO(dglazkov): If this approach doesn't produce regressions, move class to |
96 // webplugin_delegate_impl.h and implement for other platforms. | 129 // webplugin_delegate_impl.h and implement for other platforms. |
97 class DrawableContextEnforcer { | 130 class DrawableContextEnforcer { |
98 public: | 131 public: |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
250 int code, WPARAM wParam, LPARAM lParam) { | 283 int code, WPARAM wParam, LPARAM lParam) { |
251 if (code == HC_ACTION) { | 284 if (code == HC_ACTION) { |
252 MOUSEHOOKSTRUCT* hook_struct = reinterpret_cast<MOUSEHOOKSTRUCT*>(lParam); | 285 MOUSEHOOKSTRUCT* hook_struct = reinterpret_cast<MOUSEHOOKSTRUCT*>(lParam); |
253 if (hook_struct) | 286 if (hook_struct) |
254 HandleCaptureForMessage(hook_struct->hwnd, wParam); | 287 HandleCaptureForMessage(hook_struct->hwnd, wParam); |
255 } | 288 } |
256 | 289 |
257 return CallNextHookEx(NULL, code, wParam, lParam); | 290 return CallNextHookEx(NULL, code, wParam, lParam); |
258 } | 291 } |
259 | 292 |
| 293 // In addition to the key state we maintain, we also mask in the original |
| 294 // return value. This is done because system keys (e.g. tab, enter, shift) |
| 295 // and toggles (e.g. capslock, numlock) don't ever seem to be blocked. |
| 296 SHORT WINAPI WebPluginDelegateImpl::GetKeyStatePatch(int vkey) { |
| 297 if (GetSavedKeyState(vkey)) |
| 298 return g_iat_orig_get_key_state(vkey) | 0x8000; |
| 299 return g_iat_orig_get_key_state(vkey); |
| 300 } |
| 301 |
260 WebPluginDelegateImpl::WebPluginDelegateImpl( | 302 WebPluginDelegateImpl::WebPluginDelegateImpl( |
261 gfx::PluginWindowHandle containing_view, | 303 gfx::PluginWindowHandle containing_view, |
262 PluginInstance *instance) | 304 PluginInstance *instance) |
263 : parent_(containing_view), | 305 : parent_(containing_view), |
264 instance_(instance), | 306 instance_(instance), |
265 quirks_(0), | 307 quirks_(0), |
266 plugin_(NULL), | 308 plugin_(NULL), |
267 windowless_(false), | 309 windowless_(false), |
268 windowed_handle_(NULL), | 310 windowed_handle_(NULL), |
269 windowed_did_set_window_(false), | 311 windowed_did_set_window_(false), |
(...skipping 22 matching lines...) Expand all Loading... |
292 | 334 |
293 if (instance_->mime_type() == "application/x-shockwave-flash" || | 335 if (instance_->mime_type() == "application/x-shockwave-flash" || |
294 filename == kFlashPlugin) { | 336 filename == kFlashPlugin) { |
295 // Flash only requests windowless plugins if we return a Mozilla user | 337 // Flash only requests windowless plugins if we return a Mozilla user |
296 // agent. | 338 // agent. |
297 instance_->set_use_mozilla_user_agent(); | 339 instance_->set_use_mozilla_user_agent(); |
298 quirks_ |= PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE; | 340 quirks_ |= PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE; |
299 quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR; | 341 quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR; |
300 quirks_ |= PLUGIN_QUIRK_ALWAYS_NOTIFY_SUCCESS; | 342 quirks_ |= PLUGIN_QUIRK_ALWAYS_NOTIFY_SUCCESS; |
301 quirks_ |= PLUGIN_QUIRK_HANDLE_MOUSE_CAPTURE; | 343 quirks_ |= PLUGIN_QUIRK_HANDLE_MOUSE_CAPTURE; |
302 if (filename == kBuiltinFlashPlugin) | 344 if (filename == kBuiltinFlashPlugin && |
303 quirks_ |= PLUGIN_QUIRK_REPARENT_IN_BROWSER; | 345 base::win::GetVersion() >= base::win::VERSION_VISTA) { |
| 346 quirks_ |= PLUGIN_QUIRK_REPARENT_IN_BROWSER | |
| 347 PLUGIN_QUIRK_PATCH_GETKEYSTATE; |
| 348 } |
304 } else if (filename == kAcrobatReaderPlugin) { | 349 } else if (filename == kAcrobatReaderPlugin) { |
305 // Check for the version number above or equal 9. | 350 // Check for the version number above or equal 9. |
306 int major_version = GetPluginMajorVersion(plugin_info); | 351 int major_version = GetPluginMajorVersion(plugin_info); |
307 if (major_version >= 9) { | 352 if (major_version >= 9) { |
308 quirks_ |= PLUGIN_QUIRK_DIE_AFTER_UNLOAD; | 353 quirks_ |= PLUGIN_QUIRK_DIE_AFTER_UNLOAD; |
309 // 9.2 needs this. | 354 // 9.2 needs this. |
310 quirks_ |= PLUGIN_QUIRK_SETWINDOW_TWICE; | 355 quirks_ |= PLUGIN_QUIRK_SETWINDOW_TWICE; |
311 } | 356 } |
312 quirks_ |= PLUGIN_QUIRK_BLOCK_NONSTANDARD_GETURL_REQUESTS; | 357 quirks_ |= PLUGIN_QUIRK_BLOCK_NONSTANDARD_GETURL_REQUESTS; |
313 } else if (plugin_info.name.find(L"Windows Media Player") != | 358 } else if (plugin_info.name.find(L"Windows Media Player") != |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 base::win::GetVersion() == base::win::VERSION_XP && | 479 base::win::GetVersion() == base::win::VERSION_XP && |
435 (base::win::RegKey().Open(HKEY_LOCAL_MACHINE, | 480 (base::win::RegKey().Open(HKEY_LOCAL_MACHINE, |
436 L"SOFTWARE\\Microsoft\\MediaPlayer\\ShimInclusionList\\chrome.exe", | 481 L"SOFTWARE\\Microsoft\\MediaPlayer\\ShimInclusionList\\chrome.exe", |
437 KEY_READ) != ERROR_SUCCESS) && | 482 KEY_READ) != ERROR_SUCCESS) && |
438 !g_iat_patch_reg_enum_key_ex_w.Pointer()->is_patched()) { | 483 !g_iat_patch_reg_enum_key_ex_w.Pointer()->is_patched()) { |
439 g_iat_patch_reg_enum_key_ex_w.Pointer()->Patch( | 484 g_iat_patch_reg_enum_key_ex_w.Pointer()->Patch( |
440 L"wmpdxm.dll", "advapi32.dll", "RegEnumKeyExW", | 485 L"wmpdxm.dll", "advapi32.dll", "RegEnumKeyExW", |
441 WebPluginDelegateImpl::RegEnumKeyExWPatch); | 486 WebPluginDelegateImpl::RegEnumKeyExWPatch); |
442 } | 487 } |
443 | 488 |
| 489 // Under UIPI the key state does not get forwarded properly to the child |
| 490 // plugin window. So, instead we track the key state manually and intercept |
| 491 // GetKeyState. |
| 492 if ((quirks_ & PLUGIN_QUIRK_PATCH_GETKEYSTATE) && |
| 493 !g_iat_patch_get_key_state.Pointer()->is_patched()) { |
| 494 g_iat_orig_get_key_state = ::GetKeyState; |
| 495 g_iat_patch_get_key_state.Pointer()->Patch( |
| 496 L"gcswf32.dll", "user32.dll", "GetKeyState", |
| 497 WebPluginDelegateImpl::GetKeyStatePatch); |
| 498 } |
| 499 |
444 return true; | 500 return true; |
445 } | 501 } |
446 | 502 |
447 void WebPluginDelegateImpl::PlatformDestroyInstance() { | 503 void WebPluginDelegateImpl::PlatformDestroyInstance() { |
448 if (!instance_->plugin_lib()) | 504 if (!instance_->plugin_lib()) |
449 return; | 505 return; |
450 | 506 |
451 // Unpatch if this is the last plugin instance. | 507 // Unpatch if this is the last plugin instance. |
452 if (instance_->plugin_lib()->instance_count() != 1) | 508 if (instance_->plugin_lib()->instance_count() != 1) |
453 return; | 509 return; |
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
934 // Flash may flood the message queue with WM_USER+1 message causing 100% CPU | 990 // Flash may flood the message queue with WM_USER+1 message causing 100% CPU |
935 // usage. See https://bugzilla.mozilla.org/show_bug.cgi?id=132759. We | 991 // usage. See https://bugzilla.mozilla.org/show_bug.cgi?id=132759. We |
936 // prevent this by throttling the messages. | 992 // prevent this by throttling the messages. |
937 if (message == WM_USER + 1 && | 993 if (message == WM_USER + 1 && |
938 delegate->GetQuirks() & PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE) { | 994 delegate->GetQuirks() & PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE) { |
939 WebPluginDelegateImpl::ThrottleMessage(delegate->plugin_wnd_proc_, hwnd, | 995 WebPluginDelegateImpl::ThrottleMessage(delegate->plugin_wnd_proc_, hwnd, |
940 message, wparam, lparam); | 996 message, wparam, lparam); |
941 return FALSE; | 997 return FALSE; |
942 } | 998 } |
943 | 999 |
| 1000 // Track the keystate to work around a UIPI issue. |
| 1001 if (delegate->GetQuirks() & PLUGIN_QUIRK_PATCH_GETKEYSTATE) { |
| 1002 switch (message) { |
| 1003 case WM_KEYDOWN: |
| 1004 SetSavedKeyState(wparam); |
| 1005 break; |
| 1006 |
| 1007 case WM_KEYUP: |
| 1008 UnsetSavedKeyState(wparam); |
| 1009 break; |
| 1010 |
| 1011 // Clear out the saved keystate whenever the Flash thread loses focus. |
| 1012 case WM_KILLFOCUS: |
| 1013 case WM_SETFOCUS: |
| 1014 if (::GetCurrentThreadId() != ::GetWindowThreadProcessId( |
| 1015 reinterpret_cast<HWND>(wparam), NULL)) { |
| 1016 ClearSavedKeyState(); |
| 1017 } |
| 1018 break; |
| 1019 |
| 1020 default: |
| 1021 break; |
| 1022 } |
| 1023 } |
| 1024 |
944 LRESULT result; | 1025 LRESULT result; |
945 uint32 old_message = delegate->last_message_; | 1026 uint32 old_message = delegate->last_message_; |
946 delegate->last_message_ = message; | 1027 delegate->last_message_ = message; |
947 | 1028 |
948 static UINT custom_msg = RegisterWindowMessage(kPaintMessageName); | 1029 static UINT custom_msg = RegisterWindowMessage(kPaintMessageName); |
949 if (message == custom_msg) { | 1030 if (message == custom_msg) { |
950 // Get the invalid rect which is in screen coordinates and convert to | 1031 // Get the invalid rect which is in screen coordinates and convert to |
951 // window coordinates. | 1032 // window coordinates. |
952 gfx::Rect invalid_rect; | 1033 gfx::Rect invalid_rect; |
953 invalid_rect.set_x(wparam >> 16); | 1034 invalid_rect.set_x(wparam >> 16); |
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1432 ::ReleaseCapture(); | 1513 ::ReleaseCapture(); |
1433 break; | 1514 break; |
1434 | 1515 |
1435 default: | 1516 default: |
1436 break; | 1517 break; |
1437 } | 1518 } |
1438 } | 1519 } |
1439 | 1520 |
1440 } // namespace npapi | 1521 } // namespace npapi |
1441 } // namespace webkit | 1522 } // namespace webkit |
OLD | NEW |