Back to index

lightning-sunbird  0.9+nobinonly
nsAccessibilityService.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   John Gaunt (jgaunt@netscape.com)
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 // NOTE: alphabetically ordered
00040 #include "nsAccessibilityAtoms.h"
00041 #include "nsAccessibilityService.h"
00042 #include "nsCaretAccessible.h"
00043 #include "nsCURILoader.h"
00044 #include "nsDocAccessible.h"
00045 #include "nsHTMLAreaAccessible.h"
00046 #include "nsHTMLFormControlAccessibleWrap.h"
00047 #include "nsHTMLImageAccessible.h"
00048 #include "nsHTMLLinkAccessible.h"
00049 #include "nsHTMLSelectAccessible.h"
00050 #include "nsHTMLTableAccessible.h"
00051 #include "nsHTMLTextAccessible.h"
00052 #include "nsIAccessibilityService.h"
00053 #include "nsIAccessibleProvider.h"
00054 #include "nsIDOMDocument.h"
00055 #include "nsIDOMHTMLAreaElement.h"
00056 #include "nsIDOMHTMLLegendElement.h"
00057 #include "nsIDOMHTMLObjectElement.h"
00058 #include "nsIDOMHTMLOptGroupElement.h"
00059 #include "nsIDOMHTMLOptionElement.h"
00060 #include "nsIDOMWindow.h"
00061 #include "nsIDOMXULElement.h"
00062 #include "nsIDocShell.h"
00063 #include "nsIFrame.h"
00064 #include "nsImageFrame.h"
00065 #include "nsILink.h"
00066 #include "nsINameSpaceManager.h"
00067 #include "nsIObserverService.h"
00068 #include "nsIPluginInstance.h"
00069 #include "nsPresContext.h"
00070 #include "nsIPresShell.h"
00071 #include "nsITextContent.h"
00072 #include "nsIWebNavigation.h"
00073 #include "nsObjectFrame.h"
00074 #include "nsOuterDocAccessible.h"
00075 #include "nsRootAccessibleWrap.h"
00076 #include "nsTextFragment.h"
00077 #include "nsPIAccessNode.h"
00078 #include "nsUnicharUtils.h"
00079 #include "nsIWebProgress.h"
00080 
00081 #ifdef MOZ_XUL
00082 #include "nsXULAlertAccessible.h"
00083 #include "nsXULColorPickerAccessible.h"
00084 #include "nsXULFormControlAccessible.h"
00085 #include "nsXULMenuAccessibleWrap.h"
00086 #include "nsXULSelectAccessible.h"
00087 #include "nsXULTabAccessible.h"
00088 #include "nsXULTextAccessible.h"
00089 #include "nsXULTreeAccessibleWrap.h"
00090 #endif
00091 
00092 // For native window support for object/embed/applet tags
00093 #ifdef XP_WIN
00094 #include "nsHTMLWin32ObjectAccessible.h"
00095 #endif
00096 
00097 #ifdef MOZ_ACCESSIBILITY_ATK
00098 #include "nsHTMLBlockAccessible.h"
00099 #include "nsHTMLLinkAccessibleWrap.h"
00100 #include "nsHTMLFormControlAccessibleWrap.h"
00101 #include "nsHTMLTableAccessibleWrap.h"
00102 #include "nsXULFormControlAccessibleWrap.h"
00103 #endif
00104 
00105 nsAccessibilityService *nsAccessibilityService::gAccessibilityService = nsnull;
00106 
00111 nsAccessibilityService::nsAccessibilityService()
00112 {
00113   nsCOMPtr<nsIObserverService> observerService =
00114     do_GetService("@mozilla.org/observer-service;1");
00115   if (!observerService)
00116     return;
00117 
00118   observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
00119   nsCOMPtr<nsIWebProgress> progress(do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID));
00120   if (progress) {
00121     progress->AddProgressListener(NS_STATIC_CAST(nsIWebProgressListener*,this),
00122                                   nsIWebProgress::NOTIFY_STATE_DOCUMENT |
00123                                   nsIWebProgress::NOTIFY_LOCATION);
00124   }
00125   nsAccessNodeWrap::InitAccessibility();
00126 }
00127 
00128 nsAccessibilityService::~nsAccessibilityService()
00129 {
00130   nsAccessibilityService::gAccessibilityService = nsnull;
00131   nsAccessNodeWrap::ShutdownAccessibility();
00132 }
00133 
00134 NS_IMPL_THREADSAFE_ISUPPORTS5(nsAccessibilityService, nsIAccessibilityService, nsIAccessibleRetrieval,
00135                               nsIObserver, nsIWebProgressListener, nsISupportsWeakReference)
00136 
00137 // nsIObserver
00138 
00139 NS_IMETHODIMP
00140 nsAccessibilityService::Observe(nsISupports *aSubject, const char *aTopic,
00141                          const PRUnichar *aData)
00142 {
00143   if (!nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
00144     nsCOMPtr<nsIObserverService> observerService =
00145       do_GetService("@mozilla.org/observer-service;1");
00146     if (observerService) {
00147       observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
00148     }
00149     nsCOMPtr<nsIWebProgress> progress(do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID));
00150     if (progress) {
00151       progress->RemoveProgressListener(NS_STATIC_CAST(nsIWebProgressListener*,this));
00152     }
00153     nsAccessNodeWrap::ShutdownAccessibility();
00154   }
00155   return NS_OK;
00156 }
00157 
00158 // nsIWebProgressListener
00159 NS_IMETHODIMP nsAccessibilityService::OnStateChange(nsIWebProgress *aWebProgress,
00160   nsIRequest *aRequest, PRUint32 aStateFlags, nsresult aStatus)
00161 {
00162   NS_ASSERTION(aStateFlags & STATE_IS_DOCUMENT, "Other notifications excluded");
00163 
00164   if (0 == (aStateFlags & (STATE_START | STATE_STOP)) || NS_FAILED(aStatus)) {
00165     return NS_OK;
00166   }
00167 
00168   nsCOMPtr<nsIDOMWindow> domWindow;
00169   aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));
00170   NS_ASSERTION(domWindow, "DOM Window for state change is null");
00171   NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE);
00172 
00173   nsCOMPtr<nsIDOMDocument> domDoc;
00174   domWindow->GetDocument(getter_AddRefs(domDoc));
00175   nsCOMPtr<nsIDOMNode> domDocRootNode(do_QueryInterface(domDoc));
00176   NS_ENSURE_TRUE(domDocRootNode, NS_ERROR_FAILURE);
00177 
00178   nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
00179     nsAccessNode::GetDocShellTreeItemFor(domDocRootNode);
00180   NS_ASSERTION(docShellTreeItem, "No doc shell tree item for loading document");
00181   NS_ENSURE_TRUE(docShellTreeItem, NS_ERROR_FAILURE);
00182   PRInt32 contentType;
00183   docShellTreeItem->GetItemType(&contentType);
00184   if (contentType != nsIDocShellTreeItem::typeContent) {
00185     return NS_OK; // Not interested in chrome loading, just content
00186   }
00187 
00188   // Get the accessible for the new document.
00189   // If it not created yet this will create it & cache it, as well as
00190   // set up event listeners so that MSAA/ATK toolkit and internal
00191   // accessibility events will get fired.
00192   nsCOMPtr<nsIAccessible> accessible;
00193   GetAccessibleFor(domDocRootNode, getter_AddRefs(accessible));
00194   nsCOMPtr<nsPIAccessibleDocument> docAccessible =
00195     do_QueryInterface(accessible);
00196   NS_ENSURE_TRUE(docAccessible, NS_ERROR_FAILURE);
00197   PRBool isFinished = !(aStateFlags & STATE_START);
00198 
00199   docAccessible->FireDocLoadingEvent(isFinished);
00200 
00201   return NS_OK;
00202 }
00203 
00204 /* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */
00205 NS_IMETHODIMP nsAccessibilityService::OnProgressChange(nsIWebProgress *aWebProgress,
00206   nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress,
00207   PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress)
00208 {
00209   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
00210   return NS_OK;
00211 }
00212 
00213 /* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */
00214 NS_IMETHODIMP nsAccessibilityService::OnLocationChange(nsIWebProgress *aWebProgress,
00215   nsIRequest *aRequest, nsIURI *location)
00216 {
00217   // If the document is already loaded, this will just check to see
00218   // if an anchor jump event needs to be fired.
00219   // If there is no accessible for the document, we will ignore
00220   // this and the anchor jump event will be fired via OnStateChange
00221   // and STATE_STOP
00222   nsCOMPtr<nsIDOMWindow> domWindow;
00223   aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));
00224   NS_ASSERTION(domWindow, "DOM Window for state change is null");
00225   NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE);
00226 
00227   nsCOMPtr<nsIDOMDocument> domDoc;
00228   domWindow->GetDocument(getter_AddRefs(domDoc));
00229   nsCOMPtr<nsIDOMNode> domDocRootNode(do_QueryInterface(domDoc));
00230   NS_ENSURE_TRUE(domDocRootNode, NS_ERROR_FAILURE);
00231 
00232   nsCOMPtr<nsIAccessibleDocument> accessibleDoc =
00233     nsAccessNode::GetDocAccessibleFor(domDocRootNode);
00234   nsCOMPtr<nsPIAccessibleDocument> privateAccessibleDoc =
00235     do_QueryInterface(accessibleDoc);
00236   if (!privateAccessibleDoc) {
00237     return NS_OK;
00238   }
00239   return privateAccessibleDoc->FireAnchorJumpEvent();
00240 }
00241 
00242 /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
00243 NS_IMETHODIMP nsAccessibilityService::OnStatusChange(nsIWebProgress *aWebProgress,
00244   nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage)
00245 {
00246   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
00247   return NS_OK;
00248 }
00249 
00250 /* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long state); */
00251 NS_IMETHODIMP nsAccessibilityService::OnSecurityChange(nsIWebProgress *aWebProgress,
00252   nsIRequest *aRequest, PRUint32 state)
00253 {
00254   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
00255   return NS_OK;
00256 }
00257 
00258 
00259 nsresult
00260 nsAccessibilityService::GetInfo(nsISupports* aFrame, nsIFrame** aRealFrame, nsIWeakReference** aShell, nsIDOMNode** aNode)
00261 {
00262   NS_ASSERTION(aFrame,"Error -- 1st argument (aFrame) is null!!");
00263   *aRealFrame = NS_STATIC_CAST(nsIFrame*, aFrame);
00264   nsCOMPtr<nsIContent> content = (*aRealFrame)->GetContent();
00265   nsCOMPtr<nsIDOMNode> node(do_QueryInterface(content));
00266   if (!content || !node)
00267     return NS_ERROR_FAILURE;
00268   *aNode = node;
00269   NS_IF_ADDREF(*aNode);
00270 
00271   nsCOMPtr<nsIDocument> document = content->GetDocument();
00272   if (!document)
00273     return NS_ERROR_FAILURE;
00274 
00275 #ifdef DEBUG
00276   PRInt32 shells = document->GetNumberOfShells();
00277   NS_ASSERTION(shells > 0,"Error no shells!");
00278 #endif
00279 
00280   // do_GetWR only works into a |nsCOMPtr| :-(
00281   nsCOMPtr<nsIWeakReference> weakShell =
00282     do_GetWeakReference(document->GetShellAt(0));
00283   NS_IF_ADDREF(*aShell = weakShell);
00284 
00285   return NS_OK;
00286 }
00287 
00288 nsresult
00289 nsAccessibilityService::GetShellFromNode(nsIDOMNode *aNode, nsIWeakReference **aWeakShell)
00290 {
00291   nsCOMPtr<nsIDOMDocument> domDoc;
00292   aNode->GetOwnerDocument(getter_AddRefs(domDoc));
00293   nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDoc));
00294   if (!doc)
00295     return NS_ERROR_INVALID_ARG;
00296 
00297   // ---- Get the pres shell ----
00298   nsIPresShell *shell = doc->GetShellAt(0);
00299   if (!shell)
00300     return NS_ERROR_FAILURE;
00301 
00302   nsCOMPtr<nsIWeakReference> weakRef(do_GetWeakReference(shell));
00303 
00304   *aWeakShell = weakRef;
00305   NS_IF_ADDREF(*aWeakShell);
00306 
00307   return NS_OK;
00308 }
00309 
00314 NS_IMETHODIMP
00315 nsAccessibilityService::CreateOuterDocAccessible(nsIDOMNode* aDOMNode,
00316                                                  nsIAccessible **aOuterDocAccessible)
00317 {
00318   NS_ENSURE_ARG_POINTER(aDOMNode);
00319 
00320   *aOuterDocAccessible = nsnull;
00321 
00322   nsCOMPtr<nsIWeakReference> outerWeakShell;
00323   GetShellFromNode(aDOMNode, getter_AddRefs(outerWeakShell));
00324   NS_ENSURE_TRUE(outerWeakShell, NS_ERROR_FAILURE);
00325 
00326   nsOuterDocAccessible *outerDocAccessible =
00327     new nsOuterDocAccessible(aDOMNode, outerWeakShell);
00328   NS_ENSURE_TRUE(outerDocAccessible, NS_ERROR_FAILURE);
00329 
00330   NS_ADDREF(*aOuterDocAccessible = outerDocAccessible);
00331 
00332   return NS_OK;
00333 }
00334 
00335 NS_IMETHODIMP
00336 nsAccessibilityService::CreateRootAccessible(nsIPresShell *aShell,
00337                                              nsIDocument* aDocument,
00338                                              nsIAccessible **aRootAcc)
00339 {
00340   *aRootAcc = nsnull;
00341 
00342   nsCOMPtr<nsIDOMNode> rootNode(do_QueryInterface(aDocument));
00343   NS_ENSURE_TRUE(rootNode, NS_ERROR_FAILURE);
00344 
00345   nsIPresShell *presShell = aShell;
00346   if (!presShell) {
00347     presShell = aDocument->GetShellAt(0);
00348   }
00349   nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell));
00350 
00351   nsCOMPtr<nsISupports> container = aDocument->GetContainer();
00352   nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
00353     do_QueryInterface(container);
00354   NS_ENSURE_TRUE(docShellTreeItem, NS_ERROR_FAILURE);
00355   
00356   nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;
00357   docShellTreeItem->GetParent(getter_AddRefs(parentTreeItem));
00358 
00359   if (parentTreeItem) {
00360     // We only create root accessibles for the true root, othewise create a
00361     // doc accessible
00362     *aRootAcc = new nsDocAccessibleWrap(rootNode, weakShell);
00363   }
00364   else {
00365     *aRootAcc = new nsRootAccessibleWrap(rootNode, weakShell);
00366   }
00367   if (!*aRootAcc)
00368     return NS_ERROR_OUT_OF_MEMORY;
00369 
00370   nsCOMPtr<nsPIAccessNode> privateAccessNode(do_QueryInterface(*aRootAcc));
00371   privateAccessNode->Init();
00372 
00373   NS_ADDREF(*aRootAcc);
00374 
00375   return NS_OK;
00376 }
00377 
00381 NS_IMETHODIMP
00382 nsAccessibilityService::CreateHTML4ButtonAccessible(nsISupports *aFrame, nsIAccessible **_retval)
00383 {
00384   nsIFrame* frame;
00385   nsCOMPtr<nsIDOMNode> node;
00386   nsCOMPtr<nsIWeakReference> weakShell;
00387   nsresult rv = GetInfo(aFrame, &frame, getter_AddRefs(weakShell), getter_AddRefs(node));
00388   if (NS_FAILED(rv))
00389     return rv;
00390 
00391   *_retval = new nsHTML4ButtonAccessible(node, weakShell);
00392   if (! *_retval)
00393     return NS_ERROR_OUT_OF_MEMORY;
00394 
00395   NS_ADDREF(*_retval);
00396   return NS_OK;
00397 }
00398 
00399 NS_IMETHODIMP
00400 nsAccessibilityService::CreateHTMLAreaAccessible(nsIWeakReference *aShell, nsIDOMNode *aDOMNode, nsIAccessible *aParent,
00401                                                                nsIAccessible **_retval)
00402 {
00403   *_retval = new nsHTMLAreaAccessible(aDOMNode, aParent, aShell);
00404 
00405   if (! *_retval)
00406     return NS_ERROR_OUT_OF_MEMORY;
00407 
00408   NS_ADDREF(*_retval);
00409   return NS_OK;
00410 }
00411 
00412 NS_IMETHODIMP
00413 nsAccessibilityService::CreateHTMLBlockAccessible(nsISupports *aFrame, nsIAccessible **_retval)
00414 {
00415 #ifndef MOZ_ACCESSIBILITY_ATK
00416   *_retval = nsnull;
00417   return NS_ERROR_FAILURE;
00418 #else
00419   nsIFrame* frame;
00420   nsCOMPtr<nsIDOMNode> node;
00421   nsCOMPtr<nsIWeakReference> weakShell;
00422   nsresult rv = GetInfo(aFrame, &frame, getter_AddRefs(weakShell), getter_AddRefs(node));
00423   if (NS_FAILED(rv))
00424     return rv;
00425 
00426   *_retval = new nsHTMLBlockAccessible(node, weakShell);
00427   if (! *_retval)
00428     return NS_ERROR_OUT_OF_MEMORY;
00429 
00430   NS_ADDREF(*_retval);
00431   return NS_OK;
00432 #endif
00433 }
00434 
00435 NS_IMETHODIMP
00436 nsAccessibilityService::CreateHTMLButtonAccessible(nsISupports *aFrame, nsIAccessible **_retval)
00437 {
00438   nsIFrame* frame;
00439   nsCOMPtr<nsIDOMNode> node;
00440   nsCOMPtr<nsIWeakReference> weakShell;
00441   nsresult rv = GetInfo(aFrame, &frame, getter_AddRefs(weakShell), getter_AddRefs(node));
00442   if (NS_FAILED(rv))
00443     return rv;
00444 
00445   *_retval = new nsHTMLButtonAccessible(node, weakShell);
00446   if (! *_retval)
00447     return NS_ERROR_OUT_OF_MEMORY;
00448 
00449   NS_ADDREF(*_retval);
00450   return NS_OK;
00451 }
00452 
00453 NS_IMETHODIMP
00454 nsAccessibilityService::CreateHTMLButtonAccessibleXBL(nsIDOMNode *aNode, nsIAccessible **_retval)
00455 {
00456 #ifdef MOZ_XUL
00457   nsCOMPtr<nsIWeakReference> weakShell;
00458   GetShellFromNode(aNode, getter_AddRefs(weakShell));
00459 
00460   // reusing the HTML accessible widget and enhancing for XUL
00461   *_retval = new nsHTML4ButtonAccessible(aNode, weakShell);
00462   if (! *_retval)
00463     return NS_ERROR_OUT_OF_MEMORY;
00464 
00465   NS_ADDREF(*_retval);
00466 #else
00467   *_retval = nsnull;
00468 #endif // MOZ_XUL
00469   return NS_OK;
00470 }
00471 
00472 nsresult
00473 nsAccessibilityService::CreateHTMLAccessibleByMarkup(nsISupports *aFrame,
00474                                                      nsIWeakReference *aWeakShell,
00475                                                      nsIDOMNode *aNode,
00476                                                      const nsAString& aRole,
00477                                                      nsIAccessible **aAccessible)
00478 {
00479   // aFrame type was generic, we'll use the DOM to decide
00480   // if and what kind of accessible object is needed.
00481   // This method assumes we're in an HTML namespace.
00482   *aAccessible = nsnull;
00483   nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
00484   nsIAtom *tag = content->Tag();
00485   if (tag == nsAccessibilityAtoms::option) {
00486     *aAccessible = new nsHTMLSelectOptionAccessible(aNode, aWeakShell);
00487   }
00488   else if (tag == nsAccessibilityAtoms::optgroup) {
00489     *aAccessible = new nsHTMLSelectOptGroupAccessible(aNode, aWeakShell);
00490   }
00491   else if (tag == nsAccessibilityAtoms::caption) {
00492     *aAccessible = new nsEnumRoleAccessible(aNode, aWeakShell, nsIAccessible::ROLE_CAPTION);
00493   }
00494 #ifndef MOZ_ACCESSIBILITY_ATK
00495   else if (tag == nsAccessibilityAtoms::ul || tag == nsAccessibilityAtoms::ol) {
00496     *aAccessible = new nsHTMLListAccessible(aNode, aWeakShell);
00497   }
00498   else if (tag == nsAccessibilityAtoms::a) {
00499     *aAccessible = new nsHTMLLinkAccessible(aNode, aWeakShell, NS_STATIC_CAST(nsIFrame*, aFrame));
00500   }
00501   else if (content->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::onclick)) {
00502     *aAccessible = new nsLinkableAccessible(aNode, aWeakShell);
00503   }
00504   else if (tag == nsAccessibilityAtoms::li) {
00505     // Normally this is created by the list item frame which knows about the bullet frame
00506     // However, in this case the list item must have been styled using display: foo
00507     *aAccessible = new nsHTMLLIAccessible(aNode, aWeakShell, nsnull, EmptyString());
00508   }
00509   else if (tag == nsAccessibilityAtoms::abbr ||
00510            tag == nsAccessibilityAtoms::acronym ||
00511            tag == nsAccessibilityAtoms::blockquote ||
00512            tag == nsAccessibilityAtoms::dd ||
00513            tag == nsAccessibilityAtoms::dl ||
00514            tag == nsAccessibilityAtoms::dt ||
00515            tag == nsAccessibilityAtoms::form ||
00516            tag == nsAccessibilityAtoms::h1 ||
00517            tag == nsAccessibilityAtoms::h2 ||
00518            tag == nsAccessibilityAtoms::h3 ||
00519            tag == nsAccessibilityAtoms::h4 ||
00520            tag == nsAccessibilityAtoms::h5 ||
00521            tag == nsAccessibilityAtoms::h6 ||
00522            tag == nsAccessibilityAtoms::q ||
00523            tag == nsAccessibilityAtoms::tbody ||
00524            tag == nsAccessibilityAtoms::tfoot ||
00525            tag == nsAccessibilityAtoms::thead ||
00526 #else
00527   else if (
00528 #endif
00529            content->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::tabindex) ||
00530            // The role from a <body> or doc element is already exposed in nsDocAccessible
00531            (tag != nsAccessibilityAtoms::body && content->GetParent() &&
00532            !aRole.IsEmpty())) {
00533     *aAccessible = new nsAccessibleWrap(aNode, aWeakShell);
00534   }
00535   NS_IF_ADDREF(*aAccessible);
00536   return NS_OK;
00537 }
00538 
00539 NS_IMETHODIMP
00540 nsAccessibilityService::CreateHTMLLIAccessible(nsISupports *aFrame,
00541                                                nsISupports *aBulletFrame,
00542                                                const nsAString& aBulletText,
00543                                                nsIAccessible **_retval)
00544 {
00545   nsIFrame* frame;
00546   nsCOMPtr<nsIDOMNode> node;
00547   nsCOMPtr<nsIWeakReference> weakShell;
00548   nsresult rv = GetInfo(aFrame, &frame, getter_AddRefs(weakShell), getter_AddRefs(node));
00549   if (NS_FAILED(rv))
00550     return rv;
00551   nsIFrame *bulletFrame = NS_STATIC_CAST(nsIFrame*, aBulletFrame);
00552   NS_ASSERTION(bulletFrame, "bullet frame argument not a frame");
00553 
00554   *_retval = new nsHTMLLIAccessible(node, weakShell, bulletFrame, aBulletText);
00555   if (! *_retval)
00556     return NS_ERROR_OUT_OF_MEMORY;
00557 
00558   NS_ADDREF(*_retval);
00559   return NS_OK;
00560 }
00561 
00562 NS_IMETHODIMP
00563 nsAccessibilityService::CreateHTMLCheckboxAccessible(nsISupports *aFrame, nsIAccessible **_retval)
00564 {
00565   nsIFrame* frame;
00566   nsCOMPtr<nsIDOMNode> node;
00567   nsCOMPtr<nsIWeakReference> weakShell;
00568   nsresult rv = GetInfo(aFrame, &frame, getter_AddRefs(weakShell), getter_AddRefs(node));
00569   if (NS_FAILED(rv))
00570     return rv;
00571 
00572   *_retval = new nsHTMLCheckboxAccessible(node, weakShell);
00573   if (! *_retval)
00574     return NS_ERROR_OUT_OF_MEMORY;
00575 
00576   NS_ADDREF(*_retval);
00577   return NS_OK;
00578 }
00579 
00580 NS_IMETHODIMP
00581 nsAccessibilityService::CreateHTMLCheckboxAccessibleXBL(nsIDOMNode *aNode, nsIAccessible **_retval)
00582 {
00583 #ifdef MOZ_XUL
00584   nsCOMPtr<nsIWeakReference> weakShell;
00585   GetShellFromNode(aNode, getter_AddRefs(weakShell));
00586 
00587   // reusing the HTML accessible widget and enhancing for XUL
00588   *_retval = new nsHTMLCheckboxAccessible(aNode, weakShell);
00589   if (! *_retval)
00590     return NS_ERROR_OUT_OF_MEMORY;
00591 
00592   NS_ADDREF(*_retval);
00593 #else
00594   *_retval = nsnull;
00595 #endif // MOZ_XUL
00596   return NS_OK;
00597 }
00598 
00599 NS_IMETHODIMP
00600 nsAccessibilityService::CreateHTMLComboboxAccessible(nsIDOMNode* aDOMNode, nsISupports* aPresShell, nsIAccessible **_retval)
00601 {
00602   nsCOMPtr<nsIPresShell> presShell(do_QueryInterface(aPresShell));
00603   NS_ASSERTION(presShell,"Error non prescontext passed to accessible factory!!!");
00604 
00605   nsCOMPtr<nsIWeakReference> weakShell =
00606     do_GetWeakReference(presShell);
00607 
00608   *_retval = new nsHTMLComboboxAccessible(aDOMNode, weakShell);
00609   if (! *_retval)
00610     return NS_ERROR_OUT_OF_MEMORY;
00611 
00612   NS_ADDREF(*_retval);
00613   return NS_OK;
00614 }
00615 
00616 NS_IMETHODIMP
00617 nsAccessibilityService::CreateHTMLImageAccessible(nsISupports *aFrame, nsIAccessible **_retval)
00618 {
00619   nsIFrame* frame;
00620   nsCOMPtr<nsIDOMNode> node;
00621   nsCOMPtr<nsIWeakReference> weakShell;
00622   nsresult rv = GetInfo(aFrame, &frame, getter_AddRefs(weakShell), getter_AddRefs(node));
00623   if (NS_FAILED(rv))
00624     return rv;
00625 
00626   *_retval = nsnull;
00627   nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(node));
00628   if (domElement) {
00629 #ifdef MOZ_ACCESSIBILITY_ATK
00630     PRBool hasAttribute;
00631     rv = domElement->HasAttribute(NS_LITERAL_STRING("usemap"), &hasAttribute);
00632     if (NS_SUCCEEDED(rv) && hasAttribute) {
00633       //There is a "use map"
00634       *_retval = new nsHTMLImageMapAccessible(node, weakShell);
00635     }
00636     else
00637 #endif //MOZ_ACCESSIBILITY_ATK
00638       *_retval = new nsHTMLImageAccessible(node, weakShell);
00639   }
00640 
00641   if (! *_retval)
00642     return NS_ERROR_OUT_OF_MEMORY;
00643 
00644   NS_ADDREF(*_retval);
00645   return NS_OK;
00646 }
00647 
00648 NS_IMETHODIMP
00649 nsAccessibilityService::CreateHTMLGenericAccessible(nsISupports *aFrame, nsIAccessible **_retval)
00650 {
00651   nsIFrame* frame;
00652   nsCOMPtr<nsIDOMNode> node;
00653   nsCOMPtr<nsIWeakReference> weakShell;
00654   nsresult rv = GetInfo(aFrame, &frame, getter_AddRefs(weakShell), getter_AddRefs(node));
00655   if (NS_FAILED(rv))
00656     return rv;
00657 
00658   *_retval = new nsAccessibleWrap(node, weakShell);
00659   if (! *_retval)
00660     return NS_ERROR_OUT_OF_MEMORY;
00661 
00662   NS_ADDREF(*_retval);
00663   return NS_OK;
00664 }
00665 
00666 NS_IMETHODIMP
00667 nsAccessibilityService::CreateHTMLGroupboxAccessible(nsISupports *aFrame, nsIAccessible **_retval)
00668 {
00669   nsIFrame* frame;
00670   nsCOMPtr<nsIDOMNode> node;
00671   nsCOMPtr<nsIWeakReference> weakShell;
00672   nsresult rv = GetInfo(aFrame, &frame, getter_AddRefs(weakShell), getter_AddRefs(node));
00673   if (NS_FAILED(rv))
00674     return rv;
00675 
00676   *_retval = new nsHTMLGroupboxAccessible(node, weakShell);
00677   if (! *_retval)
00678     return NS_ERROR_OUT_OF_MEMORY;
00679 
00680   NS_ADDREF(*_retval);
00681   return NS_OK;
00682 }
00683 
00684 NS_IMETHODIMP
00685 nsAccessibilityService::CreateHTMLListboxAccessible(nsIDOMNode* aDOMNode, nsISupports* aPresContext, nsIAccessible **_retval)
00686 {
00687   nsCOMPtr<nsPresContext> presContext(do_QueryInterface(aPresContext));
00688   NS_ASSERTION(presContext,"Error non prescontext passed to accessible factory!!!");
00689 
00690   nsCOMPtr<nsIWeakReference> weakShell =
00691     do_GetWeakReference(presContext->PresShell());
00692 
00693   *_retval = new nsHTMLSelectListAccessible(aDOMNode, weakShell);
00694   if (! *_retval)
00695     return NS_ERROR_OUT_OF_MEMORY;
00696 
00697   NS_ADDREF(*_retval);
00698   return NS_OK;
00699 }
00700 
00710 NS_IMETHODIMP
00711 nsAccessibilityService::CreateHTMLObjectFrameAccessible(nsObjectFrame *aFrame,
00712                                                         nsIAccessible **aAccessible)
00713 {
00714   nsCOMPtr<nsIDOMNode> node;
00715   nsCOMPtr<nsIWeakReference> weakShell;
00716   nsIFrame *frame;
00717   GetInfo(NS_STATIC_CAST(nsIFrame*, aFrame), &frame, getter_AddRefs(weakShell), getter_AddRefs(node));
00718 
00719   *aAccessible = nsnull;
00720   if (!frame || frame->GetRect().IsEmpty()) {
00721     return NS_ERROR_FAILURE;
00722   }
00723   // 1) for object elements containing either HTML or TXT documents
00724   nsCOMPtr<nsIDOMDocument> domDoc;
00725   nsCOMPtr<nsIDOMHTMLObjectElement> obj(do_QueryInterface(node));
00726   if (obj)
00727     obj->GetContentDocument(getter_AddRefs(domDoc));
00728   else
00729     domDoc = do_QueryInterface(node);
00730   if (domDoc)
00731     return CreateOuterDocAccessible(node, aAccessible);
00732 
00733 #ifdef XP_WIN
00734   // 2) for plugins
00735   nsCOMPtr<nsIPluginInstance> pluginInstance ;
00736   aFrame->GetPluginInstance(*getter_AddRefs(pluginInstance));
00737   if (pluginInstance) {
00738     HWND pluginPort = nsnull;
00739     aFrame->GetPluginPort(&pluginPort);
00740     if (pluginPort) {
00741       *aAccessible = new nsHTMLWin32ObjectOwnerAccessible(node, weakShell, pluginPort);
00742       if (*aAccessible) {
00743         NS_ADDREF(*aAccessible);
00744         return NS_OK;
00745       }
00746     }
00747   }
00748 #endif
00749 
00750   // 3) for images and imagemaps, or anything else with a child frame
00751   // we have the object frame, get the image frame
00752   frame = aFrame->GetFirstChild(nsnull);
00753   if (frame) {
00754     return frame->GetAccessible(aAccessible);
00755   }
00756   return NS_ERROR_FAILURE;
00757 }
00758 
00759 NS_IMETHODIMP
00760 nsAccessibilityService::CreateHTMLRadioButtonAccessible(nsISupports *aFrame, nsIAccessible **_retval)
00761 {
00762   nsIFrame* frame;
00763   nsCOMPtr<nsIDOMNode> node;
00764   nsCOMPtr<nsIWeakReference> weakShell;
00765   nsresult rv = GetInfo(aFrame, &frame, getter_AddRefs(weakShell), getter_AddRefs(node));
00766   if (NS_FAILED(rv))
00767     return rv;
00768 
00769   *_retval = new nsHTMLRadioButtonAccessibleWrap(node, weakShell);
00770   if (! *_retval)
00771     return NS_ERROR_OUT_OF_MEMORY;
00772 
00773   NS_ADDREF(*_retval);
00774   return NS_OK;
00775 }
00776 
00777 NS_IMETHODIMP
00778 nsAccessibilityService::CreateHTMLRadioButtonAccessibleXBL(nsIDOMNode *aNode, nsIAccessible **_retval)
00779 {
00780 #ifdef MOZ_XUL
00781   nsCOMPtr<nsIWeakReference> weakShell;
00782   GetShellFromNode(aNode, getter_AddRefs(weakShell));
00783 
00784   // reusing the HTML accessible widget and enhancing for XUL
00785   *_retval = new nsHTMLRadioButtonAccessible(aNode, weakShell);
00786   if (! *_retval)
00787     return NS_ERROR_OUT_OF_MEMORY;
00788 
00789   NS_ADDREF(*_retval);
00790 #else
00791   *_retval = nsnull;
00792 #endif // MOZ_XUL
00793   return NS_OK;
00794 }
00795 
00796 NS_IMETHODIMP
00797 nsAccessibilityService::CreateHTMLSelectOptionAccessible(nsIDOMNode* aDOMNode,
00798                                                          nsIAccessible *aParent,
00799                                                          nsISupports* aPresContext,
00800                                                          nsIAccessible **_retval)
00801 {
00802   nsCOMPtr<nsPresContext> presContext(do_QueryInterface(aPresContext));
00803   NS_ASSERTION(presContext,"Error non prescontext passed to accessible factory!!!");
00804 
00805   nsCOMPtr<nsIWeakReference> weakShell =
00806     do_GetWeakReference(presContext->PresShell());
00807 
00808   *_retval = new nsHTMLSelectOptionAccessible(aDOMNode, weakShell);
00809   if (! *_retval)
00810     return NS_ERROR_OUT_OF_MEMORY;
00811 
00812   NS_ADDREF(*_retval);
00813   return NS_OK;
00814 }
00815 
00816 NS_IMETHODIMP
00817 nsAccessibilityService::CreateHTMLTableAccessible(nsISupports *aFrame, nsIAccessible **_retval)
00818 {
00819   nsIFrame* frame;
00820   nsCOMPtr<nsIDOMNode> node;
00821   nsCOMPtr<nsIWeakReference> weakShell;
00822   nsresult rv = GetInfo(aFrame, &frame, getter_AddRefs(weakShell), getter_AddRefs(node));
00823   if (NS_FAILED(rv))
00824     return rv;
00825 
00826   *_retval = new nsHTMLTableAccessibleWrap(node, weakShell);
00827   if (! *_retval)
00828     return NS_ERROR_OUT_OF_MEMORY;
00829 
00830   NS_ADDREF(*_retval);
00831   return NS_OK;
00832 }
00833 
00834 NS_IMETHODIMP
00835 nsAccessibilityService::CreateHTMLTableCaptionAccessible(nsIDOMNode *aDOMNode, nsIAccessible **_retval)
00836 {
00837   NS_ENSURE_ARG_POINTER(aDOMNode);
00838 
00839   nsresult rv = NS_OK;
00840 
00841   nsCOMPtr<nsIWeakReference> weakShell;
00842   rv = GetShellFromNode(aDOMNode, getter_AddRefs(weakShell));
00843   NS_ENSURE_SUCCESS(rv, rv);
00844 
00845   nsHTMLTableCaptionAccessible* accTableCaption =
00846     new nsHTMLTableCaptionAccessible(aDOMNode, weakShell);
00847 
00848   NS_ENSURE_TRUE(accTableCaption, NS_ERROR_OUT_OF_MEMORY);
00849 
00850   *_retval = NS_STATIC_CAST(nsIAccessible *, accTableCaption);
00851   NS_IF_ADDREF(*_retval);
00852 
00853   return rv;
00854 }
00855 
00856 NS_IMETHODIMP
00857 nsAccessibilityService::CreateHTMLTableHeadAccessible(nsIDOMNode *aDOMNode, nsIAccessible **_retval)
00858 {
00859 #ifndef MOZ_ACCESSIBILITY_ATK
00860   *_retval = nsnull;
00861   return NS_ERROR_FAILURE;
00862 #else
00863   NS_ENSURE_ARG_POINTER(aDOMNode);
00864 
00865   nsresult rv = NS_OK;
00866 
00867   nsCOMPtr<nsIWeakReference> weakShell;
00868   rv = GetShellFromNode(aDOMNode, getter_AddRefs(weakShell));
00869   NS_ENSURE_SUCCESS(rv, rv);
00870 
00871   nsHTMLTableHeadAccessible* accTableHead =
00872     new nsHTMLTableHeadAccessible(aDOMNode, weakShell);
00873 
00874   NS_ENSURE_TRUE(accTableHead, NS_ERROR_OUT_OF_MEMORY);
00875 
00876   *_retval = NS_STATIC_CAST(nsIAccessible *, accTableHead);
00877   NS_IF_ADDREF(*_retval);
00878 
00879   return rv;
00880 #endif
00881 }
00882 
00883 NS_IMETHODIMP
00884 nsAccessibilityService::CreateHTMLTableCellAccessible(nsISupports *aFrame, nsIAccessible **_retval)
00885 {
00886   nsIFrame* frame;
00887   nsCOMPtr<nsIDOMNode> node;
00888   nsCOMPtr<nsIWeakReference> weakShell;
00889   nsresult rv = GetInfo(aFrame, &frame, getter_AddRefs(weakShell), getter_AddRefs(node));
00890   if (NS_FAILED(rv))
00891     return rv;
00892 
00893   *_retval = new nsHTMLTableCellAccessibleWrap(node, weakShell);
00894   if (! *_retval)
00895     return NS_ERROR_OUT_OF_MEMORY;
00896 
00897   NS_ADDREF(*_retval);
00898   return NS_OK;
00899 }
00900 
00901 NS_IMETHODIMP
00902 nsAccessibilityService::CreateHTMLTextAccessible(nsISupports *aFrame, nsIAccessible **_retval)
00903 {
00904   nsIFrame* frame;
00905   nsCOMPtr<nsIDOMNode> node;
00906   nsCOMPtr<nsIWeakReference> weakShell;
00907   nsresult rv = GetInfo(aFrame, &frame, getter_AddRefs(weakShell), getter_AddRefs(node));
00908   if (NS_FAILED(rv))
00909     return rv;
00910 
00911   *_retval = nsnull;
00912 
00913 #ifndef MOZ_ACCESSIBILITY_ATK
00914   *_retval = new nsHTMLTextAccessible(node, weakShell, frame);
00915 #else
00916   // In ATK, we are only creating the accessible object for the text frame that is the FIRST
00917   //   text frame in its block.
00918   // A depth-first traversal from its nearest parent block frame will produce a frame sequence like
00919   //   TTTBTTBTT... (B for block frame, T for text frame), so every T frame which is the immediate
00920   //   sibling of B frame will be the FIRST text frame.
00921   nsIFrame* parentFrame = nsAccessible::GetParentBlockFrame(frame);
00922   if (! parentFrame)
00923     return NS_ERROR_FAILURE;
00924 
00925   nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(weakShell));
00926   nsIFrame* childFrame = parentFrame->GetFirstChild(nsnull);
00927   PRInt32 index = 0;
00928   nsIFrame* firstTextFrame = nsnull;
00929   PRBool ret = nsAccessible::FindTextFrame(index, presShell->GetPresContext(),
00930                                            childFrame, &firstTextFrame, frame);
00931   if (!ret || index != 0)
00932     return NS_ERROR_FAILURE;
00933 
00934   *_retval = new nsHTMLBlockAccessible(node, weakShell);
00935 #endif //MOZ_ACCESSIBILITY_ATK
00936   if (! *_retval)
00937     return NS_ERROR_OUT_OF_MEMORY;
00938 
00939   NS_ADDREF(*_retval);
00940   return NS_OK;
00941 }
00942 
00943 NS_IMETHODIMP
00944 nsAccessibilityService::CreateHTMLTextFieldAccessible(nsISupports *aFrame, nsIAccessible **_retval)
00945 {
00946   nsIFrame* frame;
00947   nsCOMPtr<nsIDOMNode> node;
00948   nsCOMPtr<nsIWeakReference> weakShell;
00949   nsresult rv = GetInfo(aFrame, &frame, getter_AddRefs(weakShell), getter_AddRefs(node));
00950   if (NS_FAILED(rv))
00951     return rv;
00952 
00953   *_retval = new nsHTMLTextFieldAccessibleWrap(node, weakShell);
00954   if (! *_retval)
00955     return NS_ERROR_OUT_OF_MEMORY;
00956 
00957   NS_ADDREF(*_retval);
00958   return NS_OK;
00959 }
00960 
00961 NS_IMETHODIMP
00962 nsAccessibilityService::CreateXULTextBoxAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
00963 {
00964 #ifdef MOZ_XUL
00965   nsCOMPtr<nsIWeakReference> weakShell;
00966   GetShellFromNode(aNode, getter_AddRefs(weakShell));
00967 
00968   *_retval = new nsXULTextFieldAccessibleWrap(aNode, weakShell);
00969 
00970   if (! *_retval)
00971     return NS_ERROR_OUT_OF_MEMORY;
00972 
00973   NS_ADDREF(*_retval);
00974 #else
00975   *_retval = nsnull;
00976 #endif // MOZ_XUL
00977   return NS_OK;
00978 }
00979 
00980 NS_IMETHODIMP
00981 nsAccessibilityService::CreateHTMLLabelAccessible(nsISupports *aFrame, nsIAccessible **_retval)
00982 {
00983   nsIFrame* frame;
00984   nsCOMPtr<nsIDOMNode> node;
00985   nsCOMPtr<nsIWeakReference> weakShell;
00986   nsresult rv = GetInfo(aFrame, &frame, getter_AddRefs(weakShell), getter_AddRefs(node));
00987   if (NS_FAILED(rv))
00988     return rv;
00989 
00990   *_retval = new nsHTMLLabelAccessible(node, weakShell);
00991   if (! *_retval)
00992     return NS_ERROR_OUT_OF_MEMORY;
00993 
00994   NS_ADDREF(*_retval);
00995   return NS_OK;
00996 }
00997 
00998 NS_IMETHODIMP
00999 nsAccessibilityService::CreateHTMLHRAccessible(nsISupports *aFrame, nsIAccessible **_retval)
01000 {
01001   nsIFrame* frame;
01002   nsCOMPtr<nsIDOMNode> node;
01003   nsCOMPtr<nsIWeakReference> weakShell;
01004   nsresult rv = GetInfo(aFrame, &frame, getter_AddRefs(weakShell), getter_AddRefs(node));
01005   if (NS_FAILED(rv))
01006     return rv;
01007 
01008   *_retval = new nsHTMLHRAccessible(node, weakShell);
01009   if (! *_retval)
01010     return NS_ERROR_OUT_OF_MEMORY;
01011 
01012   NS_ADDREF(*_retval);
01013   return NS_OK;
01014 }
01015 
01024 NS_IMETHODIMP nsAccessibilityService::CreateXULButtonAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01025 {
01026 #ifdef MOZ_XUL
01027   nsCOMPtr<nsIWeakReference> weakShell;
01028   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01029 
01030   // reusing the HTML accessible widget and enhancing for XUL
01031   *_retval = new nsXULButtonAccessible(aNode, weakShell);
01032   if (! *_retval)
01033     return NS_ERROR_OUT_OF_MEMORY;
01034 
01035   NS_ADDREF(*_retval);
01036 #else
01037   *_retval = nsnull;
01038 #endif // MOZ_XUL
01039   return NS_OK;
01040 }
01041 
01042 NS_IMETHODIMP
01043 nsAccessibilityService::CreateXULCheckboxAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01044 {
01045 #ifdef MOZ_XUL
01046   nsCOMPtr<nsIWeakReference> weakShell;
01047   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01048 
01049   // reusing the HTML accessible widget and enhancing for XUL
01050   *_retval = new nsXULCheckboxAccessible(aNode, weakShell);
01051   if (! *_retval)
01052     return NS_ERROR_OUT_OF_MEMORY;
01053 
01054   NS_ADDREF(*_retval);
01055 #else
01056   *_retval = nsnull;
01057 #endif // MOZ_XUL
01058   return NS_OK;
01059 }
01060 
01061 NS_IMETHODIMP
01062 nsAccessibilityService::CreateXULColorPickerAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01063 {
01064 #ifdef MOZ_XUL
01065   nsCOMPtr<nsIWeakReference> weakShell;
01066   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01067 
01068   *_retval = new nsXULColorPickerAccessible(aNode, weakShell);
01069   if (! *_retval)
01070     return NS_ERROR_OUT_OF_MEMORY;
01071 
01072   NS_ADDREF(*_retval);
01073 #else
01074   *_retval = nsnull;
01075 #endif // MOZ_XUL
01076   return NS_OK;
01077 }
01078 
01079 NS_IMETHODIMP
01080 nsAccessibilityService::CreateXULColorPickerTileAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01081 {
01082 #ifdef MOZ_XUL
01083   nsCOMPtr<nsIWeakReference> weakShell;
01084   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01085 
01086   *_retval = new nsXULColorPickerTileAccessible(aNode, weakShell);
01087   if (! *_retval)
01088     return NS_ERROR_OUT_OF_MEMORY;
01089 
01090   NS_ADDREF(*_retval);
01091 #else
01092   *_retval = nsnull;
01093 #endif // MOZ_XUL
01094   return NS_OK;
01095 }
01096 
01097 NS_IMETHODIMP
01098 nsAccessibilityService::CreateXULComboboxAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01099 {
01100 #ifdef MOZ_XUL
01101   nsCOMPtr<nsIWeakReference> weakShell;
01102   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01103 
01104   *_retval = new nsXULComboboxAccessible(aNode, weakShell);
01105   if (! *_retval)
01106     return NS_ERROR_OUT_OF_MEMORY;
01107 
01108   NS_ADDREF(*_retval);
01109 #else
01110   *_retval = nsnull;
01111 #endif // MOZ_XUL
01112   return NS_OK;
01113 }
01114 
01115 NS_IMETHODIMP
01116 nsAccessibilityService::CreateXULDropmarkerAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01117 {
01118 #ifdef MOZ_XUL
01119   nsCOMPtr<nsIWeakReference> weakShell;
01120   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01121 
01122   *_retval = new nsXULDropmarkerAccessible(aNode, weakShell);
01123   if (! *_retval)
01124     return NS_ERROR_OUT_OF_MEMORY;
01125 
01126   NS_ADDREF(*_retval);
01127 #else
01128   *_retval = nsnull;
01129 #endif // MOZ_XUL
01130   return NS_OK;
01131 }
01132 
01133 NS_IMETHODIMP
01134 nsAccessibilityService::CreateXULGroupboxAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01135 {
01136 #ifdef MOZ_XUL
01137   nsCOMPtr<nsIWeakReference> weakShell;
01138   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01139 
01140   *_retval = new nsXULGroupboxAccessible(aNode, weakShell);
01141   if (! *_retval)
01142     return NS_ERROR_OUT_OF_MEMORY;
01143 
01144   NS_ADDREF(*_retval);
01145 #else
01146   *_retval = nsnull;
01147 #endif // MOZ_XUL
01148   return NS_OK;
01149 }
01150 
01151 NS_IMETHODIMP
01152 nsAccessibilityService::CreateXULImageAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01153 {
01154 #ifdef MOZ_XUL
01155   // Don't include nameless images in accessible tree
01156   *_retval = nsnull;
01157 
01158   nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(aNode));
01159   if (!elt)
01160     return NS_ERROR_FAILURE;
01161   PRBool hasTextEquivalent;
01162   elt->HasAttribute(NS_LITERAL_STRING("tooltiptext"), &hasTextEquivalent); // Prefer value over tooltiptext
01163   if (!hasTextEquivalent) {
01164     return NS_OK;
01165   }
01166 
01167   nsCOMPtr<nsIWeakReference> weakShell;
01168   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01169 
01170   *_retval = new nsHTMLImageAccessible(aNode, weakShell);
01171   if (! *_retval)
01172     return NS_ERROR_OUT_OF_MEMORY;
01173 
01174   NS_ADDREF(*_retval);
01175 
01176 #else
01177   *_retval = nsnull;
01178 #endif // MOZ_XUL
01179   return NS_OK;
01180 }
01181 
01182 NS_IMETHODIMP
01183 nsAccessibilityService::CreateXULLinkAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01184 {
01185 #ifdef MOZ_XUL
01186   nsCOMPtr<nsIWeakReference> weakShell;
01187   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01188 
01189   *_retval = new nsXULLinkAccessible(aNode, weakShell);
01190   if (! *_retval)
01191     return NS_ERROR_OUT_OF_MEMORY;
01192 
01193   NS_ADDREF(*_retval);
01194 #else
01195   *_retval = nsnull;
01196 #endif // MOZ_XUL
01197   return NS_OK;
01198 }
01199 
01200 
01201 NS_IMETHODIMP
01202 nsAccessibilityService::CreateXULListboxAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01203 {
01204 #ifdef MOZ_XUL
01205   nsCOMPtr<nsIWeakReference> weakShell;
01206   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01207 
01208   *_retval = new nsXULListboxAccessible(aNode, weakShell);
01209   if (! *_retval)
01210     return NS_ERROR_OUT_OF_MEMORY;
01211 
01212   NS_ADDREF(*_retval);
01213 #else
01214   *_retval = nsnull;
01215 #endif // MOZ_XUL
01216   return NS_OK;
01217 }
01218 
01219 NS_IMETHODIMP
01220 nsAccessibilityService::CreateXULListitemAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01221 {
01222 #ifdef MOZ_XUL
01223   nsCOMPtr<nsIWeakReference> weakShell;
01224   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01225 
01226   *_retval = new nsXULListitemAccessible(aNode, weakShell);
01227   if (! *_retval)
01228     return NS_ERROR_OUT_OF_MEMORY;
01229 
01230   NS_ADDREF(*_retval);
01231 #else
01232   *_retval = nsnull;
01233 #endif // MOZ_XUL
01234   return NS_OK;
01235 }
01236 
01237 NS_IMETHODIMP
01238 nsAccessibilityService::CreateXULMenubarAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01239 {
01240 #ifdef MOZ_XUL
01241   nsCOMPtr<nsIWeakReference> weakShell;
01242   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01243 
01244   *_retval = new nsXULMenubarAccessible(aNode, weakShell);
01245   if (! *_retval)
01246     return NS_ERROR_OUT_OF_MEMORY;
01247 
01248   NS_ADDREF(*_retval);
01249 #else
01250   *_retval = nsnull;
01251 #endif // MOZ_XUL
01252   return NS_OK;
01253 }
01254 
01255 NS_IMETHODIMP
01256 nsAccessibilityService::CreateXULMenuitemAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01257 {
01258 #ifdef MOZ_XUL
01259   nsCOMPtr<nsIWeakReference> weakShell;
01260   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01261 
01262   *_retval = new nsXULMenuitemAccessibleWrap(aNode, weakShell);
01263   if (! *_retval)
01264     return NS_ERROR_OUT_OF_MEMORY;
01265 
01266   NS_ADDREF(*_retval);
01267 #else
01268   *_retval = nsnull;
01269 #endif // MOZ_XUL
01270   return NS_OK;
01271 }
01272 
01273 NS_IMETHODIMP
01274 nsAccessibilityService::CreateXULMenupopupAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01275 {
01276   *_retval = nsnull;
01277 #ifdef MOZ_XUL
01278   nsCOMPtr<nsIWeakReference> weakShell;
01279   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01280   nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
01281 #ifdef MOZ_ACCESSIBILITY_ATK
01282   // ATK considers this node to be redundant when within menubars, and it makes menu
01283   // navigation with assistive technologies more difficult
01284   // XXX In the future we will should this for consistency across the nsIAccessible
01285   // implementations on each platform for a consistent scripting environment, but
01286   // then strip out redundant accessibles in the nsAccessibleWrap class for each platform.
01287   if (content) {
01288     nsIContent *parent = content->GetParent();
01289     if (parent && parent->Tag() == nsAccessibilityAtoms::menu) {
01290       return NS_OK;
01291     }
01292   }
01293 #endif
01294  
01295   *_retval = new nsXULMenupopupAccessible(aNode, weakShell);
01296   if (! *_retval)
01297     return NS_ERROR_OUT_OF_MEMORY;
01298 
01299   NS_ADDREF(*_retval);
01300 #else
01301   *_retval = nsnull;
01302 #endif // MOZ_XUL
01303   return NS_OK;
01304 }
01305 
01306 NS_IMETHODIMP
01307 nsAccessibilityService::CreateXULMenuSeparatorAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01308 {
01309 #ifdef MOZ_XUL
01310   nsCOMPtr<nsIWeakReference> weakShell;
01311   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01312 
01313   *_retval = new nsXULMenuSeparatorAccessible(aNode, weakShell);
01314   if (! *_retval)
01315     return NS_ERROR_OUT_OF_MEMORY;
01316 
01317   NS_ADDREF(*_retval);
01318 #else
01319   *_retval = nsnull;
01320 #endif // MOZ_XUL
01321   return NS_OK;
01322 }
01323 
01324 NS_IMETHODIMP
01325 nsAccessibilityService::CreateXULAlertAccessible(nsIDOMNode *aNode, nsIAccessible **aAccessible)
01326 {
01327 #ifdef MOZ_XUL
01328   nsCOMPtr<nsIWeakReference> weakShell;
01329   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01330 
01331   *aAccessible = new nsXULAlertAccessible(aNode, weakShell);
01332   if (! *aAccessible)
01333     return NS_ERROR_OUT_OF_MEMORY;
01334 
01335   NS_ADDREF(*aAccessible);
01336 #else
01337   *_retval = nsnull;
01338 #endif
01339   return NS_OK;
01340 }
01341 
01342 NS_IMETHODIMP
01343 nsAccessibilityService::CreateXULProgressMeterAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01344 {
01345 #ifdef MOZ_XUL
01346   nsCOMPtr<nsIWeakReference> weakShell;
01347   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01348 
01349   *_retval = new nsXULProgressMeterAccessibleWrap(aNode, weakShell);
01350   if (! *_retval)
01351     return NS_ERROR_OUT_OF_MEMORY;
01352 
01353   NS_ADDREF(*_retval);
01354 #else
01355   *_retval = nsnull;
01356 #endif // MOZ_XUL
01357   return NS_OK;
01358 }
01359 
01360 NS_IMETHODIMP
01361 nsAccessibilityService::CreateXULRadioButtonAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01362 {
01363 #ifdef MOZ_XUL
01364   nsCOMPtr<nsIWeakReference> weakShell;
01365   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01366 
01367   *_retval = new nsXULRadioButtonAccessible(aNode, weakShell);
01368   if (! *_retval)
01369     return NS_ERROR_OUT_OF_MEMORY;
01370 
01371   NS_ADDREF(*_retval);
01372 #else
01373   *_retval = nsnull;
01374 #endif // MOZ_XUL
01375   return NS_OK;
01376 }
01377 
01378 NS_IMETHODIMP
01379 nsAccessibilityService::CreateXULRadioGroupAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01380 {
01381 #ifdef MOZ_XUL
01382   nsCOMPtr<nsIWeakReference> weakShell;
01383   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01384 
01385   *_retval = new nsXULRadioGroupAccessible(aNode, weakShell);
01386   if (! *_retval)
01387     return NS_ERROR_OUT_OF_MEMORY;
01388 
01389   NS_ADDREF(*_retval);
01390 #else
01391   *_retval = nsnull;
01392 #endif // MOZ_XUL
01393   return NS_OK;
01394 }
01395 
01396 NS_IMETHODIMP
01397 nsAccessibilityService::CreateXULSelectListAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01398 {
01399 #ifdef MOZ_XUL
01400   nsCOMPtr<nsIWeakReference> weakShell;
01401   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01402 
01403   *_retval = new nsXULSelectListAccessible(aNode, weakShell);
01404   if (! *_retval)
01405     return NS_ERROR_OUT_OF_MEMORY;
01406 
01407   NS_ADDREF(*_retval);
01408 #else
01409   *_retval = nsnull;
01410 #endif // MOZ_XUL
01411   return NS_OK;
01412 }
01413 
01414 NS_IMETHODIMP
01415 nsAccessibilityService::CreateXULSelectOptionAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01416 {
01417 #ifdef MOZ_XUL
01418   nsCOMPtr<nsIWeakReference> weakShell;
01419   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01420 
01421   *_retval = new nsXULSelectOptionAccessible(aNode, weakShell);
01422   if (! *_retval)
01423     return NS_ERROR_OUT_OF_MEMORY;
01424 
01425   NS_ADDREF(*_retval);
01426 #else
01427   *_retval = nsnull;
01428 #endif // MOZ_XUL
01429   return NS_OK;
01430 }
01431 
01432 NS_IMETHODIMP
01433 nsAccessibilityService::CreateXULStatusBarAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01434 {
01435 #ifdef MOZ_XUL
01436   nsCOMPtr<nsIWeakReference> weakShell;
01437   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01438 
01439   *_retval = new nsXULStatusBarAccessible(aNode, weakShell);
01440   if (! *_retval)
01441     return NS_ERROR_OUT_OF_MEMORY;
01442 
01443   NS_ADDREF(*_retval);
01444 #else
01445   *_retval = nsnull;
01446 #endif // MOZ_XUL
01447   return NS_OK;
01448 }
01449 
01450 NS_IMETHODIMP
01451 nsAccessibilityService::CreateXULTextAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01452 {
01453 #ifdef MOZ_XUL
01454   nsCOMPtr<nsIWeakReference> weakShell;
01455   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01456 
01457   // reusing the HTML accessible widget and enhancing for XUL
01458   *_retval = new nsXULTextAccessible(aNode, weakShell);
01459   if (! *_retval)
01460     return NS_ERROR_OUT_OF_MEMORY;
01461 
01462   NS_ADDREF(*_retval);
01463 #else
01464   *_retval = nsnull;
01465 #endif // MOZ_XUL
01466   return NS_OK;
01467 }
01468 
01470 NS_IMETHODIMP nsAccessibilityService::CreateXULTabAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01471 {
01472 #ifdef MOZ_XUL
01473   nsCOMPtr<nsIWeakReference> weakShell;
01474   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01475 
01476   *_retval = new nsXULTabAccessible(aNode, weakShell);
01477   if (! *_retval)
01478     return NS_ERROR_OUT_OF_MEMORY;
01479 
01480   NS_ADDREF(*_retval);
01481 #else
01482   *_retval = nsnull;
01483 #endif // MOZ_XUL
01484   return NS_OK;
01485 }
01486 
01488 NS_IMETHODIMP nsAccessibilityService::CreateXULTabBoxAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01489 {
01490 #ifdef MOZ_XUL
01491   nsCOMPtr<nsIWeakReference> weakShell;
01492   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01493 
01494   *_retval = new nsXULTabBoxAccessible(aNode, weakShell);
01495   if (! *_retval)
01496     return NS_ERROR_OUT_OF_MEMORY;
01497 
01498   NS_ADDREF(*_retval);
01499 #else
01500   *_retval = nsnull;
01501 #endif // MOZ_XUL
01502   return NS_OK;
01503 }
01504 
01506 NS_IMETHODIMP nsAccessibilityService::CreateXULTabPanelsAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01507 {
01508 #ifdef MOZ_XUL
01509   nsCOMPtr<nsIWeakReference> weakShell;
01510   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01511 
01512   *_retval = new nsXULTabPanelsAccessible(aNode, weakShell);
01513   if (! *_retval)
01514     return NS_ERROR_OUT_OF_MEMORY;
01515 
01516   NS_ADDREF(*_retval);
01517 #else
01518   *_retval = nsnull;
01519 #endif // MOZ_XUL
01520   return NS_OK;
01521 }
01522 
01524 NS_IMETHODIMP nsAccessibilityService::CreateXULTabsAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01525 {
01526 #ifdef MOZ_XUL
01527   nsCOMPtr<nsIWeakReference> weakShell;
01528   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01529 
01530   *_retval = new nsXULTabsAccessible(aNode, weakShell);
01531   if (! *_retval)
01532     return NS_ERROR_OUT_OF_MEMORY;
01533 
01534   NS_ADDREF(*_retval);
01535 #else
01536   *_retval = nsnull;
01537 #endif // MOZ_XUL
01538   return NS_OK;
01539 }
01540 
01541 NS_IMETHODIMP nsAccessibilityService::CreateXULToolbarAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01542 {
01543 #ifdef MOZ_XUL
01544   nsCOMPtr<nsIWeakReference> weakShell;
01545   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01546 
01547   *_retval = new nsXULToolbarAccessible(aNode, weakShell);
01548   if (! *_retval)
01549     return NS_ERROR_OUT_OF_MEMORY;
01550 
01551   NS_ADDREF(*_retval);
01552 #else
01553   *_retval = nsnull;
01554 #endif // MOZ_XUL
01555   return NS_OK;
01556 }
01557 
01558 NS_IMETHODIMP nsAccessibilityService::CreateXULToolbarSeparatorAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01559 {
01560 #ifdef MOZ_XUL
01561   nsCOMPtr<nsIWeakReference> weakShell;
01562   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01563 
01564   *_retval = new nsXULToolbarSeparatorAccessible(aNode, weakShell);
01565   if (! *_retval)
01566     return NS_ERROR_OUT_OF_MEMORY;
01567 
01568   NS_ADDREF(*_retval);
01569 #else
01570   *_retval = nsnull;
01571 #endif // MOZ_XUL
01572   return NS_OK;
01573 }
01574 
01575 NS_IMETHODIMP nsAccessibilityService::CreateXULTooltipAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01576 {
01577 #ifdef MOZ_XUL
01578 #ifndef MOZ_ACCESSIBILITY_ATK
01579   nsCOMPtr<nsIWeakReference> weakShell;
01580   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01581 
01582   *_retval = new nsXULTooltipAccessible(aNode, weakShell);
01583   if (! *_retval)
01584     return NS_ERROR_OUT_OF_MEMORY;
01585 
01586   NS_ADDREF(*_retval);
01587 #else
01588   *_retval = nsnull;
01589 #endif // MOZ_ACCESSIBILITY_ATK
01590 #else
01591   *_retval = nsnull;
01592 #endif // MOZ_XUL
01593   return NS_OK;
01594 }
01595 
01596 NS_IMETHODIMP nsAccessibilityService::CreateXULTreeAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01597 {
01598 #ifdef MOZ_XUL
01599   nsCOMPtr<nsIWeakReference> weakShell;
01600   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01601 
01602   *_retval = new nsXULTreeAccessibleWrap(aNode, weakShell);
01603   if (! *_retval)
01604     return NS_ERROR_OUT_OF_MEMORY;
01605 
01606   NS_ADDREF(*_retval);
01607 #else
01608   *_retval = nsnull;
01609 #endif // MOZ_XUL
01610   return NS_OK;
01611 }
01612 
01613 NS_IMETHODIMP nsAccessibilityService::CreateXULTreeColumnsAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01614 {
01615 #ifdef MOZ_XUL
01616   nsCOMPtr<nsIWeakReference> weakShell;
01617   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01618 
01619   *_retval = new nsXULTreeColumnsAccessibleWrap(aNode, weakShell);
01620   if (! *_retval)
01621     return NS_ERROR_OUT_OF_MEMORY;
01622 
01623   NS_ADDREF(*_retval);
01624 #else
01625   *_retval = nsnull;
01626 #endif // MOZ_XUL
01627   return NS_OK;
01628 }
01629 
01630 NS_IMETHODIMP nsAccessibilityService::CreateXULTreeColumnitemAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
01631 {
01632 #ifdef MOZ_XUL
01633   nsCOMPtr<nsIWeakReference> weakShell;
01634   GetShellFromNode(aNode, getter_AddRefs(weakShell));
01635 
01636   *_retval = new nsXULTreeColumnitemAccessible(aNode, weakShell);
01637   if (! *_retval)
01638     return NS_ERROR_OUT_OF_MEMORY;
01639 
01640   NS_ADDREF(*_retval);
01641 #else
01642   *_retval = nsnull;
01643 #endif // MOZ_XUL
01644   return NS_OK;
01645 }
01646 
01647 
01648 NS_IMETHODIMP nsAccessibilityService::GetCachedAccessible(nsIDOMNode *aNode,
01649                                                           nsIWeakReference *aWeakShell,
01650                                                           nsIAccessible **aAccessible)
01651 {
01652   nsCOMPtr<nsIAccessNode> accessNode;
01653   nsresult rv = GetCachedAccessNode(aNode, aWeakShell, getter_AddRefs(accessNode));
01654   nsCOMPtr<nsIAccessible> accessible(do_QueryInterface(accessNode));
01655   NS_IF_ADDREF(*aAccessible = accessible);
01656   return rv;
01657 }
01658 
01659 NS_IMETHODIMP nsAccessibilityService::GetCachedAccessNode(nsIDOMNode *aNode,
01660                                                           nsIWeakReference *aWeakShell,
01661                                                           nsIAccessNode **aAccessNode)
01662 {
01663   nsCOMPtr<nsIAccessibleDocument> accessibleDoc =
01664     nsAccessNode::GetDocAccessibleFor(aWeakShell);
01665 
01666   if (!accessibleDoc) {
01667     *aAccessNode = nsnull;
01668     return NS_ERROR_FAILURE;
01669   }
01670 
01671   return accessibleDoc->GetCachedAccessNode(NS_STATIC_CAST(void*, aNode), aAccessNode);
01672 }
01673 
01678 NS_IMETHODIMP nsAccessibilityService::GetAccessibleFor(nsIDOMNode *aNode,
01679                                                        nsIAccessible **aAccessible)
01680 {
01681   // It's not ideal to call this -- it will assume shell #0
01682   // Some of our old test scripts still use it
01683   nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
01684   nsCOMPtr<nsIDocument> doc;
01685   if (content) {
01686     doc = content->GetDocument();
01687   }
01688   else {// Could be document node
01689     doc = do_QueryInterface(aNode);
01690   }
01691   if (!doc)
01692     return NS_ERROR_FAILURE;
01693 
01694   nsIPresShell *presShell = doc->GetShellAt(0);
01695   return GetAccessibleInShell(aNode, presShell, aAccessible);
01696 }
01697 
01698 NS_IMETHODIMP nsAccessibilityService::GetAccessibleInWindow(nsIDOMNode *aNode,
01699                                                             nsIDOMWindow *aWin,
01700                                                             nsIAccessible **aAccessible)
01701 {
01702   nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(aWin));
01703   nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(webNav));
01704   if (!docShell)
01705     return NS_ERROR_FAILURE;
01706 
01707   nsCOMPtr<nsIPresShell> presShell;
01708   docShell->GetPresShell(getter_AddRefs(presShell));
01709   return GetAccessibleInShell(aNode, presShell, aAccessible);
01710 }
01711 
01712 NS_IMETHODIMP nsAccessibilityService::GetAccessibleInShell(nsIDOMNode *aNode,
01713                                                            nsIPresShell *aPresShell,
01714                                                            nsIAccessible **aAccessible)
01715 {
01716   nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(aPresShell));
01717   nsIFrame *outFrameUnused = NULL;
01718   PRBool isHiddenUnused = false;
01719   return GetAccessible(aNode, aPresShell, weakShell,
01720                        &outFrameUnused, &isHiddenUnused, aAccessible);
01721 }
01722 
01723 NS_IMETHODIMP nsAccessibilityService::GetAccessibleInWeakShell(nsIDOMNode *aNode,
01724                                                                nsIWeakReference *aWeakShell,
01725                                                                nsIAccessible **aAccessible)
01726 {
01727   nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(aWeakShell));
01728   nsIFrame *outFrameUnused = NULL;
01729   PRBool isHiddenUnused = false;
01730   return GetAccessible(aNode, presShell, aWeakShell,
01731                        &outFrameUnused, &isHiddenUnused, aAccessible);
01732 }
01733 
01734 nsresult nsAccessibilityService::InitAccessible(nsIAccessible *aAccessibleIn,
01735                                                 nsIAccessible **aAccessibleOut)
01736 {
01737   NS_ASSERTION(aAccessibleOut && !*aAccessibleOut, "Out param should already be cleared out");
01738   if (!aAccessibleIn)
01739     return NS_ERROR_FAILURE;
01740 
01741   nsCOMPtr<nsPIAccessNode> privateAccessNode = do_QueryInterface(aAccessibleIn);
01742   NS_ASSERTION(privateAccessNode, "All accessibles must support nsPIAccessNode");
01743   nsresult rv = privateAccessNode->Init(); // Add to cache, etc.
01744   if (NS_SUCCEEDED(rv)) {
01745     NS_ADDREF(*aAccessibleOut = aAccessibleIn);
01746   }
01747   return rv;
01748 }
01749 
01750 NS_IMETHODIMP nsAccessibilityService::GetAccessible(nsIDOMNode *aNode,
01751                                                     nsIPresShell *aPresShell,
01752                                                     nsIWeakReference *aWeakShell,
01753                                                     nsIFrame **aFrameHint,
01754                                                     PRBool *aIsHidden,
01755                                                     nsIAccessible **aAccessible)
01756 {
01757   NS_ENSURE_ARG_POINTER(aAccessible);
01758   NS_ENSURE_ARG_POINTER(aFrameHint);
01759   *aAccessible = nsnull;
01760   if (!aPresShell || !aWeakShell) {
01761     return NS_ERROR_FAILURE;
01762   }
01763 
01764   NS_ASSERTION(aNode, "GetAccessible() called with no node.");
01765 
01766   *aIsHidden = PR_FALSE;
01767 
01768 #ifdef DEBUG_aleventhal
01769   // Please leave this in for now, it's a convenient debugging method
01770   nsAutoString name;
01771   aNode->GetLocalName(name);
01772   if (name.LowerCaseEqualsLiteral("wizardpage"))
01773     printf("## aaronl debugging tag name\n");
01774 
01775   nsAutoString attrib;
01776   nsCOMPtr<nsIDOMElement> element(do_QueryInterface(aNode));
01777   if (element) {
01778     element->GetAttribute(NS_LITERAL_STRING("type"), attrib);
01779     if (attrib.EqualsLiteral("checkbox"))
01780       printf("## aaronl debugging attribute\n");
01781   }
01782 #endif
01783 
01784   nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
01785   if (content && content->Tag() == nsAccessibilityAtoms::map) {
01786     // Don't walk into maps, they take up no space.
01787     // The nsHTMLAreaAccessible's they contain are attached as
01788     // children of the appropriate nsHTMLImageAccessible.
01789     *aIsHidden = PR_TRUE;
01790     return NS_ERROR_FAILURE;
01791   }
01792 
01793   // Check to see if we already have an accessible for this
01794   // node in the cache
01795   nsCOMPtr<nsIAccessNode> accessNode;
01796   GetCachedAccessNode(aNode, aWeakShell, getter_AddRefs(accessNode));
01797 
01798   nsCOMPtr<nsIAccessible> newAcc;
01799   if (accessNode) {
01800     // Retrieved from cache
01801     // QI might not succeed if it's a node that's not accessible
01802     newAcc = do_QueryInterface(accessNode);
01803     if (!newAcc) {
01804       return NS_ERROR_FAILURE;
01805     }
01806     NS_ADDREF(*aAccessible = newAcc);
01807     return NS_OK;
01808   }
01809 
01810   // No cache entry, so we must create the accessible
01811   // Check to see if hidden first
01812   nsCOMPtr<nsIDocument> nodeIsDoc;
01813   if (!content) {
01814     nodeIsDoc = do_QueryInterface(aNode);
01815     if (!nodeIsDoc) {
01816       return NS_ERROR_FAILURE;   // No content, and not doc node
01817     }
01818     // This happens when we're on the document node, which will not QI to an nsIContent,
01819     nsCOMPtr<nsIAccessibleDocument> accessibleDoc =
01820       nsAccessNode::GetDocAccessibleFor(aWeakShell);
01821     if (accessibleDoc) {
01822       newAcc = do_QueryInterface(accessibleDoc);
01823       NS_ASSERTION(newAcc, "nsIAccessibleDocument is not an nsIAccessible");
01824     }
01825     else {
01826       CreateRootAccessible(aPresShell, nodeIsDoc, getter_AddRefs(newAcc)); // Does Init() for us
01827       NS_WARN_IF_FALSE(newAcc, "No root/doc accessible created");
01828     }
01829 
01830     NS_ENSURE_STATE(newAcc);
01831 
01832     *aFrameHint = aPresShell->GetRootFrame();
01833     NS_ADDREF(*aAccessible = newAcc );
01834     return NS_OK;
01835   }
01836 
01837   NS_ASSERTION(content->GetDocument(), "Creating accessible for node with no document");
01838   if (!content->GetDocument()) {
01839     return NS_ERROR_FAILURE;
01840   }
01841   NS_ASSERTION(content->GetDocument() == aPresShell->GetDocument(), "Creating accessible for wrong pres shell");
01842   if (content->GetDocument() != aPresShell->GetDocument()) {
01843     return NS_ERROR_FAILURE;
01844   }
01845 
01846   // We have a content node
01847   nsIFrame *frame = *aFrameHint;
01848 #ifdef DEBUG_aleventhal
01849   static int frameHintFailed, frameHintTried, frameHintNonexistant, frameHintFailedForText;
01850   ++frameHintTried;
01851 #endif
01852   if (!frame || content != frame->GetContent()) {
01853     // Frame hint not correct, get true frame, we try to optimize away from this
01854     aPresShell->GetPrimaryFrameFor(content, &frame);
01855     if (frame) {
01856 #ifdef DEBUG_aleventhal_
01857       // Frame hint debugging
01858       ++frameHintFailed;
01859       if (content->IsContentOfType(nsIContent::eTEXT)) {
01860         ++frameHintFailedForText;
01861       }
01862       frameHintNonexistant += !*aFrameHint;
01863       printf("Frame hint failures: %d / %d . Text fails = %d. No hint fails = %d \n", frameHintFailed, frameHintTried, frameHintFailedForText, frameHintNonexistant);
01864       if (frameHintTried >= 354) {
01865         printf("* "); // Aaron's break point
01866       }
01867 #endif
01868       if (frame->GetContent() != content) {
01869         // Not the main content for this frame!
01870         // For example, this happens because <area> elements return the
01871         // image frame as their primary frame. The main content for the
01872         // image frame is the image content.
01873 
01874         // Check if frame is an image frame, and content is <area>
01875         nsIImageFrame *imageFrame;
01876         CallQueryInterface(frame, &imageFrame);
01877         nsCOMPtr<nsIDOMHTMLAreaElement> areaElmt = do_QueryInterface(content);
01878         if (imageFrame && areaElmt) {
01879           nsCOMPtr<nsIAccessible> imageAcc;
01880           CreateHTMLImageAccessible(frame, getter_AddRefs(imageAcc));
01881           if (imageAcc) {
01882             // cache children
01883             PRInt32 childCount;
01884             imageAcc->GetChildCount(&childCount);
01885             // area accessible should be in cache now
01886             return GetCachedAccessible(aNode, aWeakShell, aAccessible);
01887           }
01888         }
01889 
01890         return NS_ERROR_FAILURE;
01891       }
01892       *aFrameHint = frame;
01893     }
01894   }
01895 
01896   // Check frame to see if it is hidden
01897   if (!frame || !frame->GetStyleVisibility()->IsVisible()) {
01898     *aIsHidden = PR_TRUE;
01899   }
01900 
01901   if (*aIsHidden) {
01902     return NS_ERROR_FAILURE;
01903   }
01904 
01908   if (content->IsContentOfType(nsIContent::eTEXT)) {
01909     // --- Create HTML for visible text frames ---
01910     if (frame->IsEmpty()) {
01911       *aIsHidden = PR_TRUE;
01912       return NS_ERROR_FAILURE;
01913     }
01914     frame->GetAccessible(getter_AddRefs(newAcc));
01915   }
01916   else if (!content->IsContentOfType(nsIContent::eHTML)) {
01917     // --- Try creating accessible non-HTML (XUL, etc.) ---
01918     // XUL elements may implement nsIAccessibleProvider via XBL
01919     // This allows them to say what kind of accessible to create
01920     // Non-HTML elements must have an nsIAccessibleProvider, tabindex
01921     // or role attribute or they're not in the accessible tree.
01922     nsAutoString role;
01923     if (nsAccessNode::GetRoleAttribute(content, role) &&
01924         StringEndsWith(role, NS_LITERAL_STRING(":presentation"))) {
01925       return NS_ERROR_FAILURE;
01926     }
01927     nsCOMPtr<nsIAccessibleProvider> accProv(do_QueryInterface(aNode));
01928     if (accProv) {
01929       accProv->GetAccessible(getter_AddRefs(newAcc));
01930     }
01931     if (newAcc) {
01932       // We have an accessible, no need to check further
01933       // newAcc may have been null from accProv->GetAccessible
01934       // if nsIAccessibleProvider is being used from content --
01935       // it's not a blessed interface.
01936     }
01937     else if (!role.IsEmpty() ||
01938              content->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::tabindex)) {
01939       newAcc = new nsAccessibleWrap(aNode, aWeakShell); // Create generic accessible
01940     }
01941     else if (content->GetNameSpaceID() == kNameSpaceID_SVG &&
01942              content->Tag() == nsAccessibilityAtoms::svg) {
01943       newAcc = new nsEnumRoleAccessible(aNode, aWeakShell, nsIAccessible::ROLE_DIAGRAM);
01944     }
01945     else if (content->GetNameSpaceID() == kNameSpaceID_MathML &&
01946              content->Tag() == nsAccessibilityAtoms::math) {
01947       newAcc = new nsEnumRoleAccessible(aNode, aWeakShell, nsIAccessible::ROLE_EQUATION);
01948     }
01949     else {
01950       return NS_ERROR_FAILURE;
01951     }
01952   }
01953   else {
01954     // --- Try creating accessible for HTML ---
01955     nsAutoString role;
01956     nsAccessNode::GetRoleAttribute(content, role);
01957     if (!content->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::tabindex)) {
01958       // If no tabindex, check for a Presentation role, which
01959       // tells us not to expose this to the accessibility hierarchy.
01960       if (StringEndsWith(role, NS_LITERAL_STRING(":presentation"),
01961                          nsCaseInsensitiveStringComparator())) {
01962         return NS_ERROR_FAILURE;
01963       }
01964       else {
01965         // If we're in table-related subcontent, check for the
01966         // Presentation role on the containing table
01967         nsIAtom *tag = content->Tag();
01968         if (tag == nsAccessibilityAtoms::td ||
01969             tag == nsAccessibilityAtoms::th ||
01970             tag == nsAccessibilityAtoms::tr ||
01971             tag == nsAccessibilityAtoms::tbody ||
01972             tag == nsAccessibilityAtoms::tfoot ||
01973             tag == nsAccessibilityAtoms::thead) {
01974           nsIContent *tableContent = content;
01975           nsAutoString tableRole;
01976           while ((tableContent = tableContent->GetParent()) != nsnull) {
01977             if (tableContent->Tag() == nsAccessibilityAtoms::table) {
01978               if (nsAccessNode::GetRoleAttribute(tableContent, tableRole) &&
01979                   StringEndsWith(tableRole, NS_LITERAL_STRING(":presentation"),
01980                   nsCaseInsensitiveStringComparator())) {
01981                 // Table that we're a descendant of is presentational
01982                 return NS_ERROR_FAILURE;
01983               }
01984               break;
01985             }
01986           }
01987         }
01988       }
01989     }
01990 
01991     frame->GetAccessible(getter_AddRefs(newAcc)); // Try using frame to do it
01992     if (!newAcc) {
01993       // Use markup (mostly tag name, perhaps attributes) to
01994       // decide if and what kind of accessible to create.
01995       CreateHTMLAccessibleByMarkup(frame, aWeakShell, aNode, role, getter_AddRefs(newAcc));
01996     }
01997   }
01998 
01999   return InitAccessible(newAcc, aAccessible);
02000 }
02001 
02002 // Called from layout when the frame tree owned by a node changes significantly
02003 NS_IMETHODIMP nsAccessibilityService::InvalidateSubtreeFor(nsIPresShell *aShell,
02004                                                            nsIContent *aChangeContent,
02005                                                            PRUint32 aEvent)
02006 {
02007   NS_ASSERTION(aEvent == nsIAccessibleEvent::EVENT_REORDER ||
02008                aEvent == nsIAccessibleEvent::EVENT_SHOW ||
02009                aEvent == nsIAccessibleEvent::EVENT_HIDE,
02010                "Incorrect aEvent passed in");
02011 
02012   nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(aShell));
02013   NS_ASSERTION(aShell, "No pres shell in call to InvalidateSubtreeFor");
02014   nsCOMPtr<nsIAccessibleDocument> accessibleDoc =
02015     nsAccessNode::GetDocAccessibleFor(weakShell);
02016   nsCOMPtr<nsPIAccessibleDocument> privateAccessibleDoc =
02017     do_QueryInterface(accessibleDoc);
02018   if (!privateAccessibleDoc) {
02019     return NS_OK;
02020   }
02021   return privateAccessibleDoc->InvalidateCacheSubtree(aChangeContent, aEvent);
02022 }
02023 
02026 
02027 nsresult
02028 nsAccessibilityService::GetAccessibilityService(nsIAccessibilityService** aResult)
02029 {
02030   NS_PRECONDITION(aResult != nsnull, "null ptr");
02031   if (! aResult)
02032       return NS_ERROR_NULL_POINTER;
02033 
02034   *aResult = nsnull;
02035   if (!nsAccessibilityService::gAccessibilityService) {
02036     gAccessibilityService = new nsAccessibilityService();
02037     if (!gAccessibilityService ) {
02038       return NS_ERROR_OUT_OF_MEMORY;
02039     }
02040   }
02041   *aResult = nsAccessibilityService::gAccessibilityService;
02042   NS_ADDREF(*aResult);
02043   return NS_OK;
02044 }
02045 
02046 nsresult
02047 NS_GetAccessibilityService(nsIAccessibilityService** aResult)
02048 {
02049   return nsAccessibilityService::GetAccessibilityService(aResult);
02050 }
02051