Bug 1014673 - Allow WM_GETOBJECT calls to succeed when mozilla window procedures are neutered by ipc WaitForNotify calls. r=bent
This commit is contained in:
@@ -86,6 +86,7 @@ extern UINT sDefaultBrowserMsgId;
|
||||
namespace {
|
||||
|
||||
const wchar_t kOldWndProcProp[] = L"MozillaIPCOldWndProc";
|
||||
const wchar_t k3rdPartyWindowProp[] = L"Mozilla3rdPartyWindow";
|
||||
|
||||
// This isn't defined before Windows XP.
|
||||
enum { WM_XP_THEMECHANGED = 0x031A };
|
||||
@@ -103,6 +104,9 @@ HHOOK gDeferredCallWndProcHook = nullptr;
|
||||
|
||||
DWORD gUIThreadId = 0;
|
||||
|
||||
// WM_GETOBJECT id pulled from uia headers
|
||||
#define MOZOBJID_UIAROOT -25
|
||||
|
||||
LRESULT CALLBACK
|
||||
DeferredMessageHook(int nCode,
|
||||
WPARAM wParam,
|
||||
@@ -161,6 +165,28 @@ ScheduleDeferredMessageRun()
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DumpNeuteredMessage(HWND hwnd, UINT uMsg)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
nsAutoCString log("Received \"nonqueued\" message ");
|
||||
log.AppendInt(uMsg);
|
||||
log.AppendLiteral(" during a synchronous IPC message for window ");
|
||||
log.AppendInt((int64_t)hwnd);
|
||||
|
||||
wchar_t className[256] = { 0 };
|
||||
if (GetClassNameW(hwnd, className, sizeof(className) - 1) > 0) {
|
||||
log.AppendLiteral(" (\"");
|
||||
log.Append(NS_ConvertUTF16toUTF8((char16_t*)className));
|
||||
log.AppendLiteral("\")");
|
||||
}
|
||||
|
||||
log.AppendLiteral(", sending it to DefWindowProc instead of the normal "
|
||||
"window procedure.");
|
||||
NS_ERROR(log.get());
|
||||
#endif
|
||||
}
|
||||
|
||||
LRESULT
|
||||
ProcessOrDeferMessage(HWND hwnd,
|
||||
UINT uMsg,
|
||||
@@ -285,7 +311,24 @@ ProcessOrDeferMessage(HWND hwnd,
|
||||
case WM_APP-1:
|
||||
return 0;
|
||||
|
||||
// We only support a query for our IAccessible or UIA pointers.
|
||||
// This should be safe, and needs to be sync.
|
||||
#if defined(ACCESSIBILITY)
|
||||
case WM_GETOBJECT: {
|
||||
if (!::GetPropW(hwnd, k3rdPartyWindowProp)) {
|
||||
DWORD objId = static_cast<DWORD>(lParam);
|
||||
WNDPROC oldWndProc = (WNDPROC)GetProp(hwnd, kOldWndProcProp);
|
||||
if ((objId == OBJID_CLIENT || objId == MOZOBJID_UIAROOT) && oldWndProc) {
|
||||
return CallWindowProcW(oldWndProc, hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif // ACCESSIBILITY
|
||||
|
||||
default: {
|
||||
// Unknown messages only are logged in debug builds and sent to
|
||||
// DefWindowProc.
|
||||
if (uMsg && uMsg == mozilla::widget::sAppShellGeckoMsgId) {
|
||||
// Widget's registered native event callback
|
||||
deferred = new DeferredSendMessage(hwnd, uMsg, wParam, lParam);
|
||||
@@ -294,31 +337,16 @@ ProcessOrDeferMessage(HWND hwnd,
|
||||
// Metro widget's system shutdown message
|
||||
deferred = new DeferredSendMessage(hwnd, uMsg, wParam, lParam);
|
||||
#endif
|
||||
} else {
|
||||
// Unknown messages only
|
||||
#ifdef DEBUG
|
||||
nsAutoCString log("Received \"nonqueued\" message ");
|
||||
log.AppendInt(uMsg);
|
||||
log.AppendLiteral(" during a synchronous IPC message for window ");
|
||||
log.AppendInt((int64_t)hwnd);
|
||||
|
||||
wchar_t className[256] = { 0 };
|
||||
if (GetClassNameW(hwnd, className, sizeof(className) - 1) > 0) {
|
||||
log.AppendLiteral(" (\"");
|
||||
log.Append(NS_ConvertUTF16toUTF8((char16_t*)className));
|
||||
log.AppendLiteral("\")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.AppendLiteral(", sending it to DefWindowProc instead of the normal "
|
||||
"window procedure.");
|
||||
NS_ERROR(log.get());
|
||||
#endif
|
||||
// No deferred message was created and we land here, this is an
|
||||
// unhandled message.
|
||||
if (!deferred) {
|
||||
DumpNeuteredMessage(hwnd, uMsg);
|
||||
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_ASSERTION(deferred, "Must have a message here!");
|
||||
|
||||
// Create the deferred message array if it doesn't exist already.
|
||||
if (!gDeferredMessages) {
|
||||
@@ -400,6 +428,7 @@ WindowIsDeferredWindow(HWND hWnd)
|
||||
if (className.EqualsLiteral("ShockwaveFlashFullScreen") ||
|
||||
className.EqualsLiteral("QTNSHIDDEN") ||
|
||||
className.EqualsLiteral("AGFullScreenWinClass")) {
|
||||
SetPropW(hWnd, k3rdPartyWindowProp, (HANDLE)1);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -407,6 +436,7 @@ WindowIsDeferredWindow(HWND hWnd)
|
||||
// earth process. The earth process can trigger a plugin incall on the browser
|
||||
// at any time, which is badness if the instance is already making an incall.
|
||||
if (className.EqualsLiteral("__geplugin_bridge_window__")) {
|
||||
SetPropW(hWnd, k3rdPartyWindowProp, (HANDLE)1);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -473,7 +503,8 @@ NeuterWindowProcedure(HWND hWnd)
|
||||
// Cleanup
|
||||
NS_WARNING("SetProp failed!");
|
||||
SetWindowLongPtr(hWnd, GWLP_WNDPROC, currentWndProc);
|
||||
RemoveProp(hWnd, kOldWndProcProp);
|
||||
RemovePropW(hWnd, kOldWndProcProp);
|
||||
RemovePropW(hWnd, k3rdPartyWindowProp);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -495,7 +526,8 @@ RestoreWindowProcedure(HWND hWnd)
|
||||
NS_ASSERTION(currentWndProc == (LONG_PTR)NeuteredWindowProc,
|
||||
"This should never be switched out from under us!");
|
||||
}
|
||||
RemoveProp(hWnd, kOldWndProcProp);
|
||||
RemovePropW(hWnd, kOldWndProcProp);
|
||||
RemovePropW(hWnd, k3rdPartyWindowProp);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK
|
||||
|
||||
@@ -77,7 +77,7 @@ UINT sDefaultBrowserMsgId = RegisterWindowMessageW(L"DefaultBrowserClosing");
|
||||
} }
|
||||
|
||||
// WM_GETOBJECT id pulled from uia headers
|
||||
#define UiaRootObjectId -25
|
||||
#define MOZOBJID_UIAROOT -25
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
@@ -892,7 +892,7 @@ MetroWidget::WindowProcedure(HWND aWnd, UINT aMsg, WPARAM aWParam, LPARAM aLPara
|
||||
// UiaReturnRawElementProvider passing the return result from FrameworkView
|
||||
// OnAutomationProviderRequested as the hwnd (me scratches head) which results in
|
||||
// GetLastError always being set to invalid handle (6) after CallWindowProc returns.
|
||||
if (dwObjId == UiaRootObjectId && gProviderRoot) {
|
||||
if (dwObjId == MOZOBJID_UIAROOT && gProviderRoot) {
|
||||
ComPtr<IRawElementProviderSimple> simple;
|
||||
gProviderRoot.As(&simple);
|
||||
if (simple) {
|
||||
|
||||
Reference in New Issue
Block a user