Commit d4a94c2a authored by jschuh@chromium.org's avatar jschuh@chromium.org

Maintain key state in the plugin delegate if UIPI is enabled.

UIPI blocks keystate across process boundaries in certain situations. To be safe we maintain our own key state and intercept calls to GetKeyState. 

BUG=86895
TEST=Adobe has test coverage.
Review URL: http://codereview.chromium.org/7529041

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@96069 0039d316-1c4b-4281-b951-d872f2087c98
parent baa90006
...@@ -78,6 +78,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate { ...@@ -78,6 +78,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
PLUGIN_QUIRK_WINDOWLESS_NO_RIGHT_CLICK = 32768, // Linux PLUGIN_QUIRK_WINDOWLESS_NO_RIGHT_CLICK = 32768, // Linux
PLUGIN_QUIRK_IGNORE_FIRST_SETWINDOW_CALL = 65536, // Windows. PLUGIN_QUIRK_IGNORE_FIRST_SETWINDOW_CALL = 65536, // Windows.
PLUGIN_QUIRK_REPARENT_IN_BROWSER = 131072, // Windows PLUGIN_QUIRK_REPARENT_IN_BROWSER = 131072, // Windows
PLUGIN_QUIRK_PATCH_GETKEYSTATE = 262144, // Windows
}; };
static WebPluginDelegateImpl* Create(const FilePath& filename, static WebPluginDelegateImpl* Create(const FilePath& filename,
...@@ -375,6 +376,9 @@ class WebPluginDelegateImpl : public WebPluginDelegate { ...@@ -375,6 +376,9 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
// SetCursor interceptor for windowless plugins. // SetCursor interceptor for windowless plugins.
static HCURSOR WINAPI SetCursorPatch(HCURSOR cursor); static HCURSOR WINAPI SetCursorPatch(HCURSOR cursor);
// GetKeyStatePatch interceptor for UIPI Flash plugin.
static SHORT WINAPI GetKeyStatePatch(int vkey);
// RegEnumKeyExW interceptor. // RegEnumKeyExW interceptor.
static LONG WINAPI RegEnumKeyExWPatch( static LONG WINAPI RegEnumKeyExWPatch(
HKEY key, DWORD index, LPWSTR name, LPDWORD name_size, LPDWORD reserved, HKEY key, DWORD index, LPWSTR name, LPDWORD name_size, LPDWORD reserved,
......
...@@ -86,6 +86,39 @@ base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_set_cursor( ...@@ -86,6 +86,39 @@ base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_set_cursor(
base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_reg_enum_key_ex_w( base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_reg_enum_key_ex_w(
base::LINKER_INITIALIZED); base::LINKER_INITIALIZED);
// Helper object for patching the GetKeyState API.
base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_get_key_state(
base::LINKER_INITIALIZED);
// Saved key state globals and helper access functions.
SHORT (WINAPI *g_iat_orig_get_key_state)(int vkey);
typedef size_t SavedStateType;
const size_t kBitsPerType = sizeof(SavedStateType) * 8;
// Bit array of key state corresponding to virtual key index (0=up, 1=down).
SavedStateType g_saved_key_state[256 / kBitsPerType];
bool GetSavedKeyState(WPARAM vkey) {
CHECK_LT(vkey, kBitsPerType * sizeof(g_saved_key_state));
if (g_saved_key_state[vkey / kBitsPerType] & 1 << (vkey % kBitsPerType))
return true;
return false;
}
void SetSavedKeyState(WPARAM vkey) {
CHECK_LT(vkey, kBitsPerType * sizeof(g_saved_key_state));
g_saved_key_state[vkey / kBitsPerType] |= 1 << (vkey % kBitsPerType);
}
void UnsetSavedKeyState(WPARAM vkey) {
CHECK_LT(vkey, kBitsPerType * sizeof(g_saved_key_state));
g_saved_key_state[vkey / kBitsPerType] &= ~(1 << (vkey % kBitsPerType));
}
void ClearSavedKeyState() {
memset(g_saved_key_state, 0, sizeof(g_saved_key_state));
}
// http://crbug.com/16114 // http://crbug.com/16114
// Enforces providing a valid device context in NPWindow, so that NPP_SetWindow // Enforces providing a valid device context in NPWindow, so that NPP_SetWindow
// is never called with NPNWindoTypeDrawable and NPWindow set to NULL. // is never called with NPNWindoTypeDrawable and NPWindow set to NULL.
...@@ -257,6 +290,15 @@ LRESULT CALLBACK WebPluginDelegateImpl::MouseHookProc( ...@@ -257,6 +290,15 @@ LRESULT CALLBACK WebPluginDelegateImpl::MouseHookProc(
return CallNextHookEx(NULL, code, wParam, lParam); return CallNextHookEx(NULL, code, wParam, lParam);
} }
// In addition to the key state we maintain, we also mask in the original
// return value. This is done because system keys (e.g. tab, enter, shift)
// and toggles (e.g. capslock, numlock) don't ever seem to be blocked.
SHORT WINAPI WebPluginDelegateImpl::GetKeyStatePatch(int vkey) {
if (GetSavedKeyState(vkey))
return g_iat_orig_get_key_state(vkey) | 0x8000;
return g_iat_orig_get_key_state(vkey);
}
WebPluginDelegateImpl::WebPluginDelegateImpl( WebPluginDelegateImpl::WebPluginDelegateImpl(
gfx::PluginWindowHandle containing_view, gfx::PluginWindowHandle containing_view,
PluginInstance *instance) PluginInstance *instance)
...@@ -299,8 +341,11 @@ WebPluginDelegateImpl::WebPluginDelegateImpl( ...@@ -299,8 +341,11 @@ WebPluginDelegateImpl::WebPluginDelegateImpl(
quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR; quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR;
quirks_ |= PLUGIN_QUIRK_ALWAYS_NOTIFY_SUCCESS; quirks_ |= PLUGIN_QUIRK_ALWAYS_NOTIFY_SUCCESS;
quirks_ |= PLUGIN_QUIRK_HANDLE_MOUSE_CAPTURE; quirks_ |= PLUGIN_QUIRK_HANDLE_MOUSE_CAPTURE;
if (filename == kBuiltinFlashPlugin) if (filename == kBuiltinFlashPlugin &&
quirks_ |= PLUGIN_QUIRK_REPARENT_IN_BROWSER; base::win::GetVersion() >= base::win::VERSION_VISTA) {
quirks_ |= PLUGIN_QUIRK_REPARENT_IN_BROWSER |
PLUGIN_QUIRK_PATCH_GETKEYSTATE;
}
} else if (filename == kAcrobatReaderPlugin) { } else if (filename == kAcrobatReaderPlugin) {
// Check for the version number above or equal 9. // Check for the version number above or equal 9.
int major_version = GetPluginMajorVersion(plugin_info); int major_version = GetPluginMajorVersion(plugin_info);
...@@ -441,6 +486,17 @@ bool WebPluginDelegateImpl::PlatformInitialize() { ...@@ -441,6 +486,17 @@ bool WebPluginDelegateImpl::PlatformInitialize() {
WebPluginDelegateImpl::RegEnumKeyExWPatch); WebPluginDelegateImpl::RegEnumKeyExWPatch);
} }
// Under UIPI the key state does not get forwarded properly to the child
// plugin window. So, instead we track the key state manually and intercept
// GetKeyState.
if ((quirks_ & PLUGIN_QUIRK_PATCH_GETKEYSTATE) &&
!g_iat_patch_get_key_state.Pointer()->is_patched()) {
g_iat_orig_get_key_state = ::GetKeyState;
g_iat_patch_get_key_state.Pointer()->Patch(
L"gcswf32.dll", "user32.dll", "GetKeyState",
WebPluginDelegateImpl::GetKeyStatePatch);
}
return true; return true;
} }
...@@ -941,6 +997,31 @@ LRESULT CALLBACK WebPluginDelegateImpl::NativeWndProc( ...@@ -941,6 +997,31 @@ LRESULT CALLBACK WebPluginDelegateImpl::NativeWndProc(
return FALSE; return FALSE;
} }
// Track the keystate to work around a UIPI issue.
if (delegate->GetQuirks() & PLUGIN_QUIRK_PATCH_GETKEYSTATE) {
switch (message) {
case WM_KEYDOWN:
SetSavedKeyState(wparam);
break;
case WM_KEYUP:
UnsetSavedKeyState(wparam);
break;
// Clear out the saved keystate whenever the Flash thread loses focus.
case WM_KILLFOCUS:
case WM_SETFOCUS:
if (::GetCurrentThreadId() != ::GetWindowThreadProcessId(
reinterpret_cast<HWND>(wparam), NULL)) {
ClearSavedKeyState();
}
break;
default:
break;
}
}
LRESULT result; LRESULT result;
uint32 old_message = delegate->last_message_; uint32 old_message = delegate->last_message_;
delegate->last_message_ = message; delegate->last_message_ = message;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment