Bug 589145 - dexpcom accessible event classes, r=davidb, sr=neil, a=davidb
[mozilla-central.git] / accessible / src / msaa / nsAccessNodeWrap.cpp
blobca44d497ae1b3a399269b5e3f21f787c69a4efeb
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"
41 #include "AccessibleApplication.h"
42 #include "ISimpleDOMNode_i.c"
44 #include "nsAccessibilityAtoms.h"
45 #include "nsAccessibilityService.h"
46 #include "nsApplicationAccessibleWrap.h"
47 #include "nsCoreUtils.h"
48 #include "nsRootAccessible.h"
50 #include "nsAttrName.h"
51 #include "nsIDocument.h"
52 #include "nsIDOMNodeList.h"
53 #include "nsIDOMNSHTMLElement.h"
54 #include "nsIDOMViewCSS.h"
55 #include "nsIFrame.h"
56 #include "nsINameSpaceManager.h"
57 #include "nsIPrefService.h"
58 #include "nsIPrefBranch.h"
59 #include "nsPIDOMWindow.h"
60 #include "nsIServiceManager.h"
62 /// the accessible library and cached methods
63 HINSTANCE nsAccessNodeWrap::gmAccLib = nsnull;
64 HINSTANCE nsAccessNodeWrap::gmUserLib = nsnull;
65 LPFNACCESSIBLEOBJECTFROMWINDOW nsAccessNodeWrap::gmAccessibleObjectFromWindow = nsnull;
66 LPFNNOTIFYWINEVENT nsAccessNodeWrap::gmNotifyWinEvent = nsnull;
67 LPFNGETGUITHREADINFO nsAccessNodeWrap::gmGetGUIThreadInfo = nsnull;
69 PRBool nsAccessNodeWrap::gIsEnumVariantSupportDisabled = 0;
70 // Used to determine whether an IAccessible2 compatible screen reader is loaded.
71 PRBool nsAccessNodeWrap::gIsIA2Disabled = PR_FALSE;
73 AccTextChangeEvent* nsAccessNodeWrap::gTextEvent = nsnull;
75 // Pref to disallow CtrlTab preview functionality if JAWS or Window-Eyes are
76 // running.
77 #define CTRLTAB_DISALLOW_FOR_SCREEN_READERS_PREF "browser.ctrlTab.disallowForScreenReaders"
80 /* For documentation of the accessibility architecture,
81 * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
84 ////////////////////////////////////////////////////////////////////////////////
85 // nsAccessNodeWrap
86 ////////////////////////////////////////////////////////////////////////////////
88 nsAccessNodeWrap::
89 nsAccessNodeWrap(nsIContent *aContent, nsIWeakReference *aShell) :
90 nsAccessNode(aContent, aShell)
94 nsAccessNodeWrap::~nsAccessNodeWrap()
98 //-----------------------------------------------------
99 // nsISupports methods
100 //-----------------------------------------------------
102 NS_IMPL_ISUPPORTS_INHERITED1(nsAccessNodeWrap, nsAccessNode, nsIWinAccessNode);
104 //-----------------------------------------------------
105 // nsIWinAccessNode methods
106 //-----------------------------------------------------
108 NS_IMETHODIMP
109 nsAccessNodeWrap::QueryNativeInterface(REFIID aIID, void** aInstancePtr)
111 return QueryInterface(aIID, aInstancePtr);
114 //-----------------------------------------------------
115 // IUnknown interface methods - see iunknown.h for documentation
116 //-----------------------------------------------------
118 STDMETHODIMP nsAccessNodeWrap::QueryInterface(REFIID iid, void** ppv)
120 *ppv = nsnull;
122 if (IID_IUnknown == iid || IID_ISimpleDOMNode == iid)
123 *ppv = static_cast<ISimpleDOMNode*>(this);
125 if (nsnull == *ppv)
126 return E_NOINTERFACE; //iid not supported.
128 (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
129 return S_OK;
132 STDMETHODIMP
133 nsAccessNodeWrap::QueryService(REFGUID guidService, REFIID iid, void** ppv)
135 static const GUID IID_SimpleDOMDeprecated = {0x0c539790,0x12e4,0x11cf,0xb6,0x61,0x00,0xaa,0x00,0x4c,0xd6,0xd8};
136 if (guidService != IID_ISimpleDOMNode &&
137 guidService != IID_SimpleDOMDeprecated &&
138 guidService != IID_IAccessible && guidService != IID_IAccessible2 &&
139 guidService != IID_IAccessibleApplication)
140 return E_INVALIDARG;
142 // Can get to IAccessibleApplication from any node via QS
143 if (iid == IID_IAccessibleApplication) {
144 nsApplicationAccessible *applicationAcc = GetApplicationAccessible();
145 if (!applicationAcc)
146 return E_NOINTERFACE;
148 nsresult rv = applicationAcc->QueryNativeInterface(iid, ppv);
149 return NS_SUCCEEDED(rv) ? S_OK : E_NOINTERFACE;
153 * To get an ISimpleDOMNode, ISimpleDOMDocument, ISimpleDOMText
154 * or any IAccessible2 interface on should use IServiceProvider like this:
155 * -----------------------------------------------------------------------
156 * ISimpleDOMDocument *pAccDoc = NULL;
157 * IServiceProvider *pServProv = NULL;
158 * pAcc->QueryInterface(IID_IServiceProvider, (void**)&pServProv);
159 * if (pServProv) {
160 * const GUID unused;
161 * pServProv->QueryService(unused, IID_ISimpleDOMDocument, (void**)&pAccDoc);
162 * pServProv->Release();
166 return QueryInterface(iid, ppv);
169 //-----------------------------------------------------
170 // ISimpleDOMNode methods
171 //-----------------------------------------------------
173 STDMETHODIMP nsAccessNodeWrap::get_nodeInfo(
174 /* [out] */ BSTR __RPC_FAR *aNodeName,
175 /* [out] */ short __RPC_FAR *aNameSpaceID,
176 /* [out] */ BSTR __RPC_FAR *aNodeValue,
177 /* [out] */ unsigned int __RPC_FAR *aNumChildren,
178 /* [out] */ unsigned int __RPC_FAR *aUniqueID,
179 /* [out] */ unsigned short __RPC_FAR *aNodeType)
181 __try{
182 *aNodeName = nsnull;
183 *aNodeValue = nsnull;
185 if (IsDefunct())
186 return E_FAIL;
188 nsCOMPtr<nsIDOMNode> DOMNode(do_QueryInterface(GetNode()));
190 PRUint16 nodeType = 0;
191 DOMNode->GetNodeType(&nodeType);
192 *aNodeType=static_cast<unsigned short>(nodeType);
194 if (*aNodeType != NODETYPE_TEXT) {
195 nsAutoString nodeName;
196 DOMNode->GetNodeName(nodeName);
197 *aNodeName = ::SysAllocString(nodeName.get());
200 nsAutoString nodeValue;
202 DOMNode->GetNodeValue(nodeValue);
203 *aNodeValue = ::SysAllocString(nodeValue.get());
205 *aNameSpaceID = IsContent() ?
206 static_cast<short>(mContent->GetNameSpaceID()) : 0;
208 // This is a unique ID for every content node. The 3rd party
209 // accessibility application can compare this to the childID we
210 // return for events such as focus events, to correlate back to
211 // data nodes in their internal object model.
212 void *uniqueID;
213 GetUniqueID(&uniqueID);
214 *aUniqueID = - NS_PTR_TO_INT32(uniqueID);
216 *aNumChildren = GetNode()->GetChildCount();
218 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
219 return S_OK;
224 STDMETHODIMP nsAccessNodeWrap::get_attributes(
225 /* [in] */ unsigned short aMaxAttribs,
226 /* [length_is][size_is][out] */ BSTR __RPC_FAR *aAttribNames,
227 /* [length_is][size_is][out] */ short __RPC_FAR *aNameSpaceIDs,
228 /* [length_is][size_is][out] */ BSTR __RPC_FAR *aAttribValues,
229 /* [out] */ unsigned short __RPC_FAR *aNumAttribs)
231 __try{
232 *aNumAttribs = 0;
234 if (IsDefunct() || IsDocument())
235 return E_FAIL;
237 PRUint32 numAttribs = mContent->GetAttrCount();
238 if (numAttribs > aMaxAttribs)
239 numAttribs = aMaxAttribs;
240 *aNumAttribs = static_cast<unsigned short>(numAttribs);
242 for (PRUint32 index = 0; index < numAttribs; index++) {
243 aNameSpaceIDs[index] = 0; aAttribValues[index] = aAttribNames[index] = nsnull;
244 nsAutoString attributeValue;
246 const nsAttrName* name = mContent->GetAttrNameAt(index);
247 aNameSpaceIDs[index] = static_cast<short>(name->NamespaceID());
248 aAttribNames[index] = ::SysAllocString(name->LocalName()->GetUTF16String());
249 mContent->GetAttr(name->NamespaceID(), name->LocalName(), attributeValue);
250 aAttribValues[index] = ::SysAllocString(attributeValue.get());
252 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
254 return S_OK;
258 STDMETHODIMP nsAccessNodeWrap::get_attributesForNames(
259 /* [in] */ unsigned short aNumAttribs,
260 /* [length_is][size_is][in] */ BSTR __RPC_FAR *aAttribNames,
261 /* [length_is][size_is][in] */ short __RPC_FAR *aNameSpaceID,
262 /* [length_is][size_is][retval] */ BSTR __RPC_FAR *aAttribValues)
264 __try {
265 if (IsDefunct() || IsDocument())
266 return E_FAIL;
268 nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(mContent));
269 nsCOMPtr<nsINameSpaceManager> nameSpaceManager =
270 do_GetService(NS_NAMESPACEMANAGER_CONTRACTID);
272 PRInt32 index;
274 for (index = 0; index < aNumAttribs; index++) {
275 aAttribValues[index] = nsnull;
276 if (aAttribNames[index]) {
277 nsAutoString attributeValue, nameSpaceURI;
278 nsAutoString attributeName(nsDependentString(static_cast<PRUnichar*>(aAttribNames[index])));
279 nsresult rv;
281 if (aNameSpaceID[index]>0 &&
282 NS_SUCCEEDED(nameSpaceManager->GetNameSpaceURI(aNameSpaceID[index], nameSpaceURI)))
283 rv = domElement->GetAttributeNS(nameSpaceURI, attributeName, attributeValue);
284 else
285 rv = domElement->GetAttribute(attributeName, attributeValue);
287 if (NS_SUCCEEDED(rv))
288 aAttribValues[index] = ::SysAllocString(attributeValue.get());
291 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
293 return S_OK;
296 /* To do: use media type if not null */
297 STDMETHODIMP nsAccessNodeWrap::get_computedStyle(
298 /* [in] */ unsigned short aMaxStyleProperties,
299 /* [in] */ boolean aUseAlternateView,
300 /* [length_is][size_is][out] */ BSTR __RPC_FAR *aStyleProperties,
301 /* [length_is][size_is][out] */ BSTR __RPC_FAR *aStyleValues,
302 /* [out] */ unsigned short __RPC_FAR *aNumStyleProperties)
304 __try{
305 *aNumStyleProperties = 0;
307 if (IsDefunct() || IsDocument())
308 return E_FAIL;
310 nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl =
311 nsCoreUtils::GetComputedStyleDeclaration(EmptyString(), mContent);
312 NS_ENSURE_TRUE(cssDecl, E_FAIL);
314 PRUint32 length;
315 cssDecl->GetLength(&length);
317 PRUint32 index, realIndex;
318 for (index = realIndex = 0; index < length && realIndex < aMaxStyleProperties; index ++) {
319 nsAutoString property, value;
320 if (NS_SUCCEEDED(cssDecl->Item(index, property)) && property.CharAt(0) != '-') // Ignore -moz-* properties
321 cssDecl->GetPropertyValue(property, value); // Get property value
322 if (!value.IsEmpty()) {
323 aStyleProperties[realIndex] = ::SysAllocString(property.get());
324 aStyleValues[realIndex] = ::SysAllocString(value.get());
325 ++realIndex;
328 *aNumStyleProperties = static_cast<unsigned short>(realIndex);
329 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
331 return S_OK;
335 STDMETHODIMP nsAccessNodeWrap::get_computedStyleForProperties(
336 /* [in] */ unsigned short aNumStyleProperties,
337 /* [in] */ boolean aUseAlternateView,
338 /* [length_is][size_is][in] */ BSTR __RPC_FAR *aStyleProperties,
339 /* [length_is][size_is][out] */ BSTR __RPC_FAR *aStyleValues)
341 __try {
342 if (IsDefunct() || IsDocument())
343 return E_FAIL;
345 nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl =
346 nsCoreUtils::GetComputedStyleDeclaration(EmptyString(), mContent);
347 NS_ENSURE_TRUE(cssDecl, E_FAIL);
349 PRUint32 index;
350 for (index = 0; index < aNumStyleProperties; index ++) {
351 nsAutoString value;
352 if (aStyleProperties[index])
353 cssDecl->GetPropertyValue(nsDependentString(static_cast<PRUnichar*>(aStyleProperties[index])), value); // Get property value
354 aStyleValues[index] = ::SysAllocString(value.get());
356 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
358 return S_OK;
361 STDMETHODIMP nsAccessNodeWrap::scrollTo(/* [in] */ boolean aScrollTopLeft)
363 __try {
364 PRUint32 scrollType =
365 aScrollTopLeft ? nsIAccessibleScrollType::SCROLL_TYPE_TOP_LEFT :
366 nsIAccessibleScrollType::SCROLL_TYPE_BOTTOM_RIGHT;
368 nsresult rv = ScrollTo(scrollType);
369 if (NS_SUCCEEDED(rv))
370 return S_OK;
371 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
373 return E_FAIL;
376 ISimpleDOMNode*
377 nsAccessNodeWrap::MakeAccessNode(nsINode *aNode)
379 if (!aNode)
380 return NULL;
382 nsAccessNodeWrap *newNode = NULL;
384 ISimpleDOMNode *iNode = NULL;
385 nsAccessible *acc =
386 GetAccService()->GetAccessibleInWeakShell(aNode, mWeakShell);
387 if (acc) {
388 IAccessible *msaaAccessible = nsnull;
389 acc->GetNativeInterface((void**)&msaaAccessible); // addrefs
390 msaaAccessible->QueryInterface(IID_ISimpleDOMNode, (void**)&iNode); // addrefs
391 msaaAccessible->Release(); // Release IAccessible
393 else {
394 nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
395 if (!content) {
396 NS_NOTREACHED("The node is a document which is not accessible!");
397 return NULL;
400 newNode = new nsAccessNodeWrap(content, mWeakShell);
401 if (!newNode)
402 return NULL;
404 newNode->Init();
405 iNode = static_cast<ISimpleDOMNode*>(newNode);
406 iNode->AddRef();
409 return iNode;
413 STDMETHODIMP nsAccessNodeWrap::get_parentNode(ISimpleDOMNode __RPC_FAR *__RPC_FAR *aNode)
415 __try {
416 if (IsDefunct())
417 return E_FAIL;
419 *aNode = MakeAccessNode(GetNode()->GetNodeParent());
421 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
423 return S_OK;
426 STDMETHODIMP nsAccessNodeWrap::get_firstChild(ISimpleDOMNode __RPC_FAR *__RPC_FAR *aNode)
428 __try {
429 if (IsDefunct())
430 return E_FAIL;
432 *aNode = MakeAccessNode(GetNode()->GetFirstChild());
434 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
436 return S_OK;
439 STDMETHODIMP nsAccessNodeWrap::get_lastChild(ISimpleDOMNode __RPC_FAR *__RPC_FAR *aNode)
441 __try {
442 if (IsDefunct())
443 return E_FAIL;
445 *aNode = MakeAccessNode(GetNode()->GetLastChild());
447 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
449 return S_OK;
452 STDMETHODIMP nsAccessNodeWrap::get_previousSibling(ISimpleDOMNode __RPC_FAR *__RPC_FAR *aNode)
454 __try {
455 if (IsDefunct())
456 return E_FAIL;
458 *aNode = MakeAccessNode(GetNode()->GetPreviousSibling());
460 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
462 return S_OK;
465 STDMETHODIMP nsAccessNodeWrap::get_nextSibling(ISimpleDOMNode __RPC_FAR *__RPC_FAR *aNode)
467 __try {
468 if (IsDefunct())
469 return E_FAIL;
471 *aNode = MakeAccessNode(GetNode()->GetNextSibling());
473 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
475 return S_OK;
478 STDMETHODIMP
479 nsAccessNodeWrap::get_childAt(unsigned aChildIndex,
480 ISimpleDOMNode __RPC_FAR *__RPC_FAR *aNode)
482 __try {
483 *aNode = nsnull;
485 if (IsDefunct())
486 return E_FAIL;
488 *aNode = MakeAccessNode(GetNode()->GetChildAt(aChildIndex));
490 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
492 return S_OK;
495 STDMETHODIMP
496 nsAccessNodeWrap::get_innerHTML(BSTR __RPC_FAR *aInnerHTML)
498 __try {
499 *aInnerHTML = nsnull;
501 nsCOMPtr<nsIDOMNSHTMLElement> domNSElement(do_QueryInterface(GetNode()));
502 if (!domNSElement)
503 return E_FAIL; // Node already shut down
505 nsAutoString innerHTML;
506 domNSElement->GetInnerHTML(innerHTML);
507 if (innerHTML.IsEmpty())
508 return S_FALSE;
510 *aInnerHTML = ::SysAllocStringLen(innerHTML.get(), innerHTML.Length());
511 if (!*aInnerHTML)
512 return E_OUTOFMEMORY;
514 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
516 return S_OK;
519 STDMETHODIMP
520 nsAccessNodeWrap::get_language(BSTR __RPC_FAR *aLanguage)
522 __try {
523 *aLanguage = NULL;
525 nsAutoString language;
526 if (NS_FAILED(GetLanguage(language))) {
527 return E_FAIL;
530 if (language.IsEmpty())
531 return S_FALSE;
533 *aLanguage = ::SysAllocStringLen(language.get(), language.Length());
534 if (!*aLanguage)
535 return E_OUTOFMEMORY;
537 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
539 return S_OK;
542 STDMETHODIMP
543 nsAccessNodeWrap::get_localInterface(
544 /* [out] */ void __RPC_FAR *__RPC_FAR *localInterface)
546 __try {
547 *localInterface = static_cast<nsIAccessNode*>(this);
548 NS_ADDREF_THIS();
549 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
550 return S_OK;
553 void nsAccessNodeWrap::InitAccessibility()
555 nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID));
556 if (prefBranch) {
557 prefBranch->GetBoolPref("accessibility.disableenumvariant", &gIsEnumVariantSupportDisabled);
560 if (!gmUserLib) {
561 gmUserLib =::LoadLibraryW(L"USER32.DLL");
564 if (gmUserLib) {
565 if (!gmNotifyWinEvent)
566 gmNotifyWinEvent = (LPFNNOTIFYWINEVENT)GetProcAddress(gmUserLib,"NotifyWinEvent");
567 if (!gmGetGUIThreadInfo)
568 gmGetGUIThreadInfo = (LPFNGETGUITHREADINFO)GetProcAddress(gmUserLib,"GetGUIThreadInfo");
571 DoATSpecificProcessing();
573 nsAccessNode::InitXPAccessibility();
576 void nsAccessNodeWrap::ShutdownAccessibility()
578 NS_IF_RELEASE(gTextEvent);
579 ::DestroyCaret();
581 nsAccessNode::ShutdownXPAccessibility();
584 int nsAccessNodeWrap::FilterA11yExceptions(unsigned int aCode, EXCEPTION_POINTERS *aExceptionInfo)
586 if (aCode == EXCEPTION_ACCESS_VIOLATION) {
587 #ifdef MOZ_CRASHREPORTER
588 // MSAA swallows crashes (because it is COM-based)
589 // but we still need to learn about those crashes so we can fix them
590 // Make sure to pass them to the crash reporter
591 nsCOMPtr<nsICrashReporter> crashReporter =
592 do_GetService("@mozilla.org/toolkit/crash-reporter;1");
593 if (crashReporter) {
594 crashReporter->WriteMinidumpForException(aExceptionInfo);
596 #endif
598 else {
599 NS_NOTREACHED("We should only be catching crash exceptions");
601 return EXCEPTION_CONTINUE_SEARCH;
604 HRESULT
605 GetHRESULT(nsresult aResult)
607 switch (aResult) {
608 case NS_OK:
609 return S_OK;
611 case NS_ERROR_INVALID_ARG: case NS_ERROR_INVALID_POINTER:
612 return E_INVALIDARG;
614 case NS_ERROR_OUT_OF_MEMORY:
615 return E_OUTOFMEMORY;
617 case NS_ERROR_NOT_IMPLEMENTED:
618 return E_NOTIMPL;
620 default:
621 return E_FAIL;
625 PRBool nsAccessNodeWrap::IsOnlyMsaaCompatibleJawsPresent()
627 HMODULE jhookhandle = ::GetModuleHandleW(L"jhook");
628 if (!jhookhandle)
629 return PR_FALSE; // No JAWS, or some other screen reader, use IA2
631 PRUnichar fileName[MAX_PATH];
632 ::GetModuleFileNameW(jhookhandle, fileName, MAX_PATH);
634 DWORD dummy;
635 DWORD length = ::GetFileVersionInfoSizeW(fileName, &dummy);
637 LPBYTE versionInfo = new BYTE[length];
638 ::GetFileVersionInfoW(fileName, 0, length, versionInfo);
640 UINT uLen;
641 VS_FIXEDFILEINFO *fixedFileInfo;
642 ::VerQueryValueW(versionInfo, L"\\", (LPVOID*)&fixedFileInfo, &uLen);
643 DWORD dwFileVersionMS = fixedFileInfo->dwFileVersionMS;
644 DWORD dwFileVersionLS = fixedFileInfo->dwFileVersionLS;
645 delete [] versionInfo;
647 DWORD dwLeftMost = HIWORD(dwFileVersionMS);
648 // DWORD dwSecondLeft = LOWORD(dwFileVersionMS);
649 DWORD dwSecondRight = HIWORD(dwFileVersionLS);
650 // DWORD dwRightMost = LOWORD(dwFileVersionLS);
652 return (dwLeftMost < 8
653 || (dwLeftMost == 8 && dwSecondRight < 2173));
656 void nsAccessNodeWrap::TurnOffNewTabSwitchingForJawsAndWE()
658 HMODULE srHandle = ::GetModuleHandleW(L"jhook");
659 if (!srHandle) {
660 // No JAWS, try Window-Eyes
661 srHandle = ::GetModuleHandleW(L"gwm32inc");
662 if (!srHandle) {
663 // no screen reader we're interested in. Bail out.
664 return;
668 // Check to see if the pref for disallowing CtrlTab is already set.
669 // If so, bail out.
670 // If not, set it.
671 nsCOMPtr<nsIPrefBranch> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID));
672 if (prefs) {
673 PRBool hasDisallowNewCtrlTabPref = PR_FALSE;
674 nsresult rv = prefs->PrefHasUserValue(CTRLTAB_DISALLOW_FOR_SCREEN_READERS_PREF,
675 &hasDisallowNewCtrlTabPref);
676 if (NS_SUCCEEDED(rv) && hasDisallowNewCtrlTabPref) {
677 // This pref has been set before. There is no default for it.
678 // Do nothing further, respect the setting that's there.
679 // That way, if noone touches it, it'll stay on after toggled once.
680 // If someone decided to turn it off, we respect that, too.
681 return;
684 // Value has never been set, set it.
685 prefs->SetBoolPref(CTRLTAB_DISALLOW_FOR_SCREEN_READERS_PREF, PR_TRUE);
689 void nsAccessNodeWrap::DoATSpecificProcessing()
691 if (IsOnlyMsaaCompatibleJawsPresent())
692 // All versions below 8.0.2173 are not compatible
693 gIsIA2Disabled = PR_TRUE;
695 TurnOffNewTabSwitchingForJawsAndWE();