bug 291077. Our IAccessible::get_accParent implementation would get screen readers into loops and cause stack overflow related crashes. r+sr=jst

This commit is contained in:
aaronleventhal%moonset.net 2005-08-18 16:35:49 +00:00
Родитель 7bc7bb4f90
Коммит 89f16dce8a
1 изменённых файлов: 32 добавлений и 11 удалений

Просмотреть файл

@ -43,6 +43,7 @@
#include "nsArray.h"
#include "nsIDOMDocument.h"
#include "nsIFrame.h"
#include "nsIScrollableFrame.h"
#include "nsINameSpaceManager.h"
#include "nsINodeInfo.h"
#include "nsIPrefService.h"
@ -171,28 +172,48 @@ STDMETHODIMP nsAccessibleWrap::get_accParent( IDispatch __RPC_FAR *__RPC_FAR *pp
return E_FAIL; // We've been shut down
nsIFrame *frame = GetFrame();
nsCOMPtr<nsIAccessible> xpParentAccessible;
GetParent(getter_AddRefs(xpParentAccessible));
HWND hwnd = 0;
if (frame) {
nsCOMPtr<nsPIAccessNode> parentAccessNode(do_QueryInterface(xpParentAccessible));
nsIFrame *parentFrame;
if (!parentAccessNode ||
((parentFrame = parentAccessNode->GetFrame()) != nsnull) && (frame->GetWindow() != parentFrame->GetWindow())) {
nsIView *view = frame->GetViewExternal();
if (view) {
// This code is essentially our implementation of WindowFromAccessibleObject,
// because MSAA iterates get_accParent() until it sees an object of ROLE_WINDOW
// to know where the window for a given accessible is. We must expose the native
// window accessible that MSAA creates for us. This must be done for the document
// object as well as any layout that creates its own window (e.g. via overflow: scroll)
HWND hWnd = (HWND)frame->GetWindow()->GetNativeData(NS_NATIVE_WINDOW);
NS_ASSERTION(hWnd, "No window handle for window");
if (SUCCEEDED(AccessibleObjectFromWindow(hWnd, OBJID_WINDOW, IID_IAccessible,
(void**)ppdispParent))) {
return S_OK;
nsIWidget *widget = view->GetWidget();
if (widget) {
// If frame has a widget that means we're at the root
// of a document or application, where there are 2 windows, one
// containing the scrollbars and one for the client area inside
hwnd = (HWND)widget->GetNativeData(NS_NATIVE_WINDOW);
NS_ASSERTION(hwnd, "No window handle for window");
hwnd = ::GetParent(hwnd); // We want the scrollable window
NS_ASSERTION(hwnd, "No window handle for window");
}
else {
// If a frame is a scrollable frame, then it has one window with the scrollbars
nsIScrollableFrame *scrollFrame = nsnull;
CallQueryInterface(frame, &scrollFrame);
if (scrollFrame) {
hwnd = (HWND)scrollFrame->GetScrolledFrame()->GetWindow()->GetNativeData(NS_NATIVE_WINDOW);
NS_ASSERTION(hwnd, "No window handle for window");
}
}
}
if (hwnd && SUCCEEDED(AccessibleObjectFromWindow(hwnd, OBJID_WINDOW, IID_IAccessible,
(void**)ppdispParent))) {
return S_OK;
}
}
nsCOMPtr<nsIAccessible> xpParentAccessible;
GetParent(getter_AddRefs(xpParentAccessible));
NS_ASSERTION(xpParentAccessible, "No parent accessible where we're not direct child of window");
if (!xpParentAccessible) {
return E_UNEXPECTED;
}
*ppdispParent = NativeAccessible(xpParentAccessible);
return S_OK;