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 void SetSavedKeyState(WPARAM vkey) { | |
101 g_saved_key_state[vkey / kBitsPerType] |= 1 << (vkey % kBitsPerType); | |
102 } | |
103 | |
104 void UnsetSavedKeyState(WPARAM vkey) { | |
105 g_saved_key_state[vkey / kBitsPerType] &= ~(1 << (vkey % kBitsPerType)); | |
106 } | |
107 | |
108 void ClearSavedKeyState() { | |
109 ::ZeroMemory(g_saved_key_state, sizeof(g_saved_key_state)); | |
110 } | |
cpu_(ooo_6.6-7.5)
2011/08/09 20:07:31
zeromemory is just a macro to memset
jschuh
2011/08/09 20:57:27
I know. It's just a habit I have, but I'm happy to
| |
111 | |
112 | |
89 // http://crbug.com/16114 | 113 // http://crbug.com/16114 |
90 // Enforces providing a valid device context in NPWindow, so that NPP_SetWindow | 114 // Enforces providing a valid device context in NPWindow, so that NPP_SetWindow |
91 // is never called with NPNWindoTypeDrawable and NPWindow set to NULL. | 115 // is never called with NPNWindoTypeDrawable and NPWindow set to NULL. |
92 // Doing so allows removing NPP_SetWindow call during painting a windowless | 116 // Doing so allows removing NPP_SetWindow call during painting a windowless |
93 // plugin, which otherwise could trigger layout change while painting by | 117 // plugin, which otherwise could trigger layout change while painting by |
94 // invoking NPN_Evaluate. Which would cause bad, bad crashes. Bad crashes. | 118 // invoking NPN_Evaluate. Which would cause bad, bad crashes. Bad crashes. |
95 // TODO(dglazkov): If this approach doesn't produce regressions, move class to | 119 // TODO(dglazkov): If this approach doesn't produce regressions, move class to |
96 // webplugin_delegate_impl.h and implement for other platforms. | 120 // webplugin_delegate_impl.h and implement for other platforms. |
97 class DrawableContextEnforcer { | 121 class DrawableContextEnforcer { |
98 public: | 122 public: |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
250 int code, WPARAM wParam, LPARAM lParam) { | 274 int code, WPARAM wParam, LPARAM lParam) { |
251 if (code == HC_ACTION) { | 275 if (code == HC_ACTION) { |
252 MOUSEHOOKSTRUCT* hook_struct = reinterpret_cast<MOUSEHOOKSTRUCT*>(lParam); | 276 MOUSEHOOKSTRUCT* hook_struct = reinterpret_cast<MOUSEHOOKSTRUCT*>(lParam); |
253 if (hook_struct) | 277 if (hook_struct) |
254 HandleCaptureForMessage(hook_struct->hwnd, wParam); | 278 HandleCaptureForMessage(hook_struct->hwnd, wParam); |
255 } | 279 } |
256 | 280 |
257 return CallNextHookEx(NULL, code, wParam, lParam); | 281 return CallNextHookEx(NULL, code, wParam, lParam); |
258 } | 282 } |
259 | 283 |
284 // In addition to the key state we maintain, we also mask in the original | |
285 // return value. This is done because system keys (e.g. tab, enter, shift) | |
286 // and toggles (e.g. capslock, numlock) don't ever seem to be blocked. | |
287 SHORT WINAPI WebPluginDelegateImpl::GetKeyStatePatch(int vkey) { | |
288 if (g_saved_key_state[vkey / kBitsPerType] & 1 << (vkey % kBitsPerType)) | |
289 return 0x8000 | g_iat_orig_get_key_state(vkey); | |
290 return g_iat_orig_get_key_state(vkey); | |
291 } | |
292 | |
260 WebPluginDelegateImpl::WebPluginDelegateImpl( | 293 WebPluginDelegateImpl::WebPluginDelegateImpl( |
261 gfx::PluginWindowHandle containing_view, | 294 gfx::PluginWindowHandle containing_view, |
262 PluginInstance *instance) | 295 PluginInstance *instance) |
263 : parent_(containing_view), | 296 : parent_(containing_view), |
264 instance_(instance), | 297 instance_(instance), |
265 quirks_(0), | 298 quirks_(0), |
266 plugin_(NULL), | 299 plugin_(NULL), |
267 windowless_(false), | 300 windowless_(false), |
268 windowed_handle_(NULL), | 301 windowed_handle_(NULL), |
269 windowed_did_set_window_(false), | 302 windowed_did_set_window_(false), |
(...skipping 22 matching lines...) Expand all Loading... | |
292 | 325 |
293 if (instance_->mime_type() == "application/x-shockwave-flash" || | 326 if (instance_->mime_type() == "application/x-shockwave-flash" || |
294 filename == kFlashPlugin) { | 327 filename == kFlashPlugin) { |
295 // Flash only requests windowless plugins if we return a Mozilla user | 328 // Flash only requests windowless plugins if we return a Mozilla user |
296 // agent. | 329 // agent. |
297 instance_->set_use_mozilla_user_agent(); | 330 instance_->set_use_mozilla_user_agent(); |
298 quirks_ |= PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE; | 331 quirks_ |= PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE; |
299 quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR; | 332 quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR; |
300 quirks_ |= PLUGIN_QUIRK_ALWAYS_NOTIFY_SUCCESS; | 333 quirks_ |= PLUGIN_QUIRK_ALWAYS_NOTIFY_SUCCESS; |
301 quirks_ |= PLUGIN_QUIRK_HANDLE_MOUSE_CAPTURE; | 334 quirks_ |= PLUGIN_QUIRK_HANDLE_MOUSE_CAPTURE; |
302 if (filename == kBuiltinFlashPlugin) | 335 if (filename == kBuiltinFlashPlugin && |
303 quirks_ |= PLUGIN_QUIRK_REPARENT_IN_BROWSER; | 336 base::win::GetVersion() >= base::win::VERSION_VISTA) { |
337 quirks_ |= PLUGIN_QUIRK_REPARENT_IN_BROWSER | | |
338 PLUGIN_QUIRK_PATCH_GETKEYSTATE; | |
339 } | |
304 } else if (filename == kAcrobatReaderPlugin) { | 340 } else if (filename == kAcrobatReaderPlugin) { |
305 // Check for the version number above or equal 9. | 341 // Check for the version number above or equal 9. |
306 int major_version = GetPluginMajorVersion(plugin_info); | 342 int major_version = GetPluginMajorVersion(plugin_info); |
307 if (major_version >= 9) { | 343 if (major_version >= 9) { |
308 quirks_ |= PLUGIN_QUIRK_DIE_AFTER_UNLOAD; | 344 quirks_ |= PLUGIN_QUIRK_DIE_AFTER_UNLOAD; |
309 // 9.2 needs this. | 345 // 9.2 needs this. |
310 quirks_ |= PLUGIN_QUIRK_SETWINDOW_TWICE; | 346 quirks_ |= PLUGIN_QUIRK_SETWINDOW_TWICE; |
311 } | 347 } |
312 quirks_ |= PLUGIN_QUIRK_BLOCK_NONSTANDARD_GETURL_REQUESTS; | 348 quirks_ |= PLUGIN_QUIRK_BLOCK_NONSTANDARD_GETURL_REQUESTS; |
313 } else if (plugin_info.name.find(L"Windows Media Player") != | 349 } 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 && | 470 base::win::GetVersion() == base::win::VERSION_XP && |
435 (base::win::RegKey().Open(HKEY_LOCAL_MACHINE, | 471 (base::win::RegKey().Open(HKEY_LOCAL_MACHINE, |
436 L"SOFTWARE\\Microsoft\\MediaPlayer\\ShimInclusionList\\chrome.exe", | 472 L"SOFTWARE\\Microsoft\\MediaPlayer\\ShimInclusionList\\chrome.exe", |
437 KEY_READ) != ERROR_SUCCESS) && | 473 KEY_READ) != ERROR_SUCCESS) && |
438 !g_iat_patch_reg_enum_key_ex_w.Pointer()->is_patched()) { | 474 !g_iat_patch_reg_enum_key_ex_w.Pointer()->is_patched()) { |
439 g_iat_patch_reg_enum_key_ex_w.Pointer()->Patch( | 475 g_iat_patch_reg_enum_key_ex_w.Pointer()->Patch( |
440 L"wmpdxm.dll", "advapi32.dll", "RegEnumKeyExW", | 476 L"wmpdxm.dll", "advapi32.dll", "RegEnumKeyExW", |
441 WebPluginDelegateImpl::RegEnumKeyExWPatch); | 477 WebPluginDelegateImpl::RegEnumKeyExWPatch); |
442 } | 478 } |
443 | 479 |
480 // Under UIPI the key state does not get forwarded properly to the child | |
481 // plugin window. So, instead we track the key state manually and intercept | |
482 // GetKeyState. | |
483 if ((quirks_ & PLUGIN_QUIRK_PATCH_GETKEYSTATE) && | |
484 !g_iat_patch_get_key_state.Pointer()->is_patched()) { | |
485 g_iat_orig_get_key_state = ::GetKeyState; | |
486 g_iat_patch_get_key_state.Pointer()->Patch( | |
487 L"gcswf32.dll", "user32.dll", "GetKeyState", | |
488 WebPluginDelegateImpl::GetKeyStatePatch); | |
489 } | |
490 | |
444 return true; | 491 return true; |
445 } | 492 } |
446 | 493 |
447 void WebPluginDelegateImpl::PlatformDestroyInstance() { | 494 void WebPluginDelegateImpl::PlatformDestroyInstance() { |
448 if (!instance_->plugin_lib()) | 495 if (!instance_->plugin_lib()) |
449 return; | 496 return; |
450 | 497 |
451 // Unpatch if this is the last plugin instance. | 498 // Unpatch if this is the last plugin instance. |
452 if (instance_->plugin_lib()->instance_count() != 1) | 499 if (instance_->plugin_lib()->instance_count() != 1) |
453 return; | 500 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 | 981 // 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 | 982 // usage. See https://bugzilla.mozilla.org/show_bug.cgi?id=132759. We |
936 // prevent this by throttling the messages. | 983 // prevent this by throttling the messages. |
937 if (message == WM_USER + 1 && | 984 if (message == WM_USER + 1 && |
938 delegate->GetQuirks() & PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE) { | 985 delegate->GetQuirks() & PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE) { |
939 WebPluginDelegateImpl::ThrottleMessage(delegate->plugin_wnd_proc_, hwnd, | 986 WebPluginDelegateImpl::ThrottleMessage(delegate->plugin_wnd_proc_, hwnd, |
940 message, wparam, lparam); | 987 message, wparam, lparam); |
941 return FALSE; | 988 return FALSE; |
942 } | 989 } |
943 | 990 |
991 // Track the keystate to work around a UIPI issue. | |
992 if (delegate->GetQuirks() & PLUGIN_QUIRK_PATCH_GETKEYSTATE) { | |
993 switch (message) { | |
994 case WM_KEYDOWN: | |
995 SetSavedKeyState(wparam); | |
cpu_(ooo_6.6-7.5)
2011/08/09 20:07:31
wparam % 256
Here or inside, your choice.
jschuh
2011/08/09 20:57:27
I assumed we shouldn't ever see a value larger tha
| |
996 break; | |
997 | |
998 case WM_KEYUP: | |
999 UnsetSavedKeyState(wparam); | |
1000 break; | |
1001 | |
1002 // Clear out the saved keystate whenever the Flash thread loses focus. | |
1003 case WM_KILLFOCUS: | |
1004 case WM_SETFOCUS: | |
1005 if (::GetCurrentThreadId() != ::GetWindowThreadProcessId( | |
1006 reinterpret_cast<HWND>(wparam), NULL)) { | |
1007 ClearSavedKeyState(); | |
1008 } | |
1009 break; | |
1010 | |
1011 default: | |
1012 break; | |
1013 } | |
1014 } | |
1015 | |
944 LRESULT result; | 1016 LRESULT result; |
945 uint32 old_message = delegate->last_message_; | 1017 uint32 old_message = delegate->last_message_; |
946 delegate->last_message_ = message; | 1018 delegate->last_message_ = message; |
947 | 1019 |
948 static UINT custom_msg = RegisterWindowMessage(kPaintMessageName); | 1020 static UINT custom_msg = RegisterWindowMessage(kPaintMessageName); |
949 if (message == custom_msg) { | 1021 if (message == custom_msg) { |
950 // Get the invalid rect which is in screen coordinates and convert to | 1022 // Get the invalid rect which is in screen coordinates and convert to |
951 // window coordinates. | 1023 // window coordinates. |
952 gfx::Rect invalid_rect; | 1024 gfx::Rect invalid_rect; |
953 invalid_rect.set_x(wparam >> 16); | 1025 invalid_rect.set_x(wparam >> 16); |
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1432 ::ReleaseCapture(); | 1504 ::ReleaseCapture(); |
1433 break; | 1505 break; |
1434 | 1506 |
1435 default: | 1507 default: |
1436 break; | 1508 break; |
1437 } | 1509 } |
1438 } | 1510 } |
1439 | 1511 |
1440 } // namespace npapi | 1512 } // namespace npapi |
1441 } // namespace webkit | 1513 } // namespace webkit |
OLD | NEW |