Chromium Code Reviews| 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 |