diff --git a/dom/plugins/PluginInstanceChild.cpp b/dom/plugins/PluginInstanceChild.cpp index 58f117ea7c04..d7ad55b35a7a 100644 --- a/dom/plugins/PluginInstanceChild.cpp +++ b/dom/plugins/PluginInstanceChild.cpp @@ -84,9 +84,6 @@ const int kFlashWMUSERMessageThrottleDelayMs = 5; #define NS_OOPP_DOUBLEPASS_MSGID TEXT("MozDoublePassMsg") -#ifndef WM_MOUSEHWHEEL -#define WM_MOUSEHWHEEL 0x020E -#endif #elif defined(XP_MACOSX) #include #endif // defined(XP_MACOSX) @@ -1060,21 +1057,6 @@ PluginInstanceChild::PluginWindowProc(HWND hWnd, if (message == WM_MOUSEACTIVATE) self->CallPluginGotFocus(); - // Prevent lockups due to plugins making rpc calls when the parent - // is making a synchronous SendMessage call to the child window. Add - // more messages as needed. - if ((InSendMessageEx(NULL)&(ISMEX_REPLIED|ISMEX_SEND)) == ISMEX_SEND) { - switch(message) { - case WM_KILLFOCUS: - case WM_MOUSEHWHEEL: - case WM_MOUSEWHEEL: - case WM_HSCROLL: - case WM_VSCROLL: - ReplyMessage(0); - break; - } - } - if (message == WM_USER+1 && (self->mQuirks & PluginInstanceChild::QUIRK_FLASH_THROTTLE_WMUSER_EVENTS)) { self->FlashThrottleMessage(hWnd, message, wParam, lParam, true); diff --git a/dom/plugins/PluginModuleChild.cpp b/dom/plugins/PluginModuleChild.cpp index 2f221b3119c1..ad1463e66378 100644 --- a/dom/plugins/PluginModuleChild.cpp +++ b/dom/plugins/PluginModuleChild.cpp @@ -66,6 +66,12 @@ using namespace mozilla::plugins; +#if defined(XP_WIN) +#ifndef WM_MOUSEHWHEEL +#define WM_MOUSEHWHEEL 0x020E +#endif +#endif + namespace { PluginModuleChild* gInstance = nsnull; } @@ -82,6 +88,7 @@ PluginModuleChild::PluginModuleChild() : #endif #ifdef OS_WIN , mNestedEventHook(NULL) + , mGlobalCallWndProcHook(NULL) #endif { NS_ASSERTION(!gInstance, "Something terribly wrong here!"); @@ -488,7 +495,7 @@ PluginModuleChild::AnswerNP_Shutdown(NPError *rv) memset(&mFunctions, 0, sizeof(mFunctions)); #ifdef OS_WIN - ResetNestedInputEventHook(); + ResetEventHooks(); #endif return true; @@ -1496,7 +1503,7 @@ PluginModuleChild::AnswerNP_Initialize(NativeThreadId* tid, NPError* _retval) #endif #ifdef OS_WIN - SetNestedInputEventHook(); + SetEventHooks(); #endif #if defined(OS_LINUX) @@ -1875,6 +1882,59 @@ PluginModuleChild::ExitedCall() mIncallPumpingStack.TruncateLength(len - 1); } +LRESULT CALLBACK +PluginModuleChild::CallWindowProcHook(int nCode, WPARAM wParam, LPARAM lParam) +{ + // Trap and reply to anything we recognize as the source of a + // potential send message deadlock. + if (nCode >= 0 && + (InSendMessageEx(NULL)&(ISMEX_REPLIED|ISMEX_SEND)) == ISMEX_SEND) { + CWPSTRUCT* pCwp = reinterpret_cast(lParam); + switch(pCwp->message) { + // Sync messages we can reply to: + case WM_SETFOCUS: + case WM_KILLFOCUS: + case WM_MOUSEHWHEEL: + case WM_MOUSEWHEEL: + case WM_HSCROLL: + case WM_VSCROLL: + case WM_CONTEXTMENU: + case WM_IME_SETCONTEXT: + case WM_WINDOWPOSCHANGED: + ReplyMessage(0); + break; + // Sync message that can't be handled: + case WM_WINDOWPOSCHANGING: + case WM_DESTROY: + case WM_PAINT: + break; + // Everything else: + default: { +#ifdef DEBUG + nsCAutoString log("Child plugin module received untrapped "); + log.AppendLiteral("synchronous message for window. msg="); + char szTmp[40]; + sprintf(szTmp, "0x%06X", pCwp->message); + log.Append(szTmp); + log.AppendLiteral(" hwnd="); + sprintf(szTmp, "0x%08X", pCwp->hwnd); + log.Append(szTmp); + PRUnichar className[256] = { 0 }; + if (GetClassNameW(pCwp->hwnd, className, + sizeof(className)/sizeof(PRUnichar)) > 0) { + log.AppendLiteral(" class='"); + log.Append(NS_ConvertUTF16toUTF8((PRUnichar*)className)); + log.AppendLiteral("'"); + } + NS_WARNING(log.get()); +#endif + } + } + } + + return CallNextHookEx(NULL, nCode, wParam, lParam); +} + LRESULT CALLBACK PluginModuleChild::NestedInputEventHook(int nCode, WPARAM wParam, LPARAM lParam) { @@ -1893,29 +1953,38 @@ PluginModuleChild::NestedInputEventHook(int nCode, WPARAM wParam, LPARAM lParam) } void -PluginModuleChild::SetNestedInputEventHook() +PluginModuleChild::SetEventHooks() { NS_ASSERTION(!mNestedEventHook, "mNestedEventHook already setup in call to SetNestedInputEventHook?"); + NS_ASSERTION(!mGlobalCallWndProcHook, + "mGlobalCallWndProcHook already setup in call to CallWindowProcHook?"); PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION)); - // WH_GETMESSAGE hooks are triggered by peek message calls in parent due to - // attached message queues, resulting in stomped in-process ipc calls. So - // we use a filter hook specific to dialogs, menus, and scroll bars to kick - // things off. + // WH_MSGFILTER event hook for detecting modal loops in the child. mNestedEventHook = SetWindowsHookEx(WH_MSGFILTER, NestedInputEventHook, NULL, GetCurrentThreadId()); + + // WH_CALLWNDPROC event hook for trapping sync messages sent from + // parent that can cause deadlocks. + mGlobalCallWndProcHook = SetWindowsHookEx(WH_CALLWNDPROC, + CallWindowProcHook, + NULL, + GetCurrentThreadId()); } void -PluginModuleChild::ResetNestedInputEventHook() +PluginModuleChild::ResetEventHooks() { PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION)); if (mNestedEventHook) UnhookWindowsHookEx(mNestedEventHook); mNestedEventHook = NULL; + if (mGlobalCallWndProcHook) + UnhookWindowsHookEx(mGlobalCallWndProcHook); + mGlobalCallWndProcHook = NULL; } #endif diff --git a/dom/plugins/PluginModuleChild.h b/dom/plugins/PluginModuleChild.h index f0a5d9eb453c..ab3a05aace5a 100644 --- a/dom/plugins/PluginModuleChild.h +++ b/dom/plugins/PluginModuleChild.h @@ -323,9 +323,13 @@ private: static LRESULT CALLBACK NestedInputEventHook(int code, WPARAM wParam, LPARAM lParam); - void SetNestedInputEventHook(); - void ResetNestedInputEventHook(); + static LRESULT CALLBACK CallWindowProcHook(int code, + WPARAM wParam, + LPARAM lParam); + void SetEventHooks(); + void ResetEventHooks(); HHOOK mNestedEventHook; + HHOOK mGlobalCallWndProcHook; #endif };