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