Bug 453883, ensure true/false marcos are available, r=joshmoz, sr=jst
[wine-gecko.git] / accessible / src / msaa / nsAccessNodeWrap.cpp
blobdd5105963b9144de688bbbab0e5b9fb44b20c955
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 2003
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Original Author: Aaron Leventhal (aaronl@netscape.com)
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 #include "nsAccessNodeWrap.h"
40 #include "ISimpleDOMNode_i.c"
41 #include "nsAccessibilityAtoms.h"
42 #include "nsIAccessibilityService.h"
43 #include "nsIAccessible.h"
44 #include "nsAttrName.h"
45 #include "nsIDocument.h"
46 #include "nsIDOMCSSStyleDeclaration.h"
47 #include "nsIDOMNodeList.h"
48 #include "nsIDOMNSHTMLElement.h"
49 #include "nsIDOMViewCSS.h"
50 #include "nsIFrame.h"
51 #include "nsINameSpaceManager.h"
52 #include "nsIPrefService.h"
53 #include "nsIPrefBranch.h"
54 #include "nsIPresShell.h"
55 #include "nsPIDOMWindow.h"
56 #include "nsRootAccessible.h"
57 #include "nsIServiceManager.h"
58 #include "AccessibleApplication.h"
59 #include "nsApplicationAccessibleWrap.h"
61 /// the accessible library and cached methods
62 HINSTANCE nsAccessNodeWrap::gmAccLib = nsnull;
63 HINSTANCE nsAccessNodeWrap::gmUserLib = nsnull;
64 LPFNACCESSIBLEOBJECTFROMWINDOW nsAccessNodeWrap::gmAccessibleObjectFromWindow = nsnull;
65 LPFNNOTIFYWINEVENT nsAccessNodeWrap::gmNotifyWinEvent = nsnull;
66 LPFNGETGUITHREADINFO nsAccessNodeWrap::gmGetGUIThreadInfo = nsnull;
68 PRBool nsAccessNodeWrap::gIsEnumVariantSupportDisabled = 0;
69 // Used to determine whether an IAccessible2 compatible screen reader is loaded.
70 PRBool nsAccessNodeWrap::gIsIA2Disabled = PR_FALSE;
72 nsIAccessibleTextChangeEvent *nsAccessNodeWrap::gTextEvent = nsnull;
74 // Pref to disallow CtrlTab preview functionality if JAWS or Window-Eyes are
75 // running.
76 #define CTRLTAB_DISALLOW_FOR_SCREEN_READERS_PREF "browser.ctrlTab.disallowForScreenReaders"
79 /* For documentation of the accessibility architecture,
80 * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
84 * Class nsAccessNodeWrap
87 //-----------------------------------------------------
88 // construction
89 //-----------------------------------------------------
91 nsAccessNodeWrap::nsAccessNodeWrap(nsIDOMNode *aNode, nsIWeakReference* aShell):
92 nsAccessNode(aNode, aShell)
96 //-----------------------------------------------------
97 // destruction
98 //-----------------------------------------------------
99 nsAccessNodeWrap::~nsAccessNodeWrap()
103 //-----------------------------------------------------
104 // nsISupports methods
105 //-----------------------------------------------------
107 NS_IMPL_ISUPPORTS_INHERITED1(nsAccessNodeWrap, nsAccessNode, nsIWinAccessNode);
109 //-----------------------------------------------------
110 // nsIWinAccessNode methods
111 //-----------------------------------------------------
113 NS_IMETHODIMP
114 nsAccessNodeWrap::QueryNativeInterface(REFIID aIID, void** aInstancePtr)
116 return QueryInterface(aIID, aInstancePtr);
119 //-----------------------------------------------------
120 // IUnknown interface methods - see iunknown.h for documentation
121 //-----------------------------------------------------
123 STDMETHODIMP nsAccessNodeWrap::QueryInterface(REFIID iid, void** ppv)
125 *ppv = nsnull;
127 if (IID_IUnknown == iid || IID_ISimpleDOMNode == iid)
128 *ppv = static_cast<ISimpleDOMNode*>(this);
130 if (nsnull == *ppv)
131 return E_NOINTERFACE; //iid not supported.
133 (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
134 return S_OK;
137 STDMETHODIMP
138 nsAccessNodeWrap::QueryService(REFGUID guidService, REFIID iid, void** ppv)
140 // Can get to IAccessibleApplication from any node via QS
141 if (iid == IID_IAccessibleApplication) {
142 nsRefPtr<nsApplicationAccessibleWrap> app =
143 GetApplicationAccessible();
144 nsresult rv = app->QueryNativeInterface(iid, ppv);
145 return NS_SUCCEEDED(rv) ? S_OK : E_NOINTERFACE;
149 * To get an ISimpleDOMNode, ISimpleDOMDocument, ISimpleDOMText
150 * or any IAccessible2 interface on should use IServiceProvider like this:
151 * -----------------------------------------------------------------------
152 * ISimpleDOMDocument *pAccDoc = NULL;
153 * IServiceProvider *pServProv = NULL;
154 * pAcc->QueryInterface(IID_IServiceProvider, (void**)&pServProv);
155 * if (pServProv) {
156 * const GUID unused;
157 * pServProv->QueryService(unused, IID_ISimpleDOMDocument, (void**)&pAccDoc);
158 * pServProv->Release();
162 return QueryInterface(iid, ppv);
165 //-----------------------------------------------------
166 // ISimpleDOMNode methods
167 //-----------------------------------------------------
169 STDMETHODIMP nsAccessNodeWrap::get_nodeInfo(
170 /* [out] */ BSTR __RPC_FAR *aNodeName,
171 /* [out] */ short __RPC_FAR *aNameSpaceID,
172 /* [out] */ BSTR __RPC_FAR *aNodeValue,
173 /* [out] */ unsigned int __RPC_FAR *aNumChildren,
174 /* [out] */ unsigned int __RPC_FAR *aUniqueID,
175 /* [out] */ unsigned short __RPC_FAR *aNodeType)
177 __try{
178 *aNodeName = nsnull;
179 *aNodeValue = nsnull;
181 if (!mDOMNode)
182 return E_FAIL;
184 nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
186 PRUint16 nodeType = 0;
187 mDOMNode->GetNodeType(&nodeType);
188 *aNodeType=static_cast<unsigned short>(nodeType);
190 if (*aNodeType != NODETYPE_TEXT) {
191 nsAutoString nodeName;
192 mDOMNode->GetNodeName(nodeName);
193 *aNodeName = ::SysAllocString(nodeName.get());
196 nsAutoString nodeValue;
198 mDOMNode->GetNodeValue(nodeValue);
199 *aNodeValue = ::SysAllocString(nodeValue.get());
200 *aNameSpaceID = content ? static_cast<short>(content->GetNameSpaceID()) : 0;
202 // This is a unique ID for every content node. The 3rd party
203 // accessibility application can compare this to the childID we
204 // return for events such as focus events, to correlate back to
205 // data nodes in their internal object model.
206 void *uniqueID;
207 GetUniqueID(&uniqueID);
208 *aUniqueID = - NS_PTR_TO_INT32(uniqueID);
210 *aNumChildren = 0;
211 PRUint32 numChildren = 0;
212 nsCOMPtr<nsIDOMNodeList> nodeList;
213 mDOMNode->GetChildNodes(getter_AddRefs(nodeList));
214 if (nodeList && NS_OK == nodeList->GetLength(&numChildren))
215 *aNumChildren = static_cast<unsigned int>(numChildren);
217 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
218 return S_OK;
223 STDMETHODIMP nsAccessNodeWrap::get_attributes(
224 /* [in] */ unsigned short aMaxAttribs,
225 /* [length_is][size_is][out] */ BSTR __RPC_FAR *aAttribNames,
226 /* [length_is][size_is][out] */ short __RPC_FAR *aNameSpaceIDs,
227 /* [length_is][size_is][out] */ BSTR __RPC_FAR *aAttribValues,
228 /* [out] */ unsigned short __RPC_FAR *aNumAttribs)
230 __try{
231 *aNumAttribs = 0;
233 nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
234 if (!content)
235 return E_FAIL;
237 PRUint32 numAttribs = content->GetAttrCount();
239 if (numAttribs > aMaxAttribs)
240 numAttribs = aMaxAttribs;
241 *aNumAttribs = static_cast<unsigned short>(numAttribs);
243 for (PRUint32 index = 0; index < numAttribs; index++) {
244 aNameSpaceIDs[index] = 0; aAttribValues[index] = aAttribNames[index] = nsnull;
245 nsAutoString attributeValue;
246 const char *pszAttributeName;
248 const nsAttrName* name = content->GetAttrNameAt(index);
249 aNameSpaceIDs[index] = static_cast<short>(name->NamespaceID());
250 name->LocalName()->GetUTF8String(&pszAttributeName);
251 aAttribNames[index] = ::SysAllocString(NS_ConvertUTF8toUTF16(pszAttributeName).get());
252 content->GetAttr(name->NamespaceID(), name->LocalName(), attributeValue);
253 aAttribValues[index] = ::SysAllocString(attributeValue.get());
255 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
257 return S_OK;
261 STDMETHODIMP nsAccessNodeWrap::get_attributesForNames(
262 /* [in] */ unsigned short aNumAttribs,
263 /* [length_is][size_is][in] */ BSTR __RPC_FAR *aAttribNames,
264 /* [length_is][size_is][in] */ short __RPC_FAR *aNameSpaceID,
265 /* [length_is][size_is][retval] */ BSTR __RPC_FAR *aAttribValues)
267 __try {
268 nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(mDOMNode));
269 nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
271 if (!domElement || !content)
272 return E_FAIL;
274 if (!content->GetDocument())
275 return E_FAIL;
277 nsCOMPtr<nsINameSpaceManager> nameSpaceManager =
278 do_GetService(NS_NAMESPACEMANAGER_CONTRACTID);
280 PRInt32 index;
282 for (index = 0; index < aNumAttribs; index++) {
283 aAttribValues[index] = nsnull;
284 if (aAttribNames[index]) {
285 nsAutoString attributeValue, nameSpaceURI;
286 nsAutoString attributeName(nsDependentString(static_cast<PRUnichar*>(aAttribNames[index])));
287 nsresult rv;
289 if (aNameSpaceID[index]>0 &&
290 NS_SUCCEEDED(nameSpaceManager->GetNameSpaceURI(aNameSpaceID[index], nameSpaceURI)))
291 rv = domElement->GetAttributeNS(nameSpaceURI, attributeName, attributeValue);
292 else
293 rv = domElement->GetAttribute(attributeName, attributeValue);
295 if (NS_SUCCEEDED(rv))
296 aAttribValues[index] = ::SysAllocString(attributeValue.get());
299 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
301 return S_OK;
304 /* To do: use media type if not null */
305 STDMETHODIMP nsAccessNodeWrap::get_computedStyle(
306 /* [in] */ unsigned short aMaxStyleProperties,
307 /* [in] */ boolean aUseAlternateView,
308 /* [length_is][size_is][out] */ BSTR __RPC_FAR *aStyleProperties,
309 /* [length_is][size_is][out] */ BSTR __RPC_FAR *aStyleValues,
310 /* [out] */ unsigned short __RPC_FAR *aNumStyleProperties)
312 __try{
313 *aNumStyleProperties = 0;
315 if (IsDefunct())
316 return E_FAIL;
318 nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
319 GetComputedStyleDeclaration(EmptyString(), mDOMNode, getter_AddRefs(cssDecl));
320 NS_ENSURE_TRUE(cssDecl, E_FAIL);
322 PRUint32 length;
323 cssDecl->GetLength(&length);
325 PRUint32 index, realIndex;
326 for (index = realIndex = 0; index < length && realIndex < aMaxStyleProperties; index ++) {
327 nsAutoString property, value;
328 if (NS_SUCCEEDED(cssDecl->Item(index, property)) && property.CharAt(0) != '-') // Ignore -moz-* properties
329 cssDecl->GetPropertyValue(property, value); // Get property value
330 if (!value.IsEmpty()) {
331 aStyleProperties[realIndex] = ::SysAllocString(property.get());
332 aStyleValues[realIndex] = ::SysAllocString(value.get());
333 ++realIndex;
336 *aNumStyleProperties = static_cast<unsigned short>(realIndex);
337 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
339 return S_OK;
343 STDMETHODIMP nsAccessNodeWrap::get_computedStyleForProperties(
344 /* [in] */ unsigned short aNumStyleProperties,
345 /* [in] */ boolean aUseAlternateView,
346 /* [length_is][size_is][in] */ BSTR __RPC_FAR *aStyleProperties,
347 /* [length_is][size_is][out] */ BSTR __RPC_FAR *aStyleValues)
349 __try {
350 if (IsDefunct())
351 return E_FAIL;
353 nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
354 GetComputedStyleDeclaration(EmptyString(), mDOMNode, getter_AddRefs(cssDecl));
355 NS_ENSURE_TRUE(cssDecl, E_FAIL);
357 PRUint32 index;
358 for (index = 0; index < aNumStyleProperties; index ++) {
359 nsAutoString value;
360 if (aStyleProperties[index])
361 cssDecl->GetPropertyValue(nsDependentString(static_cast<PRUnichar*>(aStyleProperties[index])), value); // Get property value
362 aStyleValues[index] = ::SysAllocString(value.get());
364 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
366 return S_OK;
369 STDMETHODIMP nsAccessNodeWrap::scrollTo(/* [in] */ boolean aScrollTopLeft)
371 __try {
372 PRUint32 scrollType =
373 aScrollTopLeft ? nsIAccessibleScrollType::SCROLL_TYPE_TOP_LEFT :
374 nsIAccessibleScrollType::SCROLL_TYPE_BOTTOM_RIGHT;
376 nsresult rv = ScrollTo(scrollType);
377 if (NS_SUCCEEDED(rv))
378 return S_OK;
379 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
381 return E_FAIL;
384 ISimpleDOMNode* nsAccessNodeWrap::MakeAccessNode(nsIDOMNode *node)
386 if (!node)
387 return NULL;
389 nsAccessNodeWrap *newNode = NULL;
391 nsCOMPtr<nsIContent> content(do_QueryInterface(node));
392 nsCOMPtr<nsIDocument> doc;
394 if (content)
395 doc = content->GetDocument();
396 else {
397 // Get the document via QueryInterface, since there is no content node
398 doc = do_QueryInterface(node);
399 content = do_QueryInterface(node);
402 if (!doc)
403 return NULL;
405 nsCOMPtr<nsIAccessibilityService> accService(do_GetService("@mozilla.org/accessibilityService;1"));
406 if (!accService)
407 return NULL;
409 ISimpleDOMNode *iNode = NULL;
410 nsCOMPtr<nsIAccessible> nsAcc;
411 accService->GetAccessibleInWeakShell(node, mWeakShell, getter_AddRefs(nsAcc));
412 if (nsAcc) {
413 nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(nsAcc));
414 NS_ASSERTION(accessNode, "nsIAccessible impl does not inherit from nsIAccessNode");
415 IAccessible *msaaAccessible;
416 nsAcc->GetNativeInterface((void**)&msaaAccessible); // addrefs
417 msaaAccessible->QueryInterface(IID_ISimpleDOMNode, (void**)&iNode); // addrefs
418 msaaAccessible->Release(); // Release IAccessible
420 else {
421 newNode = new nsAccessNodeWrap(node, mWeakShell);
422 if (!newNode)
423 return NULL;
425 newNode->Init();
426 iNode = static_cast<ISimpleDOMNode*>(newNode);
427 iNode->AddRef();
430 return iNode;
434 STDMETHODIMP nsAccessNodeWrap::get_parentNode(ISimpleDOMNode __RPC_FAR *__RPC_FAR *aNode)
436 __try {
437 if (!mDOMNode)
438 return E_FAIL;
440 nsCOMPtr<nsIDOMNode> node;
441 mDOMNode->GetParentNode(getter_AddRefs(node));
442 *aNode = MakeAccessNode(node);
443 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
445 return S_OK;
448 STDMETHODIMP nsAccessNodeWrap::get_firstChild(ISimpleDOMNode __RPC_FAR *__RPC_FAR *aNode)
450 __try {
451 if (!mDOMNode)
452 return E_FAIL;
454 nsCOMPtr<nsIDOMNode> node;
455 mDOMNode->GetFirstChild(getter_AddRefs(node));
456 *aNode = MakeAccessNode(node);
457 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
459 return S_OK;
462 STDMETHODIMP nsAccessNodeWrap::get_lastChild(ISimpleDOMNode __RPC_FAR *__RPC_FAR *aNode)
464 __try {
465 if (!mDOMNode)
466 return E_FAIL;
468 nsCOMPtr<nsIDOMNode> node;
469 mDOMNode->GetLastChild(getter_AddRefs(node));
470 *aNode = MakeAccessNode(node);
471 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
473 return S_OK;
476 STDMETHODIMP nsAccessNodeWrap::get_previousSibling(ISimpleDOMNode __RPC_FAR *__RPC_FAR *aNode)
478 __try {
479 if (!mDOMNode)
480 return E_FAIL;
482 nsCOMPtr<nsIDOMNode> node;
483 mDOMNode->GetPreviousSibling(getter_AddRefs(node));
484 *aNode = MakeAccessNode(node);
485 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
487 return S_OK;
490 STDMETHODIMP nsAccessNodeWrap::get_nextSibling(ISimpleDOMNode __RPC_FAR *__RPC_FAR *aNode)
492 __try {
493 if (!mDOMNode)
494 return E_FAIL;
496 nsCOMPtr<nsIDOMNode> node;
497 mDOMNode->GetNextSibling(getter_AddRefs(node));
498 *aNode = MakeAccessNode(node);
499 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
501 return S_OK;
504 STDMETHODIMP
505 nsAccessNodeWrap::get_childAt(unsigned aChildIndex,
506 ISimpleDOMNode __RPC_FAR *__RPC_FAR *aNode)
508 __try {
509 *aNode = nsnull;
511 nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
512 if (!content)
513 return E_FAIL; // Node already shut down
515 nsCOMPtr<nsIDOMNode> node =
516 do_QueryInterface(content->GetChildAt(aChildIndex));
518 if (!node)
519 return E_FAIL; // No such child
521 *aNode = MakeAccessNode(node);
522 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
524 return S_OK;
527 STDMETHODIMP
528 nsAccessNodeWrap::get_innerHTML(BSTR __RPC_FAR *aInnerHTML)
530 __try {
531 *aInnerHTML = nsnull;
533 nsCOMPtr<nsIDOMNSHTMLElement> domNSElement(do_QueryInterface(mDOMNode));
534 if (!domNSElement)
535 return E_FAIL; // Node already shut down
537 nsAutoString innerHTML;
538 domNSElement->GetInnerHTML(innerHTML);
539 if (innerHTML.IsEmpty())
540 return S_FALSE;
542 *aInnerHTML = ::SysAllocStringLen(innerHTML.get(), innerHTML.Length());
543 if (!*aInnerHTML)
544 return E_OUTOFMEMORY;
546 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
548 return S_OK;
551 STDMETHODIMP
552 nsAccessNodeWrap::get_language(BSTR __RPC_FAR *aLanguage)
554 __try {
555 *aLanguage = NULL;
557 nsAutoString language;
558 if (NS_FAILED(GetLanguage(language))) {
559 return E_FAIL;
562 if (language.IsEmpty())
563 return S_FALSE;
565 *aLanguage = ::SysAllocStringLen(language.get(), language.Length());
566 if (!*aLanguage)
567 return E_OUTOFMEMORY;
569 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
571 return S_OK;
574 STDMETHODIMP
575 nsAccessNodeWrap::get_localInterface(
576 /* [out] */ void __RPC_FAR *__RPC_FAR *localInterface)
578 __try {
579 *localInterface = static_cast<nsIAccessNode*>(this);
580 NS_ADDREF_THIS();
581 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
582 return S_OK;
585 void nsAccessNodeWrap::InitAccessibility()
587 if (gIsAccessibilityActive) {
588 return;
591 nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID));
592 if (prefBranch) {
593 prefBranch->GetBoolPref("accessibility.disableenumvariant", &gIsEnumVariantSupportDisabled);
596 if (!gmUserLib) {
597 gmUserLib =::LoadLibraryW(L"USER32.DLL");
600 if (gmUserLib) {
601 if (!gmNotifyWinEvent)
602 gmNotifyWinEvent = (LPFNNOTIFYWINEVENT)GetProcAddress(gmUserLib,"NotifyWinEvent");
603 if (!gmGetGUIThreadInfo)
604 gmGetGUIThreadInfo = (LPFNGETGUITHREADINFO)GetProcAddress(gmUserLib,"GetGUIThreadInfo");
607 DoATSpecificProcessing();
609 nsAccessNode::InitXPAccessibility();
612 void nsAccessNodeWrap::ShutdownAccessibility()
614 NS_IF_RELEASE(gTextEvent);
615 ::DestroyCaret();
617 if (!gIsAccessibilityActive) {
618 return;
621 nsAccessNode::ShutdownXPAccessibility();
624 int nsAccessNodeWrap::FilterA11yExceptions(unsigned int aCode, EXCEPTION_POINTERS *aExceptionInfo)
626 if (aCode == EXCEPTION_ACCESS_VIOLATION) {
627 #ifdef MOZ_CRASHREPORTER
628 // MSAA swallows crashes (because it is COM-based)
629 // but we still need to learn about those crashes so we can fix them
630 // Make sure to pass them to the crash reporter
631 nsCOMPtr<nsICrashReporter> crashReporter =
632 do_GetService("@mozilla.org/toolkit/crash-reporter;1");
633 if (crashReporter) {
634 crashReporter->WriteMinidumpForException(aExceptionInfo);
636 #endif
638 else {
639 NS_NOTREACHED("We should only be catching crash exceptions");
641 return EXCEPTION_CONTINUE_SEARCH;
644 HRESULT
645 GetHRESULT(nsresult aResult)
647 switch (aResult) {
648 case NS_OK:
649 return S_OK;
651 case NS_ERROR_INVALID_ARG: case NS_ERROR_INVALID_POINTER:
652 return E_INVALIDARG;
654 case NS_ERROR_OUT_OF_MEMORY:
655 return E_OUTOFMEMORY;
657 case NS_ERROR_NOT_IMPLEMENTED:
658 return E_NOTIMPL;
660 default:
661 return E_FAIL;
665 PRBool nsAccessNodeWrap::IsOnlyMsaaCompatibleJawsPresent()
667 HMODULE jhookhandle = ::GetModuleHandleW(L"jhook");
668 if (!jhookhandle)
669 return PR_FALSE; // No JAWS, or some other screen reader, use IA2
671 PRUnichar fileName[MAX_PATH];
672 ::GetModuleFileNameW(jhookhandle, fileName, MAX_PATH);
674 DWORD dummy;
675 DWORD length = ::GetFileVersionInfoSizeW(fileName, &dummy);
677 LPBYTE versionInfo = new BYTE[length];
678 ::GetFileVersionInfoW(fileName, 0, length, versionInfo);
680 UINT uLen;
681 VS_FIXEDFILEINFO *fixedFileInfo;
682 ::VerQueryValueW(versionInfo, L"\\", (LPVOID*)&fixedFileInfo, &uLen);
683 DWORD dwFileVersionMS = fixedFileInfo->dwFileVersionMS;
684 DWORD dwFileVersionLS = fixedFileInfo->dwFileVersionLS;
685 delete [] versionInfo;
687 DWORD dwLeftMost = HIWORD(dwFileVersionMS);
688 // DWORD dwSecondLeft = LOWORD(dwFileVersionMS);
689 DWORD dwSecondRight = HIWORD(dwFileVersionLS);
690 // DWORD dwRightMost = LOWORD(dwFileVersionLS);
692 return (dwLeftMost < 8
693 || (dwLeftMost == 8 && dwSecondRight < 2173));
696 void nsAccessNodeWrap::TurnOffNewTabSwitchingForJawsAndWE()
698 HMODULE srHandle = ::GetModuleHandleW(L"jhook");
699 if (!srHandle) {
700 // No JAWS, try Window-Eyes
701 srHandle = ::GetModuleHandleW(L"gwm32inc");
702 if (!srHandle) {
703 // no screen reader we're interested in. Bail out.
704 return;
708 // Check to see if the pref for disallowing CtrlTab is already set.
709 // If so, bail out.
710 // If not, set it.
711 nsCOMPtr<nsIPrefBranch> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID));
712 if (prefs) {
713 PRBool hasDisallowNewCtrlTabPref = PR_FALSE;
714 nsresult rv = prefs->PrefHasUserValue(CTRLTAB_DISALLOW_FOR_SCREEN_READERS_PREF,
715 &hasDisallowNewCtrlTabPref);
716 if (NS_SUCCEEDED(rv) && hasDisallowNewCtrlTabPref) {
717 // This pref has been set before. There is no default for it.
718 // Do nothing further, respect the setting that's there.
719 // That way, if noone touches it, it'll stay on after toggled once.
720 // If someone decided to turn it off, we respect that, too.
721 return;
724 // Value has never been set, set it.
725 prefs->SetBoolPref(CTRLTAB_DISALLOW_FOR_SCREEN_READERS_PREF, PR_TRUE);
729 void nsAccessNodeWrap::DoATSpecificProcessing()
731 if (IsOnlyMsaaCompatibleJawsPresent())
732 // All versions below 8.0.2173 are not compatible
733 gIsIA2Disabled = PR_TRUE;
735 TurnOffNewTabSwitchingForJawsAndWE();