зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
7bc7bb4f90
Коммит
89f16dce8a
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче