author | Jason Duell <jduell.mcbugs@gmail.com> |
Tue, 22 Jun 2010 17:33:57 -0700 | |
changeset 46909 | 155d97b3f8c9f6e74239e9cca56db40e53610dc1 |
parent 46908 | f80302dc4c6cdc3ec12ca024388f3bc3a70f62cf (current diff) |
parent 44122 | b9ef5bc12c38be88d58fb259852ed912612b141a (diff) |
child 46910 | 7050d2595c2da5d660ec1e0c62af72dbe0cc4943 |
push id | 14210 |
push user | dougt@mozilla.com |
push date | Thu, 01 Jul 2010 06:28:42 +0000 |
treeherder | mozilla-central@3aff97777291 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
milestone | 1.9.3a6pre |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/.hgtags +++ b/.hgtags @@ -43,8 +43,9 @@ 65c1582465efe99899189519fccaf7b2826fcb2e 27937722da69ad0e8fd140a00671413068226a5b last-mozilla-central 27937722da69ad0e8fd140a00671413068226a5b last-mozilla-central a732c6d3c078f80635255c78bfaadffa5828a8a5 last-mozilla-central a732c6d3c078f80635255c78bfaadffa5828a8a5 last-mozilla-central 925595f3c08634cc42e33158ea6858bb55623ef7 last-mozilla-central dba2abb7db57078c5a4810884834d3056a5d56c2 last-mozilla-central 138f593553b66c9f815e8f57870c19d6347f7702 UPDATE_PACKAGING_R9 138f593553b66c9f815e8f57870c19d6347f7702 UPDATE_PACKAGING_R10 +138f593553b66c9f815e8f57870c19d6347f7702 UPDATE_PACKAGING_R11
--- a/accessible/public/nsIAccessNode.idl +++ b/accessible/public/nsIAccessNode.idl @@ -51,64 +51,25 @@ interface nsIDOMCSSPrimitiveValue; * The nsIAccessNode implementations are instantiated lazily. * The nsIAccessNode tree for a given dom window * has a one to one relationship to the DOM tree. * If the DOM node for this access node is "accessible", * then a QueryInterface to nsIAccessible will succeed. * * @status UNDER_REVIEW */ -[scriptable, uuid(bd458843-1895-42c6-b7f9-f0ca88eeab6b)] +[scriptable, uuid(ef16ff42-0256-4b48-ae87-b18a95b7f7d6)] interface nsIAccessNode : nsISupports { /** * The DOM node this nsIAccessNode is associated with. */ readonly attribute nsIDOMNode DOMNode; /** - * The number of DOM children for the DOM node, which - * matches the number of nsIAccessNode children for this - * nsIAccessNode. - */ - readonly attribute long numChildren; - - /** - * Get the nth child of this node - * @param childNum Zero-based child index - * @return The nth nsIAccessNode child - */ - nsIAccessNode getChildNodeAt(in long childNum); - - /** - * The parent nsIAccessNode - */ - readonly attribute nsIAccessNode parentNode; - - /** - * The first nsIAccessNode child - */ - readonly attribute nsIAccessNode firstChildNode; - - /** - * The last nsIAccessNode child - */ - readonly attribute nsIAccessNode lastChildNode; - - /** - * The previous nsIAccessNode sibling - */ - readonly attribute nsIAccessNode previousSiblingNode; - - /** - * The next nsIAccessNode sibling - */ - readonly attribute nsIAccessNode nextSiblingNode; - - /** * The document accessible that this access node resides in. */ readonly attribute nsIAccessibleDocument document; /** * The root document accessible that this access node resides in. */ readonly attribute nsIAccessibleDocument rootDocument;
--- a/accessible/public/nsIAccessibilityService.h +++ b/accessible/public/nsIAccessibilityService.h @@ -46,20 +46,20 @@ class nsAccessible; class nsIContent; class nsIDocument; class nsIFrame; class nsIPresShell; class nsObjectFrame; -// 9f43b315-53c6-4d46-9818-9c8593e91984 +// 10ff6dca-b219-4b64-9a4c-67a62b86edce #define NS_IACCESSIBILITYSERVICE_IID \ -{0x9f43b315, 0x53c6, 0x4d46, \ - {0x98, 0x18, 0x9c, 0x85, 0x93, 0xe9, 0x19, 0x84} } +{ 0x10ff6dca, 0xb219, 0x4b64, \ + { 0x9a, 0x4c, 0x67, 0xa6, 0x2b, 0x86, 0xed, 0xce } } class nsIAccessibilityService : public nsIAccessibleRetrieval { public: NS_DECLARE_STATIC_IID_ACCESSOR(NS_IACCESSIBILITYSERVICE_IID) /** * Return an accessible object for a DOM node in the given pres shell. @@ -162,16 +162,22 @@ public: /** * Notify accessibility that anchor jump has been accomplished to the given * target. Used by layout. */ virtual void NotifyOfAnchorJumpTo(nsIContent *aTarget) = 0; /** + * Notify the accessibility service that the given presshell is + * being destroyed. + */ + virtual void PresShellDestroyed(nsIPresShell *aPresShell) = 0; + + /** * Fire accessible event of the given type for the given target. * * @param aEvent [in] accessible event type * @param aTarget [in] target of accessible event */ virtual nsresult FireAccessibleEvent(PRUint32 aEvent, nsIAccessible *aTarget) = 0; };
--- a/accessible/public/nsIAccessibleEvent.idl +++ b/accessible/public/nsIAccessibleEvent.idl @@ -56,17 +56,17 @@ interface nsIDOMNode; * using code something like this: * nsCOMPtr<nsIObserverService> observerService = * do_GetService("@mozilla.org/observer-service;1", &rv); * if (NS_SUCCEEDED(rv)) * rv = observerService->AddObserver(this, "accessible-event", PR_TRUE); * * @status UNDER_REVIEW */ -[scriptable, uuid(5713f093-1d67-4666-b9e2-516f410976bc)] +[scriptable, uuid(c68b4386-dca7-4b88-8988-7a95ce7be92f)] interface nsIAccessibleEvent : nsISupports { /** * An object has been created. */ const unsigned long EVENT_SHOW = 0x0001; /** @@ -252,217 +252,207 @@ interface nsIAccessibleEvent : nsISuppor const unsigned long EVENT_MINIMIZE_START = 0x0025; /** * A window object has been minimized or maximized */ const unsigned long EVENT_MINIMIZE_END = 0x0026; /** - * XXX: - */ - const unsigned long EVENT_DOCUMENT_LOAD_START = 0x0027; - - /** * The loading of the document has completed. */ - const unsigned long EVENT_DOCUMENT_LOAD_COMPLETE = 0x0028; + const unsigned long EVENT_DOCUMENT_LOAD_COMPLETE = 0x0027; /** * The document contents are being reloaded. */ - const unsigned long EVENT_DOCUMENT_RELOAD = 0x0029; + const unsigned long EVENT_DOCUMENT_RELOAD = 0x0028; /** * The loading of the document was interrupted. */ - const unsigned long EVENT_DOCUMENT_LOAD_STOPPED = 0x002A; + const unsigned long EVENT_DOCUMENT_LOAD_STOPPED = 0x0029; /** * The document wide attributes of the document object have changed. */ - const unsigned long EVENT_DOCUMENT_ATTRIBUTES_CHANGED = 0x002B; + const unsigned long EVENT_DOCUMENT_ATTRIBUTES_CHANGED = 0x002A; /** * The contents of the document have changed. */ - const unsigned long EVENT_DOCUMENT_CONTENT_CHANGED = 0x002C; + const unsigned long EVENT_DOCUMENT_CONTENT_CHANGED = 0x002B; - const unsigned long EVENT_PROPERTY_CHANGED = 0x002D; - const unsigned long EVENT_SELECTION_CHANGED = 0x002E; + const unsigned long EVENT_PROPERTY_CHANGED = 0x002C; + const unsigned long EVENT_SELECTION_CHANGED = 0x002D; /** * A text object's attributes changed. * Also see EVENT_OBJECT_ATTRIBUTE_CHANGED. */ - const unsigned long EVENT_TEXT_ATTRIBUTE_CHANGED = 0x002F; + const unsigned long EVENT_TEXT_ATTRIBUTE_CHANGED = 0x002E; /** * The caret has moved to a new position. */ - const unsigned long EVENT_TEXT_CARET_MOVED = 0x0030; + const unsigned long EVENT_TEXT_CARET_MOVED = 0x002F; /** * This event indicates general text changes, i.e. changes to text that is * exposed through the IAccessibleText and IAccessibleEditableText interfaces. */ - const unsigned long EVENT_TEXT_CHANGED = 0x0031; + const unsigned long EVENT_TEXT_CHANGED = 0x0030; /** * Text was inserted. */ - const unsigned long EVENT_TEXT_INSERTED = 0x0032; + const unsigned long EVENT_TEXT_INSERTED = 0x0031; /** * Text was removed. */ - const unsigned long EVENT_TEXT_REMOVED = 0x0033; + const unsigned long EVENT_TEXT_REMOVED = 0x0032; /** * Text was updated. */ - const unsigned long EVENT_TEXT_UPDATED = 0x0034; + const unsigned long EVENT_TEXT_UPDATED = 0x0033; /** * The text selection changed. */ - const unsigned long EVENT_TEXT_SELECTION_CHANGED = 0x0035; + const unsigned long EVENT_TEXT_SELECTION_CHANGED = 0x0034; /** * A visibile data event indicates the change of the visual appearance * of an accessible object. This includes for example most of the * attributes available via the IAccessibleComponent interface. */ - const unsigned long EVENT_VISIBLE_DATA_CHANGED = 0x0036; + const unsigned long EVENT_VISIBLE_DATA_CHANGED = 0x0035; /** * The caret moved from one column to the next. */ - const unsigned long EVENT_TEXT_COLUMN_CHANGED = 0x0037; + const unsigned long EVENT_TEXT_COLUMN_CHANGED = 0x0036; /** * The caret moved from one section to the next. */ - const unsigned long EVENT_SECTION_CHANGED = 0x0038; + const unsigned long EVENT_SECTION_CHANGED = 0x0037; /** * A table caption changed. */ - const unsigned long EVENT_TABLE_CAPTION_CHANGED = 0x0039; + const unsigned long EVENT_TABLE_CAPTION_CHANGED = 0x0038; /** * A table's data changed. */ - const unsigned long EVENT_TABLE_MODEL_CHANGED = 0x003A; + const unsigned long EVENT_TABLE_MODEL_CHANGED = 0x0039; /** * A table's summary changed. */ - const unsigned long EVENT_TABLE_SUMMARY_CHANGED = 0x003B; + const unsigned long EVENT_TABLE_SUMMARY_CHANGED = 0x003A; /** * A table's row description changed. */ - const unsigned long EVENT_TABLE_ROW_DESCRIPTION_CHANGED = 0x003C; + const unsigned long EVENT_TABLE_ROW_DESCRIPTION_CHANGED = 0x003B; /** * A table's row header changed. */ - const unsigned long EVENT_TABLE_ROW_HEADER_CHANGED = 0x003D; + const unsigned long EVENT_TABLE_ROW_HEADER_CHANGED = 0x003C; - const unsigned long EVENT_TABLE_ROW_INSERT = 0x003E; - const unsigned long EVENT_TABLE_ROW_DELETE = 0x003F; - const unsigned long EVENT_TABLE_ROW_REORDER = 0x0040; + const unsigned long EVENT_TABLE_ROW_INSERT = 0x003D; + const unsigned long EVENT_TABLE_ROW_DELETE = 0x003E; + const unsigned long EVENT_TABLE_ROW_REORDER = 0x003F; /** * A table's column description changed. */ - const unsigned long EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED = 0x0041; + const unsigned long EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED = 0x0040; /** * A table's column header changed. */ - const unsigned long EVENT_TABLE_COLUMN_HEADER_CHANGED = 0x0042; + const unsigned long EVENT_TABLE_COLUMN_HEADER_CHANGED = 0x0041; - const unsigned long EVENT_TABLE_COLUMN_INSERT = 0x0043; - const unsigned long EVENT_TABLE_COLUMN_DELETE = 0x0044; - const unsigned long EVENT_TABLE_COLUMN_REORDER = 0x0045; + const unsigned long EVENT_TABLE_COLUMN_INSERT = 0x0042; + const unsigned long EVENT_TABLE_COLUMN_DELETE = 0x0043; + const unsigned long EVENT_TABLE_COLUMN_REORDER = 0x0044; - const unsigned long EVENT_WINDOW_ACTIVATE = 0x0046; - const unsigned long EVENT_WINDOW_CREATE = 0x0047; - const unsigned long EVENT_WINDOW_DEACTIVATE = 0x0048; - const unsigned long EVENT_WINDOW_DESTROY = 0x0049; - const unsigned long EVENT_WINDOW_MAXIMIZE = 0x004A; - const unsigned long EVENT_WINDOW_MINIMIZE = 0x004B; - const unsigned long EVENT_WINDOW_RESIZE = 0x004C; - const unsigned long EVENT_WINDOW_RESTORE = 0x004D; + const unsigned long EVENT_WINDOW_ACTIVATE = 0x0045; + const unsigned long EVENT_WINDOW_CREATE = 0x0046; + const unsigned long EVENT_WINDOW_DEACTIVATE = 0x0047; + const unsigned long EVENT_WINDOW_DESTROY = 0x0048; + const unsigned long EVENT_WINDOW_MAXIMIZE = 0x0049; + const unsigned long EVENT_WINDOW_MINIMIZE = 0x004A; + const unsigned long EVENT_WINDOW_RESIZE = 0x004B; + const unsigned long EVENT_WINDOW_RESTORE = 0x004C; /** * The ending index of this link within the containing string has changed. */ - const unsigned long EVENT_HYPERLINK_END_INDEX_CHANGED = 0x004E; + const unsigned long EVENT_HYPERLINK_END_INDEX_CHANGED = 0x004D; /** * The number of anchors assoicated with this hyperlink object has changed. */ - const unsigned long EVENT_HYPERLINK_NUMBER_OF_ANCHORS_CHANGED = 0x004F; + const unsigned long EVENT_HYPERLINK_NUMBER_OF_ANCHORS_CHANGED = 0x004E; /** * The hyperlink selected state changed from selected to unselected or * from unselected to selected. */ - const unsigned long EVENT_HYPERLINK_SELECTED_LINK_CHANGED = 0x0050; + const unsigned long EVENT_HYPERLINK_SELECTED_LINK_CHANGED = 0x004F; /** * One of the links associated with the hypertext object has been activated. */ - const unsigned long EVENT_HYPERTEXT_LINK_ACTIVATED = 0x0051; + const unsigned long EVENT_HYPERTEXT_LINK_ACTIVATED = 0x0050; /** * One of the links associated with the hypertext object has been selected. */ - const unsigned long EVENT_HYPERTEXT_LINK_SELECTED = 0x0052; + const unsigned long EVENT_HYPERTEXT_LINK_SELECTED = 0x0051; /** * The starting index of this link within the containing string has changed. */ - const unsigned long EVENT_HYPERLINK_START_INDEX_CHANGED = 0x0053; + const unsigned long EVENT_HYPERLINK_START_INDEX_CHANGED = 0x0052; /** * Focus has changed from one hypertext object to another, or focus moved * from a non-hypertext object to a hypertext object, or focus moved from a * hypertext object to a non-hypertext object. */ - const unsigned long EVENT_HYPERTEXT_CHANGED = 0x0054; + const unsigned long EVENT_HYPERTEXT_CHANGED = 0x0053; /** * The number of hyperlinks associated with a hypertext object changed. */ - const unsigned long EVENT_HYPERTEXT_NLINKS_CHANGED = 0x0055; + const unsigned long EVENT_HYPERTEXT_NLINKS_CHANGED = 0x0054; /** * An object's attributes changed. Also see EVENT_TEXT_ATTRIBUTE_CHANGED. */ - const unsigned long EVENT_OBJECT_ATTRIBUTE_CHANGED = 0x0056; + const unsigned long EVENT_OBJECT_ATTRIBUTE_CHANGED = 0x0055; /** * A slide changed in a presentation document or a page boundary was * crossed in a word processing document. */ - const unsigned long EVENT_PAGE_CHANGED = 0x0057; - - /** - * Used internally in Gecko. - */ - const unsigned long EVENT_INTERNAL_LOAD = 0x0058; + const unsigned long EVENT_PAGE_CHANGED = 0x0056; /** * Help make sure event map does not get out-of-line. */ - const unsigned long EVENT_LAST_ENTRY = 0x0059; + const unsigned long EVENT_LAST_ENTRY = 0x0057; /** * The type of event, based on the enumerated event values * defined in this interface. */ readonly attribute unsigned long eventType; /**
--- a/accessible/public/nsIAccessibleHyperText.idl +++ b/accessible/public/nsIAccessibleHyperText.idl @@ -39,41 +39,51 @@ * * ***** END LICENSE BLOCK ***** */ #include "nsISupports.idl" #include "nsIAccessibleHyperLink.idl" /** * A cross-platform interface that deals with text which contains hyperlinks. + * Each link is an embedded object representing exactly 1 character within + * the hypertext. + * + * Current implementation assumes every embedded object is a link. */ -[scriptable, uuid(d56bd454-8ff3-4edc-b266-baeada00267b)] +[scriptable, uuid(b33684e2-090c-4e1d-a3d9-f4b46f4237b9)] interface nsIAccessibleHyperText : nsISupports { /** - * Returns the number of links contained within this hypertext object. + * Return the number of links contained within this hypertext object. */ readonly attribute long linkCount; - /* - * Returns the link index at the given character index. - * Each link is an embedded object representing exactly 1 character within - * the hypertext. + /** + * Return link accessible at the given index. * - * @param charIndex the 0-based character index. + * @param index [in] 0-based index of the link that is to be retrieved * - * @returns long 0-based link's index. - * A return value of -1 indicates no link is present at that index. + * @return link accessible or null if there is no link at that index */ - long getLinkIndex(in long charIndex); + nsIAccessibleHyperLink getLinkAt(in long index); /** - * Retrieves the nsIAccessibleHyperLink object at the given link index. + * Return index of the given link. * - * @param linkIndex 0-based index of the link that is to be retrieved. - * This can be retrieved via getLinkIndex (see above). + * @param link [in] link accessible the index is requested for * - * @returns nsIAccessibleHyperLink Object representing the link properties - * or NS_ERROR_INVALID_ARG if there is no link at that index. + * @return index of the given link or null if there's no link within + * hypertext accessible */ - nsIAccessibleHyperLink getLink(in long linkIndex); + long getLinkIndex(in nsIAccessibleHyperLink link); + + /* + * Return link index at the given offset within hypertext accessible. + * + * @param offset [in] the 0-based character index + * + * @return 0-based link's index or -1 if no link is present at that + * offset + */ + long getLinkIndexAtOffset(in long offset); };
--- a/accessible/public/nsIAccessibleRetrieval.idl +++ b/accessible/public/nsIAccessibleRetrieval.idl @@ -51,17 +51,17 @@ interface nsIDOMDOMStringList; * An interface for in-process accessibility clients * wishing to get an nsIAccessible or nsIAccessNode for * a given DOM node. * More documentation at: * http://www.mozilla.org/projects/ui/accessibility * * @status UNDER_REVIEW */ -[scriptable, uuid(3e5cbd5c-dbab-4ea3-b82b-4cd6201d6fe0)] +[scriptable, uuid(420f0f49-27c1-4ac1-b509-5aba4353909b)] interface nsIAccessibleRetrieval : nsISupports { /** * Return application accessible. */ nsIAccessible getApplicationAccessible(); /** @@ -123,16 +123,26 @@ interface nsIAccessibleRetrieval : nsISu /** * Get the type of accessible relation as a string. * * @param aRelationType - the accessible relation type constant * @return - accessible relation type presented as human readable string */ AString getStringRelationType(in unsigned long aRelationType); + + /** + * Return an accessible for the given DOM node from the cache. + * @note the method is intended for testing purposes + * + * @param aNode [in] the DOM node to get an accessible for + * + * @return cached accessible for the given DOM node if any + */ + nsIAccessible getAccessibleFromCache(in nsIDOMNode aNode); }; %{ C++ // for component registration // {663CA4A8-D219-4000-925D-D8F66406B626} #define NS_ACCESSIBLE_RETRIEVAL_CID \
--- a/accessible/src/atk/nsAccessNodeWrap.cpp +++ b/accessible/src/atk/nsAccessNodeWrap.cpp @@ -39,26 +39,27 @@ #include "nsAccessNodeWrap.h" #include "nsApplicationAccessibleWrap.h" /* For documentation of the accessibility architecture, * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html */ -/* - * Class nsAccessNodeWrap - */ +//////////////////////////////////////////////////////////////////////////////// +// nsAccessNodeWrap +//////////////////////////////////////////////////////////////////////////////// //----------------------------------------------------- // construction //----------------------------------------------------- -nsAccessNodeWrap::nsAccessNodeWrap(nsIDOMNode *aNode, nsIWeakReference* aShell): - nsAccessNode(aNode, aShell) +nsAccessNodeWrap:: + nsAccessNodeWrap(nsIContent *aContent, nsIWeakReference *aShell) : + nsAccessNode(aContent, aShell) { } //----------------------------------------------------- // destruction //----------------------------------------------------- nsAccessNodeWrap::~nsAccessNodeWrap() {
--- a/accessible/src/atk/nsAccessNodeWrap.h +++ b/accessible/src/atk/nsAccessNodeWrap.h @@ -43,16 +43,16 @@ #ifndef _nsAccessNodeWrap_H_ #define _nsAccessNodeWrap_H_ #include "nsAccessNode.h" class nsAccessNodeWrap : public nsAccessNode { public: // construction, destruction - nsAccessNodeWrap(nsIDOMNode *aNode, nsIWeakReference* aShell); + nsAccessNodeWrap(nsIContent *aContent, nsIWeakReference *aShell); virtual ~nsAccessNodeWrap(); static void InitAccessibility(); static void ShutdownAccessibility(); }; #endif
--- a/accessible/src/atk/nsAccessibleWrap.cpp +++ b/accessible/src/atk/nsAccessibleWrap.cpp @@ -265,20 +265,19 @@ mai_atk_object_get_type(void) return type; } #ifdef MAI_LOGGING PRInt32 nsAccessibleWrap::mAccWrapCreated = 0; PRInt32 nsAccessibleWrap::mAccWrapDeleted = 0; #endif -nsAccessibleWrap::nsAccessibleWrap(nsIDOMNode* aNode, - nsIWeakReference *aShell) - : nsAccessible(aNode, aShell), - mAtkObject(nsnull) +nsAccessibleWrap:: + nsAccessibleWrap(nsIContent *aContent, nsIWeakReference *aShell) : + nsAccessible(aContent, aShell), mAtkObject(nsnull) { #ifdef MAI_LOGGING ++mAccWrapCreated; #endif MAI_LOG_DEBUG(("==nsAccessibleWrap creating: this=%p,total=%d left=%d\n", (void*)this, mAccWrapCreated, (mAccWrapCreated-mAccWrapDeleted))); } @@ -302,21 +301,21 @@ void nsAccessibleWrap::ShutdownAtkObject MAI_ATK_OBJECT(mAtkObject)->accWrap = nsnull; } SetMaiHyperlink(nsnull); g_object_unref(mAtkObject); mAtkObject = nsnull; } } -nsresult +void nsAccessibleWrap::Shutdown() { ShutdownAtkObject(); - return nsAccessible::Shutdown(); + nsAccessible::Shutdown(); } MaiHyperlink* nsAccessibleWrap::GetMaiHyperlink(PRBool aCreate /* = PR_TRUE */) { // make sure mAtkObject is created GetAtkObject(); NS_ASSERTION(quark_mai_hyperlink, "quark_mai_hyperlink not initialized"); @@ -557,17 +556,17 @@ GetUniqueMaiAtkTypeName(PRUint16 interfa MAI_LOG_DEBUG(("MaiWidget::LastedTypeName=%s\n", name)); return name; } PRBool nsAccessibleWrap::IsValidObject() { // to ensure we are not shut down - return (mDOMNode != nsnull); + return !IsDefunct(); } /* static functions for ATK callbacks */ void classInitCB(AtkObjectClass *aClass) { GObjectClass *gobject_class = G_OBJECT_CLASS(aClass); @@ -864,65 +863,42 @@ getParentCB(AtkObject *aAtkObj) gint getChildCountCB(AtkObject *aAtkObj) { nsAccessibleWrap *accWrap = GetAccessibleWrap(aAtkObj); if (!accWrap || nsAccUtils::MustPrune(accWrap)) { return 0; } - PRInt32 count = 0; - nsCOMPtr<nsIAccessibleHyperText> hyperText; - accWrap->QueryInterface(NS_GET_IID(nsIAccessibleHyperText), getter_AddRefs(hyperText)); - if (hyperText) { - // If HyperText, then number of links matches number of children - hyperText->GetLinkCount(&count); - } - else { - nsCOMPtr<nsIAccessibleText> accText; - accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText), getter_AddRefs(accText)); - if (!accText) { // Accessible text that is not a HyperText has no children - accWrap->GetChildCount(&count); - } - } - return count; + // Links within hypertext accessible play role of accessible children in + // ATK since every embedded object is a link and text accessibles are + // ignored. + nsRefPtr<nsHyperTextAccessible> hyperText = do_QueryObject(accWrap); + return hyperText ? hyperText->GetLinkCount() : accWrap->GetChildCount(); } AtkObject * refChildCB(AtkObject *aAtkObj, gint aChildIndex) { // aChildIndex should not be less than zero if (aChildIndex < 0) { return nsnull; } nsAccessibleWrap *accWrap = GetAccessibleWrap(aAtkObj); if (!accWrap || nsAccUtils::MustPrune(accWrap)) { return nsnull; } - nsCOMPtr<nsIAccessible> accChild; - nsCOMPtr<nsIAccessibleHyperText> hyperText; - accWrap->QueryInterface(NS_GET_IID(nsIAccessibleHyperText), getter_AddRefs(hyperText)); - if (hyperText) { - // If HyperText, then number of links matches number of children. - // XXX Fix this so it is not O(n^2) to walk through the children - // (bug 566328). - nsCOMPtr<nsIAccessibleHyperLink> hyperLink; - hyperText->GetLink(aChildIndex, getter_AddRefs(hyperLink)); - accChild = do_QueryInterface(hyperLink); - } - else { - nsCOMPtr<nsIAccessibleText> accText; - accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText), getter_AddRefs(accText)); - if (!accText) { // Accessible Text that is not HyperText has no children - accWrap->GetChildAt(aChildIndex, getter_AddRefs(accChild)); - } - } - + // Links within hypertext accessible play role of accessible children in + // ATK since every embedded object is a link and text accessibles are + // ignored. + nsRefPtr<nsHyperTextAccessible> hyperText = do_QueryObject(accWrap); + nsAccessible* accChild = hyperText ? hyperText->GetLinkAt(aChildIndex) : + accWrap->GetChildAt(aChildIndex); if (!accChild) return nsnull; AtkObject* childAtkObj = nsAccessibleWrap::GetAtkObject(accChild); NS_ASSERTION(childAtkObj, "Fail to get AtkObj"); if (!childAtkObj) return nsnull; @@ -943,31 +919,22 @@ getIndexInParentCB(AtkObject *aAtkObj) return -1; } nsAccessible *parent = accWrap->GetParent(); if (!parent) { return -1; // No parent } - PRInt32 currentIndex = 0; - - PRInt32 childCount = parent->GetChildCount(); - for (PRInt32 idx = 0; idx < childCount; idx++) { - nsAccessible *sibling = parent->GetChildAt(idx); - if (sibling == accWrap) { - return currentIndex; - } - - if (nsAccUtils::IsEmbeddedObject(sibling)) { - ++ currentIndex; - } - } - - return -1; + // Links within hypertext accessible play role of accessible children in + // ATK since every embedded object is a link and text accessibles are + // ignored. + nsRefPtr<nsHyperTextAccessible> hyperTextParent(do_QueryObject(parent)); + return hyperTextParent ? + hyperTextParent->GetLinkIndex(accWrap) : parent->GetIndexOf(accWrap); } static void TranslateStates(PRUint32 aState, const AtkStateMap *aStateMap, AtkStateSet *aStateSet) { NS_ASSERTION(aStateSet, "Can't pass in null state set"); // Convert every state to an entry in AtkStateMap @@ -1104,18 +1071,17 @@ nsAccessibleWrap::HandleAccEvent(nsAccEv NS_ENSURE_SUCCESS(rv, rv); return FirePlatformEvent(aEvent); } nsresult nsAccessibleWrap::FirePlatformEvent(nsAccEvent *aEvent) { - nsCOMPtr<nsIAccessible> accessible; - aEvent->GetAccessible(getter_AddRefs(accessible)); + nsAccessible *accessible = aEvent->GetAccessible(); NS_ENSURE_TRUE(accessible, NS_ERROR_FAILURE); PRUint32 type = aEvent->GetEventType(); AtkObject *atkObj = nsAccessibleWrap::GetAtkObject(accessible); // We don't create ATK objects for nsIAccessible plain text leaves, // just return NS_OK in such case @@ -1152,17 +1118,17 @@ nsAccessibleWrap::FirePlatformEvent(nsAc PR_FALSE, PR_TRUE); return FireAtkStateChangeEvent(stateChangeEvent, atkObj); } } break; case nsIAccessibleEvent::EVENT_VALUE_CHANGE: { MAI_LOG_DEBUG(("\n\nReceived: EVENT_VALUE_CHANGE\n")); - nsCOMPtr<nsIAccessibleValue> value(do_QueryInterface(accessible)); + nsCOMPtr<nsIAccessibleValue> value(do_QueryObject(accessible)); if (value) { // Make sure this is a numeric value // Don't fire for MSAA string value changes (e.g. text editing) // ATK values are always numeric g_object_notify( (GObject*)atkObj, "accessible-value" ); } } break; case nsIAccessibleEvent::EVENT_SELECTION_CHANGED: @@ -1174,23 +1140,22 @@ nsAccessibleWrap::FirePlatformEvent(nsAc MAI_LOG_DEBUG(("\n\nReceived: EVENT_TEXT_SELECTION_CHANGED\n")); g_signal_emit_by_name(atkObj, "text_selection_changed"); break; case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED: { MAI_LOG_DEBUG(("\n\nReceived: EVENT_TEXT_CARET_MOVED\n")); - nsCOMPtr<nsIAccessibleCaretMoveEvent> caretMoveEvent(do_QueryInterface(aEvent)); + nsAccCaretMoveEvent *caretMoveEvent = downcast_accEvent(aEvent); NS_ASSERTION(caretMoveEvent, "Event needs event data"); if (!caretMoveEvent) break; - PRInt32 caretOffset = -1; - caretMoveEvent->GetCaretOffset(&caretOffset); + PRInt32 caretOffset = caretMoveEvent->GetCaretOffset(); MAI_LOG_DEBUG(("\n\nCaret postion: %d", caretOffset)); g_signal_emit_by_name(atkObj, "text_caret_moved", // Curent caret position caretOffset); } break; @@ -1204,40 +1169,38 @@ nsAccessibleWrap::FirePlatformEvent(nsAc case nsIAccessibleEvent::EVENT_TABLE_MODEL_CHANGED: MAI_LOG_DEBUG(("\n\nReceived: EVENT_TABLE_MODEL_CHANGED\n")); g_signal_emit_by_name(atkObj, "model_changed"); break; case nsIAccessibleEvent::EVENT_TABLE_ROW_INSERT: { MAI_LOG_DEBUG(("\n\nReceived: EVENT_TABLE_ROW_INSERT\n")); - nsCOMPtr<nsIAccessibleTableChangeEvent> tableEvent = do_QueryInterface(aEvent); + nsAccTableChangeEvent *tableEvent = downcast_accEvent(aEvent); NS_ENSURE_TRUE(tableEvent, NS_ERROR_FAILURE); - PRInt32 rowIndex, numRows; - tableEvent->GetRowOrColIndex(&rowIndex); - tableEvent->GetNumRowsOrCols(&numRows); + PRInt32 rowIndex = tableEvent->GetIndex(); + PRInt32 numRows = tableEvent->GetCount(); g_signal_emit_by_name(atkObj, "row_inserted", // After which the rows are inserted rowIndex, // The number of the inserted numRows); } break; case nsIAccessibleEvent::EVENT_TABLE_ROW_DELETE: { MAI_LOG_DEBUG(("\n\nReceived: EVENT_TABLE_ROW_DELETE\n")); - nsCOMPtr<nsIAccessibleTableChangeEvent> tableEvent = do_QueryInterface(aEvent); + nsAccTableChangeEvent *tableEvent = downcast_accEvent(aEvent); NS_ENSURE_TRUE(tableEvent, NS_ERROR_FAILURE); - PRInt32 rowIndex, numRows; - tableEvent->GetRowOrColIndex(&rowIndex); - tableEvent->GetNumRowsOrCols(&numRows); + PRInt32 rowIndex = tableEvent->GetIndex(); + PRInt32 numRows = tableEvent->GetCount(); g_signal_emit_by_name(atkObj, "row_deleted", // After which the rows are deleted rowIndex, // The number of the deleted numRows); } break; @@ -1247,40 +1210,38 @@ nsAccessibleWrap::FirePlatformEvent(nsAc MAI_LOG_DEBUG(("\n\nReceived: EVENT_TABLE_ROW_REORDER\n")); g_signal_emit_by_name(atkObj, "row_reordered"); break; } case nsIAccessibleEvent::EVENT_TABLE_COLUMN_INSERT: { MAI_LOG_DEBUG(("\n\nReceived: EVENT_TABLE_COLUMN_INSERT\n")); - nsCOMPtr<nsIAccessibleTableChangeEvent> tableEvent = do_QueryInterface(aEvent); + nsAccTableChangeEvent *tableEvent = downcast_accEvent(aEvent); NS_ENSURE_TRUE(tableEvent, NS_ERROR_FAILURE); - PRInt32 colIndex, numCols; - tableEvent->GetRowOrColIndex(&colIndex); - tableEvent->GetNumRowsOrCols(&numCols); + PRInt32 colIndex = tableEvent->GetIndex(); + PRInt32 numCols = tableEvent->GetCount(); g_signal_emit_by_name(atkObj, "column_inserted", // After which the columns are inserted colIndex, // The number of the inserted numCols); } break; case nsIAccessibleEvent::EVENT_TABLE_COLUMN_DELETE: { MAI_LOG_DEBUG(("\n\nReceived: EVENT_TABLE_COLUMN_DELETE\n")); - nsCOMPtr<nsIAccessibleTableChangeEvent> tableEvent = do_QueryInterface(aEvent); + nsAccTableChangeEvent *tableEvent = downcast_accEvent(aEvent); NS_ENSURE_TRUE(tableEvent, NS_ERROR_FAILURE); - PRInt32 colIndex, numCols; - tableEvent->GetRowOrColIndex(&colIndex); - tableEvent->GetNumRowsOrCols(&numCols); + PRInt32 colIndex = tableEvent->GetIndex(); + PRInt32 numCols = tableEvent->GetCount(); g_signal_emit_by_name(atkObj, "column_deleted", // After which the columns are deleted colIndex, // The number of the deleted numCols); } break; @@ -1314,30 +1275,30 @@ nsAccessibleWrap::FirePlatformEvent(nsAc case nsIAccessibleEvent::EVENT_MENU_END: MAI_LOG_DEBUG(("\n\nReceived: EVENT_MENU_END\n")); break; case nsIAccessibleEvent::EVENT_WINDOW_ACTIVATE: { MAI_LOG_DEBUG(("\n\nReceived: EVENT_WINDOW_ACTIVATED\n")); nsRootAccessible *rootAcc = - static_cast<nsRootAccessible *>(accessible.get()); + static_cast<nsRootAccessible *>(accessible); rootAcc->mActivated = PR_TRUE; guint id = g_signal_lookup ("activate", MAI_TYPE_ATK_OBJECT); g_signal_emit(atkObj, id, 0); // Always fire a current focus event after activation. rootAcc->FireCurrentFocusEvent(); } break; case nsIAccessibleEvent::EVENT_WINDOW_DEACTIVATE: { MAI_LOG_DEBUG(("\n\nReceived: EVENT_WINDOW_DEACTIVATED\n")); nsRootAccessible *rootAcc = - static_cast<nsRootAccessible *>(accessible.get()); + static_cast<nsRootAccessible *>(accessible); rootAcc->mActivated = PR_FALSE; guint id = g_signal_lookup ("deactivate", MAI_TYPE_ATK_OBJECT); g_signal_emit(atkObj, id, 0); } break; case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE: { MAI_LOG_DEBUG(("\n\nReceived: EVENT_DOCUMENT_LOAD_COMPLETE\n")); @@ -1374,28 +1335,22 @@ nsAccessibleWrap::FirePlatformEvent(nsAc } nsresult nsAccessibleWrap::FireAtkStateChangeEvent(nsAccEvent *aEvent, AtkObject *aObject) { MAI_LOG_DEBUG(("\n\nReceived: EVENT_STATE_CHANGE\n")); - nsCOMPtr<nsIAccessibleStateChangeEvent> event = - do_QueryInterface(aEvent); + nsAccStateChangeEvent *event = downcast_accEvent(aEvent); NS_ENSURE_TRUE(event, NS_ERROR_FAILURE); - PRUint32 state = 0; - event->GetState(&state); - - PRBool isExtra; - event->IsExtraState(&isExtra); - - PRBool isEnabled; - event->IsEnabled(&isEnabled); + PRUint32 state = event->GetState(); + PRBool isExtra = event->IsExtraState(); + PRBool isEnabled = event->IsStateEnabled(); PRInt32 stateIndex = AtkStateMap::GetStateIndexFor(state); if (stateIndex >= 0) { const AtkStateMap *atkStateMap = isExtra ? gAtkStateMapExt : gAtkStateMap; NS_ASSERTION(atkStateMap[stateIndex].stateMapEntryType != kNoSuchState, "No such state"); if (atkStateMap[stateIndex].atkState != kNone) { @@ -1416,28 +1371,22 @@ nsAccessibleWrap::FireAtkStateChangeEven } nsresult nsAccessibleWrap::FireAtkTextChangedEvent(nsAccEvent *aEvent, AtkObject *aObject) { MAI_LOG_DEBUG(("\n\nReceived: EVENT_TEXT_REMOVED/INSERTED\n")); - nsCOMPtr<nsIAccessibleTextChangeEvent> event = - do_QueryInterface(aEvent); + nsAccTextChangeEvent *event = downcast_accEvent(aEvent); NS_ENSURE_TRUE(event, NS_ERROR_FAILURE); - PRInt32 start = 0; - event->GetStart(&start); - - PRUint32 length = 0; - event->GetLength(&length); - - PRBool isInserted; - event->IsInserted(&isInserted); + PRInt32 start = event->GetStartOffset(); + PRUint32 length = event->GetLength(); + PRBool isInserted = event->IsTextInserted(); PRBool isFromUserInput = aEvent->IsFromUserInput(); char *signal_name = g_strconcat(isInserted ? "text_changed::insert" : "text_changed::delete", isFromUserInput ? "" : kNonUserInputEvent, NULL); g_signal_emit_by_name(aObject, signal_name, start, length); g_free (signal_name);
--- a/accessible/src/atk/nsAccessibleWrap.h +++ b/accessible/src/atk/nsAccessibleWrap.h @@ -80,22 +80,22 @@ class MaiHyperlink; /** * nsAccessibleWrap, and its descendents in atk directory provide the * implementation of AtkObject. */ class nsAccessibleWrap: public nsAccessible { public: - nsAccessibleWrap(nsIDOMNode*, nsIWeakReference *aShell); + nsAccessibleWrap(nsIContent *aContent, nsIWeakReference *aShell); virtual ~nsAccessibleWrap(); void ShutdownAtkObject(); // nsAccessNode - virtual nsresult Shutdown(); + virtual void Shutdown(); #ifdef MAI_LOGGING virtual void DumpnsAccessibleWrapInfo(int aDepth) {} static PRInt32 mAccWrapCreated; static PRInt32 mAccWrapDeleted; #endif // return the atk object for this nsAccessibleWrap
--- a/accessible/src/atk/nsApplicationAccessibleWrap.cpp +++ b/accessible/src/atk/nsApplicationAccessibleWrap.cpp @@ -432,17 +432,17 @@ mai_util_remove_key_event_listener (guin if (g_hash_table_size(key_listener_list) == 0) { gtk_key_snooper_remove(key_snooper_id); } } AtkObject * mai_util_get_root(void) { - if (nsAccessibilityService::gIsShutdown) { + if (nsAccessibilityService::IsShutdown()) { // We've shutdown, try to use gail instead // (to avoid assert in spi_atk_tidy_windows()) if (gail_get_root) return gail_get_root(); return nsnull; } @@ -527,17 +527,17 @@ nsApplicationAccessibleWrap::nsApplicati } nsApplicationAccessibleWrap::~nsApplicationAccessibleWrap() { MAI_LOG_DEBUG(("======Destory AppRootAcc=%p\n", (void*)this)); nsAccessibleWrap::ShutdownAtkObject(); } -nsresult +PRBool nsApplicationAccessibleWrap::Init() { // XXX following code is copied from widget/src/gtk2/nsWindow.cpp // we should put it to somewhere that can be used from both modules // see bug 390761 // check if accessibility enabled/disabled by environment variable PRBool isGnomeATEnabled = PR_FALSE;
--- a/accessible/src/atk/nsApplicationAccessibleWrap.h +++ b/accessible/src/atk/nsApplicationAccessibleWrap.h @@ -50,17 +50,17 @@ public: static void Unload(); static void PreCreate(); public: nsApplicationAccessibleWrap(); virtual ~nsApplicationAccessibleWrap(); // nsAccessNode - virtual nsresult Init(); + virtual PRBool Init(); // return the atk object for app root accessible NS_IMETHOD GetNativeInterface(void **aOutAccessible); // nsApplicationAccessible virtual nsresult AddRootAccessible(nsIAccessible *aRootAccWrap); virtual nsresult RemoveRootAccessible(nsIAccessible *aRootAccWrap); };
--- a/accessible/src/atk/nsDocAccessibleWrap.cpp +++ b/accessible/src/atk/nsDocAccessibleWrap.cpp @@ -38,20 +38,23 @@ * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsMai.h" #include "nsDocAccessibleWrap.h" -//----- nsDocAccessibleWrap ----- +//////////////////////////////////////////////////////////////////////////////// +// nsDocAccessibleWrap +//////////////////////////////////////////////////////////////////////////////// -nsDocAccessibleWrap::nsDocAccessibleWrap(nsIDOMNode *aDOMNode, - nsIWeakReference *aShell): - nsDocAccessible(aDOMNode, aShell), mActivated(PR_FALSE) +nsDocAccessibleWrap:: + nsDocAccessibleWrap(nsIDocument *aDocument, nsIContent *aRootContent, + nsIWeakReference *aShell) : + nsDocAccessible(aDocument, aRootContent, aShell), mActivated(PR_FALSE) { } nsDocAccessibleWrap::~nsDocAccessibleWrap() { }
--- a/accessible/src/atk/nsDocAccessibleWrap.h +++ b/accessible/src/atk/nsDocAccessibleWrap.h @@ -46,15 +46,16 @@ #ifndef _nsDocAccessibleWrap_H_ #define _nsDocAccessibleWrap_H_ #include "nsDocAccessible.h" class nsDocAccessibleWrap: public nsDocAccessible { public: - nsDocAccessibleWrap(nsIDOMNode *aNode, nsIWeakReference *aShell); + nsDocAccessibleWrap(nsIDocument *aDocument, nsIContent *aRootContent, + nsIWeakReference *aShell); virtual ~nsDocAccessibleWrap(); PRBool mActivated; }; #endif
--- a/accessible/src/atk/nsMaiInterfaceComponent.cpp +++ b/accessible/src/atk/nsMaiInterfaceComponent.cpp @@ -73,19 +73,18 @@ refAccessibleAtPointCB(AtkComponent *aCo AtkCoordType aCoordType) { nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aComponent)); if (!accWrap || nsAccUtils::MustPrune(accWrap)) return nsnull; // nsIAccessible getChildAtPoint (x,y) is in screen pixels. if (aCoordType == ATK_XY_WINDOW) { - nsCOMPtr<nsIDOMNode> domNode; - accWrap->GetDOMNode(getter_AddRefs(domNode)); - nsIntPoint winCoords = nsCoreUtils::GetScreenCoordsForWindow(domNode); + nsIntPoint winCoords = + nsCoreUtils::GetScreenCoordsForWindow(accWrap->GetNode()); aAccX += winCoords.x; aAccY += winCoords.y; } nsCOMPtr<nsIAccessible> pointAcc; accWrap->GetChildAtPoint(aAccX, aAccY, getter_AddRefs(pointAcc)); if (!pointAcc) { return nsnull; @@ -114,19 +113,18 @@ getExtentsCB(AtkComponent *aComponent, PRInt32 nsAccX, nsAccY, nsAccWidth, nsAccHeight; // Returned in screen coordinates nsresult rv = accWrap->GetBounds(&nsAccX, &nsAccY, &nsAccWidth, &nsAccHeight); if (NS_FAILED(rv)) return; if (aCoordType == ATK_XY_WINDOW) { - nsCOMPtr<nsIDOMNode> domNode; - accWrap->GetDOMNode(getter_AddRefs(domNode)); - nsIntPoint winCoords = nsCoreUtils::GetScreenCoordsForWindow(domNode); + nsIntPoint winCoords = + nsCoreUtils::GetScreenCoordsForWindow(accWrap->GetNode()); nsAccX -= winCoords.x; nsAccY -= winCoords.y; } *aAccX = nsAccX; *aAccY = nsAccY; *aAccWidth = nsAccWidth; *aAccHeight = nsAccHeight;
--- a/accessible/src/atk/nsMaiInterfaceHypertext.cpp +++ b/accessible/src/atk/nsMaiInterfaceHypertext.cpp @@ -35,17 +35,17 @@ * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsMaiInterfaceHypertext.h" #include "nsIAccessibleDocument.h" -#include "nsAccessNode.h" +#include "nsHyperTextAccessible.h" void hypertextInterfaceInitCB(AtkHypertextIface *aIface) { g_return_if_fail(aIface != NULL); aIface->get_link = getLinkCB; aIface->get_n_links = getLinkCountCB; @@ -54,65 +54,53 @@ hypertextInterfaceInitCB(AtkHypertextIfa AtkHyperlink * getLinkCB(AtkHypertext *aText, gint aLinkIndex) { nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText)); if (!accWrap) return nsnull; - nsCOMPtr<nsIAccessibleHyperText> hyperText; - accWrap->QueryInterface(NS_GET_IID(nsIAccessibleHyperText), - getter_AddRefs(hyperText)); + nsRefPtr<nsHyperTextAccessible> hyperText = do_QueryObject(accWrap); NS_ENSURE_TRUE(hyperText, nsnull); - nsCOMPtr<nsIAccessibleHyperLink> hyperLink; - nsresult rv = hyperText->GetLink(aLinkIndex, getter_AddRefs(hyperLink)); - if (NS_FAILED(rv) || !hyperLink) + nsAccessible* hyperLink = hyperText->GetLinkAt(aLinkIndex); + if (!hyperLink) return nsnull; - nsCOMPtr<nsIAccessible> hyperLinkAcc(do_QueryInterface(hyperLink)); - AtkObject *hyperLinkAtkObj = nsAccessibleWrap::GetAtkObject(hyperLinkAcc); + AtkObject* hyperLinkAtkObj = nsAccessibleWrap::GetAtkObject(hyperLink); nsAccessibleWrap *accChild = GetAccessibleWrap(hyperLinkAtkObj); NS_ENSURE_TRUE(accChild, nsnull); MaiHyperlink *maiHyperlink = accChild->GetMaiHyperlink(); NS_ENSURE_TRUE(maiHyperlink, nsnull); return maiHyperlink->GetAtkHyperlink(); } gint getLinkCountCB(AtkHypertext *aText) { nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText)); if (!accWrap) return -1; - nsCOMPtr<nsIAccessibleHyperText> hyperText; - accWrap->QueryInterface(NS_GET_IID(nsIAccessibleHyperText), - getter_AddRefs(hyperText)); + nsRefPtr<nsHyperTextAccessible> hyperText = do_QueryObject(accWrap); NS_ENSURE_TRUE(hyperText, -1); - PRInt32 count = -1; - nsresult rv = hyperText->GetLinkCount(&count); - NS_ENSURE_SUCCESS(rv, -1); - - return count; + return hyperText->GetLinkCount(); } gint getLinkIndexCB(AtkHypertext *aText, gint aCharIndex) { nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText)); if (!accWrap) return -1; - nsCOMPtr<nsIAccessibleHyperText> hyperText; - accWrap->QueryInterface(NS_GET_IID(nsIAccessibleHyperText), - getter_AddRefs(hyperText)); + nsRefPtr<nsHyperTextAccessible> hyperText = do_QueryObject(accWrap); NS_ENSURE_TRUE(hyperText, -1); PRInt32 index = -1; - nsresult rv = hyperText->GetLinkIndex(aCharIndex, &index); + nsresult rv = hyperText->GetLinkIndexAtOffset(aCharIndex, &index); NS_ENSURE_SUCCESS(rv, -1); return index; }
--- a/accessible/src/atk/nsRootAccessibleWrap.cpp +++ b/accessible/src/atk/nsRootAccessibleWrap.cpp @@ -38,17 +38,17 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsMai.h" #include "nsRootAccessibleWrap.h" nsNativeRootAccessibleWrap::nsNativeRootAccessibleWrap(AtkObject *aAccessible): - nsRootAccessible(nsnull, nsnull) + nsRootAccessible(nsnull, nsnull, nsnull) { g_object_ref(aAccessible); mAtkObject = aAccessible; } nsNativeRootAccessibleWrap::~nsNativeRootAccessibleWrap() { g_object_unref(mAtkObject);
new file mode 100644 --- /dev/null +++ b/accessible/src/base/AccCollector.cpp @@ -0,0 +1,118 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Alexander Surkov <surkov.alexander@gmail.com> (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "AccCollector.h" + +#include "nsAccessible.h" + +//////////////////////////////////////////////////////////////////////////////// +// nsAccCollector +//////////////////////////////////////////////////////////////////////////////// + +AccCollector:: + AccCollector(nsAccessible* aRoot, filters::FilterFuncPtr aFilterFunc) : + mFilterFunc(aFilterFunc), mRoot(aRoot), mRootChildIdx(0) +{ +} + +AccCollector::~AccCollector() +{ +} + +PRUint32 +AccCollector::Count() +{ + EnsureNGetIndex(nsnull); + return mObjects.Length(); +} + +nsAccessible* +AccCollector::GetAccessibleAt(PRUint32 aIndex) +{ + nsAccessible *accessible = mObjects.SafeElementAt(aIndex, nsnull); + if (accessible) + return accessible; + + return EnsureNGetObject(aIndex); +} + +PRInt32 +AccCollector::GetIndexAt(nsAccessible *aAccessible) +{ + PRInt32 index = mObjects.IndexOf(aAccessible); + if (index != -1) + return index; + + return EnsureNGetIndex(aAccessible); +} + +//////////////////////////////////////////////////////////////////////////////// +// nsAccCollector protected + +nsAccessible* +AccCollector::EnsureNGetObject(PRUint32 aIndex) +{ + PRInt32 childCount = mRoot->GetChildCount(); + while (mRootChildIdx < childCount) { + nsAccessible* child = mRoot->GetChildAt(mRootChildIdx++); + if (!mFilterFunc(child)) + continue; + + mObjects.AppendElement(child); + if (mObjects.Length() - 1 == aIndex) + return mObjects[aIndex]; + } + + return nsnull; +} + +PRInt32 +AccCollector::EnsureNGetIndex(nsAccessible* aAccessible) +{ + PRInt32 childCount = mRoot->GetChildCount(); + while (mRootChildIdx < childCount) { + nsAccessible* child = mRoot->GetChildAt(mRootChildIdx++); + if (!mFilterFunc(child)) + continue; + + mObjects.AppendElement(child); + if (child == aAccessible) + return mObjects.Length() - 1; + } + + return -1; +}
new file mode 100644 --- /dev/null +++ b/accessible/src/base/AccCollector.h @@ -0,0 +1,94 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Alexander Surkov <surkov.alexander@gmail.com> (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef AccCollector_h_ +#define AccCollector_h_ + +#include "filters.h" + +#include "nscore.h" +#include "nsTArray.h" + +/** + * Collect accessible children complying with filter function. Provides quick + * access to accessible by index. + */ +class AccCollector +{ +public: + AccCollector(nsAccessible* aRoot, filters::FilterFuncPtr aFilterFunc); + virtual ~AccCollector(); + + /** + * Return accessible count within the collection. + */ + PRUint32 Count(); + + /** + * Return an accessible from the collection at the given index. + */ + nsAccessible* GetAccessibleAt(PRUint32 aIndex); + + /** + * Return index of the given accessible within the collection. + */ + PRInt32 GetIndexAt(nsAccessible* aAccessible); + +protected: + /** + * Ensure accessible at the given index is stored and return it. + */ + nsAccessible* EnsureNGetObject(PRUint32 aIndex); + + /** + * Ensure index for the given accessible is stored and return it. + */ + PRInt32 EnsureNGetIndex(nsAccessible* aAccessible); + + filters::FilterFuncPtr mFilterFunc; + nsAccessible* mRoot; + PRInt32 mRootChildIdx; + + nsTArray<nsAccessible*> mObjects; + +private: + AccCollector(); + AccCollector(const AccCollector&); + AccCollector& operator =(const AccCollector&); +}; + +#endif
rename from accessible/src/base/nsAccIterator.cpp rename to accessible/src/base/AccIterator.cpp --- a/accessible/src/base/nsAccIterator.cpp +++ b/accessible/src/base/AccIterator.cpp @@ -30,40 +30,42 @@ * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -#include "nsAccIterator.h" +#include "AccIterator.h" + +#include "nsAccessible.h" //////////////////////////////////////////////////////////////////////////////// // nsAccIterator -nsAccIterator::nsAccIterator(nsAccessible *aAccessible, - AccIteratorFilterFuncPtr aFilterFunc, - IterationType aIterationType) : +AccIterator::AccIterator(nsAccessible *aAccessible, + filters::FilterFuncPtr aFilterFunc, + IterationType aIterationType) : mFilterFunc(aFilterFunc), mIsDeep(aIterationType != eFlatNav) { mState = new IteratorState(aAccessible); } -nsAccIterator::~nsAccIterator() +AccIterator::~AccIterator() { while (mState) { IteratorState *tmp = mState; mState = tmp->mParentState; delete tmp; } } nsAccessible* -nsAccIterator::GetNext() +AccIterator::GetNext() { while (mState) { nsAccessible *child = mState->mParent->GetChildAt(mState->mIndex++); if (!child) { IteratorState *tmp = mState; mState = mState->mParentState; delete tmp; @@ -81,13 +83,13 @@ nsAccIterator::GetNext() } return nsnull; } //////////////////////////////////////////////////////////////////////////////// // nsAccIterator::IteratorState -nsAccIterator::IteratorState::IteratorState(nsAccessible *aParent, - IteratorState *mParentState) : +AccIterator::IteratorState::IteratorState(nsAccessible *aParent, + IteratorState *mParentState) : mParent(aParent), mIndex(0), mParentState(mParentState) { }
rename from accessible/src/base/nsAccIterator.h rename to accessible/src/base/AccIterator.h --- a/accessible/src/base/nsAccIterator.h +++ b/accessible/src/base/AccIterator.h @@ -33,29 +33,24 @@ * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #ifndef nsAccIterator_h_ #define nsAccIterator_h_ -#include "nsAccessible.h" -#include "nsAccUtils.h" - -/** - * Return true if the traversed accessible complies with filter. - */ -typedef PRBool (*AccIteratorFilterFuncPtr) (nsAccessible *); +#include "filters.h" +#include "nscore.h" /** * Allows to iterate through accessible children or subtree complying with * filter function. */ -class nsAccIterator +class AccIterator { public: /** * Used to define iteration type. */ enum IterationType { /** * Navigation happens through direct children. @@ -64,61 +59,38 @@ public: /** * Navigation through subtree excluding iterator root; if the accessible * complies with filter, iterator ignores its children. */ eTreeNav }; - nsAccIterator(nsAccessible *aRoot, AccIteratorFilterFuncPtr aFilterFunc, - IterationType aIterationType = eFlatNav); - ~nsAccIterator(); + AccIterator(nsAccessible* aRoot, filters::FilterFuncPtr aFilterFunc, + IterationType aIterationType = eFlatNav); + ~AccIterator(); /** * Return next accessible complying with filter function. Return the first * accessible for the first time. */ nsAccessible *GetNext(); - /** - * Predefined filters. - */ - static PRBool GetSelected(nsAccessible *aAccessible) - { - return nsAccUtils::State(aAccessible) & nsIAccessibleStates::STATE_SELECTED; - } - static PRBool GetSelectable(nsAccessible *aAccessible) - { - return nsAccUtils::State(aAccessible) & nsIAccessibleStates::STATE_SELECTABLE; - } - static PRBool GetRow(nsAccessible *aAccessible) - { - return nsAccUtils::Role(aAccessible) == nsIAccessibleRole::ROLE_ROW; - } - static PRBool GetCell(nsAccessible *aAccessible) - { - PRUint32 role = nsAccUtils::Role(aAccessible); - return role == nsIAccessibleRole::ROLE_GRID_CELL || - role == nsIAccessibleRole::ROLE_ROWHEADER || - role == nsIAccessibleRole::ROLE_COLUMNHEADER; - } - private: - nsAccIterator(); - nsAccIterator(const nsAccIterator&); - nsAccIterator& operator =(const nsAccIterator&); + AccIterator(); + AccIterator(const AccIterator&); + AccIterator& operator =(const AccIterator&); struct IteratorState { IteratorState(nsAccessible *aParent, IteratorState *mParentState = nsnull); nsAccessible *mParent; PRInt32 mIndex; IteratorState *mParentState; }; - AccIteratorFilterFuncPtr mFilterFunc; + filters::FilterFuncPtr mFilterFunc; PRBool mIsDeep; IteratorState *mState; }; #endif
--- a/accessible/src/base/Makefile.in +++ b/accessible/src/base/Makefile.in @@ -43,19 +43,22 @@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk MODULE = accessibility LIBRARY_NAME = accessibility_base_s LIBXUL_LIBRARY = 1 CPPSRCS = \ + AccCollector.cpp \ + AccIterator.cpp \ + filters.cpp \ + nsAccDocManager.cpp \ nsAccessNode.cpp \ nsAccEvent.cpp \ - nsAccIterator.cpp \ nsARIAGridAccessible.cpp \ nsARIAMap.cpp \ nsDocAccessible.cpp \ nsOuterDocAccessible.cpp \ nsAccessibilityAtoms.cpp \ nsCoreUtils.cpp \ nsAccUtils.cpp \ nsRelUtils.cpp \
new file mode 100644 --- /dev/null +++ b/accessible/src/base/filters.cpp @@ -0,0 +1,74 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Alexander Surkov <surkov.alexander@gmail.com> (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "filters.h" + +#include "nsAccessible.h" +#include "nsAccUtils.h" + +bool +filters::GetSelected(nsAccessible* aAccessible) +{ + return nsAccUtils::State(aAccessible) & nsIAccessibleStates::STATE_SELECTED; +} + +bool +filters::GetSelectable(nsAccessible* aAccessible) +{ + return nsAccUtils::State(aAccessible) & nsIAccessibleStates::STATE_SELECTABLE; +} + +bool +filters::GetRow(nsAccessible* aAccessible) +{ + return nsAccUtils::Role(aAccessible) == nsIAccessibleRole::ROLE_ROW; +} + +bool +filters::GetCell(nsAccessible* aAccessible) +{ + PRUint32 role = nsAccUtils::Role(aAccessible); + return role == nsIAccessibleRole::ROLE_GRID_CELL || + role == nsIAccessibleRole::ROLE_ROWHEADER || + role == nsIAccessibleRole::ROLE_COLUMNHEADER; +} + +bool +filters::GetEmbeddedObject(nsAccessible* aAccessible) +{ + return nsAccUtils::IsEmbeddedObject(aAccessible); +}
new file mode 100644 --- /dev/null +++ b/accessible/src/base/filters.h @@ -0,0 +1,60 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Alexander Surkov <surkov.alexander@gmail.com> (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef a11yFilters_h_ +#define a11yFilters_h_ + +class nsAccessible; + +/** + * Predefined filters used for nsAccIterator and nsAccCollector. + */ +namespace filters { + + /** + * Return true if the traversed accessible complies with filter. + */ + typedef bool (*FilterFuncPtr) (nsAccessible*); + + bool GetSelected(nsAccessible* aAccessible); + bool GetSelectable(nsAccessible* aAccessible); + bool GetRow(nsAccessible* aAccessible); + bool GetCell(nsAccessible* aAccessible); + bool GetEmbeddedObject(nsAccessible* aAccessible); +} + +#endif
--- a/accessible/src/base/nsARIAGridAccessible.cpp +++ b/accessible/src/base/nsARIAGridAccessible.cpp @@ -33,32 +33,33 @@ * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsARIAGridAccessible.h" -#include "nsAccIterator.h" +#include "AccIterator.h" +#include "nsAccUtils.h" #include "nsIMutableArray.h" #include "nsComponentManagerUtils.h" //////////////////////////////////////////////////////////////////////////////// // nsARIAGridAccessible //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Constructor -nsARIAGridAccessible::nsARIAGridAccessible(nsIDOMNode* aDomNode, - nsIWeakReference* aShell) : - nsAccessibleWrap(aDomNode, aShell) +nsARIAGridAccessible:: + nsARIAGridAccessible(nsIContent *aContent, nsIWeakReference *aShell) : + nsAccessibleWrap(aContent, aShell) { } //////////////////////////////////////////////////////////////////////////////// // nsISupports NS_IMPL_ISUPPORTS_INHERITED1(nsARIAGridAccessible, nsAccessible, @@ -96,20 +97,20 @@ NS_IMETHODIMP nsARIAGridAccessible::GetColumnCount(PRInt32 *acolumnCount) { NS_ENSURE_ARG_POINTER(acolumnCount); *acolumnCount = 0; if (IsDefunct()) return NS_ERROR_FAILURE; - nsAccIterator rowIter(this, nsAccIterator::GetRow); + AccIterator rowIter(this, filters::GetRow); nsAccessible *row = rowIter.GetNext(); - nsAccIterator cellIter(row, nsAccIterator::GetCell); + AccIterator cellIter(row, filters::GetCell); nsAccessible *cell = nsnull; while ((cell = cellIter.GetNext())) (*acolumnCount)++; return NS_OK; } @@ -117,17 +118,17 @@ NS_IMETHODIMP nsARIAGridAccessible::GetRowCount(PRInt32 *arowCount) { NS_ENSURE_ARG_POINTER(arowCount); *arowCount = 0; if (IsDefunct()) return NS_ERROR_FAILURE; - nsAccIterator rowIter(this, nsAccIterator::GetRow); + AccIterator rowIter(this, filters::GetRow); while (rowIter.GetNext()) (*arowCount)++; return NS_OK; } NS_IMETHODIMP nsARIAGridAccessible::GetCellAt(PRInt32 aRowIndex, PRInt32 aColumnIndex, @@ -287,17 +288,17 @@ nsARIAGridAccessible::IsColumnSelected(P NS_ENSURE_ARG_POINTER(aIsSelected); *aIsSelected = PR_FALSE; if (IsDefunct()) return NS_ERROR_FAILURE; NS_ENSURE_ARG(IsValidColumn(aColumn)); - nsAccIterator rowIter(this, nsAccIterator::GetRow); + AccIterator rowIter(this, filters::GetRow); nsAccessible *row = rowIter.GetNext(); if (!row) return NS_OK; do { if (!nsAccUtils::IsARIASelected(row)) { nsAccessible *cell = GetCellInRowAt(row, aColumn); if (!cell) // Do not fail due to wrong markup @@ -320,17 +321,17 @@ nsARIAGridAccessible::IsRowSelected(PRIn if (IsDefunct()) return NS_ERROR_FAILURE; nsAccessible *row = GetRowAt(aRow); NS_ENSURE_ARG(row); if (!nsAccUtils::IsARIASelected(row)) { - nsAccIterator cellIter(row, nsAccIterator::GetCell); + AccIterator cellIter(row, filters::GetCell); nsAccessible *cell = nsnull; while ((cell = cellIter.GetNext())) { if (!nsAccUtils::IsARIASelected(cell)) return NS_OK; } } *aIsSelected = PR_TRUE; @@ -369,26 +370,26 @@ nsARIAGridAccessible::GetSelectedCellCou *aCount = 0; if (IsDefunct()) return NS_ERROR_FAILURE; PRInt32 colCount = 0; GetColumnCount(&colCount); - nsAccIterator rowIter(this, nsAccIterator::GetRow); + AccIterator rowIter(this, filters::GetRow); nsAccessible *row = nsnull; while ((row = rowIter.GetNext())) { if (nsAccUtils::IsARIASelected(row)) { (*aCount) += colCount; continue; } - nsAccIterator cellIter(row, nsAccIterator::GetCell); + AccIterator cellIter(row, filters::GetCell); nsAccessible *cell = nsnull; while ((cell = cellIter.GetNext())) { if (nsAccUtils::IsARIASelected(cell)) (*aCount)++; } } @@ -405,26 +406,26 @@ NS_IMETHODIMP nsARIAGridAccessible::GetSelectedRowCount(PRUint32* aCount) { NS_ENSURE_ARG_POINTER(aCount); *aCount = 0; if (IsDefunct()) return NS_ERROR_FAILURE; - nsAccIterator rowIter(this, nsAccIterator::GetRow); + AccIterator rowIter(this, filters::GetRow); nsAccessible *row = nsnull; while ((row = rowIter.GetNext())) { if (nsAccUtils::IsARIASelected(row)) { (*aCount)++; continue; } - nsAccIterator cellIter(row, nsAccIterator::GetCell); + AccIterator cellIter(row, filters::GetCell); nsAccessible *cell = cellIter.GetNext(); if (!cell) continue; PRBool isRowSelected = PR_TRUE; do { if (!nsAccUtils::IsARIASelected(cell)) { isRowSelected = PR_FALSE; @@ -448,33 +449,33 @@ nsARIAGridAccessible::GetSelectedCells(n if (IsDefunct()) return NS_ERROR_FAILURE; nsresult rv = NS_OK; nsCOMPtr<nsIMutableArray> selCells = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); - nsAccIterator rowIter(this, nsAccIterator::GetRow); + AccIterator rowIter(this, filters::GetRow); nsAccessible *row = nsnull; while (row = rowIter.GetNext()) { - nsAccIterator cellIter(row, nsAccIterator::GetCell); - nsIAccessible *cell = nsnull; + AccIterator cellIter(row, filters::GetCell); + nsAccessible *cell = nsnull; if (nsAccUtils::IsARIASelected(row)) { while (cell = cellIter.GetNext()) - selCells->AppendElement(cell, PR_FALSE); + selCells->AppendElement(static_cast<nsIAccessible *>(cell), PR_FALSE); continue; } while (cell = cellIter.GetNext()) { if (nsAccUtils::IsARIASelected(cell)) - selCells->AppendElement(cell, PR_FALSE); + selCells->AppendElement(static_cast<nsIAccessible *>(cell), PR_FALSE); } } NS_ADDREF(*aCells = selCells); return NS_OK; } NS_IMETHODIMP @@ -492,28 +493,28 @@ nsARIAGridAccessible::GetSelectedCellInd PRInt32 rowCount = 0; GetRowCount(&rowCount); PRInt32 colCount = 0; GetColumnCount(&colCount); nsTArray<PRInt32> selCells(rowCount * colCount); - nsAccIterator rowIter(this, nsAccIterator::GetRow); + AccIterator rowIter(this, filters::GetRow); nsAccessible *row = nsnull; for (PRInt32 rowIdx = 0; row = rowIter.GetNext(); rowIdx++) { if (nsAccUtils::IsARIASelected(row)) { for (PRInt32 colIdx = 0; colIdx < colCount; colIdx++) selCells.AppendElement(rowIdx * colCount + colIdx); continue; } - nsAccIterator cellIter(row, nsAccIterator::GetCell); + AccIterator cellIter(row, filters::GetCell); nsAccessible *cell = nsnull; for (PRInt32 colIdx = 0; cell = cellIter.GetNext(); colIdx++) { if (nsAccUtils::IsARIASelected(cell)) selCells.AppendElement(rowIdx * colCount + colIdx); } } @@ -552,26 +553,26 @@ nsARIAGridAccessible::GetSelectedRowIndi PRInt32 rowCount = 0; GetRowCount(&rowCount); if (!rowCount) return NS_OK; nsTArray<PRInt32> selRows(rowCount); - nsAccIterator rowIter(this, nsAccIterator::GetRow); + AccIterator rowIter(this, filters::GetRow); nsAccessible *row = nsnull; for (PRInt32 rowIdx = 0; row = rowIter.GetNext(); rowIdx++) { if (nsAccUtils::IsARIASelected(row)) { selRows.AppendElement(rowIdx); continue; } - nsAccIterator cellIter(row, nsAccIterator::GetCell); + AccIterator cellIter(row, filters::GetCell); nsAccessible *cell = cellIter.GetNext(); if (!cell) continue; PRBool isRowSelected = PR_TRUE; do { if (!nsAccUtils::IsARIASelected(cell)) { isRowSelected = PR_FALSE; @@ -598,17 +599,17 @@ nsARIAGridAccessible::GetSelectedRowIndi NS_IMETHODIMP nsARIAGridAccessible::SelectRow(PRInt32 aRow) { NS_ENSURE_ARG(IsValidRow(aRow)); if (IsDefunct()) return NS_ERROR_FAILURE; - nsAccIterator rowIter(this, nsAccIterator::GetRow); + AccIterator rowIter(this, filters::GetRow); nsAccessible *row = nsnull; for (PRInt32 rowIdx = 0; row = rowIter.GetNext(); rowIdx++) { nsresult rv = SetARIASelected(row, rowIdx == aRow); NS_ENSURE_SUCCESS(rv, rv); } return NS_OK; @@ -617,17 +618,17 @@ nsARIAGridAccessible::SelectRow(PRInt32 NS_IMETHODIMP nsARIAGridAccessible::SelectColumn(PRInt32 aColumn) { NS_ENSURE_ARG(IsValidColumn(aColumn)); if (IsDefunct()) return NS_ERROR_FAILURE; - nsAccIterator rowIter(this, nsAccIterator::GetRow); + AccIterator rowIter(this, filters::GetRow); nsAccessible *row = nsnull; while ((row = rowIter.GetNext())) { // Unselect all cells in the row. nsresult rv = SetARIASelected(row, PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); // Select cell at the column index. @@ -656,17 +657,17 @@ nsARIAGridAccessible::UnselectRow(PRInt3 NS_IMETHODIMP nsARIAGridAccessible::UnselectColumn(PRInt32 aColumn) { NS_ENSURE_ARG(IsValidColumn(aColumn)); if (IsDefunct()) return NS_ERROR_FAILURE; - nsAccIterator rowIter(this, nsAccIterator::GetRow); + AccIterator rowIter(this, filters::GetRow); nsAccessible *row = nsnull; while ((row = rowIter.GetNext())) { nsAccessible *cell = GetCellInRowAt(row, aColumn); if (cell) { nsresult rv = SetARIASelected(cell, PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); } @@ -725,43 +726,43 @@ nsARIAGridAccessible::IsValidRowNColumn( return aColumn < colCount; } nsAccessible* nsARIAGridAccessible::GetRowAt(PRInt32 aRow) { PRInt32 rowIdx = aRow; - nsAccIterator rowIter(this, nsAccIterator::GetRow); + AccIterator rowIter(this, filters::GetRow); nsAccessible *row = rowIter.GetNext(); while (rowIdx != 0 && (row = rowIter.GetNext())) rowIdx--; return row; } nsAccessible* nsARIAGridAccessible::GetCellInRowAt(nsAccessible *aRow, PRInt32 aColumn) { PRInt32 colIdx = aColumn; - nsAccIterator cellIter(aRow, nsAccIterator::GetCell); + AccIterator cellIter(aRow, filters::GetCell); nsAccessible *cell = cellIter.GetNext(); while (colIdx != 0 && (cell = cellIter.GetNext())) colIdx--; return cell; } nsresult nsARIAGridAccessible::SetARIASelected(nsAccessible *aAccessible, PRBool aIsSelected, PRBool aNotify) { - nsCOMPtr<nsIContent> content(do_QueryInterface(aAccessible->GetDOMNode())); + nsIContent *content = aAccessible->GetContent(); NS_ENSURE_STATE(content); nsresult rv = NS_OK; if (aIsSelected) rv = content->SetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_selected, NS_LITERAL_STRING("true"), aNotify); else rv = content->UnsetAttr(kNameSpaceID_None, @@ -779,17 +780,17 @@ nsARIAGridAccessible::SetARIASelected(ns if (aIsSelected) return NS_OK; PRUint32 role = nsAccUtils::Role(aAccessible); // If the given accessible is row that was unselected then remove // aria-selected from cell accessible. if (role == nsIAccessibleRole::ROLE_ROW) { - nsAccIterator cellIter(aAccessible, nsAccIterator::GetCell); + AccIterator cellIter(aAccessible, filters::GetCell); nsAccessible *cell = nsnull; while ((cell = cellIter.GetNext())) { rv = SetARIASelected(cell, PR_FALSE, PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); } return NS_OK; } @@ -802,17 +803,17 @@ nsARIAGridAccessible::SetARIASelected(ns role == nsIAccessibleRole::ROLE_COLUMNHEADER) { nsAccessible *row = aAccessible->GetParent(); if (nsAccUtils::Role(row) == nsIAccessibleRole::ROLE_ROW && nsAccUtils::IsARIASelected(row)) { rv = SetARIASelected(row, PR_FALSE, PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); - nsAccIterator cellIter(row, nsAccIterator::GetCell); + AccIterator cellIter(row, filters::GetCell); nsAccessible *cell = nsnull; while ((cell = cellIter.GetNext())) { if (cell != aAccessible) { rv = SetARIASelected(cell, PR_TRUE, PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); } } } @@ -828,17 +829,17 @@ nsARIAGridAccessible::GetSelectedColumns NS_ENSURE_ARG_POINTER(acolumnCount); *acolumnCount = 0; if (aColumns) *aColumns = nsnull; if (IsDefunct()) return NS_ERROR_FAILURE; - nsAccIterator rowIter(this, nsAccIterator::GetRow); + AccIterator rowIter(this, filters::GetRow); nsAccessible *row = rowIter.GetNext(); if (!row) return NS_OK; PRInt32 colCount = 0; GetColumnCount(&colCount); if (!colCount) return NS_OK; @@ -851,17 +852,17 @@ nsARIAGridAccessible::GetSelectedColumns isColSelArray[i] = PR_TRUE; do { if (nsAccUtils::IsARIASelected(row)) continue; PRInt32 colIdx = 0; - nsAccIterator cellIter(row, nsAccIterator::GetCell); + AccIterator cellIter(row, filters::GetCell); nsAccessible *cell = nsnull; for (colIdx = 0; cell = cellIter.GetNext(); colIdx++) { if (isColSelArray.SafeElementAt(colIdx, PR_FALSE) && !nsAccUtils::IsARIASelected(cell)) { isColSelArray[colIdx] = PR_FALSE; selColCount--; } } @@ -892,19 +893,19 @@ nsARIAGridAccessible::GetSelectedColumns //////////////////////////////////////////////////////////////////////////////// // nsARIAGridCellAccessible //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Constructor -nsARIAGridCellAccessible::nsARIAGridCellAccessible(nsIDOMNode* aDomNode, - nsIWeakReference* aShell) : - nsHyperTextAccessibleWrap(aDomNode, aShell) +nsARIAGridCellAccessible:: + nsARIAGridCellAccessible(nsIContent *aContent, nsIWeakReference *aShell) : + nsHyperTextAccessibleWrap(aContent, aShell) { } //////////////////////////////////////////////////////////////////////////////// // nsISupports NS_IMPL_ISUPPORTS_INHERITED1(nsARIAGridCellAccessible, nsHyperTextAccessible, @@ -1053,18 +1054,17 @@ NS_IMETHODIMP nsARIAGridCellAccessible::IsSelected(PRBool *aIsSelected) { NS_ENSURE_ARG_POINTER(aIsSelected); *aIsSelected = PR_FALSE; if (IsDefunct()) return NS_ERROR_FAILURE; - nsCOMPtr<nsIAccessible> row; - GetParent(getter_AddRefs(row)); + nsAccessible *row = GetParent(); if (nsAccUtils::Role(row) != nsIAccessibleRole::ROLE_ROW) return NS_OK; if (!nsAccUtils::IsARIASelected(row) && !nsAccUtils::IsARIASelected(this)) return NS_OK; *aIsSelected = PR_TRUE; return NS_OK; @@ -1079,27 +1079,21 @@ nsARIAGridCellAccessible::GetARIAState(P nsresult rv = nsHyperTextAccessibleWrap::GetARIAState(aState, aExtraState); NS_ENSURE_SUCCESS(rv, rv); // Return if the gridcell has aria-selected="true". if (*aState & nsIAccessibleStates::STATE_SELECTED) return NS_OK; // Check aria-selected="true" on the row. - nsCOMPtr<nsIAccessible> row; - GetParent(getter_AddRefs(row)); + nsAccessible *row = GetParent(); if (nsAccUtils::Role(row) != nsIAccessibleRole::ROLE_ROW) return NS_OK; - nsRefPtr<nsAccessible> acc = do_QueryObject(row); - nsCOMPtr<nsIDOMNode> rowNode; - acc->GetDOMNode(getter_AddRefs(rowNode)); - NS_ENSURE_STATE(rowNode); - - nsCOMPtr<nsIContent> rowContent(do_QueryInterface(rowNode)); + nsIContent *rowContent = row->GetContent(); if (nsAccUtils::HasDefinedARIAToken(rowContent, nsAccessibilityAtoms::aria_selected) && !rowContent->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::aria_selected, nsAccessibilityAtoms::_false, eCaseMatters)) { *aState |= nsIAccessibleStates::STATE_SELECTABLE | nsIAccessibleStates::STATE_SELECTED;
--- a/accessible/src/base/nsARIAGridAccessible.h +++ b/accessible/src/base/nsARIAGridAccessible.h @@ -45,17 +45,17 @@ /** * Accessible for ARIA grid and treegrid. */ class nsARIAGridAccessible : public nsAccessibleWrap, public nsIAccessibleTable { public: - nsARIAGridAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell); + nsARIAGridAccessible(nsIContent *aContent, nsIWeakReference *aShell); // nsISupports NS_DECL_ISUPPORTS_INHERITED // nsIAccessibleTable NS_DECL_NSIACCESSIBLETABLE protected: @@ -105,17 +105,17 @@ protected: /** * Accessible for ARIA gridcell and rowheader/columnheader. */ class nsARIAGridCellAccessible : public nsHyperTextAccessibleWrap, public nsIAccessibleTableCell { public: - nsARIAGridCellAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell); + nsARIAGridCellAccessible(nsIContent *aContent, nsIWeakReference *aShell); // nsISupports NS_DECL_ISUPPORTS_INHERITED // nsIAccessibleTableCell NS_DECL_NSIACCESSIBLETABLECELL // nsAccessible
--- a/accessible/src/base/nsAccCache.h +++ b/accessible/src/base/nsAccCache.h @@ -37,32 +37,32 @@ * ***** END LICENSE BLOCK ***** */ #ifndef _nsAccCache_H_ #define _nsAccCache_H_ #include "nsRefPtrHashtable.h" #include "nsCycleCollectionParticipant.h" -class nsIAccessNode; +class nsIAccessible; //////////////////////////////////////////////////////////////////////////////// // Accessible cache utils //////////////////////////////////////////////////////////////////////////////// /** * Shutdown and removes the accessible from cache. */ template <class T> static PLDHashOperator -ClearCacheEntry(const void* aKey, nsRefPtr<T>& aAccessNode, void* aUserArg) +ClearCacheEntry(const void* aKey, nsRefPtr<T>& aAccessible, void* aUserArg) { - NS_ASSERTION(aAccessNode, "Calling ClearCacheEntry with a NULL pointer!"); - if (aAccessNode) - aAccessNode->Shutdown(); + NS_ASSERTION(aAccessible, "Calling ClearCacheEntry with a NULL pointer!"); + if (aAccessible) + aAccessible->Shutdown(); return PL_DHASH_REMOVE; } /** * Clear the cache and shutdown the accessibles. */ template <class T> @@ -72,25 +72,25 @@ ClearCache(nsRefPtrHashtable<nsVoidPtrHa aCache.Enumerate(ClearCacheEntry<T>, nsnull); } /** * Traverse the accessible cache entry for cycle collector. */ template <class T> static PLDHashOperator -CycleCollectorTraverseCacheEntry(const void *aKey, T *aAccessNode, +CycleCollectorTraverseCacheEntry(const void *aKey, T *aAccessible, void *aUserArg) { nsCycleCollectionTraversalCallback *cb = static_cast<nsCycleCollectionTraversalCallback*>(aUserArg); NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "accessible cache entry"); - nsISupports *supports = static_cast<nsIAccessNode*>(aAccessNode); + nsISupports *supports = static_cast<nsIAccessible*>(aAccessible); cb->NoteXPCOMChild(supports); return PL_DHASH_NEXT; } /** * Traverse the accessible cache for cycle collector. */ template <class T>
new file mode 100644 --- /dev/null +++ b/accessible/src/base/nsAccDocManager.cpp @@ -0,0 +1,578 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Alexander Surkov <surkov.alexander@gmail.com> (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsAccDocManager.h" + +#include "nsAccessibilityService.h" +#include "nsAccUtils.h" +#include "nsOuterDocAccessible.h" +#include "nsRootAccessibleWrap.h" + +#include "nsCURILoader.h" +#include "nsDocShellLoadTypes.h" +#include "nsIChannel.h" +#include "nsIContentViewer.h" +#include "nsIDOMDocument.h" +#include "nsIEventListenerManager.h" +#include "nsIDOMEventTarget.h" +#include "nsIDOMWindow.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsIWebNavigation.h" +#include "nsServiceManagerUtils.h" + +//////////////////////////////////////////////////////////////////////////////// +// nsAccDocManager +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +// nsAccDocManager public + +nsDocAccessible* +nsAccDocManager::GetDocAccessible(nsIDocument *aDocument) +{ + if (!aDocument) + return nsnull; + + nsDocAccessible *docAcc = + mDocAccessibleCache.GetWeak(static_cast<void*>(aDocument)); + if (docAcc) + return docAcc; + + return CreateDocOrRootAccessible(aDocument); +} + +nsAccessible* +nsAccDocManager::FindAccessibleInCache(void *aUniqueID) const +{ + nsSearchAccessibleInCacheArg arg; + arg.mUniqueID = aUniqueID; + + mDocAccessibleCache.EnumerateRead(SearchAccessibleInDocCache, + static_cast<void*>(&arg)); + + return arg.mAccessible; +} + +void +nsAccDocManager::ShutdownDocAccessiblesInTree(nsIDocument *aDocument) +{ + nsCOMPtr<nsISupports> container = aDocument->GetContainer(); + nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(container); + ShutdownDocAccessiblesInTree(treeItem, aDocument); +} + + +//////////////////////////////////////////////////////////////////////////////// +// nsAccDocManager protected + +PRBool +nsAccDocManager::Init() +{ + mDocAccessibleCache.Init(4); + + nsCOMPtr<nsIWebProgress> progress = + do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID); + + if (!progress) + return PR_FALSE; + + progress->AddProgressListener(static_cast<nsIWebProgressListener*>(this), + nsIWebProgress::NOTIFY_STATE_DOCUMENT); + + return PR_TRUE; +} + +void +nsAccDocManager::Shutdown() +{ + nsCOMPtr<nsIWebProgress> progress = + do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID); + + if (progress) + progress->RemoveProgressListener(static_cast<nsIWebProgressListener*>(this)); + + ClearDocCache(); +} + +void +nsAccDocManager::ShutdownDocAccessible(nsIDocument *aDocument) +{ + nsDocAccessible* docAccessible = + mDocAccessibleCache.GetWeak(static_cast<void*>(aDocument)); + if (!docAccessible) + return; + + // We're allowed to not remove listeners when accessible document is shutdown + // since we don't keep strong reference on chrome event target and listeners + // are removed automatically when chrome event target goes away. + + docAccessible->Shutdown(); + mDocAccessibleCache.Remove(static_cast<void*>(aDocument)); +} + +//////////////////////////////////////////////////////////////////////////////// +// nsISupports + +NS_IMPL_THREADSAFE_ISUPPORTS3(nsAccDocManager, + nsIWebProgressListener, + nsIDOMEventListener, + nsISupportsWeakReference) + +//////////////////////////////////////////////////////////////////////////////// +// nsIWebProgressListener + +NS_IMETHODIMP +nsAccDocManager::OnStateChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, PRUint32 aStateFlags, + nsresult aStatus) +{ + NS_ASSERTION(aStateFlags & STATE_IS_DOCUMENT, "Other notifications excluded"); + + if (nsAccessibilityService::IsShutdown() || !aWebProgress || + (aStateFlags & (STATE_START | STATE_STOP)) == 0) + return NS_OK; + + nsCOMPtr<nsIDOMWindow> DOMWindow; + aWebProgress->GetDOMWindow(getter_AddRefs(DOMWindow)); + NS_ENSURE_STATE(DOMWindow); + + nsCOMPtr<nsIDOMDocument> DOMDocument; + DOMWindow->GetDocument(getter_AddRefs(DOMDocument)); + NS_ENSURE_STATE(DOMDocument); + + nsCOMPtr<nsIDocument> document(do_QueryInterface(DOMDocument)); + + // Document was loaded. + if (aStateFlags & STATE_STOP) { + NS_LOG_ACCDOCLOAD("document loaded", aWebProgress, aRequest, aStateFlags) + + // Figure out an event type to notify the document has been loaded. + PRUint32 eventType = nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED; + + // Some XUL documents get start state and then stop state with failure + // status when everything is ok. Fire document load complete event in this + // case. + if (NS_SUCCEEDED(aStatus) || !nsCoreUtils::IsContentDocument(document)) + eventType = nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE; + + // If end consumer has been retargeted for loaded content then do not fire + // any event because it means no new document has been loaded, for example, + // it happens when user clicks on file link. + if (aRequest) { + PRUint32 loadFlags = 0; + aRequest->GetLoadFlags(&loadFlags); + if (loadFlags & nsIChannel::LOAD_RETARGETED_DOCUMENT_URI) + eventType = 0; + } + + HandleDOMDocumentLoad(document, eventType); + return NS_OK; + } + + // Document loading was started. + NS_LOG_ACCDOCLOAD("start document loading", aWebProgress, aRequest, + aStateFlags) + + if (!IsEventTargetDocument(document)) + return NS_OK; + + nsDocAccessible *docAcc = + mDocAccessibleCache.GetWeak(static_cast<void*>(document)); + if (!docAcc) + return NS_OK; + + nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(DOMWindow)); + nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(webNav)); + NS_ENSURE_STATE(docShell); + + // Fire reload and state busy events on existing document accessible while + // event from user input flag can be calculated properly and accessible + // is alive. When new document gets loaded then this one is destroyed. + PRUint32 loadType; + docShell->GetLoadType(&loadType); + if (loadType == LOAD_RELOAD_NORMAL || + loadType == LOAD_RELOAD_BYPASS_CACHE || + loadType == LOAD_RELOAD_BYPASS_PROXY || + loadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE) { + + // Fire reload event. + nsRefPtr<nsAccEvent> reloadEvent = + new nsAccEvent(nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD, docAcc); + nsEventShell::FireEvent(reloadEvent); + } + + // Fire state busy change event. Use delayed event since we don't care + // actually if event isn't delivered when the document goes away like a shot. + nsRefPtr<nsAccEvent> stateEvent = + new nsAccStateChangeEvent(document, nsIAccessibleStates::STATE_BUSY, + PR_FALSE, PR_TRUE); + docAcc->FireDelayedAccessibleEvent(stateEvent); + + return NS_OK; +} + +NS_IMETHODIMP +nsAccDocManager::OnProgressChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, + PRInt32 aCurSelfProgress, + PRInt32 aMaxSelfProgress, + PRInt32 aCurTotalProgress, + PRInt32 aMaxTotalProgress) +{ + NS_NOTREACHED("notification excluded in AddProgressListener(...)"); + return NS_OK; +} + +NS_IMETHODIMP +nsAccDocManager::OnLocationChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, nsIURI *aLocation) +{ + NS_NOTREACHED("notification excluded in AddProgressListener(...)"); + return NS_OK; +} + +NS_IMETHODIMP +nsAccDocManager::OnStatusChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, nsresult aStatus, + const PRUnichar *aMessage) +{ + NS_NOTREACHED("notification excluded in AddProgressListener(...)"); + return NS_OK; +} + +NS_IMETHODIMP +nsAccDocManager::OnSecurityChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, + PRUint32 aState) +{ + NS_NOTREACHED("notification excluded in AddProgressListener(...)"); + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////////////// +// nsIDOMEventListener + +NS_IMETHODIMP +nsAccDocManager::HandleEvent(nsIDOMEvent *aEvent) +{ + nsAutoString type; + aEvent->GetType(type); + + nsCOMPtr<nsIDOMEventTarget> target; + aEvent->GetTarget(getter_AddRefs(target)); + + nsCOMPtr<nsIDocument> document(do_QueryInterface(target)); + NS_ASSERTION(document, "pagehide or DOMContentLoaded for non document!"); + if (!document) + return NS_OK; + + if (type.EqualsLiteral("pagehide")) { + // 'pagehide' event is registered on every DOM document we create an + // accessible for, process the event for the target. This document + // accessible and all its sub document accessible are shutdown as result of + // processing. + + NS_LOG_ACCDOCDESTROY("received 'pagehide' event", document) + + // Ignore 'pagehide' on temporary documents since we ignore them entirely in + // accessibility. + if (document->IsInitialDocument()) + return NS_OK; + + // Shutdown this one and sub document accessibles. + ShutdownDocAccessiblesInTree(document); + return NS_OK; + } + + // XXX: handle error pages loading separately since they get neither + // webprogress notifications nor 'pageshow' event. + if (type.EqualsLiteral("DOMContentLoaded") && + nsCoreUtils::IsErrorPage(document)) { + NS_LOG_ACCDOCLOAD2("handled 'DOMContentLoaded' event", document) + HandleDOMDocumentLoad(document, + nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE, + PR_TRUE); + } + + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////////////// +// nsAccDocManager private + +void +nsAccDocManager::HandleDOMDocumentLoad(nsIDocument *aDocument, + PRUint32 aLoadEventType, + PRBool aMarkAsLoaded) +{ + // Document accessible can be created before we were notified the DOM document + // was loaded completely. However if it's not created yet then create it. + nsDocAccessible *docAcc = + mDocAccessibleCache.GetWeak(static_cast<void*>(aDocument)); + + if (!docAcc) { + docAcc = CreateDocOrRootAccessible(aDocument); + NS_ASSERTION(docAcc, "Can't create document accessible!"); + if (!docAcc) + return; + } + + if (aMarkAsLoaded) + docAcc->MarkAsLoaded(); + + // Do not fire document complete/stop events for root chrome document + // accessibles and for frame/iframe documents because + // a) screen readers start working on focus event in the case of root chrome + // documents + // b) document load event on sub documents causes screen readers to act is if + // entire page is reloaded. + if (!IsEventTargetDocument(aDocument)) { + // XXX: AT doesn't update their virtual buffer once frame is loaded and it + // has dynamic content added after frame load. There's something wrong how + // we handle this changes. + if (!nsCoreUtils::IsRootDocument(aDocument)) { + docAcc->InvalidateCacheSubtree(nsnull, + nsIAccessibilityService::NODE_SIGNIFICANT_CHANGE); + } + return; + } + + // Fire complete/load stopped if the load event type is given. + if (aLoadEventType) { + nsRefPtr<nsAccEvent> loadEvent = new nsAccEvent(aLoadEventType, aDocument); + docAcc->FireDelayedAccessibleEvent(loadEvent); + } + + // Fire busy state change event. + nsRefPtr<nsAccEvent> stateEvent = + new nsAccStateChangeEvent(aDocument, nsIAccessibleStates::STATE_BUSY, + PR_FALSE, PR_FALSE); + docAcc->FireDelayedAccessibleEvent(stateEvent); +} + +PRBool +nsAccDocManager::IsEventTargetDocument(nsIDocument *aDocument) const +{ + nsCOMPtr<nsISupports> container = aDocument->GetContainer(); + nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = + do_QueryInterface(container); + NS_ASSERTION(docShellTreeItem, "No document shell for document!"); + + nsCOMPtr<nsIDocShellTreeItem> parentTreeItem; + docShellTreeItem->GetParent(getter_AddRefs(parentTreeItem)); + + // It's not a root document. + if (parentTreeItem) { + nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot; + docShellTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot)); + + // It's not a sub document, i.e. a frame or iframe. + return (sameTypeRoot == docShellTreeItem); + } + + // It's not chrome root document. + PRInt32 contentType; + docShellTreeItem->GetItemType(&contentType); + return (contentType == nsIDocShellTreeItem::typeContent); +} + +void +nsAccDocManager::AddListeners(nsIDocument *aDocument, + PRBool aAddDOMContentLoadedListener) +{ + nsPIDOMWindow *window = aDocument->GetWindow(); + nsPIDOMEventTarget *target = window->GetChromeEventHandler(); + nsIEventListenerManager* elm = target->GetListenerManager(PR_TRUE); + elm->AddEventListenerByType(this, NS_LITERAL_STRING("pagehide"), + NS_EVENT_FLAG_CAPTURE, nsnull); + + NS_LOG_ACCDOCCREATE_TEXT(" added 'pagehide' listener") + + if (aAddDOMContentLoadedListener) { + elm->AddEventListenerByType(this, NS_LITERAL_STRING("DOMContentLoaded"), + NS_EVENT_FLAG_CAPTURE, nsnull); + NS_LOG_ACCDOCCREATE_TEXT(" added 'DOMContentLoaded' listener") + } +} + +nsDocAccessible* +nsAccDocManager::CreateDocOrRootAccessible(nsIDocument *aDocument) +{ + // Ignore temporary, hiding and svg resource documents. + if (aDocument->IsInitialDocument() || !aDocument->IsVisible() || + aDocument->GetDisplayDocument()) + return nsnull; + + // Ignore documents without presshell. + nsIPresShell *presShell = aDocument->GetPrimaryShell(); + if (!presShell) + return nsnull; + + // Do not create document accessible until role content is loaded, otherwise + // we get accessible document with wrong role. + nsIContent *rootElm = nsCoreUtils::GetRoleContent(aDocument); + if (!rootElm) + return nsnull; + + PRBool isRootDoc = nsCoreUtils::IsRootDocument(aDocument); + + // Ensure the document container node is accessible, otherwise do not create + // document accessible. + nsAccessible *outerDocAcc = nsnull; + if (!isRootDoc) { + nsIDocument* parentDoc = aDocument->GetParentDocument(); + if (!parentDoc) + return nsnull; + + nsIContent* ownerContent = parentDoc->FindContentForSubDocument(aDocument); + if (!ownerContent) + return nsnull; + + // XXXaaronl: ideally we would traverse the presshell chain. Since there's + // no easy way to do that, we cheat and use the document hierarchy. + // GetAccessible() is bad because it doesn't support our concept of multiple + // presshells per doc. It should be changed to use + // GetAccessibleInWeakShell(). + outerDocAcc = GetAccService()->GetAccessible(ownerContent); + if (!outerDocAcc) + return nsnull; + } + + nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell)); + + // We only create root accessibles for the true root, otherwise create a + // doc accessible. + nsDocAccessible *docAcc = isRootDoc ? + new nsRootAccessibleWrap(aDocument, rootElm, weakShell) : + new nsDocAccessibleWrap(aDocument, rootElm, weakShell); + + if (!docAcc) + return nsnull; + + // Cache and addref document accessible. + if (!mDocAccessibleCache.Put(static_cast<void*>(aDocument), docAcc)) { + delete docAcc; + return nsnull; + } + + // XXX: ideally we should initialize an accessible and then put it into tree, + // also this code should be shared between doc and root accessibles. + if (outerDocAcc) { + // Root document accessible doesn't have associated outerdoc accessible, it + // adds itself to application accessible instead. + outerDocAcc->AppendChild(docAcc); + } + + if (!GetAccService()->InitAccessible(docAcc, + nsAccUtils::GetRoleMapEntry(aDocument))) { + mDocAccessibleCache.Remove(static_cast<void*>(aDocument)); + return nsnull; + } + + NS_LOG_ACCDOCCREATE("document creation finished", aDocument) + + AddListeners(aDocument, isRootDoc); + return docAcc; +} + +void +nsAccDocManager::ShutdownDocAccessiblesInTree(nsIDocShellTreeItem *aTreeItem, + nsIDocument *aDocument) +{ + nsCOMPtr<nsIDocShellTreeNode> treeNode(do_QueryInterface(aTreeItem)); + + if (treeNode) { + PRInt32 subDocumentsCount = 0; + treeNode->GetChildCount(&subDocumentsCount); + for (PRInt32 idx = 0; idx < subDocumentsCount; idx++) { + nsCOMPtr<nsIDocShellTreeItem> treeItemChild; + treeNode->GetChildAt(idx, getter_AddRefs(treeItemChild)); + NS_ASSERTION(treeItemChild, "No tree item when there should be"); + if (!treeItemChild) + continue; + + nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(treeItemChild)); + nsCOMPtr<nsIContentViewer> contentViewer; + docShell->GetContentViewer(getter_AddRefs(contentViewer)); + if (!contentViewer) + continue; + + ShutdownDocAccessiblesInTree(treeItemChild, contentViewer->GetDocument()); + } + } + + ShutdownDocAccessible(aDocument); +} + +//////////////////////////////////////////////////////////////////////////////// +// nsAccDocManager static + +PLDHashOperator +nsAccDocManager::ClearDocCacheEntry(const void* aKey, + nsRefPtr<nsDocAccessible>& aDocAccessible, + void* aUserArg) +{ + nsAccDocManager *accDocMgr = static_cast<nsAccDocManager*>(aUserArg); + + NS_ASSERTION(aDocAccessible, + "Calling ClearDocCacheEntry with a NULL pointer!"); + + if (aDocAccessible) + aDocAccessible->Shutdown(); + + return PL_DHASH_REMOVE; +} + +PLDHashOperator +nsAccDocManager::SearchAccessibleInDocCache(const void* aKey, + nsDocAccessible* aDocAccessible, + void* aUserArg) +{ + NS_ASSERTION(aDocAccessible, + "No doc accessible for the object in doc accessible cache!"); + + if (aDocAccessible) { + nsSearchAccessibleInCacheArg* arg = + static_cast<nsSearchAccessibleInCacheArg*>(aUserArg); + arg->mAccessible = aDocAccessible->GetCachedAccessible(arg->mUniqueID); + if (arg->mAccessible) + return PL_DHASH_STOP; + } + + return PL_DHASH_NEXT; +}
new file mode 100644 --- /dev/null +++ b/accessible/src/base/nsAccDocManager.h @@ -0,0 +1,581 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Alexander Surkov <surkov.alexander@gmail.com> (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsAccDocManager_h_ +#define nsAccDocManager_h_ + +#include "nsAccessible.h" + +#include "nsIDocument.h" +#include "nsIDOMEventListener.h" +#include "nsIWebProgress.h" +#include "nsIWebProgressListener.h" +#include "nsWeakReference.h" + +class nsDocAccessible; + +//#define DEBUG_ACCDOCMGR + +/** + * Manage the document accessible life cycle. + */ +class nsAccDocManager : public nsIWebProgressListener, + public nsIDOMEventListener, + public nsSupportsWeakReference +{ +public: + virtual ~nsAccDocManager() { }; + + NS_DECL_ISUPPORTS + NS_DECL_NSIWEBPROGRESSLISTENER + NS_DECL_NSIDOMEVENTLISTENER + + /** + * Return document accessible for the given DOM node. + */ + nsDocAccessible *GetDocAccessible(nsIDocument *aDocument); + + /** + * Search through all document accessibles for an accessible with the given + * unique id. + */ + nsAccessible *FindAccessibleInCache(void *aUniqueID) const; + + /** + * Shutdown document accessibles in the tree starting from the given one. + * + * @param aDocument [in] the DOM document of start document accessible + */ + void ShutdownDocAccessiblesInTree(nsIDocument *aDocument); + + /** + * Return document accessible from the cache. Convenient method for testing. + */ + inline nsDocAccessible* GetDocAccessibleFromCache(nsIDocument* aDocument) const + { + return mDocAccessibleCache.GetWeak(static_cast<void*>(aDocument)); + } + +protected: + nsAccDocManager() { }; + + /** + * Initialize the manager. + */ + PRBool Init(); + + /** + * Shutdown the manager. + */ + void Shutdown(); + + /** + * Shutdown the document accessible. + */ + void ShutdownDocAccessible(nsIDocument* aDocument); + +private: + nsAccDocManager(const nsAccDocManager&); + nsAccDocManager& operator =(const nsAccDocManager&); + +private: + /** + * Create an accessible document if it was't created and fire accessibility + * events if needed. + * + * @param aDocument [in] loaded DOM document + * @param aLoadEventType [in] specifies the event type to fire load event, + * if 0 then no event is fired + * @param aMarkAsLoaded [in] indicates whether we should mark forcedly + * an accessible document as loaded (used for error + * pages only which do not get 'pageshow' event) + */ + void HandleDOMDocumentLoad(nsIDocument *aDocument, + PRUint32 aLoadEventType, + PRBool aMarkAsLoaded = PR_FALSE); + + /** + * Return true if accessibility events accompanying document accessible + * loading should be fired. + * + * The rules are: do not fire events for root chrome document accessibles and + * for sub document accessibles (like HTML frame of iframe) of the loading + * document accessible. + * + * XXX: in general AT expect events for document accessible loading into + * tabbrowser, events from other document accessibles may break AT. We need to + * figure out what AT wants to know about loading page (for example, some of + * them have separate processing of iframe documents on the page and therefore + * they need a way to distinguish sub documents from page document). Ideally + * we should make events firing for any loaded document and provide additional + * info AT are needing. + */ + PRBool IsEventTargetDocument(nsIDocument *aDocument) const; + + /** + * Add 'pagehide' and 'DOMContentLoaded' event listeners. + */ + void AddListeners(nsIDocument *aDocument, PRBool aAddPageShowListener); + + /** + * Create document or root accessible. + */ + nsDocAccessible *CreateDocOrRootAccessible(nsIDocument *aDocument); + + /** + * Shutdown document accessibles in the tree starting from given tree item. + */ + void ShutdownDocAccessiblesInTree(nsIDocShellTreeItem *aTreeItem, + nsIDocument *aDocument); + + typedef nsRefPtrHashtable<nsVoidPtrHashKey, nsDocAccessible> + nsDocAccessibleHashtable; + + /** + * Shutdown and remove the document accessible from cache. + */ + static PLDHashOperator + ClearDocCacheEntry(const void* aKey, + nsRefPtr<nsDocAccessible>& aDocAccessible, + void* aUserArg); + + /** + * Clear the cache and shutdown the document accessibles. + */ + void ClearDocCache() + { + mDocAccessibleCache.Enumerate(ClearDocCacheEntry, static_cast<void*>(this)); + } + + struct nsSearchAccessibleInCacheArg + { + nsAccessible *mAccessible; + void *mUniqueID; + }; + + static PLDHashOperator + SearchAccessibleInDocCache(const void* aKey, + nsDocAccessible* aDocAccessible, + void* aUserArg); + + nsDocAccessibleHashtable mDocAccessibleCache; +}; + +/** + * nsAccDocManager debugging macros. + */ +#ifdef DEBUG_ACCDOCMGR + +// Enable these to log accessible document loading, creation or destruction. +#define DEBUG_ACCDOCMGR_DOCLOAD +#define DEBUG_ACCDOCMGR_DOCCREATE +#define DEBUG_ACCDOCMGR_DOCDESTROY + +// Common macros, do not use directly. +#define NS_LOG_ACCDOC_ADDRESS(aDocument, aDocAcc) \ + printf("DOM id: %p, acc id: %p", aDocument, aDocAcc); + +#define NS_LOG_ACCDOC_URI(aDocument) \ + nsIURI *uri = aDocument->GetDocumentURI(); \ + nsCAutoString spec; \ + uri->GetSpec(spec); \ + printf("uri: %s", spec); + +#define NS_LOG_ACCDOC_TYPE(aDocument) \ + PRBool isContent = nsCoreUtils::IsContentDocument(aDocument); \ + printf("%s document", (isContent ? "content" : "chrome")); + +#define NS_LOG_ACCDOC_SHELLSTATE(aDocument) \ + nsCOMPtr<nsISupports> container = aDocument->GetContainer(); \ + nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container); \ + PRUint32 busyFlags = nsIDocShell::BUSY_FLAGS_NONE; \ + docShell->GetBusyFlags(&busyFlags); \ + nsCAutoString docShellBusy; \ + if (busyFlags == nsIDocShell::BUSY_FLAGS_NONE) \ + docShellBusy.AppendLiteral("'none'"); \ + if (busyFlags & nsIDocShell::BUSY_FLAGS_BUSY) \ + docShellBusy.AppendLiteral("'busy'"); \ + if (busyFlags & nsIDocShell::BUSY_FLAGS_BEFORE_PAGE_LOAD) \ + docShellBusy.AppendLiteral(", 'before page load'"); \ + if (busyFlags & nsIDocShell::BUSY_FLAGS_PAGE_LOADING) \ + docShellBusy.AppendLiteral(", 'page loading'"); \ + printf("docshell busy: %s", docShellBusy.get()); + +#define NS_LOG_ACCDOC_DOCSTATES(aDocument) \ + const char *docState = 0; \ + nsIDocument::ReadyState docStateFlag = aDocument->GetReadyStateEnum(); \ + switch (docStateFlag) { \ + case nsIDocument::READYSTATE_UNINITIALIZED: \ + docState = "uninitialized"; \ + break; \ + case nsIDocument::READYSTATE_LOADING: \ + docState = "loading"; \ + break; \ + case nsIDocument::READYSTATE_INTERACTIVE: \ + docState = "interactive"; \ + break; \ + case nsIDocument::READYSTATE_COMPLETE: \ + docState = "complete"; \ + break; \ + } \ + printf("doc state: %s", docState); \ + printf(", %sinitial", aDocument->IsInitialDocument() ? "" : "not "); \ + printf(", %sshowing", aDocument->IsShowing() ? "" : "not "); \ + printf(", %svisible", aDocument->IsVisible() ? "" : "not "); \ + printf(", %sactive", aDocument->IsActive() ? "" : "not "); + +#define NS_LOG_ACCDOC_DOCPRESSHELL(aDocument) \ + nsIPresShell *ps = aDocument->GetPrimaryShell(); \ + printf("presshell: %p", ps); \ + nsIScrollableFrame *sf = ps ? \ + ps->GetRootScrollFrameAsScrollableExternal() : nsnull; \ + printf(", root scroll frame: %p", sf); + +#define NS_LOG_ACCDOC_DOCLOADGROUP(aDocument) \ + nsCOMPtr<nsILoadGroup> loadGroup = aDocument->GetDocumentLoadGroup(); \ + printf("load group: %p", loadGroup); + +#define NS_LOG_ACCDOC_DOCPARENT(aDocument) \ + nsIDocument *parentDoc = aDocument->GetParentDocument(); \ + printf("parent id: %p", parentDoc); \ + if (parentDoc) { \ + printf("\n parent "); \ + NS_LOG_ACCDOC_URI(parentDoc) \ + printf("\n"); \ + } + +#define NS_LOG_ACCDOC_SHELLLOADTYPE(aDocShell) \ + { \ + printf("load type: "); \ + PRUint32 loadType; \ + docShell->GetLoadType(&loadType); \ + switch (loadType) { \ + case LOAD_NORMAL: \ + printf("normal; "); \ + break; \ + case LOAD_NORMAL_REPLACE: \ + printf("normal replace; "); \ + break; \ + case LOAD_NORMAL_EXTERNAL: \ + printf("normal external; "); \ + break; \ + case LOAD_HISTORY: \ + printf("history; "); \ + break; \ + case LOAD_NORMAL_BYPASS_CACHE: \ + printf("normal bypass cache; "); \ + break; \ + case LOAD_NORMAL_BYPASS_PROXY: \ + printf("normal bypass proxy; "); \ + break; \ + case LOAD_NORMAL_BYPASS_PROXY_AND_CACHE: \ + printf("normal bypass proxy and cache; "); \ + break; \ + case LOAD_RELOAD_NORMAL: \ + printf("reload normal; "); \ + break; \ + case LOAD_RELOAD_BYPASS_CACHE: \ + printf("reload bypass cache; "); \ + break; \ + case LOAD_RELOAD_BYPASS_PROXY: \ + printf("reload bypass proxy; "); \ + break; \ + case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE: \ + printf("reload bypass proxy and cache; "); \ + break; \ + case LOAD_LINK: \ + printf("link; "); \ + break; \ + case LOAD_REFRESH: \ + printf("refresh; "); \ + break; \ + case LOAD_RELOAD_CHARSET_CHANGE: \ + printf("reload charset change; "); \ + break; \ + case LOAD_BYPASS_HISTORY: \ + printf("bypass history; "); \ + break; \ + case LOAD_STOP_CONTENT: \ + printf("stop content; "); \ + break; \ + case LOAD_STOP_CONTENT_AND_REPLACE: \ + printf("stop content and replace; "); \ + break; \ + case LOAD_PUSHSTATE: \ + printf("load pushstate; "); \ + break; \ + case LOAD_ERROR_PAGE: \ + printf("error page;"); \ + break; \ + default: \ + printf("unknown"); \ + } \ + } + +#define NS_LOG_ACCDOC_DOCINFO_BEGIN \ + printf(" {\n"); +#define NS_LOG_ACCDOC_DOCINFO_BODY(aDocument, aDocAcc) \ + { \ + printf(" "); \ + NS_LOG_ACCDOC_ADDRESS(aDocument, aDocAcc) \ + printf("\n "); \ + NS_LOG_ACCDOC_URI(aDocument) \ + printf("\n "); \ + NS_LOG_ACCDOC_SHELLSTATE(aDocument) \ + printf("; "); \ + NS_LOG_ACCDOC_TYPE(aDocument) \ + printf("\n "); \ + NS_LOG_ACCDOC_DOCSTATES(aDocument) \ + printf("\n "); \ + NS_LOG_ACCDOC_DOCPRESSHELL(aDocument) \ + printf("\n "); \ + NS_LOG_ACCDOC_DOCLOADGROUP(aDocument) \ + printf(", "); \ + NS_LOG_ACCDOC_DOCPARENT(aDocument) \ + printf("\n"); \ + } +#define NS_LOG_ACCDOC_DOCINFO_END \ + printf(" }\n"); + +#define NS_LOG_ACCDOC_DOCINFO(aDocument, aDocAcc) \ + NS_LOG_ACCDOC_DOCINFO_BEGIN \ + NS_LOG_ACCDOC_DOCINFO_BODY(aDocument, aDocAcc) \ + NS_LOG_ACCDOC_DOCINFO_END + +#define NS_GET_ACCDOC_EVENTTYPE(aEvent) \ + nsCAutoString strEventType; \ + PRUint32 type = aEvent->GetEventType(); \ + if (type == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED) { \ + strEventType.AssignLiteral("load stopped"); \ + } else if (type == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE) { \ + strEventType.AssignLiteral("load complete"); \ + } else if (type == nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD) { \ + strEventType.AssignLiteral("reload"); \ + } else if (type == nsIAccessibleEvent::EVENT_STATE_CHANGE) { \ + nsAccStateChangeEvent *event = downcast_accEvent(aEvent); \ + if (event->GetState() == nsIAccessibleStates::STATE_BUSY) { \ + strEventType.AssignLiteral("busy "); \ + if (event->IsStateEnabled()) \ + strEventType.AppendLiteral("true"); \ + else \ + strEventType.AppendLiteral("false"); \ + } \ + } + +#define NS_LOG_ACCDOC_ACCADDRESS(aName, aAcc) \ + { \ + nsINode* node = aAcc->GetNode(); \ + nsIDocument* doc = aAcc->GetDocumentNode(); \ + nsDocAccessible *docacc = GetAccService()->GetDocAccessibleFromCache(doc); \ + printf(" " aName " accessible: %p, node: %p\n", aAcc, node); \ + printf(" docacc for " aName " accessible: %p, node: %p\n", docacc, doc); \ + printf(" "); \ + NS_LOG_ACCDOC_URI(doc) \ + printf("\n"); \ + } + +#define NS_LOG_ACCDOC_MSG(aMsg) \ + printf("\n" aMsg "\n"); \ + +#define NS_LOG_ACCDOC_TEXT(aMsg) \ + printf(" " aMsg "\n"); + +// Accessible document loading macros. +#ifdef DEBUG_ACCDOCMGR_DOCLOAD + +#define NS_LOG_ACCDOCLOAD_REQUEST(aRequest) \ + if (aRequest) { \ + nsCAutoString name; \ + aRequest->GetName(name); \ + printf(" request spec: %s\n", name.get()); \ + PRUint32 loadFlags = 0; \ + aRequest->GetLoadFlags(&loadFlags); \ + printf(" request load flags: %x; ", loadFlags); \ + if (loadFlags & nsIChannel::LOAD_DOCUMENT_URI) \ + printf("document uri; "); \ + if (loadFlags & nsIChannel::LOAD_RETARGETED_DOCUMENT_URI) \ + printf("retargeted document uri; "); \ + if (loadFlags & nsIChannel::LOAD_REPLACE) \ + printf("replace; "); \ + if (loadFlags & nsIChannel::LOAD_INITIAL_DOCUMENT_URI) \ + printf("initial document uri; "); \ + if (loadFlags & nsIChannel::LOAD_TARGETED) \ + printf("targeted; "); \ + if (loadFlags & nsIChannel::LOAD_CALL_CONTENT_SNIFFERS) \ + printf("call content sniffers; "); \ + if (loadFlags & nsIChannel::LOAD_CLASSIFY_URI) \ + printf("classify uri; "); \ + } else { \ + printf(" no request"); \ + } + +#define NS_LOG_ACCDOCLOAD(aMsg, aWebProgress, aRequest, aStateFlags) \ + { \ + NS_LOG_ACCDOC_MSG("A11Y DOCLOAD: " aMsg); \ + \ + nsCOMPtr<nsIDOMWindow> DOMWindow; \ + aWebProgress->GetDOMWindow(getter_AddRefs(DOMWindow)); \ + if (DOMWindow) { \ + nsCOMPtr<nsIDOMDocument> DOMDocument; \ + DOMWindow->GetDocument(getter_AddRefs(DOMDocument)); \ + if (DOMDocument) { \ + nsCOMPtr<nsIDocument> document(do_QueryInterface(DOMDocument)); \ + nsDocAccessible *docAcc = \ + GetAccService()->GetDocAccessibleFromCache(document); \ + NS_LOG_ACCDOC_DOCINFO(document, docAcc) \ + \ + printf(" {\n"); \ + nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(DOMWindow)); \ + nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(webNav)); \ + printf(" "); \ + NS_LOG_ACCDOC_SHELLLOADTYPE(docShell) \ + printf("\n"); \ + NS_LOG_ACCDOCLOAD_REQUEST(aRequest) \ + printf("\n"); \ + printf(" state flags: %x", aStateFlags); \ + PRBool isDocLoading; \ + aWebProgress->GetIsLoadingDocument(&isDocLoading); \ + printf(", document is %sloading\n", (isDocLoading ? "" : "not ")); \ + printf(" }\n"); \ + } \ + } \ + } + +#define NS_LOG_ACCDOCLOAD2(aMsg, aDocument) \ + { \ + NS_LOG_ACCDOC_MSG("A11Y DOCLOAD: " aMsg); \ + nsDocAccessible *docAcc = \ + GetAccService()->GetDocAccessibleFromCache(aDocument); \ + NS_LOG_ACCDOC_DOCINFO(aDocument, docAcc) \ + } + +#define NS_LOG_ACCDOCLOAD_FIREEVENT(aEvent) \ + { \ + NS_GET_ACCDOC_EVENTTYPE(aEvent) \ + if (!strEventType.IsEmpty()) \ + printf(" fire: %s\n", strEventType.get()); \ + } + +#define NS_LOG_ACCDOCLOAD_HANDLEEVENT(aEvent) \ + { \ + NS_GET_ACCDOC_EVENTTYPE(aEvent) \ + nsCOMPtr<nsIDocument> doc(do_QueryInterface(aEvent->GetNode())); \ + if (doc && !strEventType.IsEmpty()) { \ + printf("\nA11Y DOCEVENT: handled '%s' event ", strEventType.get()); \ + nsDocAccessible *docAcc = aEvent->GetDocAccessible(); \ + NS_LOG_ACCDOC_DOCINFO(doc, docAcc) \ + printf("\n"); \ + } \ + } + +#define NS_LOG_ACCDOCLOAD_TEXT(aMsg) \ + NS_LOG_ACCDOC_TEXT(aMsg) + +#endif // DEBUG_ACCDOCMGR_DOCLOAD + +// Accessible document creation macros. +#ifdef DEBUG_ACCDOCMGR_DOCCREATE +#define NS_LOG_ACCDOCCREATE_FOR(aMsg, aDocument, aDocAcc) \ + NS_LOG_ACCDOC_MSG("A11Y DOCCREATE: " aMsg); \ + NS_LOG_ACCDOC_DOCINFO(aDocument, aDocAcc) + +#define NS_LOG_ACCDOCCREATE(aMsg, aDocument) \ + { \ + nsDocAccessible *docAcc = \ + GetAccService()->GetDocAccessibleFromCache(aDocument); \ + NS_LOG_ACCDOCCREATE_FOR(aMsg, aDocument, docAcc) \ + } + +#define NS_LOG_ACCDOCCREATE_ACCADDRESS(aName, aAcc) \ + NS_LOG_ACCDOC_ACCADDRESS(aName, aAcc) + +#define NS_LOG_ACCDOCCREATE_TEXT(aMsg) \ + NS_LOG_ACCDOC_TEXT(aMsg) + +#endif // DEBUG_ACCDOCMGR_DOCCREATE + +// Accessible document destruction macros. +#ifdef DEBUG_ACCDOCMGR_DOCDESTROY +#define NS_LOG_ACCDOCDESTROY_FOR(aMsg, aDocument, aDocAcc) \ + NS_LOG_ACCDOC_MSG("A11Y DOCDESTROY: " aMsg); \ + NS_LOG_ACCDOC_DOCINFO(aDocument, aDocAcc) + +#define NS_LOG_ACCDOCDESTROY(aMsg, aDocument) \ + { \ + nsDocAccessible* docAcc = \ + GetAccService()->GetDocAccessibleFromCache(aDocument); \ + NS_LOG_ACCDOCDESTROY_FOR(aMsg, aDocument, docAcc) \ + } + +#define NS_LOG_ACCDOCDESTROY_ACCADDRESS(aName, aAcc) \ + NS_LOG_ACCDOC_ACCADDRESS(aName, aAcc) + +#define NS_LOG_ACCDOCDESTROY_MSG(aMsg) \ + NS_LOG_ACCDOC_MSG(aMsg) + +#define NS_LOG_ACCDOCDESTROY_TEXT(aMsg) \ + NS_LOG_ACCDOC_TEXT(aMsg) + +#endif // DEBUG_ACCDOCMGR_DOCDESTROY + +#endif // DEBUG_ACCDOCMGR + +#ifndef DEBUG_ACCDOCMGR_DOCLOAD +#define NS_LOG_ACCDOCLOAD(aMsg, aWebProgress, aRequest, aStateFlags) +#define NS_LOG_ACCDOCLOAD2(aMsg, aDocument) +#define NS_LOG_ACCDOCLOAD_EVENT(aMsg, aEvent) +#define NS_LOG_ACCDOCLOAD_FIREEVENT(aEvent) +#define NS_LOG_ACCDOCLOAD_HANDLEEVENT(aEvent) +#define NS_LOG_ACCDOCLOAD_TEXT(aMsg) +#endif + +#ifndef DEBUG_ACCDOCMGR_DOCCREATE +#define NS_LOG_ACCDOCCREATE_FOR(aMsg, aDocument, aDocAcc) +#define NS_LOG_ACCDOCCREATE(aMsg, aDocument) +#define NS_LOG_ACCDOCCREATE_ACCADDRESS(aName, aAcc) +#define NS_LOG_ACCDOCCREATE_TEXT(aMsg) +#endif + +#ifndef DEBUG_ACCDOCMGR_DOCDESTROY +#define NS_LOG_ACCDOCDESTROY_FOR(aMsg, aDocument, aDocAcc) +#define NS_LOG_ACCDOCDESTROY(aMsg, aDocument) +#define NS_LOG_ACCDOCDESTROY_MSG(aMsg) +#define NS_LOG_ACCDOCDESTROY_ACCADDRESS(aName, aAcc) +#define NS_LOG_ACCDOCDESTROY_TEXT(aMsg) +#endif + +#endif // nsAccDocManager_h_
--- a/accessible/src/base/nsAccEvent.cpp +++ b/accessible/src/base/nsAccEvent.cpp @@ -44,60 +44,62 @@ #include "nsDocAccessible.h" #include "nsIAccessibleText.h" #ifdef MOZ_XUL #include "nsXULTreeAccessible.h" #endif #include "nsIDOMDocument.h" #include "nsIEventStateManager.h" -#include "nsIPersistentProperties2.h" #include "nsIServiceManager.h" #ifdef MOZ_XUL #include "nsIDOMXULMultSelectCntrlEl.h" #endif -#include "nsIContent.h" -#include "nsIPresShell.h" -#include "nsPresContext.h" //////////////////////////////////////////////////////////////////////////////// // nsAccEvent //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // nsAccEvent. nsISupports -NS_IMPL_CYCLE_COLLECTION_1(nsAccEvent, mAccessible) +NS_IMPL_CYCLE_COLLECTION_CLASS(nsAccEvent) +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsAccEvent) + NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAccessible) +NS_IMPL_CYCLE_COLLECTION_UNLINK_END +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsAccEvent) + NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mAccessible"); + cb.NoteXPCOMChild(static_cast<nsIAccessible*>(tmp->mAccessible)); +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsAccEvent) NS_INTERFACE_MAP_ENTRY(nsIAccessibleEvent) - NS_INTERFACE_MAP_ENTRY(nsAccEvent) NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_END NS_IMPL_CYCLE_COLLECTING_ADDREF(nsAccEvent) NS_IMPL_CYCLE_COLLECTING_RELEASE(nsAccEvent) //////////////////////////////////////////////////////////////////////////////// // nsAccEvent. Constructors -nsAccEvent::nsAccEvent(PRUint32 aEventType, nsIAccessible *aAccessible, +nsAccEvent::nsAccEvent(PRUint32 aEventType, nsAccessible *aAccessible, PRBool aIsAsync, EIsFromUserInput aIsFromUserInput, EEventRule aEventRule) : mEventType(aEventType), mEventRule(aEventRule), mIsAsync(aIsAsync), mAccessible(aAccessible) { CaptureIsFromUserInput(aIsFromUserInput); } -nsAccEvent::nsAccEvent(PRUint32 aEventType, nsIDOMNode *aDOMNode, +nsAccEvent::nsAccEvent(PRUint32 aEventType, nsINode *aNode, PRBool aIsAsync, EIsFromUserInput aIsFromUserInput, EEventRule aEventRule) : mEventType(aEventType), mEventRule(aEventRule), mIsAsync(aIsAsync), - mNode(do_QueryInterface(aDOMNode)) + mNode(aNode) { CaptureIsFromUserInput(aIsFromUserInput); } //////////////////////////////////////////////////////////////////////////////// // nsAccEvent: nsIAccessibleEvent NS_IMETHODIMP @@ -122,20 +124,17 @@ nsAccEvent::GetEventType(PRUint32 *aEven } NS_IMETHODIMP nsAccEvent::GetAccessible(nsIAccessible **aAccessible) { NS_ENSURE_ARG_POINTER(aAccessible); *aAccessible = nsnull; - if (!mAccessible) - mAccessible = GetAccessibleByNode(); - - NS_IF_ADDREF(*aAccessible = mAccessible); + NS_IF_ADDREF(*aAccessible = GetAccessible()); return NS_OK; } NS_IMETHODIMP nsAccEvent::GetDOMNode(nsIDOMNode **aDOMNode) { NS_ENSURE_ARG_POINTER(aDOMNode); *aDOMNode = nsnull; @@ -156,56 +155,54 @@ nsAccEvent::GetAccessibleDocument(nsIAcc NS_IF_ADDREF(*aDocAccessible = GetDocAccessible()); return NS_OK; } //////////////////////////////////////////////////////////////////////////////// // nsAccEvent: public methods +nsAccessible * +nsAccEvent::GetAccessible() +{ + if (!mAccessible) + mAccessible = GetAccessibleForNode(); + + return mAccessible; +} + nsINode* nsAccEvent::GetNode() { - if (!mNode) { - nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(mAccessible)); - if (!accessNode) - return nsnull; - - nsCOMPtr<nsIDOMNode> DOMNode; - accessNode->GetDOMNode(getter_AddRefs(DOMNode)); - - mNode = do_QueryInterface(DOMNode); - } + if (!mNode && mAccessible) + mNode = mAccessible->GetNode(); return mNode; } nsDocAccessible* nsAccEvent::GetDocAccessible() { nsINode *node = GetNode(); if (node) - return nsAccessNode::GetDocAccessibleFor(node->GetOwnerDoc()); + return GetAccService()->GetDocAccessible(node->GetOwnerDoc()); return nsnull; } //////////////////////////////////////////////////////////////////////////////// // nsAccEvent: protected methods -already_AddRefed<nsIAccessible> -nsAccEvent::GetAccessibleByNode() +nsAccessible * +nsAccEvent::GetAccessibleForNode() const { if (!mNode) return nsnull; - nsCOMPtr<nsIDOMNode> DOMNode(do_QueryInterface(mNode)); - - nsCOMPtr<nsIAccessible> accessible; - GetAccService()->GetAccessibleFor(DOMNode, getter_AddRefs(accessible)); + nsAccessible *accessible = GetAccService()->GetAccessible(mNode); #ifdef MOZ_XUL // hack for xul tree table. We need a better way for firing delayed event // against xul tree table. see bug 386821. // There will be problem if some day we want to fire delayed event against // the xul tree itself or an unselected treeitem. nsCOMPtr<nsIContent> content(do_QueryInterface(mNode)); if (content && content->NodeInfo()->Equals(nsAccessibilityAtoms::tree, @@ -215,30 +212,29 @@ nsAccEvent::GetAccessibleByNode() do_QueryInterface(mNode); if (multiSelect) { PRInt32 treeIndex = -1; multiSelect->GetCurrentIndex(&treeIndex); if (treeIndex >= 0) { nsRefPtr<nsXULTreeAccessible> treeAcc = do_QueryObject(accessible); if (treeAcc) - accessible = treeAcc->GetTreeItemAccessible(treeIndex); + return treeAcc->GetTreeItemAccessible(treeIndex); } } } #endif - return accessible.forget(); + return accessible; } void nsAccEvent::CaptureIsFromUserInput(EIsFromUserInput aIsFromUserInput) { - nsCOMPtr<nsIDOMNode> targetNode; - GetDOMNode(getter_AddRefs(targetNode)); + nsINode *targetNode = GetNode(); #ifdef DEBUG if (!targetNode) { // XXX: remove this hack during reorganization of 506907. Meanwhile we // want to get rid an assertion for application accessible events which // don't have DOM node (see bug 506206). nsApplicationAccessible *applicationAcc = nsAccessNode::GetApplicationAccessible(); @@ -271,23 +267,22 @@ nsAccEvent::CaptureIsFromUserInput(EIsFr mIsFromUserInput = esm->IsHandlingUserInputExternal(); } //////////////////////////////////////////////////////////////////////////////// // nsAccReorderEvent //////////////////////////////////////////////////////////////////////////////// -NS_IMPL_ISUPPORTS_INHERITED1(nsAccReorderEvent, nsAccEvent, - nsAccReorderEvent) +NS_IMPL_ISUPPORTS_INHERITED0(nsAccReorderEvent, nsAccEvent) -nsAccReorderEvent::nsAccReorderEvent(nsIAccessible *aAccTarget, +nsAccReorderEvent::nsAccReorderEvent(nsAccessible *aAccTarget, PRBool aIsAsynch, PRBool aIsUnconditional, - nsIDOMNode *aReasonNode) : + nsINode *aReasonNode) : nsAccEvent(::nsIAccessibleEvent::EVENT_REORDER, aAccTarget, aIsAsynch, eAutoDetect, nsAccEvent::eCoalesceFromSameSubtree), mUnconditionalEvent(aIsUnconditional), mReasonNode(aReasonNode) { } PRBool nsAccReorderEvent::IsUnconditionalEvent() @@ -296,88 +291,87 @@ nsAccReorderEvent::IsUnconditionalEvent( } PRBool nsAccReorderEvent::HasAccessibleInReasonSubtree() { if (!mReasonNode) return PR_FALSE; - nsCOMPtr<nsIAccessible> accessible; - GetAccService()->GetAccessibleFor(mReasonNode, getter_AddRefs(accessible)); - + nsAccessible *accessible = GetAccService()->GetAccessible(mReasonNode); return accessible || nsAccUtils::HasAccessibleChildren(mReasonNode); } //////////////////////////////////////////////////////////////////////////////// // nsAccStateChangeEvent //////////////////////////////////////////////////////////////////////////////// NS_IMPL_ISUPPORTS_INHERITED1(nsAccStateChangeEvent, nsAccEvent, nsIAccessibleStateChangeEvent) // Note: we pass in eAllowDupes to the base class because we don't currently // support correct state change coalescence (XXX Bug 569356). Also we need to // decide how to coalesce events created via accessible (instead of node). nsAccStateChangeEvent:: - nsAccStateChangeEvent(nsIAccessible *aAccessible, + nsAccStateChangeEvent(nsAccessible *aAccessible, PRUint32 aState, PRBool aIsExtraState, PRBool aIsEnabled, PRBool aIsAsynch, EIsFromUserInput aIsFromUserInput): nsAccEvent(nsIAccessibleEvent::EVENT_STATE_CHANGE, aAccessible, aIsAsynch, aIsFromUserInput, eAllowDupes), mState(aState), mIsExtraState(aIsExtraState), mIsEnabled(aIsEnabled) { } nsAccStateChangeEvent:: - nsAccStateChangeEvent(nsIDOMNode *aNode, - PRUint32 aState, PRBool aIsExtraState, + nsAccStateChangeEvent(nsINode *aNode, PRUint32 aState, PRBool aIsExtraState, PRBool aIsEnabled): nsAccEvent(::nsIAccessibleEvent::EVENT_STATE_CHANGE, aNode), mState(aState), mIsExtraState(aIsExtraState), mIsEnabled(aIsEnabled) { } nsAccStateChangeEvent:: - nsAccStateChangeEvent(nsIDOMNode *aNode, - PRUint32 aState, PRBool aIsExtraState): + nsAccStateChangeEvent(nsINode *aNode, PRUint32 aState, PRBool aIsExtraState) : nsAccEvent(::nsIAccessibleEvent::EVENT_STATE_CHANGE, aNode), mState(aState), mIsExtraState(aIsExtraState) { - // Use GetAccessibleByNode() because we do not want to store an accessible + // Use GetAccessibleForNode() because we do not want to store an accessible // since it leads to problems with delayed events in the case when // an accessible gets reorder event before delayed event is processed. - nsCOMPtr<nsIAccessible> accessible(GetAccessibleByNode()); + nsAccessible *accessible = GetAccessibleForNode(); if (accessible) { PRUint32 state = 0, extraState = 0; accessible->GetState(&state, mIsExtraState ? &extraState : nsnull); mIsEnabled = ((mIsExtraState ? extraState : state) & mState) != 0; } else { mIsEnabled = PR_FALSE; } } NS_IMETHODIMP nsAccStateChangeEvent::GetState(PRUint32 *aState) { + NS_ENSURE_ARG_POINTER(aState); *aState = mState; return NS_OK; } NS_IMETHODIMP nsAccStateChangeEvent::IsExtraState(PRBool *aIsExtraState) { + NS_ENSURE_ARG_POINTER(aIsExtraState); *aIsExtraState = mIsExtraState; return NS_OK; } NS_IMETHODIMP nsAccStateChangeEvent::IsEnabled(PRBool *aIsEnabled) { + NS_ENSURE_ARG_POINTER(aIsEnabled); *aIsEnabled = mIsEnabled; return NS_OK; } //////////////////////////////////////////////////////////////////////////////// // nsAccTextChangeEvent //////////////////////////////////////////////////////////////////////////////// @@ -388,49 +382,47 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsAccTextCh // events coalescence. We fire delayed text change events in nsDocAccessible but // we continue to base the event off the accessible object rather than just the // node. This means we won't try to create an accessible based on the node when // we are ready to fire the event and so we will no longer assert at that point // if the node was removed from the document. Either way, the AT won't work with // a defunct accessible so the behaviour should be equivalent. // XXX revisit this when coalescence is faster (eCoalesceFromSameSubtree) nsAccTextChangeEvent:: - nsAccTextChangeEvent(nsIAccessible *aAccessible, - PRInt32 aStart, PRUint32 aLength, PRBool aIsInserted, + nsAccTextChangeEvent(nsAccessible *aAccessible, + PRInt32 aStart, PRUint32 aLength, + nsAString& aModifiedText, PRBool aIsInserted, PRBool aIsAsynch, EIsFromUserInput aIsFromUserInput) : nsAccEvent(aIsInserted ? nsIAccessibleEvent::EVENT_TEXT_INSERTED : nsIAccessibleEvent::EVENT_TEXT_REMOVED, aAccessible, aIsAsynch, aIsFromUserInput, eAllowDupes), - mStart(aStart), mLength(aLength), mIsInserted(aIsInserted) + mStart(aStart), mLength(aLength), mIsInserted(aIsInserted), + mModifiedText(aModifiedText) { -#ifdef XP_WIN - nsCOMPtr<nsIAccessibleText> textAccessible = do_QueryInterface(aAccessible); - NS_ASSERTION(textAccessible, "Should not be firing test change event for non-text accessible!!!"); - if (textAccessible) { - textAccessible->GetText(aStart, aStart + aLength, mModifiedText); - } -#endif } NS_IMETHODIMP nsAccTextChangeEvent::GetStart(PRInt32 *aStart) { + NS_ENSURE_ARG_POINTER(aStart); *aStart = mStart; return NS_OK; } NS_IMETHODIMP nsAccTextChangeEvent::GetLength(PRUint32 *aLength) { + NS_ENSURE_ARG_POINTER(aLength); *aLength = mLength; return NS_OK; } NS_IMETHODIMP nsAccTextChangeEvent::IsInserted(PRBool *aIsInserted) { + NS_ENSURE_ARG_POINTER(aIsInserted); *aIsInserted = mIsInserted; return NS_OK; } NS_IMETHODIMP nsAccTextChangeEvent::GetModifiedText(nsAString& aModifiedText) { aModifiedText = mModifiedText; @@ -440,24 +432,24 @@ nsAccTextChangeEvent::GetModifiedText(ns //////////////////////////////////////////////////////////////////////////////// // nsAccCaretMoveEvent //////////////////////////////////////////////////////////////////////////////// NS_IMPL_ISUPPORTS_INHERITED1(nsAccCaretMoveEvent, nsAccEvent, nsIAccessibleCaretMoveEvent) nsAccCaretMoveEvent:: - nsAccCaretMoveEvent(nsIAccessible *aAccessible, PRInt32 aCaretOffset) : + nsAccCaretMoveEvent(nsAccessible *aAccessible, PRInt32 aCaretOffset) : nsAccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aAccessible, PR_TRUE), // Currently always asynch mCaretOffset(aCaretOffset) { } nsAccCaretMoveEvent:: - nsAccCaretMoveEvent(nsIDOMNode *aNode) : + nsAccCaretMoveEvent(nsINode *aNode) : nsAccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aNode, PR_TRUE), // Currently always asynch mCaretOffset(-1) { } NS_IMETHODIMP nsAccCaretMoveEvent::GetCaretOffset(PRInt32* aCaretOffset) { @@ -470,17 +462,17 @@ nsAccCaretMoveEvent::GetCaretOffset(PRIn //////////////////////////////////////////////////////////////////////////////// // nsAccTableChangeEvent //////////////////////////////////////////////////////////////////////////////// NS_IMPL_ISUPPORTS_INHERITED1(nsAccTableChangeEvent, nsAccEvent, nsIAccessibleTableChangeEvent) nsAccTableChangeEvent:: - nsAccTableChangeEvent(nsIAccessible *aAccessible, PRUint32 aEventType, + nsAccTableChangeEvent(nsAccessible *aAccessible, PRUint32 aEventType, PRInt32 aRowOrColIndex, PRInt32 aNumRowsOrCols, PRBool aIsAsynch): nsAccEvent(aEventType, aAccessible, aIsAsynch), mRowOrColIndex(aRowOrColIndex), mNumRowsOrCols(aNumRowsOrCols) { } NS_IMETHODIMP nsAccTableChangeEvent::GetRowOrColIndex(PRInt32* aRowOrColIndex)
--- a/accessible/src/base/nsAccEvent.h +++ b/accessible/src/base/nsAccEvent.h @@ -38,45 +38,34 @@ * * ***** END LICENSE BLOCK ***** */ #ifndef _nsAccEvent_H_ #define _nsAccEvent_H_ #include "nsIAccessibleEvent.h" -#include "nsCOMPtr.h" -#include "nsCOMArray.h" -#include "nsString.h" -#include "nsCycleCollectionParticipant.h" - -#include "nsINode.h" -#include "nsIDOMNode.h" +#include "nsAccessible.h" class nsDocAccessible; // Constants used to point whether the event is from user input. enum EIsFromUserInput { // eNoUserInput: event is not from user input eNoUserInput = 0, // eFromUserInput: event is from user input eFromUserInput = 1, // eAutoDetect: the value should be obtained from event state manager eAutoDetect = -1 }; -#define NS_ACCEVENT_IMPL_CID \ -{ /* 39bde096-317e-4294-b23b-4af4a9b283f7 */ \ - 0x39bde096, \ - 0x317e, \ - 0x4294, \ - { 0xb2, 0x3b, 0x4a, 0xf4, 0xa9, 0xb2, 0x83, 0xf7 } \ -} - +/** + * Generic accessible event. + */ class nsAccEvent: public nsIAccessibleEvent { public: // Rule for accessible events. // The rule will be applied when flushing pending events. enum EEventRule { // eAllowDupes : More than one event of the same type is allowed. @@ -95,174 +84,264 @@ public: // eRemoveDupes : For repeat events, only the newest event in queue // will be emitted. eRemoveDupes, // eDoNotEmit : This event is confirmed as a duplicate, do not emit it. eDoNotEmit }; - NS_DECLARE_STATIC_IID_ACCESSOR(NS_ACCEVENT_IMPL_CID) - // Initialize with an nsIAccessible - nsAccEvent(PRUint32 aEventType, nsIAccessible *aAccessible, + nsAccEvent(PRUint32 aEventType, nsAccessible *aAccessible, PRBool aIsAsynch = PR_FALSE, EIsFromUserInput aIsFromUserInput = eAutoDetect, EEventRule aEventRule = eRemoveDupes); // Initialize with an nsIDOMNode - nsAccEvent(PRUint32 aEventType, nsIDOMNode *aDOMNode, - PRBool aIsAsynch = PR_FALSE, + nsAccEvent(PRUint32 aEventType, nsINode *aNode, PRBool aIsAsynch = PR_FALSE, EIsFromUserInput aIsFromUserInput = eAutoDetect, EEventRule aEventRule = eRemoveDupes); virtual ~nsAccEvent() {} NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_CLASS(nsAccEvent) NS_DECL_NSIACCESSIBLEEVENT // nsAccEvent PRUint32 GetEventType() const { return mEventType; } EEventRule GetEventRule() const { return mEventRule; } PRBool IsAsync() const { return mIsAsync; } PRBool IsFromUserInput() const { return mIsFromUserInput; } - nsIAccessible* GetAccessible() const { return mAccessible; } + nsAccessible *GetAccessible(); nsINode* GetNode(); nsDocAccessible* GetDocAccessible(); + enum EventGroup { + eGenericEvent, + eReorderEvent, + eStateChangeEvent, + eTextChangeEvent, + eCaretMoveEvent, + eTableChangeEvent + }; + + static const EventGroup kEventGroup = eGenericEvent; + virtual unsigned int GetEventGroups() const + { + return 1U << eGenericEvent; + } + protected: /** * Get an accessible from event target node. */ - already_AddRefed<nsIAccessible> GetAccessibleByNode(); + nsAccessible *GetAccessibleForNode() const; /** * Determine whether the event is from user input by event state manager if * it's not pointed explicetly. */ void CaptureIsFromUserInput(EIsFromUserInput aIsFromUserInput); PRBool mIsFromUserInput; PRUint32 mEventType; EEventRule mEventRule; PRPackedBool mIsAsync; - nsCOMPtr<nsIAccessible> mAccessible; + nsRefPtr<nsAccessible> mAccessible; nsCOMPtr<nsINode> mNode; friend class nsAccEventQueue; }; -NS_DEFINE_STATIC_IID_ACCESSOR(nsAccEvent, NS_ACCEVENT_IMPL_CID) - -#define NS_ACCREORDEREVENT_IMPL_CID \ -{ /* f2629eb8-2458-4358-868c-3912b15b767a */ \ - 0xf2629eb8, \ - 0x2458, \ - 0x4358, \ - { 0x86, 0x8c, 0x39, 0x12, 0xb1, 0x5b, 0x76, 0x7a } \ -} - +/** + * Accessible reorder event. + */ class nsAccReorderEvent : public nsAccEvent { public: - - nsAccReorderEvent(nsIAccessible *aAccTarget, PRBool aIsAsynch, - PRBool aIsUnconditional, nsIDOMNode *aReasonNode); - - NS_DECLARE_STATIC_IID_ACCESSOR(NS_ACCREORDEREVENT_IMPL_CID) + nsAccReorderEvent(nsAccessible *aAccTarget, PRBool aIsAsynch, + PRBool aIsUnconditional, nsINode *aReasonNode); NS_DECL_ISUPPORTS_INHERITED + // nsAccEvent + static const EventGroup kEventGroup = eReorderEvent; + virtual unsigned int GetEventGroups() const + { + return nsAccEvent::GetEventGroups() | (1U << eReorderEvent); + } + + // nsAccReorderEvent /** * Return true if event is unconditional, i.e. must be fired. */ PRBool IsUnconditionalEvent(); /** * Return true if changed DOM node has accessible in its tree. */ PRBool HasAccessibleInReasonSubtree(); private: PRBool mUnconditionalEvent; - nsCOMPtr<nsIDOMNode> mReasonNode; + nsCOMPtr<nsINode> mReasonNode; }; -NS_DEFINE_STATIC_IID_ACCESSOR(nsAccReorderEvent, NS_ACCREORDEREVENT_IMPL_CID) - +/** + * Accessible state change event. + */ class nsAccStateChangeEvent: public nsAccEvent, public nsIAccessibleStateChangeEvent { public: - nsAccStateChangeEvent(nsIAccessible *aAccessible, + nsAccStateChangeEvent(nsAccessible *aAccessible, PRUint32 aState, PRBool aIsExtraState, PRBool aIsEnabled, PRBool aIsAsynch = PR_FALSE, EIsFromUserInput aIsFromUserInput = eAutoDetect); - nsAccStateChangeEvent(nsIDOMNode *aNode, - PRUint32 aState, PRBool aIsExtraState, + nsAccStateChangeEvent(nsINode *aNode, PRUint32 aState, PRBool aIsExtraState, PRBool aIsEnabled); - nsAccStateChangeEvent(nsIDOMNode *aNode, - PRUint32 aState, PRBool aIsExtraState); + nsAccStateChangeEvent(nsINode *aNode, PRUint32 aState, PRBool aIsExtraState); NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIACCESSIBLESTATECHANGEEVENT + // nsAccEvent + static const EventGroup kEventGroup = eStateChangeEvent; + virtual unsigned int GetEventGroups() const + { + return nsAccEvent::GetEventGroups() | (1U << eStateChangeEvent); + } + + // nsAccStateChangeEvent + PRUint32 GetState() const { return mState; } + PRBool IsExtraState() const { return mIsExtraState; } + PRBool IsStateEnabled() const { return mIsEnabled; } + private: PRUint32 mState; PRBool mIsExtraState; PRBool mIsEnabled; }; + +/** + * Accessible text change event. + */ class nsAccTextChangeEvent: public nsAccEvent, public nsIAccessibleTextChangeEvent { public: - nsAccTextChangeEvent(nsIAccessible *aAccessible, PRInt32 aStart, PRUint32 aLength, + nsAccTextChangeEvent(nsAccessible *aAccessible, PRInt32 aStart, + PRUint32 aLength, nsAString& aModifiedText, PRBool aIsInserted, PRBool aIsAsynch = PR_FALSE, EIsFromUserInput aIsFromUserInput = eAutoDetect); NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIACCESSIBLETEXTCHANGEEVENT + // nsAccEvent + static const EventGroup kEventGroup = eTextChangeEvent; + virtual unsigned int GetEventGroups() const + { + return nsAccEvent::GetEventGroups() | (1U << eTextChangeEvent); + } + + // nsAccTextChangeEvent + PRInt32 GetStartOffset() const { return mStart; } + PRUint32 GetLength() const { return mLength; } + PRBool IsTextInserted() const { return mIsInserted; } + private: PRInt32 mStart; PRUint32 mLength; PRBool mIsInserted; nsString mModifiedText; }; + +/** + * Accessible caret move event. + */ class nsAccCaretMoveEvent: public nsAccEvent, public nsIAccessibleCaretMoveEvent { public: - nsAccCaretMoveEvent(nsIAccessible *aAccessible, PRInt32 aCaretOffset); - nsAccCaretMoveEvent(nsIDOMNode *aNode); + nsAccCaretMoveEvent(nsAccessible *aAccessible, PRInt32 aCaretOffset); + nsAccCaretMoveEvent(nsINode *aNode); NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIACCESSIBLECARETMOVEEVENT + // nsAccEvent + static const EventGroup kEventGroup = eCaretMoveEvent; + virtual unsigned int GetEventGroups() const + { + return nsAccEvent::GetEventGroups() | (1U << eCaretMoveEvent); + } + + // nsAccCaretMoveEvent + PRInt32 GetCaretOffset() const { return mCaretOffset; } + private: PRInt32 mCaretOffset; }; + +/** + * Accessible table change event. + */ class nsAccTableChangeEvent : public nsAccEvent, - public nsIAccessibleTableChangeEvent { + public nsIAccessibleTableChangeEvent +{ public: - nsAccTableChangeEvent(nsIAccessible *aAccessible, PRUint32 aEventType, + nsAccTableChangeEvent(nsAccessible *aAccessible, PRUint32 aEventType, PRInt32 aRowOrColIndex, PRInt32 aNumRowsOrCols, PRBool aIsAsynch); - NS_DECL_ISUPPORTS + NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIACCESSIBLETABLECHANGEEVENT + // nsAccEvent + static const EventGroup kEventGroup = eTableChangeEvent; + virtual unsigned int GetEventGroups() const + { + return nsAccEvent::GetEventGroups() | (1U << eTableChangeEvent); + } + + // nsAccTableChangeEvent + PRUint32 GetIndex() const { return mRowOrColIndex; } + PRUint32 GetCount() const { return mNumRowsOrCols; } + private: PRUint32 mRowOrColIndex; // the start row/column after which the rows are inserted/deleted. PRUint32 mNumRowsOrCols; // the number of inserted/deleted rows/columns }; + +/** + * Downcast the generic accessible event object to derived type. + */ +class downcast_accEvent +{ +public: + downcast_accEvent(nsAccEvent *e) : mRawPtr(e) { } + + template<class Destination> + operator Destination*() { + if (!mRawPtr) + return nsnull; + + return mRawPtr->GetEventGroups() & (1U << Destination::kEventGroup) ? + static_cast<Destination*>(mRawPtr) : nsnull; + } + +private: + nsAccEvent *mRawPtr; +}; + #endif
--- a/accessible/src/base/nsAccTreeWalker.cpp +++ b/accessible/src/base/nsAccTreeWalker.cpp @@ -37,16 +37,19 @@ * * ***** END LICENSE BLOCK ***** */ #include "nsAccTreeWalker.h" #include "nsAccessible.h" #include "nsAccessibilityService.h" +#include "nsINodeList.h" +#include "nsIPresShell.h" + //////////////////////////////////////////////////////////////////////////////// // WalkState //////////////////////////////////////////////////////////////////////////////// struct WalkState { WalkState(nsIContent *aContent) : content(aContent), childIdx(0), prevState(nsnull) {} @@ -104,19 +107,18 @@ nsAccTreeWalker::GetNextChildInternal(PR if (mState->childList) mState->childList->GetLength(&length); while (mState->childIdx < length) { nsIContent* childNode = mState->childList->GetNodeAt(mState->childIdx); mState->childIdx++; PRBool isHidden = PR_FALSE; - nsCOMPtr<nsIDOMNode> childDOMNode(do_QueryInterface(childNode)); nsRefPtr<nsAccessible> accessible = - GetAccService()->GetAccessible(childDOMNode, presShell, mWeakShell, + GetAccService()->GetAccessible(childNode, presShell, mWeakShell, &isHidden); if (accessible) return accessible.forget(); // Walk down into subtree to find accessibles. if (!isHidden) { if (!PushState(childNode))
--- a/accessible/src/base/nsAccUtils.cpp +++ b/accessible/src/base/nsAccUtils.cpp @@ -96,61 +96,54 @@ nsAccUtils::SetAccGroupAttrs(nsIPersiste value.Truncate(); value.AppendInt(aSetSize); SetAccAttr(aAttributes, nsAccessibilityAtoms::setsize, value); } } PRInt32 -nsAccUtils::GetDefaultLevel(nsAccessible *aAcc) +nsAccUtils::GetDefaultLevel(nsAccessible *aAccessible) { - PRUint32 role = nsAccUtils::Role(aAcc); + PRUint32 role = nsAccUtils::Role(aAccessible); if (role == nsIAccessibleRole::ROLE_OUTLINEITEM) return 1; if (role == nsIAccessibleRole::ROLE_ROW) { - nsCOMPtr<nsIAccessible> parent = aAcc->GetParent(); + nsAccessible *parent = aAccessible->GetParent(); if (Role(parent) == nsIAccessibleRole::ROLE_TREE_TABLE) { // It is a row inside flatten treegrid. Group level is always 1 until it // is overriden by aria-level attribute. return 1; } } return 0; } PRInt32 -nsAccUtils::GetARIAOrDefaultLevel(nsIAccessible *aAcc) +nsAccUtils::GetARIAOrDefaultLevel(nsAccessible *aAccessible) { - nsRefPtr<nsAccessible> acc = do_QueryObject(aAcc); - NS_ENSURE_TRUE(acc, 0); - - nsCOMPtr<nsIDOMNode> node; - acc->GetDOMNode(getter_AddRefs(node)); - nsCOMPtr<nsIContent> content(do_QueryInterface(node)); - NS_ENSURE_TRUE(content, 0); - PRInt32 level = 0; - nsCoreUtils::GetUIntAttr(content, nsAccessibilityAtoms::aria_level, &level); + nsCoreUtils::GetUIntAttr(aAccessible->GetContent(), + nsAccessibilityAtoms::aria_level, &level); if (level != 0) return level; - return GetDefaultLevel(acc); + return GetDefaultLevel(aAccessible); } void -nsAccUtils::GetPositionAndSizeForXULSelectControlItem(nsIDOMNode *aNode, +nsAccUtils::GetPositionAndSizeForXULSelectControlItem(nsIContent *aContent, PRInt32 *aPosInSet, PRInt32 *aSetSize) { - nsCOMPtr<nsIDOMXULSelectControlItemElement> item(do_QueryInterface(aNode)); + nsCOMPtr<nsIDOMXULSelectControlItemElement> item(do_QueryInterface(aContent)); if (!item) return; nsCOMPtr<nsIDOMXULSelectControlElement> control; item->GetControl(getter_AddRefs(control)); if (!control) return; @@ -177,21 +170,21 @@ nsAccUtils::GetPositionAndSizeForXULSele (*aPosInSet)--; } } (*aPosInSet)++; // group position is 1-index based. } void -nsAccUtils::GetPositionAndSizeForXULContainerItem(nsIDOMNode *aNode, +nsAccUtils::GetPositionAndSizeForXULContainerItem(nsIContent *aContent, PRInt32 *aPosInSet, PRInt32 *aSetSize) { - nsCOMPtr<nsIDOMXULContainerItemElement> item(do_QueryInterface(aNode)); + nsCOMPtr<nsIDOMXULContainerItemElement> item(do_QueryInterface(aContent)); if (!item) return; nsCOMPtr<nsIDOMXULContainerElement> container; item->GetParentContainer(getter_AddRefs(container)); if (!container) return; @@ -241,19 +234,19 @@ nsAccUtils::GetPositionAndSizeForXULCont PRUint32 itemState = State(itemAcc); if (!(itemState & nsIAccessibleStates::STATE_INVISIBLE)) (*aSetSize)++; } } } PRInt32 -nsAccUtils::GetLevelForXULContainerItem(nsIDOMNode *aNode) +nsAccUtils::GetLevelForXULContainerItem(nsIContent *aContent) { - nsCOMPtr<nsIDOMXULContainerItemElement> item(do_QueryInterface(aNode)); + nsCOMPtr<nsIDOMXULContainerItemElement> item(do_QueryInterface(aContent)); if (!item) return 0; nsCOMPtr<nsIDOMXULContainerElement> container; item->GetParentContainer(getter_AddRefs(container)); if (!container) return 0; @@ -282,18 +275,17 @@ nsAccUtils::SetLiveContainerAttributes(n // container-relevant attribute if (relevant.IsEmpty() && nsAccUtils::HasDefinedARIAToken(ancestor, nsAccessibilityAtoms::aria_relevant) && ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_relevant, relevant)) SetAccAttr(aAttributes, nsAccessibilityAtoms::containerRelevant, relevant); // container-live, and container-live-role attributes if (live.IsEmpty()) { - nsCOMPtr<nsIDOMNode> node(do_QueryInterface(ancestor)); - nsRoleMapEntry *role = GetRoleMapEntry(node); + nsRoleMapEntry *role = GetRoleMapEntry(ancestor); if (nsAccUtils::HasDefinedARIAToken(ancestor, nsAccessibilityAtoms::aria_live)) { ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_live, live); } else if (role) { GetLiveAttrValue(role->liveAttRule, live); } if (!live.IsEmpty()) { @@ -338,56 +330,44 @@ nsAccUtils::HasDefinedARIAToken(nsIConte aContent->AttrValueIs(kNameSpaceID_None, aAtom, nsAccessibilityAtoms::_undefined, eCaseMatters)) { return PR_FALSE; } return PR_TRUE; } PRBool -nsAccUtils::HasAccessibleChildren(nsIDOMNode *aNode) +nsAccUtils::HasAccessibleChildren(nsINode *aNode) { if (!aNode) return PR_FALSE; - nsCOMPtr<nsIContent> content(do_QueryInterface(aNode)); - if (!content) - return PR_FALSE; - nsIPresShell *presShell = nsCoreUtils::GetPresShellFor(aNode); if (!presShell) return PR_FALSE; - nsIFrame *frame = content->GetPrimaryFrame(); - if (!frame) - return PR_FALSE; - + nsIContent *content = nsCoreUtils::GetRoleContent(aNode); nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell)); nsAccTreeWalker walker(weakShell, content, PR_FALSE); nsRefPtr<nsAccessible> accessible = walker.GetNextChild(); return accessible ? PR_TRUE : PR_FALSE; } -already_AddRefed<nsIAccessible> -nsAccUtils::GetAncestorWithRole(nsIAccessible *aDescendant, PRUint32 aRole) +nsAccessible * +nsAccUtils::GetAncestorWithRole(nsAccessible *aDescendant, PRUint32 aRole) { - nsCOMPtr<nsIAccessible> parentAccessible = aDescendant, testRoleAccessible; - while (NS_SUCCEEDED(parentAccessible->GetParent(getter_AddRefs(testRoleAccessible))) && - testRoleAccessible) { - PRUint32 testRole = nsAccUtils::Role(testRoleAccessible); - if (testRole == aRole) { - nsIAccessible *returnAccessible = testRoleAccessible; - NS_ADDREF(returnAccessible); - return returnAccessible; - } - nsCOMPtr<nsIAccessibleDocument> docAccessible = do_QueryInterface(testRoleAccessible); - if (docAccessible) { + nsAccessible *document = aDescendant->GetDocAccessible(); + nsAccessible *parent = aDescendant; + while ((parent = parent->GetParent())) { + PRUint32 testRole = nsAccUtils::Role(parent); + if (testRole == aRole) + return parent; + + if (parent == document) break; - } - parentAccessible.swap(testRoleAccessible); } return nsnull; } void nsAccUtils::GetARIATreeItemParent(nsIAccessible *aStartTreeItem, nsIContent *aStartContent, nsIAccessible **aTreeItemParentResult) @@ -482,77 +462,61 @@ nsAccUtils::GetARIATreeItemParent(nsIAcc role = nsAccUtils::Role(prevAccessible); } if (role == nsIAccessibleRole::ROLE_OUTLINEITEM) { // Previous sibling of parent group is a tree item -- this is the conceptual tree item parent NS_ADDREF(*aTreeItemParentResult = prevAccessible); } } -already_AddRefed<nsIAccessible> -nsAccUtils::GetSelectableContainer(nsIAccessible *aAccessible, PRUint32 aState) +nsAccessible * +nsAccUtils::GetSelectableContainer(nsAccessible *aAccessible, PRUint32 aState) { if (!aAccessible) return nsnull; if (!(aState & nsIAccessibleStates::STATE_SELECTABLE)) return nsnull; nsCOMPtr<nsIAccessibleSelectable> container; - nsCOMPtr<nsIAccessible> parent, accessible(aAccessible); + nsAccessible *parent = aAccessible; while (!container) { - accessible->GetParent(getter_AddRefs(parent)); - + parent = parent->GetParent(); if (!parent || Role(parent) == nsIAccessibleRole::ROLE_PANE) return nsnull; - container = do_QueryInterface(parent); - parent.swap(accessible); + container = do_QueryObject(parent); } - return accessible.forget(); + return parent; } -already_AddRefed<nsIAccessible> -nsAccUtils::GetMultiSelectableContainer(nsIDOMNode *aNode) +nsAccessible * +nsAccUtils::GetMultiSelectableContainer(nsINode *aNode) { - nsCOMPtr<nsIAccessible> accessible; - GetAccService()->GetAccessibleFor(aNode, getter_AddRefs(accessible)); - - nsCOMPtr<nsIAccessible> container = - GetSelectableContainer(accessible, State(accessible)); + nsAccessible *accessible = GetAccService()->GetAccessible(aNode); + nsAccessible *container = GetSelectableContainer(accessible, + State(accessible)); if (State(container) & nsIAccessibleStates::STATE_MULTISELECTABLE) - return container.forget(); - + return container; return nsnull; } PRBool -nsAccUtils::IsARIASelected(nsIAccessible *aAccessible) +nsAccUtils::IsARIASelected(nsAccessible *aAccessible) { - nsRefPtr<nsAccessible> acc = do_QueryObject(aAccessible); - nsCOMPtr<nsIDOMNode> node; - acc->GetDOMNode(getter_AddRefs(node)); - NS_ASSERTION(node, "No DOM node!"); - - if (node) { - nsCOMPtr<nsIContent> content(do_QueryInterface(node)); - if (content->AttrValueIs(kNameSpaceID_None, - nsAccessibilityAtoms::aria_selected, - nsAccessibilityAtoms::_true, eCaseMatters)) - return PR_TRUE; - } - - return PR_FALSE; + return aAccessible->GetContent()-> + AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::aria_selected, + nsAccessibilityAtoms::_true, eCaseMatters); } -already_AddRefed<nsIAccessibleText> +already_AddRefed<nsHyperTextAccessible> nsAccUtils::GetTextAccessibleFromSelection(nsISelection *aSelection, - nsIDOMNode **aNode) + nsINode **aNode) { // Get accessible from selection's focus DOM point (the DOM point where // selection is ended). nsCOMPtr<nsIDOMNode> focusDOMNode; aSelection->GetFocusNode(getter_AddRefs(focusDOMNode)); if (!focusDOMNode) return nsnull; @@ -563,51 +527,43 @@ nsAccUtils::GetTextAccessibleFromSelecti nsCOMPtr<nsINode> focusNode(do_QueryInterface(focusDOMNode)); nsCOMPtr<nsINode> resultNode = nsCoreUtils::GetDOMNodeFromDOMPoint(focusNode, focusOffset); // Get text accessible containing the result node. while (resultNode) { // Make sure to get the correct starting node for selection events inside // XBL content trees. - nsCOMPtr<nsIDOMNode> resultDOMNode(do_QueryInterface(resultNode)); - nsCOMPtr<nsIDOMNode> relevantDOMNode; - GetAccService()->GetRelevantContentNodeFor(resultDOMNode, - getter_AddRefs(relevantDOMNode)); - if (relevantDOMNode) { - resultNode = do_QueryInterface(relevantDOMNode); - resultDOMNode.swap(relevantDOMNode); - } - - if (!resultNode || !resultNode->IsNodeOfType(nsINode::eTEXT)) { - nsAccessible *accessible = GetAccService()->GetAccessible(resultDOMNode); + resultNode = GetAccService()->GetRelevantContentNodeFor(resultNode); + if (!resultNode->IsNodeOfType(nsINode::eTEXT)) { + nsAccessible *accessible = GetAccService()->GetAccessible(resultNode); if (accessible) { - nsIAccessibleText *textAcc = nsnull; + nsHyperTextAccessible *textAcc = nsnull; CallQueryInterface(accessible, &textAcc); if (textAcc) { if (aNode) - resultDOMNode.forget(aNode); + NS_ADDREF(*aNode = resultNode); return textAcc; } } } - resultNode = resultNode->GetParent(); + resultNode = resultNode->GetNodeParent(); } NS_NOTREACHED("No nsIAccessibleText for selection change event!"); return nsnull; } nsresult nsAccUtils::ConvertToScreenCoords(PRInt32 aX, PRInt32 aY, PRUint32 aCoordinateType, - nsIAccessNode *aAccessNode, + nsAccessNode *aAccessNode, nsIntPoint *aCoords) { NS_ENSURE_ARG_POINTER(aCoords); aCoords->MoveTo(aX, aY); switch (aCoordinateType) { case nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE: @@ -632,17 +588,17 @@ nsAccUtils::ConvertToScreenCoords(PRInt3 } return NS_OK; } nsresult nsAccUtils::ConvertScreenCoordsTo(PRInt32 *aX, PRInt32 *aY, PRUint32 aCoordinateType, - nsIAccessNode *aAccessNode) + nsAccessNode *aAccessNode) { switch (aCoordinateType) { case nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE: break; case nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE: { NS_ENSURE_ARG(aAccessNode); @@ -664,54 +620,39 @@ nsAccUtils::ConvertScreenCoordsTo(PRInt3 default: return NS_ERROR_INVALID_ARG; } return NS_OK; } nsIntPoint -nsAccUtils::GetScreenCoordsForWindow(nsIAccessNode *aAccessNode) +nsAccUtils::GetScreenCoordsForWindow(nsAccessNode *aAccessNode) { - nsCOMPtr<nsIDOMNode> DOMNode; - aAccessNode->GetDOMNode(getter_AddRefs(DOMNode)); - if (DOMNode) - return nsCoreUtils::GetScreenCoordsForWindow(DOMNode); - - return nsIntPoint(0, 0); + return nsCoreUtils::GetScreenCoordsForWindow(aAccessNode->GetNode()); } nsIntPoint -nsAccUtils::GetScreenCoordsForParent(nsIAccessNode *aAccessNode) +nsAccUtils::GetScreenCoordsForParent(nsAccessNode *aAccessNode) { - nsRefPtr<nsAccessNode> parent; - nsCOMPtr<nsIAccessible> accessible(do_QueryInterface(aAccessNode)); - if (accessible) { - nsCOMPtr<nsIAccessible> parentAccessible; - accessible->GetParent(getter_AddRefs(parentAccessible)); - parent = do_QueryObject(parentAccessible); - } else { - nsCOMPtr<nsIAccessNode> parentAccessNode; - aAccessNode->GetParentNode(getter_AddRefs(parentAccessNode)); - parent = do_QueryObject(parentAccessNode); - } - + nsAccessible *parent = + GetAccService()->GetContainerAccessible(aAccessNode->GetNode(), PR_TRUE); if (!parent) return nsIntPoint(0, 0); nsIFrame *parentFrame = parent->GetFrame(); if (!parentFrame) return nsIntPoint(0, 0); nsIntRect parentRect = parentFrame->GetScreenRectExternal(); return nsIntPoint(parentRect.x, parentRect.y); } nsRoleMapEntry* -nsAccUtils::GetRoleMapEntry(nsIDOMNode *aNode) +nsAccUtils::GetRoleMapEntry(nsINode *aNode) { nsIContent *content = nsCoreUtils::GetRoleContent(aNode); nsAutoString roleString; if (!content || !content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::role, roleString) || roleString.IsEmpty()) { // We treat role="" as if the role attribute is absent (per aria spec:8.1.1) return nsnull; @@ -870,21 +811,19 @@ nsAccUtils::MustPrune(nsIAccessible *aAc role == nsIAccessibleRole::ROLE_TOGGLE_BUTTON || role == nsIAccessibleRole::ROLE_GRAPHIC || role == nsIAccessibleRole::ROLE_SLIDER || role == nsIAccessibleRole::ROLE_PROGRESSBAR || role == nsIAccessibleRole::ROLE_SEPARATOR; } PRBool -nsAccUtils::IsNodeRelevant(nsIDOMNode *aNode) +nsAccUtils::IsNodeRelevant(nsINode *aNode) { - nsCOMPtr<nsIDOMNode> relevantNode; - GetAccService()->GetRelevantContentNodeFor(aNode, getter_AddRefs(relevantNode)); - return aNode == relevantNode; + return aNode == GetAccService()->GetRelevantContentNodeFor(aNode); } nsresult nsAccUtils::GetHeaderCellsFor(nsIAccessibleTable *aTable, nsIAccessibleTableCell *aCell, PRInt32 aRowOrColHeaderCells, nsIArray **aCells) { nsresult rv = NS_OK;
--- a/accessible/src/base/nsAccUtils.h +++ b/accessible/src/base/nsAccUtils.h @@ -40,25 +40,31 @@ #define nsAccUtils_h_ #include "nsIAccessible.h" #include "nsIAccessNode.h" #include "nsIAccessibleDocument.h" #include "nsIAccessibleRole.h" #include "nsIAccessibleText.h" #include "nsIAccessibleTable.h" + #include "nsARIAMap.h" +#include "nsAccessibilityService.h" +#include "nsCoreUtils.h" +#include "nsIContent.h" +#include "nsIDocShell.h" #include "nsIDOMNode.h" #include "nsIPersistentProperties2.h" -#include "nsIContent.h" +#include "nsIPresShell.h" #include "nsPoint.h" class nsAccessNode; class nsAccessible; +class nsHyperTextAccessible; class nsHTMLTableAccessible; class nsDocAccessible; #ifdef MOZ_XUL class nsXULTreeAccessible; #endif class nsAccUtils { @@ -96,38 +102,38 @@ public: * Get default value of the level for the given accessible. */ static PRInt32 GetDefaultLevel(nsAccessible *aAcc); /** * Return ARIA level value or the default one if ARIA is missed for the * given accessible. */ - static PRInt32 GetARIAOrDefaultLevel(nsIAccessible *aAcc); + static PRInt32 GetARIAOrDefaultLevel(nsAccessible *aAccessible); /** * Compute position in group (posinset) and group size (setsize) for * nsIDOMXULSelectControlItemElement node. */ - static void GetPositionAndSizeForXULSelectControlItem(nsIDOMNode *aNode, + static void GetPositionAndSizeForXULSelectControlItem(nsIContent *aContent, PRInt32 *aPosInSet, PRInt32 *aSetSize); /** * Compute group position and group size (posinset and setsize) for * nsIDOMXULContainerItemElement node. */ - static void GetPositionAndSizeForXULContainerItem(nsIDOMNode *aNode, + static void GetPositionAndSizeForXULContainerItem(nsIContent *aContent, PRInt32 *aPosInSet, PRInt32 *aSetSize); /** * Compute group level for nsIDOMXULContainerItemElement node. */ - static PRInt32 GetLevelForXULContainerItem(nsIDOMNode *aNode); + static PRInt32 GetLevelForXULContainerItem(nsIContent *aContent); /** * Set container-foo live region attributes for the given node. * * @param aAttributes where to store the attributes * @param aStartContent node to start from * @param aTopContent node to end at */ @@ -140,28 +146,62 @@ public: * property is not present, or is "" or "undefined". Do not call * this method for properties of type string, decimal, IDREF or IDREFS. * * Return PR_TRUE if the ARIA property is defined, otherwise PR_FALSE */ static PRBool HasDefinedARIAToken(nsIContent *aContent, nsIAtom *aAtom); /** - * Return true if the given DOM node contains accessible children. + * Return document accessible for the given presshell. */ - static PRBool HasAccessibleChildren(nsIDOMNode *aNode); + static nsDocAccessible *GetDocAccessibleFor(nsIWeakReference *aWeakShell) + { + nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(aWeakShell)); + return presShell ? + GetAccService()->GetDocAccessible(presShell->GetDocument()) : nsnull; + } + + /** + * Return document accessible for the given DOM node. + */ + static nsDocAccessible *GetDocAccessibleFor(nsINode *aNode) + { + nsIPresShell *presShell = nsCoreUtils::GetPresShellFor(aNode); + return presShell ? + GetAccService()->GetDocAccessible(presShell->GetDocument()) : nsnull; + } /** - * If an ancestor in this document exists with the given role, return it - * @param aDescendant Descendant to start search with - * @param aRole Role to find matching ancestor for - * @return The ancestor accessible with the given role, or nsnull if no match is found + * Return document accessible for the given docshell. + */ + static nsDocAccessible *GetDocAccessibleFor(nsIDocShellTreeItem *aContainer) + { + nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aContainer)); + nsCOMPtr<nsIPresShell> presShell; + docShell->GetPresShell(getter_AddRefs(presShell)); + return presShell ? + GetAccService()->GetDocAccessible(presShell->GetDocument()) : nsnull; + } + + /** + * Return true if the given DOM node contains accessible children. + */ + static PRBool HasAccessibleChildren(nsINode *aNode); + + /** + * Return ancestor in this document with the given role if it exists. + * + * @param aDescendant [in] descendant to start search with + * @param aRole [in] role to find matching ancestor for + * @return the ancestor accessible with the given role, or + * nsnull if no match is found */ - static already_AddRefed<nsIAccessible> - GetAncestorWithRole(nsIAccessible *aDescendant, PRUint32 aRole); + static nsAccessible * GetAncestorWithRole(nsAccessible *aDescendant, + PRUint32 aRole); /** * For an ARIA tree item , get the accessible that represents its conceptual parent. * This method will use the correct method for the given way the tree is constructed. * The conceptual parent is what the user sees as the parent, not the DOM or accessible parent. * @param aStartTreeItem The tree item to get the parent for * @param aStartTreeItemContent The content node for the tree item * @param The tree item's parent, or null if none @@ -172,95 +212,96 @@ public: nsIAccessible **aTreeItemParent); /** * Return single or multi selectable container for the given item. * * @param aAccessible [in] the item accessible * @param aState [in] the state of the item accessible */ - static already_AddRefed<nsIAccessible> - GetSelectableContainer(nsIAccessible *aAccessible, PRUint32 aState); + static nsAccessible *GetSelectableContainer(nsAccessible *aAccessible, + PRUint32 aState); /** * Return multi selectable container for the given item. */ - static already_AddRefed<nsIAccessible> - GetMultiSelectableContainer(nsIDOMNode *aNode); + static nsAccessible *GetMultiSelectableContainer(nsINode *aNode); /** * Return true if the DOM node of given accessible has aria-selected="true" * attribute. */ - static PRBool IsARIASelected(nsIAccessible *aAccessible); + static PRBool IsARIASelected(nsAccessible *aAccessible); /** * Return text accessible containing focus point of the given selection. * Used for normal and misspelling selection changes processing. * * @param aSelection [in] the given selection * @param aNode [out, optional] the DOM node of text accessible * @return text accessible */ - static already_AddRefed<nsIAccessibleText> + static already_AddRefed<nsHyperTextAccessible> GetTextAccessibleFromSelection(nsISelection *aSelection, - nsIDOMNode **aNode = nsnull); + nsINode **aNode = nsnull); /** * Converts the given coordinates to coordinates relative screen. * * @param aX [in] the given x coord * @param aY [in] the given y coord * @param aCoordinateType [in] specifies coordinates origin (refer to * nsIAccessibleCoordinateType) * @param aAccessNode [in] the accessible if coordinates are given * relative it. * @param aCoords [out] converted coordinates */ static nsresult ConvertToScreenCoords(PRInt32 aX, PRInt32 aY, PRUint32 aCoordinateType, - nsIAccessNode *aAccessNode, + nsAccessNode *aAccessNode, nsIntPoint *aCoords); /** * Converts the given coordinates relative screen to another coordinate * system. * * @param aX [in, out] the given x coord * @param aY [in, out] the given y coord * @param aCoordinateType [in] specifies coordinates origin (refer to * nsIAccessibleCoordinateType) * @param aAccessNode [in] the accessible if coordinates are given * relative it */ static nsresult ConvertScreenCoordsTo(PRInt32 *aX, PRInt32 *aY, PRUint32 aCoordinateType, - nsIAccessNode *aAccessNode); + nsAccessNode *aAccessNode); /** * Returns coordinates relative screen for the top level window. * * @param aAccessNode the accessible hosted in the window */ - static nsIntPoint GetScreenCoordsForWindow(nsIAccessNode *aAccessNode); + static nsIntPoint GetScreenCoordsForWindow(nsAccessNode *aAccessNode); /** * Returns coordinates relative screen for the parent of the given accessible. * * @param aAccessNode the accessible */ - static nsIntPoint GetScreenCoordsForParent(nsIAccessNode *aAccessNode); + static nsIntPoint GetScreenCoordsForParent(nsAccessNode *aAccessNode); /** * Get the role map entry for a given DOM node. This will use the first * ARIA role if the role attribute provides a space delimited list of roles. - * @param aNode The DOM node to get the role map entry for - * @return A pointer to the role map entry for the ARIA role, or nsnull if none + * + * @param aNode [in] the DOM node to get the role map entry for + * @return a pointer to the role map entry for the ARIA role, or nsnull + * if none */ - static nsRoleMapEntry* GetRoleMapEntry(nsIDOMNode *aNode); + static nsRoleMapEntry *GetRoleMapEntry(nsINode *aNode); /** * Return the role of the given accessible. */ static PRUint32 Role(nsIAccessible *aAcc) { PRUint32 role = nsIAccessibleRole::ROLE_NOTHING; if (aAcc) @@ -368,17 +409,17 @@ public: * to platform accessibility APIs, should the children be pruned off? */ static PRBool MustPrune(nsIAccessible *aAccessible); /** * Return true if the given node can be accessible and attached to * the document's accessible tree. */ - static PRBool IsNodeRelevant(nsIDOMNode *aNode); + static PRBool IsNodeRelevant(nsINode *aNode); /** * Search hint enum constants. Used by GetHeaderCellsFor() method. */ enum { // search for row header cells, left direction eRowHeaderCells, // search for column header cells, top direction
--- a/accessible/src/base/nsAccessNode.cpp +++ b/accessible/src/base/nsAccessNode.cpp @@ -75,22 +75,20 @@ #include "mozilla/Services.h" /* For documentation of the accessibility architecture, * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html */ nsIStringBundle *nsAccessNode::gStringBundle = 0; nsIStringBundle *nsAccessNode::gKeyStringBundle = 0; -nsIDOMNode *nsAccessNode::gLastFocusedNode = 0; +nsINode *nsAccessNode::gLastFocusedNode = nsnull; PRBool nsAccessNode::gIsCacheDisabled = PR_FALSE; PRBool nsAccessNode::gIsFormFillEnabled = PR_FALSE; -nsRefPtrHashtable<nsVoidPtrHashKey, nsDocAccessible> - nsAccessNode::gGlobalDocAccessibleCache; nsApplicationAccessible *nsAccessNode::gApplicationAccessible = nsnull; /* * Class nsAccessNode */ //////////////////////////////////////////////////////////////////////////////// @@ -106,18 +104,19 @@ NS_INTERFACE_MAP_END NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsAccessNode, nsIAccessNode) NS_IMPL_CYCLE_COLLECTING_RELEASE_FULL(nsAccessNode, nsIAccessNode, LastRelease()) //////////////////////////////////////////////////////////////////////////////// // nsAccessNode construction/desctruction -nsAccessNode::nsAccessNode(nsIDOMNode *aNode, nsIWeakReference* aShell): - mDOMNode(aNode), mWeakShell(aShell) +nsAccessNode:: + nsAccessNode(nsIContent *aContent, nsIWeakReference *aShell) : + mContent(aContent), mWeakShell(aShell) { #ifdef DEBUG_A11Y mIsInitialized = PR_FALSE; #endif } nsAccessNode::~nsAccessNode() { @@ -133,103 +132,54 @@ void nsAccessNode::LastRelease() } // ... then die. NS_DELETEXPCOM(this); } //////////////////////////////////////////////////////////////////////////////// // nsAccessNode public -nsresult +PRBool nsAccessNode::Init() { - // We have to put this here, instead of constructor, otherwise - // we don't have the virtual GetUniqueID() method for the hash key. - // We need that for accessibles that don't have DOM nodes - -#ifdef DEBUG_A11Y - NS_ASSERTION(!mIsInitialized, "Initialized twice!"); -#endif - nsRefPtr<nsDocAccessible> docAcc = GetDocAccessible(); - if (!docAcc) { - // No doc accessible yet for this node's document. - // There was probably an accessible event fired before the - // current document was ever asked for by the assistive technology. - // Create a doc accessible so we can cache this node - nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell)); - if (presShell) { - nsCOMPtr<nsIDOMNode> docNode(do_QueryInterface(presShell->GetDocument())); - if (docNode) { - nsAccessible *accessible = - GetAccService()->GetAccessibleInWeakShell(docNode, mWeakShell); - docAcc = do_QueryObject(accessible); - } - } - NS_ASSERTION(docAcc, "Cannot cache new nsAccessNode"); - if (!docAcc) { - return NS_ERROR_FAILURE; - } - } - - void* uniqueID; - GetUniqueID(&uniqueID); - - if (!docAcc->CacheAccessNode(uniqueID, this)) - return NS_ERROR_OUT_OF_MEMORY; - - // Make sure an ancestor in real content is cached - // so that nsDocAccessible::RefreshNodes() can find the anonymous subtree to release when - // the root node goes away - nsCOMPtr<nsIContent> content = do_QueryInterface(mDOMNode); - if (content && content->IsInAnonymousSubtree()) { - // Specific examples of where this is used: <input type="file"> and <xul:findbar> - nsAccessible *parent = GetAccService()->GetContainerAccessible(mDOMNode, - PR_TRUE); - if (parent) - parent->EnsureChildren(); - } - -#ifdef DEBUG_A11Y - mIsInitialized = PR_TRUE; -#endif - - return NS_OK; + return PR_TRUE; } -nsresult +void nsAccessNode::Shutdown() { - mDOMNode = nsnull; + mContent = nsnull; mWeakShell = nsnull; - - return NS_OK; } // nsIAccessNode NS_IMETHODIMP nsAccessNode::GetUniqueID(void **aUniqueID) { - *aUniqueID = static_cast<void*>(mDOMNode); + *aUniqueID = static_cast<void*>(GetNode()); return NS_OK; } // nsIAccessNode -NS_IMETHODIMP nsAccessNode::GetOwnerWindow(void **aWindow) +NS_IMETHODIMP +nsAccessNode::GetOwnerWindow(void **aWindow) { + NS_ENSURE_ARG_POINTER(aWindow); *aWindow = nsnull; - nsCOMPtr<nsIAccessibleDocument> docAccessible(GetDocAccessible()); - if (!docAccessible) - return NS_ERROR_FAILURE; // This node or doc accessible is shut down - return docAccessible->GetWindowHandle(aWindow); + + if (IsDefunct()) + return NS_ERROR_FAILURE; + + return GetDocAccessible()->GetWindowHandle(aWindow); } nsApplicationAccessible* nsAccessNode::GetApplicationAccessible() { - NS_ASSERTION(!nsAccessibilityService::gIsShutdown, + NS_ASSERTION(!nsAccessibilityService::IsShutdown(), "Accessibility wasn't initialized!"); if (!gApplicationAccessible) { nsApplicationAccessibleWrap::PreCreate(); gApplicationAccessible = new nsApplicationAccessibleWrap(); if (!gApplicationAccessible) return nsnull; @@ -257,18 +207,16 @@ void nsAccessNode::InitXPAccessibility() stringBundleService->CreateBundle(ACCESSIBLE_BUNDLE_URL, &gStringBundle); stringBundleService->CreateBundle(PLATFORM_KEYS_BUNDLE_URL, &gKeyStringBundle); } nsAccessibilityAtoms::AddRefAtoms(); - gGlobalDocAccessibleCache.Init(4); - nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID)); if (prefBranch) { prefBranch->GetBoolPref("accessibility.disablecache", &gIsCacheDisabled); prefBranch->GetBoolPref("browser.formfill.enable", &gIsFormFillEnabled); } NotifyA11yInitOrShutdown(PR_TRUE); } @@ -293,33 +241,31 @@ void nsAccessNode::ShutdownXPAccessibili // Called by nsAccessibilityService::Shutdown() // which happens when xpcom is shutting down // at exit of program NS_IF_RELEASE(gStringBundle); NS_IF_RELEASE(gKeyStringBundle); NS_IF_RELEASE(gLastFocusedNode); - ClearCache(gGlobalDocAccessibleCache); - // Release gApplicationAccessible after everything else is shutdown // so we don't accidently create it again while tearing down root accessibles nsApplicationAccessibleWrap::Unload(); if (gApplicationAccessible) { gApplicationAccessible->Shutdown(); NS_RELEASE(gApplicationAccessible); } NotifyA11yInitOrShutdown(PR_FALSE); } PRBool nsAccessNode::IsDefunct() { - if (!mDOMNode) + if (!mContent) return PR_TRUE; // Call GetPresShell() since the accessible may be shut down in it. nsCOMPtr<nsIPresShell> presShell(GetPresShell()); return !presShell; } already_AddRefed<nsIPresShell> nsAccessNode::GetPresShell() @@ -344,100 +290,71 @@ nsPresContext* nsAccessNode::GetPresCont { nsCOMPtr<nsIPresShell> presShell(GetPresShell()); if (!presShell) { return nsnull; } return presShell->GetPresContext(); } +nsDocAccessible * +nsAccessNode::GetDocAccessible() const +{ + return mContent ? + GetAccService()->GetDocAccessible(mContent->GetOwnerDoc()) : nsnull; +} + already_AddRefed<nsRootAccessible> nsAccessNode::GetRootAccessible() { nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = - nsCoreUtils::GetDocShellTreeItemFor(mDOMNode); - NS_ASSERTION(docShellTreeItem, "No docshell tree item for mDOMNode"); + nsCoreUtils::GetDocShellTreeItemFor(mContent); + NS_ASSERTION(docShellTreeItem, "No docshell tree item for mContent"); if (!docShellTreeItem) { return nsnull; } nsCOMPtr<nsIDocShellTreeItem> root; docShellTreeItem->GetRootTreeItem(getter_AddRefs(root)); NS_ASSERTION(root, "No root content tree item"); if (!root) { return nsnull; } - nsCOMPtr<nsIAccessibleDocument> accDoc = GetDocAccessibleFor(root); - if (!accDoc) { - return nsnull; - } - - // nsRootAccessible has a special QI - // that let us get that concrete type directly. - nsRootAccessible* rootAccessible; - accDoc->QueryInterface(NS_GET_IID(nsRootAccessible), (void**)&rootAccessible); // addrefs - return rootAccessible; + nsDocAccessible *docAcc = nsAccUtils::GetDocAccessibleFor(root); + nsRefPtr<nsRootAccessible> rootAcc = do_QueryObject(docAcc); + return rootAcc.forget(); } nsIFrame* nsAccessNode::GetFrame() { - nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode)); - return content ? content->GetPrimaryFrame() : nsnull; + return mContent ? mContent->GetPrimaryFrame() : nsnull; } -#ifdef DEBUG -PRBool -nsAccessNode::IsInCache() -{ - nsCOMPtr<nsIAccessibleDocument> accessibleDoc = - nsAccessNode::GetDocAccessibleFor(mWeakShell); - - if (!accessibleDoc) - return nsnull; - - void* uniqueID = nsnull; - GetUniqueID(&uniqueID); - - nsRefPtr<nsDocAccessible> docAccessible = do_QueryObject(accessibleDoc); - return docAccessible->GetCachedAccessNode(uniqueID) ? PR_TRUE : PR_FALSE; -} -#endif - //////////////////////////////////////////////////////////////////////////////// // nsIAccessNode NS_IMETHODIMP -nsAccessNode::GetDOMNode(nsIDOMNode **aNode) -{ - NS_IF_ADDREF(*aNode = mDOMNode); - return NS_OK; -} - -NS_IMETHODIMP -nsAccessNode::GetNumChildren(PRInt32 *aNumChildren) +nsAccessNode::GetDOMNode(nsIDOMNode **aDOMNode) { - nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode)); - - if (!content) { - *aNumChildren = 0; + NS_ENSURE_ARG_POINTER(aDOMNode); + *aDOMNode = nsnull; - return NS_ERROR_NULL_POINTER; - } - - *aNumChildren = content->GetChildCount(); + nsINode *node = GetNode(); + if (node) + CallQueryInterface(node, aDOMNode); return NS_OK; } NS_IMETHODIMP nsAccessNode::GetDocument(nsIAccessibleDocument **aDocument) { NS_ENSURE_ARG_POINTER(aDocument); - NS_IF_ADDREF(*aDocument = GetDocAccessibleFor(mWeakShell)); + NS_IF_ADDREF(*aDocument = GetDocAccessible()); return NS_OK; } NS_IMETHODIMP nsAccessNode::GetRootDocument(nsIAccessibleDocument **aRootDocument) { NS_ENSURE_ARG_POINTER(aRootDocument); @@ -446,17 +363,17 @@ nsAccessNode::GetRootDocument(nsIAccessi return NS_OK; } NS_IMETHODIMP nsAccessNode::GetInnerHTML(nsAString& aInnerHTML) { aInnerHTML.Truncate(); - nsCOMPtr<nsIDOMNSHTMLElement> domNSElement(do_QueryInterface(mDOMNode)); + nsCOMPtr<nsIDOMNSHTMLElement> domNSElement(do_QueryInterface(mContent)); NS_ENSURE_TRUE(domNSElement, NS_ERROR_NULL_POINTER); return domNSElement->GetInnerHTML(aInnerHTML); } NS_IMETHODIMP nsAccessNode::ScrollTo(PRUint32 aScrollType) { @@ -491,301 +408,98 @@ nsAccessNode::ScrollToPoint(PRUint32 aCo nsIFrame *parentFrame = frame; while ((parentFrame = parentFrame->GetParent())) nsCoreUtils::ScrollFrameToPoint(parentFrame, frame, coords); return NS_OK; } -// nsAccessNode protected -nsresult -nsAccessNode::MakeAccessNode(nsIDOMNode *aNode, nsIAccessNode **aAccessNode) -{ - *aAccessNode = nsnull; - - nsCOMPtr<nsIAccessNode> accessNode = - GetAccService()->GetCachedAccessNode(aNode, mWeakShell); - - if (!accessNode) - accessNode = GetAccService()->GetAccessibleInWeakShell(aNode, mWeakShell); - - if (accessNode) { - NS_ADDREF(*aAccessNode = accessNode); - return NS_OK; - } - - nsAccessNode *newAccessNode = new nsAccessNode(aNode, mWeakShell); - if (!newAccessNode) { - return NS_ERROR_OUT_OF_MEMORY; - } - - NS_ADDREF(*aAccessNode = newAccessNode); - newAccessNode->Init(); - - return NS_OK; -} - -NS_IMETHODIMP -nsAccessNode::GetFirstChildNode(nsIAccessNode **aAccessNode) -{ - NS_ENSURE_ARG_POINTER(aAccessNode); - *aAccessNode = nsnull; - NS_ENSURE_TRUE(mDOMNode, NS_ERROR_NULL_POINTER); - - nsCOMPtr<nsIDOMNode> domNode; - mDOMNode->GetFirstChild(getter_AddRefs(domNode)); - - return domNode ? MakeAccessNode(domNode, aAccessNode) : NS_OK; -} - -NS_IMETHODIMP -nsAccessNode::GetLastChildNode(nsIAccessNode **aAccessNode) -{ - NS_ENSURE_ARG_POINTER(aAccessNode); - *aAccessNode = nsnull; - NS_ENSURE_TRUE(mDOMNode, NS_ERROR_NULL_POINTER); - - nsCOMPtr<nsIDOMNode> domNode; - mDOMNode->GetLastChild(getter_AddRefs(domNode)); - - return domNode ? MakeAccessNode(domNode, aAccessNode) : NS_OK; -} - -NS_IMETHODIMP -nsAccessNode::GetParentNode(nsIAccessNode **aAccessNode) -{ - NS_ENSURE_ARG_POINTER(aAccessNode); - *aAccessNode = nsnull; - NS_ENSURE_TRUE(mDOMNode, NS_ERROR_NULL_POINTER); - - nsCOMPtr<nsIDOMNode> domNode; - mDOMNode->GetParentNode(getter_AddRefs(domNode)); - - return domNode ? MakeAccessNode(domNode, aAccessNode) : NS_OK; -} - -NS_IMETHODIMP -nsAccessNode::GetPreviousSiblingNode(nsIAccessNode **aAccessNode) -{ - NS_ENSURE_ARG_POINTER(aAccessNode); - *aAccessNode = nsnull; - NS_ENSURE_TRUE(mDOMNode, NS_ERROR_NULL_POINTER); - - nsCOMPtr<nsIDOMNode> domNode; - mDOMNode->GetPreviousSibling(getter_AddRefs(domNode)); - - return domNode ? MakeAccessNode(domNode, aAccessNode) : NS_OK; -} - -NS_IMETHODIMP -nsAccessNode::GetNextSiblingNode(nsIAccessNode **aAccessNode) -{ - NS_ENSURE_ARG_POINTER(aAccessNode); - *aAccessNode = nsnull; - NS_ENSURE_TRUE(mDOMNode, NS_ERROR_NULL_POINTER); - - nsCOMPtr<nsIDOMNode> domNode; - mDOMNode->GetNextSibling(getter_AddRefs(domNode)); - - return domNode ? MakeAccessNode(domNode, aAccessNode) : NS_OK; -} - -NS_IMETHODIMP -nsAccessNode::GetChildNodeAt(PRInt32 aChildNum, nsIAccessNode **aAccessNode) -{ - NS_ENSURE_ARG_POINTER(aAccessNode); - *aAccessNode = nsnull; - - nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode)); - NS_ENSURE_TRUE(content, NS_ERROR_NULL_POINTER); - - nsCOMPtr<nsIDOMNode> domNode = - do_QueryInterface(content->GetChildAt(aChildNum)); - - return domNode ? MakeAccessNode(domNode, aAccessNode) : NS_OK; -} - NS_IMETHODIMP nsAccessNode::GetComputedStyleValue(const nsAString& aPseudoElt, const nsAString& aPropertyName, nsAString& aValue) { if (IsDefunct()) return NS_ERROR_FAILURE; - nsCOMPtr<nsIDOMCSSStyleDeclaration> styleDecl; - nsCoreUtils::GetComputedStyleDeclaration(aPseudoElt, mDOMNode, - getter_AddRefs(styleDecl)); + nsCOMPtr<nsIDOMCSSStyleDeclaration> styleDecl = + nsCoreUtils::GetComputedStyleDeclaration(aPseudoElt, mContent); NS_ENSURE_TRUE(styleDecl, NS_ERROR_FAILURE); return styleDecl->GetPropertyValue(aPropertyName, aValue); } NS_IMETHODIMP nsAccessNode::GetComputedStyleCSSValue(const nsAString& aPseudoElt, const nsAString& aPropertyName, nsIDOMCSSPrimitiveValue **aCSSValue) { NS_ENSURE_ARG_POINTER(aCSSValue); *aCSSValue = nsnull; if (IsDefunct()) return NS_ERROR_FAILURE; - nsCOMPtr<nsIDOMCSSStyleDeclaration> styleDecl; - nsCoreUtils::GetComputedStyleDeclaration(aPseudoElt, mDOMNode, - getter_AddRefs(styleDecl)); + nsCOMPtr<nsIDOMCSSStyleDeclaration> styleDecl = + nsCoreUtils::GetComputedStyleDeclaration(aPseudoElt, mContent); NS_ENSURE_STATE(styleDecl); nsCOMPtr<nsIDOMCSSValue> cssValue; styleDecl->GetPropertyCSSValue(aPropertyName, getter_AddRefs(cssValue)); NS_ENSURE_TRUE(cssValue, NS_ERROR_FAILURE); return CallQueryInterface(cssValue, aCSSValue); } -//////////////////////////////////////////////////////////////////////////////// -// nsAccessNode public static - -nsDocAccessible* -nsAccessNode::GetDocAccessibleFor(nsIDocument *aDocument) -{ - return aDocument ? - gGlobalDocAccessibleCache.GetWeak(static_cast<void*>(aDocument)) : nsnull; -} - -nsDocAccessible* -nsAccessNode::GetDocAccessibleFor(nsIWeakReference *aWeakShell) -{ - nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(aWeakShell)); - if (!presShell) { - return nsnull; - } - - return GetDocAccessibleFor(presShell->GetDocument()); -} - -already_AddRefed<nsIAccessibleDocument> -nsAccessNode::GetDocAccessibleFor(nsIDocShellTreeItem *aContainer, - PRBool aCanCreate) +// nsAccessNode public +already_AddRefed<nsINode> +nsAccessNode::GetCurrentFocus() { - if (!aCanCreate) { - nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aContainer)); - NS_ASSERTION(docShell, "This method currently only supports docshells"); - nsCOMPtr<nsIPresShell> presShell; - docShell->GetPresShell(getter_AddRefs(presShell)); - if (!presShell) - return nsnull; - - nsDocAccessible *docAcc = GetDocAccessibleFor(presShell->GetDocument()); - NS_IF_ADDREF(docAcc); - return docAcc; - } - - nsCOMPtr<nsIDOMNode> node = nsCoreUtils::GetDOMNodeForContainer(aContainer); - if (!node) { - return nsnull; - } - - nsCOMPtr<nsIAccessible> accessible; - GetAccService()->GetAccessibleFor(node, getter_AddRefs(accessible)); - nsIAccessibleDocument *docAccessible = nsnull; - if (accessible) { - CallQueryInterface(accessible, &docAccessible); - } - return docAccessible; -} - -nsDocAccessible* -nsAccessNode::GetDocAccessibleFor(nsIDOMNode *aNode) -{ - nsIPresShell *presShell = nsCoreUtils::GetPresShellFor(aNode); - if (presShell) - return GetDocAccessibleFor(presShell->GetDocument()); - - nsCOMPtr<nsIDocument> doc(do_QueryInterface(aNode)); - if (doc) { - return GetDocAccessibleFor(doc); - } - - return nsnull; -} - -already_AddRefed<nsIDOMNode> nsAccessNode::GetCurrentFocus() -{ - nsIPresShell *shell = nsCoreUtils::GetPresShellFor(mDOMNode); + // XXX: consider to use nsFocusManager directly, it allows us to avoid + // unnecessary query interface calls. + nsCOMPtr<nsIPresShell> shell = GetPresShell(); NS_ENSURE_TRUE(shell, nsnull); - nsCOMPtr<nsIDocument> doc = shell->GetDocument(); + nsIDocument *doc = shell->GetDocument(); NS_ENSURE_TRUE(doc, nsnull); nsIDOMWindow* win = doc->GetWindow(); nsCOMPtr<nsIDOMWindow> focusedWindow; nsCOMPtr<nsIDOMElement> focusedElement; nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID); if (fm) fm->GetFocusedElementForWindow(win, PR_TRUE, getter_AddRefs(focusedWindow), getter_AddRefs(focusedElement)); - nsIDOMNode *focusedNode = nsnull; + nsINode *focusedNode = nsnull; if (focusedElement) { CallQueryInterface(focusedElement, &focusedNode); } else if (focusedWindow) { nsCOMPtr<nsIDOMDocument> doc; focusedWindow->GetDocument(getter_AddRefs(doc)); if (doc) CallQueryInterface(doc, &focusedNode); } return focusedNode; } -// nsIAccessNode NS_IMETHODIMP nsAccessNode::GetLanguage(nsAString& aLanguage) { aLanguage.Truncate(); - nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode)); - if (!content) { - // For documents make sure we look for lang attribute on - // document element - nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(mDOMNode)); - if (domDoc) { - nsCOMPtr<nsIDOMHTMLDocument> htmlDoc(do_QueryInterface(mDOMNode)); - if (htmlDoc) { - // Make sure we look for lang attribute on HTML <body> - nsCOMPtr<nsIDOMHTMLElement> bodyElement; - htmlDoc->GetBody(getter_AddRefs(bodyElement)); - content = do_QueryInterface(bodyElement); - } - if (!content) { - nsCOMPtr<nsIDOMElement> docElement; - domDoc->GetDocumentElement(getter_AddRefs(docElement)); - content = do_QueryInterface(docElement); - } - } - if (!content) { - return NS_ERROR_FAILURE; - } - } - nsCoreUtils::GetLanguageFor(content, nsnull, aLanguage); + if (IsDefunct()) + return NS_ERROR_FAILURE; + + nsCoreUtils::GetLanguageFor(mContent, nsnull, aLanguage); if (aLanguage.IsEmpty()) { // Nothing found, so use document's language - nsIDocument *doc = content->GetOwnerDoc(); + nsIDocument *doc = mContent->GetOwnerDoc(); if (doc) { doc->GetHeaderData(nsAccessibilityAtoms::headerContentLanguage, aLanguage); } } return NS_OK; } - -//////////////////////////////////////////////////////////////////////////////// -// nsAccessNode protected - -nsDocAccessible* -nsAccessNode::GetDocAccessible() const -{ - return GetDocAccessibleFor(mWeakShell); -}
--- a/accessible/src/base/nsAccessNode.h +++ b/accessible/src/base/nsAccessNode.h @@ -47,164 +47,166 @@ #include "nsIAccessibleTypes.h" #include "a11yGeneric.h" #include "nsIContent.h" #include "nsIDOMNode.h" #include "nsINameSpaceManager.h" #include "nsIStringBundle.h" -#include "nsRefPtrHashtable.h" #include "nsWeakReference.h" class nsAccessNode; class nsApplicationAccessible; class nsDocAccessible; class nsIAccessibleDocument; class nsRootAccessible; class nsIPresShell; class nsPresContext; class nsIFrame; class nsIDocShellTreeItem; -typedef nsRefPtrHashtable<nsVoidPtrHashKey, nsAccessNode> - nsAccessNodeHashtable; - #define ACCESSIBLE_BUNDLE_URL "chrome://global-platform/locale/accessible.properties" #define PLATFORM_KEYS_BUNDLE_URL "chrome://global-platform/locale/platformKeys.properties" #define NS_ACCESSNODE_IMPL_CID \ { /* 2b07e3d7-00b3-4379-aa0b-ea22e2c8ffda */ \ 0x2b07e3d7, \ 0x00b3, \ 0x4379, \ { 0xaa, 0x0b, 0xea, 0x22, 0xe2, 0xc8, 0xff, 0xda } \ } class nsAccessNode: public nsIAccessNode { - public: // construction, destruction - nsAccessNode(nsIDOMNode *, nsIWeakReference* aShell); - virtual ~nsAccessNode(); +public: + + nsAccessNode(nsIContent *aContent, nsIWeakReference *aShell); + virtual ~nsAccessNode(); NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsAccessNode, nsIAccessNode) NS_DECL_NSIACCESSNODE NS_DECLARE_STATIC_IID_ACCESSOR(NS_ACCESSNODE_IMPL_CID) static void InitXPAccessibility(); static void ShutdownXPAccessibility(); /** * Return an application accessible. */ static nsApplicationAccessible* GetApplicationAccessible(); /** - * Return the document accessible for this accesnode. + * Return the document accessible for this access node. */ - nsDocAccessible* GetDocAccessible() const; + nsDocAccessible *GetDocAccessible() const; /** * Return the root document accessible for this accessnode. */ already_AddRefed<nsRootAccessible> GetRootAccessible(); - static nsIDOMNode *gLastFocusedNode; + /** + * Reference to a node of focused accessible. + */ + static nsINode *gLastFocusedNode; - already_AddRefed<nsIDOMNode> GetCurrentFocus(); + /** + * Return focused node within accessible window. + * + * XXX: it shouldn't break us if we return focused node not depending on + * window so that we can turn this method into util method. + */ + already_AddRefed<nsINode> GetCurrentFocus(); /** * Returns true when the accessible is defunct. */ virtual PRBool IsDefunct(); - /** - * Initialize the access node object, add it to the cache. - */ - virtual nsresult Init(); + /** + * Initialize the access node object, add it to the cache. + */ + virtual PRBool Init(); - /** - * Shutdown the access node object. - */ - virtual nsresult Shutdown(); + /** + * Shutdown the access node object. + */ + virtual void Shutdown(); /** * Return frame for the given access node object. */ virtual nsIFrame* GetFrame(); /** * Return DOM node associated with this accessible. */ - nsIDOMNode *GetDOMNode() const { return mDOMNode; } + already_AddRefed<nsIDOMNode> GetDOMNode() const + { + nsIDOMNode *DOMNode = nsnull; + if (GetNode()) + CallQueryInterface(GetNode(), &DOMNode); + return DOMNode; + } + + /** + * Return DOM node associated with the accessible. + */ + virtual nsINode* GetNode() const { return mContent; } + nsIContent* GetContent() const { return mContent; } + nsIDocument* GetDocumentNode() const + { return mContent ? mContent->GetOwnerDoc() : nsnull; } + + /** + * Return node type information of DOM node associated with the accessible. + */ + PRBool IsContent() const + { + return GetNode() && GetNode()->IsNodeOfType(nsINode::eCONTENT); + } + PRBool IsDocument() const + { + return GetNode() && GetNode()->IsNodeOfType(nsINode::eDOCUMENT); + } /** * Return the corresponding press shell for this accessible. */ already_AddRefed<nsIPresShell> GetPresShell(); /** * Return true if the accessible still has presentation shell. Light-weight * version of IsDefunct() method. */ PRBool HasWeakShell() const { return !!mWeakShell; } -#ifdef DEBUG - /** - * Return true if the access node is cached. - */ - PRBool IsInCache(); -#endif - - /** - * Return cached document accessible. - */ - static nsDocAccessible* GetDocAccessibleFor(nsIDocument *aDocument); - static nsDocAccessible* GetDocAccessibleFor(nsIWeakReference *aWeakShell); - static nsDocAccessible* GetDocAccessibleFor(nsIDOMNode *aNode); - - /** - * Return document accessible. - */ - static already_AddRefed<nsIAccessibleDocument> - GetDocAccessibleFor(nsIDocShellTreeItem *aContainer, - PRBool aCanCreate = PR_FALSE); - protected: - nsresult MakeAccessNode(nsIDOMNode *aNode, nsIAccessNode **aAccessNode); - nsPresContext* GetPresContext(); void LastRelease(); - nsCOMPtr<nsIDOMNode> mDOMNode; - nsCOMPtr<nsIWeakReference> mWeakShell; - -#ifdef DEBUG_A11Y - PRBool mIsInitialized; -#endif + nsCOMPtr<nsIContent> mContent; + nsCOMPtr<nsIWeakReference> mWeakShell; /** * Notify global nsIObserver's that a11y is getting init'd or shutdown */ static void NotifyA11yInitOrShutdown(PRBool aIsInit); // Static data, we do our own refcounting for our static data static nsIStringBundle *gStringBundle; static nsIStringBundle *gKeyStringBundle; static PRBool gIsCacheDisabled; static PRBool gIsFormFillEnabled; - static nsRefPtrHashtable<nsVoidPtrHashKey, nsDocAccessible> - gGlobalDocAccessibleCache; - private: static nsApplicationAccessible *gApplicationAccessible; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsAccessNode, NS_ACCESSNODE_IMPL_CID) #endif
--- a/accessible/src/base/nsAccessibilityAtomList.h +++ b/accessible/src/base/nsAccessibilityAtomList.h @@ -52,24 +52,28 @@ The first argument to ACCESSIBILITY_ATOM is the C++ identifier of the atom The second argument is the string value of the atom ******/ // Alphabetical list of generic atoms ACCESSIBILITY_ATOM(button, "button") +ACCESSIBILITY_ATOM(checkbox, "checkbox") ACCESSIBILITY_ATOM(col, "col") ACCESSIBILITY_ATOM(_empty, "") ACCESSIBILITY_ATOM(_false, "false") ACCESSIBILITY_ATOM(image, "image") ACCESSIBILITY_ATOM(menu, "menu") ACCESSIBILITY_ATOM(menuButton, "menu-button") ACCESSIBILITY_ATOM(menugenerated, "menugenerated") +ACCESSIBILITY_ATOM(multiple, "multiple") +ACCESSIBILITY_ATOM(open, "open") ACCESSIBILITY_ATOM(password, "password") +ACCESSIBILITY_ATOM(radio, "radio") ACCESSIBILITY_ATOM(reset, "reset") ACCESSIBILITY_ATOM(row, "row") ACCESSIBILITY_ATOM(submit, "submit") ACCESSIBILITY_ATOM(_true, "true") ACCESSIBILITY_ATOM(_undefined, "undefined") // Header info ACCESSIBILITY_ATOM(headerContentLanguage, "content-language") @@ -117,16 +121,17 @@ ACCESSIBILITY_ATOM(h6, "h6") ACCESSIBILITY_ATOM(item, "item") // XForms ACCESSIBILITY_ATOM(itemset, "itemset") // XForms ACCESSIBILITY_ATOM(img, "img") ACCESSIBILITY_ATOM(input, "input") ACCESSIBILITY_ATOM(label, "label") ACCESSIBILITY_ATOM(legend, "legend") ACCESSIBILITY_ATOM(li, "li") ACCESSIBILITY_ATOM(link, "link") +ACCESSIBILITY_ATOM(listcell, "listcell") // XUL ACCESSIBILITY_ATOM(listcols, "listcols") // XUL ACCESSIBILITY_ATOM(listcol, "listcol") // XUL ACCESSIBILITY_ATOM(listhead, "listhead") // XUL ACCESSIBILITY_ATOM(listheader, "listheader") // XUL ACCESSIBILITY_ATOM(map, "map") ACCESSIBILITY_ATOM(math, "math") ACCESSIBILITY_ATOM(menupopup, "menupopup") // XUL ACCESSIBILITY_ATOM(object, "object") @@ -156,44 +161,48 @@ ACCESSIBILITY_ATOM(tr, "tr") ACCESSIBILITY_ATOM(tree, "tree") ACCESSIBILITY_ATOM(ul, "ul") // Alphabetical list of attributes (DOM) ACCESSIBILITY_ATOM(acceltext, "acceltext") ACCESSIBILITY_ATOM(accesskey, "accesskey") ACCESSIBILITY_ATOM(alt, "alt") ACCESSIBILITY_ATOM(anonid, "anonid") // Used for ID's in XBL +ACCESSIBILITY_ATOM(checked, "checked") ACCESSIBILITY_ATOM(contenteditable, "contenteditable") ACCESSIBILITY_ATOM(control, "control") ACCESSIBILITY_ATOM(disabled, "disabled") ACCESSIBILITY_ATOM(_class, "class") ACCESSIBILITY_ATOM(cycles, "cycles") // used for XUL cycler attribute ACCESSIBILITY_ATOM(curpos, "curpos") // XUL ACCESSIBILITY_ATOM(data, "data") ACCESSIBILITY_ATOM(_default, "default") // XUL button ACCESSIBILITY_ATOM(draggable, "draggable") ACCESSIBILITY_ATOM(droppable, "droppable") // XUL combo box ACCESSIBILITY_ATOM(editable, "editable") ACCESSIBILITY_ATOM(_for, "for") ACCESSIBILITY_ATOM(headers, "headers") // HTML table ACCESSIBILITY_ATOM(hidden, "hidden") // XUL tree columns +ACCESSIBILITY_ATOM(hover, "hover") // XUL color picker ACCESSIBILITY_ATOM(href, "href") // XUL, XLink ACCESSIBILITY_ATOM(increment, "increment") // XUL ACCESSIBILITY_ATOM(lang, "lang") ACCESSIBILITY_ATOM(linkedPanel, "linkedpanel") // XUL ACCESSIBILITY_ATOM(longDesc, "longdesc") ACCESSIBILITY_ATOM(max, "max") // XUL ACCESSIBILITY_ATOM(maxpos, "maxpos") // XUL ACCESSIBILITY_ATOM(minpos, "minpos") // XUL +ACCESSIBILITY_ATOM(_moz_menuactive, "_moz-menuactive") // XUL ACCESSIBILITY_ATOM(multiline, "multiline") // XUL ACCESSIBILITY_ATOM(name, "name") ACCESSIBILITY_ATOM(onclick, "onclick") ACCESSIBILITY_ATOM(popup, "popup") ACCESSIBILITY_ATOM(readonly, "readonly") ACCESSIBILITY_ATOM(scope, "scope") // HTML table +ACCESSIBILITY_ATOM(seltype, "seltype") // XUL listbox ACCESSIBILITY_ATOM(simple, "simple") // XLink ACCESSIBILITY_ATOM(src, "src") ACCESSIBILITY_ATOM(selected, "selected") ACCESSIBILITY_ATOM(summary, "summary") ACCESSIBILITY_ATOM(tabindex, "tabindex") ACCESSIBILITY_ATOM(title, "title") ACCESSIBILITY_ATOM(toolbarname, "toolbarname") ACCESSIBILITY_ATOM(tooltiptext, "tooltiptext")
--- a/accessible/src/base/nsAccessibilityService.cpp +++ b/accessible/src/base/nsAccessibilityService.cpp @@ -57,39 +57,27 @@ #include "nsIAccessibleProvider.h" #include "nsIDOMDocument.h" #include "nsIDOMHTMLAreaElement.h" #include "nsIDOMHTMLLegendElement.h" #include "nsIDOMHTMLObjectElement.h" #include "nsIDOMHTMLOptGroupElement.h" #include "nsIDOMHTMLOptionElement.h" -#include "nsIDOMWindow.h" #include "nsIDOMXULElement.h" #include "nsIHTMLDocument.h" -#include "nsIDocShell.h" -#include "nsIFrame.h" -#include "nsIInterfaceRequestorUtils.h" #include "nsIImageFrame.h" #include "nsILink.h" -#include "nsINameSpaceManager.h" #include "nsIObserverService.h" #include "nsIPluginInstance.h" -#include "nsIPresShell.h" #include "nsISupportsUtils.h" -#include "nsIWebNavigation.h" #include "nsObjectFrame.h" #include "nsOuterDocAccessible.h" #include "nsRootAccessibleWrap.h" #include "nsTextFragment.h" -#include "nsServiceManagerUtils.h" -#include "nsUnicharUtils.h" -#include "nsIWebProgress.h" -#include "nsNetError.h" -#include "nsDocShellLoadTypes.h" #include "mozilla/Services.h" #ifdef MOZ_XUL #include "nsXULAlertAccessible.h" #include "nsXULColorPickerAccessible.h" #include "nsXULComboboxAccessible.h" #include "nsXULFormControlAccessible.h" #include "nsXULListboxAccessibleWrap.h" @@ -114,562 +102,348 @@ //////////////////////////////////////////////////////////////////////////////// // nsAccessibilityService //////////////////////////////////////////////////////////////////////////////// nsAccessibilityService *nsAccessibilityService::gAccessibilityService = nsnull; PRBool nsAccessibilityService::gIsShutdown = PR_TRUE; -nsAccessibilityService::nsAccessibilityService() +nsAccessibilityService::nsAccessibilityService() : nsAccDocManager() { NS_TIME_FUNCTION; - - // Add observers. - nsCOMPtr<nsIObserverService> observerService = - mozilla::services::GetObserverService(); - if (!observerService) - return; - - observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE); - nsCOMPtr<nsIWebProgress> progress(do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID)); - if (progress) { - progress->AddProgressListener(static_cast<nsIWebProgressListener*>(this), - nsIWebProgress::NOTIFY_STATE_DOCUMENT); - } - - // Initialize accessibility. - nsAccessNodeWrap::InitAccessibility(); } nsAccessibilityService::~nsAccessibilityService() { NS_ASSERTION(gIsShutdown, "Accessibility wasn't shutdown!"); gAccessibilityService = nsnull; } -NS_IMPL_THREADSAFE_ISUPPORTS5(nsAccessibilityService, nsIAccessibilityService, nsIAccessibleRetrieval, - nsIObserver, nsIWebProgressListener, nsISupportsWeakReference) +//////////////////////////////////////////////////////////////////////////////// +// nsISupports +NS_IMPL_ISUPPORTS_INHERITED3(nsAccessibilityService, + nsAccDocManager, + nsIAccessibilityService, + nsIAccessibleRetrieval, + nsIObserver) //////////////////////////////////////////////////////////////////////////////// // nsIObserver NS_IMETHODIMP nsAccessibilityService::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData) { - if (!nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) { - - // Remove observers. - nsCOMPtr<nsIObserverService> observerService = - mozilla::services::GetObserverService(); - if (observerService) - observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID); - - nsCOMPtr<nsIWebProgress> progress(do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID)); - if (progress) - progress->RemoveProgressListener(static_cast<nsIWebProgressListener*>(this)); - - // Application is going to be closed, shutdown accessibility and mark - // accessibility service as shutdown to prevent calls of its methods. - // Don't null accessibility service static member at this point to be safe - // if someone will try to operate with it. - - NS_ASSERTION(!gIsShutdown, "Accessibility was shutdown already"); - - gIsShutdown = PR_TRUE; - nsAccessNodeWrap::ShutdownAccessibility(); - } + if (!nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) + Shutdown(); return NS_OK; } -//////////////////////////////////////////////////////////////////////////////// -// nsIWebProgressListener - -NS_IMETHODIMP nsAccessibilityService::OnStateChange(nsIWebProgress *aWebProgress, - nsIRequest *aRequest, PRUint32 aStateFlags, nsresult aStatus) -{ - NS_ASSERTION(aStateFlags & STATE_IS_DOCUMENT, "Other notifications excluded"); - - if (gIsShutdown || !aWebProgress || - (aStateFlags & (STATE_START | STATE_STOP)) == 0) { - return NS_OK; - } - - nsCAutoString name; - aRequest->GetName(name); - if (name.EqualsLiteral("about:blank")) - return NS_OK; - - if (NS_FAILED(aStatus) && (aStateFlags & STATE_START)) - return NS_OK; - - if (aStateFlags & STATE_START) { - NS_DISPATCH_RUNNABLEMETHOD_ARG2(ProcessDocLoadEvent, this, aWebProgress, - nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_START) - } else if (NS_SUCCEEDED(aStatus)) { - NS_DISPATCH_RUNNABLEMETHOD_ARG2(ProcessDocLoadEvent, this, aWebProgress, - nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE) - } else { // Failed end load - NS_DISPATCH_RUNNABLEMETHOD_ARG2(ProcessDocLoadEvent, this, aWebProgress, - nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED) - } - - return NS_OK; -} - -// nsAccessibilityService private -void -nsAccessibilityService::ProcessDocLoadEvent(nsIWebProgress *aWebProgress, - PRUint32 aEventType) -{ - if (gIsShutdown) - return; - - nsCOMPtr<nsIDOMWindow> domWindow; - aWebProgress->GetDOMWindow(getter_AddRefs(domWindow)); - NS_ENSURE_TRUE(domWindow,); - - if (aEventType == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_START) { - nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(domWindow)); - nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(webNav)); - NS_ENSURE_TRUE(docShell,); - PRUint32 loadType; - docShell->GetLoadType(&loadType); - if (loadType == LOAD_RELOAD_NORMAL || - loadType == LOAD_RELOAD_BYPASS_CACHE || - loadType == LOAD_RELOAD_BYPASS_PROXY || - loadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE) { - aEventType = nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD; - } - } - - nsCOMPtr<nsIDOMDocument> domDoc; - domWindow->GetDocument(getter_AddRefs(domDoc)); - nsCOMPtr<nsIDOMNode> docNode = do_QueryInterface(domDoc); - NS_ENSURE_TRUE(docNode,); - - nsCOMPtr<nsIAccessible> accessible; - GetAccessibleFor(docNode, getter_AddRefs(accessible)); - nsRefPtr<nsDocAccessible> docAcc = do_QueryObject(accessible); - NS_ENSURE_TRUE(docAcc,); - - docAcc->FireDocLoadEvents(aEventType); -} - // nsIAccessibilityService void nsAccessibilityService::NotifyOfAnchorJumpTo(nsIContent *aTarget) { nsIDocument *document = aTarget->GetCurrentDoc(); - nsCOMPtr<nsIDOMNode> documentNode(do_QueryInterface(document)); - if (!documentNode) + if (!document) return; - nsCOMPtr<nsIDOMNode> targetNode(do_QueryInterface(aTarget)); - + nsINode *targetNode = aTarget; nsAccessible *targetAcc = GetAccessible(targetNode); // Getting the targetAcc above will have ensured accessible doc creation. // XXX Bug 561683 - nsRefPtr<nsDocAccessible> accessibleDoc = - nsAccessNode::GetDocAccessibleFor(documentNode); - if (!accessibleDoc) + nsDocAccessible *docAccessible = GetDocAccessible(document); + if (!docAccessible) return; // If the jump target is not accessible then fire an event for nearest // accessible in parent chain. if (!targetAcc) { targetAcc = GetContainerAccessible(targetNode, PR_TRUE); - targetNode = targetAcc->GetDOMNode(); + targetNode = targetAcc->GetNode(); } NS_ASSERTION(targetNode, "No accessible in parent chain!? Expect at least a document accessible."); if (!targetNode) return; // XXX note in rare cases the node could go away before we flush the queue, // for example if the node becomes inaccessible, or is removed from the DOM. - accessibleDoc->FireDelayedAccessibleEvent( - nsIAccessibleEvent::EVENT_SCROLLING_START, - targetNode); + docAccessible-> + FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_SCROLLING_START, + targetNode); } // nsIAccessibilityService nsresult nsAccessibilityService::FireAccessibleEvent(PRUint32 aEvent, nsIAccessible *aTarget) { - nsEventShell::FireEvent(aEvent, aTarget); - return NS_OK; -} - -/* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */ -NS_IMETHODIMP nsAccessibilityService::OnProgressChange(nsIWebProgress *aWebProgress, - nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress, - PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress) -{ - NS_NOTREACHED("notification excluded in AddProgressListener(...)"); - return NS_OK; -} - -/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */ -NS_IMETHODIMP nsAccessibilityService::OnLocationChange(nsIWebProgress *aWebProgress, - nsIRequest *aRequest, nsIURI *location) -{ - NS_NOTREACHED("notification excluded in AddProgressListener(...)"); + nsRefPtr<nsAccessible> accessible(do_QueryObject(aTarget)); + nsEventShell::FireEvent(aEvent, accessible); return NS_OK; } -/* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */ -NS_IMETHODIMP nsAccessibilityService::OnStatusChange(nsIWebProgress *aWebProgress, - nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage) -{ - NS_NOTREACHED("notification excluded in AddProgressListener(...)"); - return NS_OK; -} - -/* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long state); */ -NS_IMETHODIMP nsAccessibilityService::OnSecurityChange(nsIWebProgress *aWebProgress, - nsIRequest *aRequest, PRUint32 state) -{ - NS_NOTREACHED("notification excluded in AddProgressListener(...)"); - return NS_OK; -} - - // nsAccessibilityService private nsresult -nsAccessibilityService::GetInfo(nsIFrame* aFrame, nsIWeakReference** aShell, nsIDOMNode** aNode) +nsAccessibilityService::GetInfo(nsIFrame *aFrame, nsIWeakReference **aShell, + nsIContent **aContent) { NS_ASSERTION(aFrame,"Error -- 1st argument (aFrame) is null!!"); if (!aFrame) { return NS_ERROR_FAILURE; } - nsCOMPtr<nsIContent> content = aFrame->GetContent(); - nsCOMPtr<nsIDOMNode> node(do_QueryInterface(content)); - if (!content || !node) + nsIContent* content = aFrame->GetContent(); + if (!content) return NS_ERROR_FAILURE; - *aNode = node; - NS_IF_ADDREF(*aNode); - - nsCOMPtr<nsIDocument> document = content->GetDocument(); + nsIDocument* document = content->GetOwnerDoc(); if (!document) return NS_ERROR_FAILURE; NS_ASSERTION(document->GetPrimaryShell(),"Error no shells!"); // do_GetWR only works into a |nsCOMPtr| :-( nsCOMPtr<nsIWeakReference> weakShell = do_GetWeakReference(document->GetPrimaryShell()); - NS_IF_ADDREF(*aShell = weakShell); - return NS_OK; -} - -// nsAccessibilityService public -nsresult -nsAccessibilityService::GetShellFromNode(nsIDOMNode *aNode, nsIWeakReference **aWeakShell) -{ - nsCOMPtr<nsIDOMDocument> domDoc; - aNode->GetOwnerDocument(getter_AddRefs(domDoc)); - nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDoc)); - if (!doc) - return NS_ERROR_INVALID_ARG; - - // ---- Get the pres shell ---- - nsIPresShell *shell = doc->GetPrimaryShell(); - if (!shell) - return NS_ERROR_FAILURE; - - nsCOMPtr<nsIWeakReference> weakRef(do_GetWeakReference(shell)); - - *aWeakShell = weakRef; - NS_IF_ADDREF(*aWeakShell); + weakShell.forget(aShell); + NS_IF_ADDREF(*aContent = content); return NS_OK; } //////////////////////////////////////////////////////////////////////////////// // nsIAccessibilityService nsresult nsAccessibilityService::CreateOuterDocAccessible(nsIDOMNode* aDOMNode, nsIAccessible **aOuterDocAccessible) { NS_ENSURE_ARG_POINTER(aDOMNode); *aOuterDocAccessible = nsnull; - nsCOMPtr<nsIWeakReference> outerWeakShell; - GetShellFromNode(aDOMNode, getter_AddRefs(outerWeakShell)); + nsCOMPtr<nsIContent> content(do_QueryInterface(aDOMNode)); + nsCOMPtr<nsIWeakReference> outerWeakShell = + nsCoreUtils::GetWeakShellFor(content); NS_ENSURE_TRUE(outerWeakShell, NS_ERROR_FAILURE); nsOuterDocAccessible *outerDocAccessible = - new nsOuterDocAccessible(aDOMNode, outerWeakShell); + new nsOuterDocAccessible(content, outerWeakShell); NS_ENSURE_TRUE(outerDocAccessible, NS_ERROR_FAILURE); NS_ADDREF(*aOuterDocAccessible = outerDocAccessible); return NS_OK; } -// nsAccessibilityService private -already_AddRefed<nsAccessible> -nsAccessibilityService::CreateDocOrRootAccessible(nsIPresShell *aShell, - nsIDocument* aDocument) -{ - nsCOMPtr<nsIDOMNode> rootNode(do_QueryInterface(aDocument)); - NS_ENSURE_TRUE(rootNode, nsnull); - - nsIPresShell *presShell = aShell; - if (!presShell) { - presShell = aDocument->GetPrimaryShell(); - } - nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell)); - - nsCOMPtr<nsISupports> container = aDocument->GetContainer(); - nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container); - NS_ENSURE_TRUE(docShell, nsnull); - - nsCOMPtr<nsIContentViewer> contentViewer; - docShell->GetContentViewer(getter_AddRefs(contentViewer)); - NS_ENSURE_TRUE(contentViewer, nsnull); // Doc was already shut down - - PRUint32 busyFlags; - docShell->GetBusyFlags(&busyFlags); - if (busyFlags != nsIDocShell::BUSY_FLAGS_NONE) { - nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(docShell)); - nsCOMPtr<nsIURI> uri; - webNav->GetCurrentURI(getter_AddRefs(uri)); - NS_ENSURE_TRUE(uri, nsnull); - - nsCAutoString url; - uri->GetSpec(url); - if (url.EqualsLiteral("about:blank")) { - // No load events for a busy about:blank -- they are often temporary. - return nsnull; - } - } - - nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = - do_QueryInterface(container); - NS_ENSURE_TRUE(docShellTreeItem, nsnull); - - nsCOMPtr<nsIDocShellTreeItem> parentTreeItem; - docShellTreeItem->GetParent(getter_AddRefs(parentTreeItem)); - - nsRefPtr<nsAccessible> accessible; - if (parentTreeItem) { - // We only create root accessibles for the true root, othewise create a - // doc accessible - accessible = new nsDocAccessibleWrap(rootNode, weakShell); - } - else { - accessible = new nsRootAccessibleWrap(rootNode, weakShell); - } - - return accessible.forget(); -} - /** * HTML widget creation */ nsresult -nsAccessibilityService::CreateHTML4ButtonAccessible(nsIFrame *aFrame, nsIAccessible **_retval) +nsAccessibilityService::CreateHTML4ButtonAccessible(nsIFrame *aFrame, + nsIAccessible **aAccessible) { - nsCOMPtr<nsIDOMNode> node; + nsCOMPtr<nsIContent> content; nsCOMPtr<nsIWeakReference> weakShell; - nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), getter_AddRefs(node)); + nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), + getter_AddRefs(content)); if (NS_FAILED(rv)) return rv; - *_retval = new nsHTML4ButtonAccessible(node, weakShell); - if (! *_retval) + *aAccessible = new nsHTML4ButtonAccessible(content, weakShell); + if (!*aAccessible) return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(*_retval); + NS_ADDREF(*aAccessible); return NS_OK; } nsresult -nsAccessibilityService::CreateHTMLButtonAccessible(nsIFrame *aFrame, nsIAccessible **_retval) +nsAccessibilityService::CreateHTMLButtonAccessible(nsIFrame *aFrame, + nsIAccessible **aAccessible) { - nsCOMPtr<nsIDOMNode> node; + nsCOMPtr<nsIContent> content; nsCOMPtr<nsIWeakReference> weakShell; - nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), getter_AddRefs(node)); + nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), + getter_AddRefs(content)); if (NS_FAILED(rv)) return rv; - *_retval = new nsHTMLButtonAccessible(node, weakShell); - if (! *_retval) + *aAccessible = new nsHTMLButtonAccessible(content, weakShell); + if (!*aAccessible) return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(*_retval); + NS_ADDREF(*aAccessible); return NS_OK; } // nsAccessibilityService private already_AddRefed<nsAccessible> nsAccessibilityService::CreateHTMLAccessibleByMarkup(nsIFrame *aFrame, nsIWeakReference *aWeakShell, - nsIDOMNode *aNode) + nsINode *aNode) { // This method assumes we're in an HTML namespace. nsRefPtr<nsAccessible> accessible; nsCOMPtr<nsIContent> content(do_QueryInterface(aNode)); nsIAtom *tag = content->Tag(); if (tag == nsAccessibilityAtoms::legend) { - accessible = new nsHTMLLegendAccessible(aNode, aWeakShell); + accessible = new nsHTMLLegendAccessible(content, aWeakShell); } else if (tag == nsAccessibilityAtoms::option) { - accessible = new nsHTMLSelectOptionAccessible(aNode, aWeakShell); + accessible = new nsHTMLSelectOptionAccessible(content, aWeakShell); } else if (tag == nsAccessibilityAtoms::optgroup) { - accessible = new nsHTMLSelectOptGroupAccessible(aNode, aWeakShell); + accessible = new nsHTMLSelectOptGroupAccessible(content, aWeakShell); } else if (tag == nsAccessibilityAtoms::ul || tag == nsAccessibilityAtoms::ol || tag == nsAccessibilityAtoms::dl) { - accessible = new nsHTMLListAccessible(aNode, aWeakShell); + accessible = new nsHTMLListAccessible(content, aWeakShell); } else if (tag == nsAccessibilityAtoms::a) { // Only some roles truly enjoy life as nsHTMLLinkAccessibles, for details // see closed bug 494807. nsRoleMapEntry *roleMapEntry = nsAccUtils::GetRoleMapEntry(aNode); if (roleMapEntry && roleMapEntry->role != nsIAccessibleRole::ROLE_NOTHING && roleMapEntry->role != nsIAccessibleRole::ROLE_LINK) { - accessible = new nsHyperTextAccessibleWrap(aNode, aWeakShell); + accessible = new nsHyperTextAccessibleWrap(content, aWeakShell); } else { - accessible = new nsHTMLLinkAccessible(aNode, aWeakShell); + accessible = new nsHTMLLinkAccessible(content, aWeakShell); } } else if (tag == nsAccessibilityAtoms::dt || (tag == nsAccessibilityAtoms::li && aFrame->GetType() != nsAccessibilityAtoms::blockFrame)) { // Normally for li, it is created by the list item frame (in nsBlockFrame) // which knows about the bullet frame; however, in this case the list item // must have been styled using display: foo - accessible = new nsHTMLLIAccessible(aNode, aWeakShell, EmptyString()); + accessible = new nsHTMLLIAccessible(content, aWeakShell, EmptyString()); } else if (tag == nsAccessibilityAtoms::abbr || tag == nsAccessibilityAtoms::acronym || tag == nsAccessibilityAtoms::blockquote || tag == nsAccessibilityAtoms::dd || tag == nsAccessibilityAtoms::form || tag == nsAccessibilityAtoms::h1 || tag == nsAccessibilityAtoms::h2 || tag == nsAccessibilityAtoms::h3 || tag == nsAccessibilityAtoms::h4 || tag == nsAccessibilityAtoms::h5 || tag == nsAccessibilityAtoms::h6 || tag == nsAccessibilityAtoms::q) { - accessible = new nsHyperTextAccessibleWrap(aNode, aWeakShell); + accessible = new nsHyperTextAccessibleWrap(content, aWeakShell); } else if (tag == nsAccessibilityAtoms::tr) { - accessible = new nsEnumRoleAccessible(aNode, aWeakShell, - nsIAccessibleRole::ROLE_ROW); + accessible = new nsEnumRoleAccessible(content, aWeakShell, + nsIAccessibleRole::ROLE_ROW); } else if (nsCoreUtils::IsHTMLTableHeader(content)) { - accessible = new nsHTMLTableHeaderCellAccessibleWrap(aNode, aWeakShell); + accessible = new nsHTMLTableHeaderCellAccessibleWrap(content, aWeakShell); } return accessible.forget(); } nsresult nsAccessibilityService::CreateHTMLLIAccessible(nsIFrame *aFrame, nsIFrame *aBulletFrame, const nsAString& aBulletText, - nsIAccessible **_retval) + nsIAccessible **aAccessible) { - nsCOMPtr<nsIDOMNode> node; + nsCOMPtr<nsIContent> content; nsCOMPtr<nsIWeakReference> weakShell; - nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), getter_AddRefs(node)); + nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), + getter_AddRefs(content)); if (NS_FAILED(rv)) return rv; - *_retval = new nsHTMLLIAccessible(node, weakShell, aBulletText); - if (! *_retval) + *aAccessible = new nsHTMLLIAccessible(content, weakShell, aBulletText); + if (!*aAccessible) return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(*_retval); - return NS_OK; -} - -nsresult -nsAccessibilityService::CreateHyperTextAccessible(nsIFrame *aFrame, nsIAccessible **aAccessible) -{ - nsCOMPtr<nsIDOMNode> node; - nsCOMPtr<nsIWeakReference> weakShell; - nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), getter_AddRefs(node)); - if (NS_FAILED(rv)) - return rv; - - nsCOMPtr<nsIContent> content(do_QueryInterface(node)); - NS_ENSURE_TRUE(content, NS_ERROR_FAILURE); - - *aAccessible = new nsHyperTextAccessibleWrap(node, weakShell); - NS_ENSURE_TRUE(*aAccessible, NS_ERROR_OUT_OF_MEMORY); - NS_ADDREF(*aAccessible); return NS_OK; } nsresult -nsAccessibilityService::CreateHTMLCheckboxAccessible(nsIFrame *aFrame, nsIAccessible **_retval) +nsAccessibilityService::CreateHyperTextAccessible(nsIFrame *aFrame, + nsIAccessible **aAccessible) { - nsCOMPtr<nsIDOMNode> node; + nsCOMPtr<nsIContent> content; nsCOMPtr<nsIWeakReference> weakShell; - nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), getter_AddRefs(node)); + nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), + getter_AddRefs(content)); if (NS_FAILED(rv)) return rv; - *_retval = new nsHTMLCheckboxAccessible(node, weakShell); - if (! *_retval) + *aAccessible = new nsHyperTextAccessibleWrap(content, weakShell); + if (!*aAccessible) return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(*_retval); + NS_ADDREF(*aAccessible); return NS_OK; } nsresult -nsAccessibilityService::CreateHTMLComboboxAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aPresShell, nsIAccessible **_retval) +nsAccessibilityService::CreateHTMLCheckboxAccessible(nsIFrame *aFrame, + nsIAccessible **aAccessible) { - *_retval = new nsHTMLComboboxAccessible(aDOMNode, aPresShell); - if (! *_retval) + nsCOMPtr<nsIContent> content; + nsCOMPtr<nsIWeakReference> weakShell; + nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), + getter_AddRefs(content)); + if (NS_FAILED(rv)) + return rv; + + *aAccessible = new nsHTMLCheckboxAccessible(content, weakShell); + if (!*aAccessible) return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(*_retval); + NS_ADDREF(*aAccessible); + return NS_OK; +} + +nsresult +nsAccessibilityService::CreateHTMLComboboxAccessible(nsIDOMNode *aDOMNode, + nsIWeakReference *aPresShell, + nsIAccessible **aAccessible) +{ + nsCOMPtr<nsIContent> content(do_QueryInterface(aDOMNode)); + *aAccessible = new nsHTMLComboboxAccessible(content, aPresShell); + if (!*aAccessible) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(*aAccessible); return NS_OK; } nsresult nsAccessibilityService::CreateHTMLImageAccessible(nsIFrame *aFrame, nsIAccessible **aAccessible) { NS_ENSURE_ARG_POINTER(aAccessible); *aAccessible = nsnull; - nsCOMPtr<nsIDOMNode> node; + nsCOMPtr<nsIContent> content; nsCOMPtr<nsIWeakReference> weakShell; - nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), getter_AddRefs(node)); + nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), + getter_AddRefs(content)); if (NS_FAILED(rv)) return rv; - nsCOMPtr<nsIContent> content = do_QueryInterface(node); - NS_ENSURE_STATE(content); - nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(content->GetCurrentDoc()); nsCOMPtr<nsIDOMHTMLMapElement> mapElm; if (htmlDoc) { nsAutoString mapElmName; content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::usemap, mapElmName); @@ -677,75 +451,80 @@ nsAccessibilityService::CreateHTMLImageA if (!mapElmName.IsEmpty()) { if (mapElmName.CharAt(0) == '#') mapElmName.Cut(0,1); mapElm = htmlDoc->GetImageMap(mapElmName); } } if (mapElm) - *aAccessible = new nsHTMLImageMapAccessible(node, weakShell, mapElm); + *aAccessible = new nsHTMLImageMapAccessible(content, weakShell, mapElm); else - *aAccessible = new nsHTMLImageAccessibleWrap(node, weakShell); + *aAccessible = new nsHTMLImageAccessibleWrap(content, weakShell); if (!*aAccessible) return NS_ERROR_OUT_OF_MEMORY; NS_ADDREF(*aAccessible); return NS_OK; } nsresult nsAccessibilityService::CreateHTMLGenericAccessible(nsIFrame *aFrame, nsIAccessible **aAccessible) { return CreateHyperTextAccessible(aFrame, aAccessible); } nsresult -nsAccessibilityService::CreateHTMLGroupboxAccessible(nsIFrame *aFrame, nsIAccessible **_retval) +nsAccessibilityService::CreateHTMLGroupboxAccessible(nsIFrame *aFrame, + nsIAccessible **aAccessible) { - nsCOMPtr<nsIDOMNode> node; + nsCOMPtr<nsIContent> content; nsCOMPtr<nsIWeakReference> weakShell; - nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), getter_AddRefs(node)); + nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), + getter_AddRefs(content)); if (NS_FAILED(rv)) return rv; - *_retval = new nsHTMLGroupboxAccessible(node, weakShell); - if (! *_retval) + *aAccessible = new nsHTMLGroupboxAccessible(content, weakShell); + if (!*aAccessible) return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(*_retval); + NS_ADDREF(*aAccessible); return NS_OK; } nsresult -nsAccessibilityService::CreateHTMLListboxAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aPresShell, nsIAccessible **_retval) +nsAccessibilityService::CreateHTMLListboxAccessible(nsIDOMNode* aDOMNode, + nsIWeakReference *aPresShell, + nsIAccessible **aAccessible) { - *_retval = new nsHTMLSelectListAccessible(aDOMNode, aPresShell); - if (! *_retval) + nsCOMPtr<nsIContent> content(do_QueryInterface(aDOMNode)); + *aAccessible = new nsHTMLSelectListAccessible(content, aPresShell); + if (!*aAccessible) return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(*_retval); + NS_ADDREF(*aAccessible); return NS_OK; } nsresult nsAccessibilityService::CreateHTMLMediaAccessible(nsIFrame *aFrame, nsIAccessible **aAccessible) { NS_ENSURE_ARG_POINTER(aAccessible); *aAccessible = nsnull; - nsCOMPtr<nsIDOMNode> node; + nsCOMPtr<nsIContent> content; nsCOMPtr<nsIWeakReference> weakShell; nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), - getter_AddRefs(node)); + getter_AddRefs(content)); NS_ENSURE_SUCCESS(rv, rv); - *aAccessible = new nsEnumRoleAccessible(node, weakShell, + *aAccessible = new nsEnumRoleAccessible(content, weakShell, nsIAccessibleRole::ROLE_GROUPING); NS_ENSURE_TRUE(*aAccessible, NS_ERROR_OUT_OF_MEMORY); NS_ADDREF(*aAccessible); return NS_OK; } /** @@ -756,45 +535,48 @@ nsAccessibilityService::CreateHTMLMediaA * have to go to the plugin to get the accessible content * 3) An image or imagemap, where the image frame points back to * the object element DOMNode */ nsresult nsAccessibilityService::CreateHTMLObjectFrameAccessible(nsObjectFrame *aFrame, nsIAccessible **aAccessible) { - nsCOMPtr<nsIDOMNode> node; + NS_ENSURE_ARG_POINTER(aAccessible); + *aAccessible = nsnull; + + nsCOMPtr<nsIContent> content; nsCOMPtr<nsIWeakReference> weakShell; - GetInfo(aFrame, getter_AddRefs(weakShell), getter_AddRefs(node)); + GetInfo(aFrame, getter_AddRefs(weakShell), getter_AddRefs(content)); - *aAccessible = nsnull; if (aFrame->GetRect().IsEmpty()) { return NS_ERROR_FAILURE; } // 1) for object elements containing either HTML or TXT documents - nsCOMPtr<nsIDOMDocument> domDoc; - nsCOMPtr<nsIDOMHTMLObjectElement> obj(do_QueryInterface(node)); - if (obj) + nsCOMPtr<nsIDOMHTMLObjectElement> obj(do_QueryInterface(content)); + if (obj) { + nsCOMPtr<nsIDOMDocument> domDoc; obj->GetContentDocument(getter_AddRefs(domDoc)); - else - domDoc = do_QueryInterface(node); - if (domDoc) - return CreateOuterDocAccessible(node, aAccessible); + if (domDoc) { + nsCOMPtr<nsIDOMNode> DOMNode(do_QueryInterface(content)); + return CreateOuterDocAccessible(DOMNode, aAccessible); + } + } #ifdef XP_WIN // 2) for plugins nsCOMPtr<nsIPluginInstance> pluginInstance ; aFrame->GetPluginInstance(*getter_AddRefs(pluginInstance)); if (pluginInstance) { // Note: pluginPort will be null if windowless. HWND pluginPort = nsnull; aFrame->GetPluginPort(&pluginPort); *aAccessible = - new nsHTMLWin32ObjectOwnerAccessible(node, weakShell, pluginPort); + new nsHTMLWin32ObjectOwnerAccessible(content, weakShell, pluginPort); NS_ENSURE_TRUE(*aAccessible, NS_ERROR_OUT_OF_MEMORY); NS_ADDREF(*aAccessible); return NS_OK; } #endif // 3) for images and imagemaps, or anything else with a child frame @@ -802,214 +584,285 @@ nsAccessibilityService::CreateHTMLObject nsIFrame *frame = aFrame->GetFirstChild(nsnull); if (frame) return frame->GetAccessible(aAccessible); return NS_OK; } nsresult -nsAccessibilityService::CreateHTMLRadioButtonAccessible(nsIFrame *aFrame, nsIAccessible **_retval) +nsAccessibilityService::CreateHTMLRadioButtonAccessible(nsIFrame *aFrame, + nsIAccessible **aAccessible) { - nsCOMPtr<nsIDOMNode> node; + nsCOMPtr<nsIContent> content; nsCOMPtr<nsIWeakReference> weakShell; - nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), getter_AddRefs(node)); + nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), + getter_AddRefs(content)); if (NS_FAILED(rv)) return rv; - *_retval = new nsHTMLRadioButtonAccessible(node, weakShell); - if (! *_retval) + *aAccessible = new nsHTMLRadioButtonAccessible(content, weakShell); + if (!*aAccessible) return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(*_retval); + NS_ADDREF(*aAccessible); return NS_OK; } nsresult -nsAccessibilityService::CreateHTMLSelectOptionAccessible(nsIDOMNode* aDOMNode, +nsAccessibilityService::CreateHTMLSelectOptionAccessible(nsIDOMNode *aDOMNode, nsIAccessible *aParent, - nsIWeakReference* aPresShell, - nsIAccessible **_retval) + nsIWeakReference *aPresShell, + nsIAccessible **aAccessible) { - *_retval = new nsHTMLSelectOptionAccessible(aDOMNode, aPresShell); - if (! *_retval) + nsCOMPtr<nsIContent> content(do_QueryInterface(aDOMNode)); + *aAccessible = new nsHTMLSelectOptionAccessible(content, aPresShell); + if (!*aAccessible) return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(*_retval); + NS_ADDREF(*aAccessible); return NS_OK; } nsresult -nsAccessibilityService::CreateHTMLTableAccessible(nsIFrame *aFrame, nsIAccessible **_retval) +nsAccessibilityService::CreateHTMLTableAccessible(nsIFrame *aFrame, + nsIAccessible **aAccessible) { - nsCOMPtr<nsIDOMNode> node; + nsCOMPtr<nsIContent> content; nsCOMPtr<nsIWeakReference> weakShell; - nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), getter_AddRefs(node)); + nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), + getter_AddRefs(content)); if (NS_FAILED(rv)) return rv; - *_retval = new nsHTMLTableAccessibleWrap(node, weakShell); - if (! *_retval) + *aAccessible = new nsHTMLTableAccessibleWrap(content, weakShell); + if (!*aAccessible) return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(*_retval); + NS_ADDREF(*aAccessible); return NS_OK; } nsresult nsAccessibilityService::CreateHTMLTableCellAccessible(nsIFrame *aFrame, nsIAccessible **aAccessible) { - nsCOMPtr<nsIDOMNode> node; + NS_ENSURE_ARG_POINTER(aAccessible); + *aAccessible = nsnull; + + nsCOMPtr<nsIContent> content; nsCOMPtr<nsIWeakReference> weakShell; - nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), getter_AddRefs(node)); + nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), + getter_AddRefs(content)); if (NS_FAILED(rv)) return rv; - *aAccessible = new nsHTMLTableCellAccessibleWrap(node, weakShell); - if (!*aAccessible) + *aAccessible = new nsHTMLTableCellAccessibleWrap(content, weakShell); + if (!*aAccessible) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(*aAccessible); + return NS_OK; +} + +nsresult +nsAccessibilityService::CreateHTMLTextAccessible(nsIFrame *aFrame, + nsIAccessible **aAccessible) +{ + *aAccessible = nsnull; + + nsCOMPtr<nsIContent> content; + nsCOMPtr<nsIWeakReference> weakShell; + nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), + getter_AddRefs(content)); + if (NS_FAILED(rv)) + return rv; + + // XXX Don't create ATK objects for these + *aAccessible = new nsHTMLTextAccessible(content, weakShell); + if (!*aAccessible) return NS_ERROR_OUT_OF_MEMORY; NS_ADDREF(*aAccessible); return NS_OK; } nsresult -nsAccessibilityService::CreateHTMLTextAccessible(nsIFrame *aFrame, nsIAccessible **_retval) +nsAccessibilityService::CreateHTMLTextFieldAccessible(nsIFrame *aFrame, + nsIAccessible **aAccessible) { - *_retval = nsnull; - - nsCOMPtr<nsIDOMNode> node; + nsCOMPtr<nsIContent> content; nsCOMPtr<nsIWeakReference> weakShell; - nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), getter_AddRefs(node)); + nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), + getter_AddRefs(content)); if (NS_FAILED(rv)) return rv; - // XXX Don't create ATK objects for these - *_retval = new nsHTMLTextAccessible(node, weakShell); - if (! *_retval) + *aAccessible = new nsHTMLTextFieldAccessible(content, weakShell); + if (!*aAccessible) return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(*_retval); + NS_ADDREF(*aAccessible); return NS_OK; } nsresult -nsAccessibilityService::CreateHTMLTextFieldAccessible(nsIFrame *aFrame, nsIAccessible **_retval) +nsAccessibilityService::CreateHTMLLabelAccessible(nsIFrame *aFrame, + nsIAccessible **aAccessible) { - nsCOMPtr<nsIDOMNode> node; + nsCOMPtr<nsIContent> content; nsCOMPtr<nsIWeakReference> weakShell; - nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), getter_AddRefs(node)); + nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), + getter_AddRefs(content)); if (NS_FAILED(rv)) return rv; - *_retval = new nsHTMLTextFieldAccessible(node, weakShell); - if (! *_retval) + *aAccessible = new nsHTMLLabelAccessible(content, weakShell); + if (!*aAccessible) return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(*_retval); + NS_ADDREF(*aAccessible); return NS_OK; } nsresult -nsAccessibilityService::CreateHTMLLabelAccessible(nsIFrame *aFrame, nsIAccessible **_retval) +nsAccessibilityService::CreateHTMLHRAccessible(nsIFrame *aFrame, + nsIAccessible **aAccessible) { - nsCOMPtr<nsIDOMNode> node; + nsCOMPtr<nsIContent> content; nsCOMPtr<nsIWeakReference> weakShell; - nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), getter_AddRefs(node)); + nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), + getter_AddRefs(content)); if (NS_FAILED(rv)) return rv; - *_retval = new nsHTMLLabelAccessible(node, weakShell); - if (! *_retval) + *aAccessible = new nsHTMLHRAccessible(content, weakShell); + if (!*aAccessible) return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(*_retval); + NS_ADDREF(*aAccessible); return NS_OK; } nsresult -nsAccessibilityService::CreateHTMLHRAccessible(nsIFrame *aFrame, nsIAccessible **_retval) +nsAccessibilityService::CreateHTMLBRAccessible(nsIFrame *aFrame, + nsIAccessible **aAccessible) { - nsCOMPtr<nsIDOMNode> node; + nsCOMPtr<nsIContent> content; nsCOMPtr<nsIWeakReference> weakShell; - nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), getter_AddRefs(node)); + nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), + getter_AddRefs(content)); if (NS_FAILED(rv)) return rv; - *_retval = new nsHTMLHRAccessible(node, weakShell); - if (! *_retval) + *aAccessible = new nsHTMLBRAccessible(content, weakShell); + if (!*aAccessible) return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(*_retval); + NS_ADDREF(*aAccessible); return NS_OK; } nsresult -nsAccessibilityService::CreateHTMLBRAccessible(nsIFrame *aFrame, nsIAccessible **_retval) +nsAccessibilityService::CreateHTMLCaptionAccessible(nsIFrame *aFrame, + nsIAccessible **aAccessible) { - nsCOMPtr<nsIDOMNode> node; + nsCOMPtr<nsIContent> content; nsCOMPtr<nsIWeakReference> weakShell; - nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), getter_AddRefs(node)); + nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), + getter_AddRefs(content)); if (NS_FAILED(rv)) return rv; - *_retval = new nsHTMLBRAccessible(node, weakShell); - if (! *_retval) + *aAccessible = new nsHTMLCaptionAccessible(content, weakShell); + if (!*aAccessible) return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(*_retval); + NS_ADDREF(*aAccessible); return NS_OK; } -nsresult -nsAccessibilityService::CreateHTMLCaptionAccessible(nsIFrame *aFrame, nsIAccessible **_retval) +void +nsAccessibilityService::PresShellDestroyed(nsIPresShell *aPresShell) { - nsCOMPtr<nsIDOMNode> node; - nsCOMPtr<nsIWeakReference> weakShell; - nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), getter_AddRefs(node)); - if (NS_FAILED(rv)) - return rv; + // Presshell destruction will automatically destroy shells for descendant + // documents, so no need to worry about those. Just shut down the accessible + // for this one document. That keeps us from having bad behavior in case of + // deep bushy subtrees. + // When document subtree containing iframe is hidden then we don't get + // pagehide event for the iframe's underlying document and its presshell is + // destroyed before we're notified styles were changed. Shutdown the document + // accessible early. + nsIDocument* doc = aPresShell->GetDocument(); + if (!doc) + return; - *_retval = new nsHTMLCaptionAccessible(node, weakShell); - if (! *_retval) - return NS_ERROR_OUT_OF_MEMORY; - - NS_ADDREF(*_retval); - return NS_OK; + NS_LOG_ACCDOCDESTROY("presshell destroyed", doc) + ShutdownDocAccessible(doc); } -// nsAccessibilityService public -nsAccessNode* -nsAccessibilityService::GetCachedAccessNode(nsIDOMNode *aNode, +// nsAccessibilityService protected +nsAccessible * +nsAccessibilityService::GetCachedAccessible(nsINode *aNode, nsIWeakReference *aWeakShell) { - nsCOMPtr<nsIAccessibleDocument> accessibleDoc = - nsAccessNode::GetDocAccessibleFor(aWeakShell); - - if (!accessibleDoc) - return nsnull; - - nsRefPtr<nsDocAccessible> docAccessible = do_QueryObject(accessibleDoc); - return docAccessible->GetCachedAccessNode(static_cast<void*>(aNode)); + nsDocAccessible *docAccessible = GetDocAccessible(aNode->GetOwnerDoc()); + return docAccessible ? + docAccessible->GetCachedAccessible(static_cast<void*>(aNode)) : nsnull; } //////////////////////////////////////////////////////////////////////////////// // nsIAccessibleRetrieval NS_IMETHODIMP nsAccessibilityService::GetApplicationAccessible(nsIAccessible **aAccessibleApplication) { NS_ENSURE_ARG_POINTER(aAccessibleApplication); NS_IF_ADDREF(*aAccessibleApplication = nsAccessNode::GetApplicationAccessible()); return NS_OK; } NS_IMETHODIMP +nsAccessibilityService::GetAccessibleFor(nsIDOMNode *aNode, + nsIAccessible **aAccessible) +{ + NS_ENSURE_ARG_POINTER(aAccessible); + + nsCOMPtr<nsINode> node(do_QueryInterface(aNode)); + NS_IF_ADDREF(*aAccessible = GetAccessible(node)); + return NS_OK; +} + +NS_IMETHODIMP +nsAccessibilityService::GetAttachedAccessibleFor(nsIDOMNode *aDOMNode, + nsIAccessible **aAccessible) +{ + NS_ENSURE_ARG(aDOMNode); + NS_ENSURE_ARG_POINTER(aAccessible); + + nsCOMPtr<nsINode> node(do_QueryInterface(aDOMNode)); + NS_IF_ADDREF(*aAccessible = GetAttachedAccessibleFor(node)); + return NS_OK; +} + +NS_IMETHODIMP +nsAccessibilityService::GetRelevantContentNodeFor(nsIDOMNode *aNode, + nsIDOMNode **aRelevantNode) +{ + NS_ENSURE_ARG(aNode); + NS_ENSURE_ARG_POINTER(aRelevantNode); + + nsCOMPtr<nsINode> node(do_QueryInterface(aNode)); + nsINode *relevantNode = GetRelevantContentNodeFor(node); + CallQueryInterface(relevantNode, aRelevantNode); + return NS_OK; +} + +NS_IMETHODIMP nsAccessibilityService::GetStringRole(PRUint32 aRole, nsAString& aString) { if ( aRole >= NS_ARRAY_LENGTH(kRoleNames)) { aString.AssignLiteral("unknown"); return NS_OK; } CopyUTF8toUTF16(kRoleNames[aRole], aString); @@ -1158,153 +1011,141 @@ nsAccessibilityService::GetStringRelatio aString.AssignLiteral("unknown"); return NS_OK; } CopyUTF8toUTF16(kRelationTypeNames[aRelationType], aString); return NS_OK; } - -/** - * GetAccessibleFor - get an nsIAccessible from a DOM node - */ - NS_IMETHODIMP -nsAccessibilityService::GetAccessibleFor(nsIDOMNode *aNode, - nsIAccessible **aAccessible) +nsAccessibilityService::GetAccessibleFromCache(nsIDOMNode* aNode, + nsIAccessible** aAccessible) { NS_ENSURE_ARG_POINTER(aAccessible); - NS_IF_ADDREF(*aAccessible = GetAccessible(aNode)); + // Search for an accessible in each of our per document accessible object + // caches. If we don't find it, and the given node is itself a document, check + // our cache of document accessibles (document cache). Note usually shutdown + // document accessibles are not stored in the document cache, however an + // "unofficially" shutdown document (i.e. not from nsAccDocManager) can still + // exist in the document cache. + nsCOMPtr<nsINode> node(do_QueryInterface(aNode)); + nsAccessible* accessible = FindAccessibleInCache(static_cast<void*>(node)); + if (!accessible) { + nsCOMPtr<nsIDocument> document(do_QueryInterface(node)); + if (document) + accessible = GetDocAccessibleFromCache(document); + } + + NS_IF_ADDREF(*aAccessible = accessible); return NS_OK; } -NS_IMETHODIMP -nsAccessibilityService::GetAttachedAccessibleFor(nsIDOMNode *aNode, - nsIAccessible **aAccessible) -{ - NS_ENSURE_ARG(aNode); - NS_ENSURE_ARG_POINTER(aAccessible); - - *aAccessible = nsnull; - - nsCOMPtr<nsIDOMNode> relevantNode; - nsresult rv = GetRelevantContentNodeFor(aNode, getter_AddRefs(relevantNode)); - NS_ENSURE_SUCCESS(rv, rv); - - if (relevantNode != aNode) - return NS_OK; - - return GetAccessibleFor(aNode, aAccessible); -} - +// nsIAccesibilityService nsAccessible* nsAccessibilityService::GetAccessibleInShell(nsIDOMNode *aNode, nsIPresShell *aPresShell) { if (!aNode || !aPresShell) return nsnull; + nsCOMPtr<nsINode> node(do_QueryInterface(aNode)); nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(aPresShell)); nsRefPtr<nsAccessible> accessible = - GetAccessible(aNode, aPresShell, weakShell); + GetAccessible(node, aPresShell, weakShell); return accessible; } //////////////////////////////////////////////////////////////////////////////// // nsAccessibilityService public nsAccessible * -nsAccessibilityService::GetAccessible(nsIDOMNode *aNode) +nsAccessibilityService::GetAccessible(nsINode *aNode) { if (!aNode) return nsnull; nsIPresShell *presShell = nsCoreUtils::GetPresShellFor(aNode); if (!presShell) return nsnull; nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell)); nsRefPtr<nsAccessible> accessible = GetAccessible(aNode, presShell, weakShell); return accessible; } nsAccessible * -nsAccessibilityService::GetAccessibleInWeakShell(nsIDOMNode *aNode, +nsAccessibilityService::GetAccessibleInWeakShell(nsINode *aNode, nsIWeakReference *aWeakShell) { if (!aNode || !aWeakShell) return nsnull; nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(aWeakShell)); nsRefPtr<nsAccessible> accessible = GetAccessible(aNode, presShell, aWeakShell); return accessible; } nsAccessible * -nsAccessibilityService::GetContainerAccessible(nsIDOMNode *aNode, +nsAccessibilityService::GetContainerAccessible(nsINode *aNode, PRBool aCanCreate) { if (!aNode) return nsnull; - nsCOMPtr<nsINode> currNode(do_QueryInterface(aNode)); - nsIDocument *document = currNode->GetCurrentDoc(); + nsIDocument *document = aNode->GetCurrentDoc(); if (!document) return nsnull; nsIPresShell *presShell = document->GetPrimaryShell(); if (!presShell) return nsnull; + nsINode *currNode = aNode; nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell)); nsAccessible *accessible = nsnull; while (!accessible && (currNode = currNode->GetNodeParent())) { - nsCOMPtr<nsIDOMNode> currDOMNode(do_QueryInterface(currNode)); - - nsCOMPtr<nsIDOMNode> relevantDOMNode; - GetAccService()->GetRelevantContentNodeFor(currDOMNode, - getter_AddRefs(relevantDOMNode)); - if (relevantDOMNode) { - currNode = do_QueryInterface(relevantDOMNode); - currDOMNode.swap(relevantDOMNode); - } + currNode = GetAccService()->GetRelevantContentNodeFor(currNode); if (aCanCreate) { - accessible = - GetAccService()->GetAccessibleInWeakShell(currDOMNode, weakShell); + accessible = GetAccService()->GetAccessibleInWeakShell(currNode, + weakShell); } else { // Only return cached accessible, don't create anything. - nsRefPtr<nsAccessible> cachedAcc = - do_QueryObject(GetCachedAccessNode(currDOMNode, weakShell)); - - accessible = cachedAcc; + accessible = GetCachedAccessible(currNode, weakShell); } } return accessible; } -//////////////////////////////////////////////////////////////////////////////// -// nsAccessibilityService private +nsAccessible * +nsAccessibilityService::GetAttachedAccessibleFor(nsINode *aNode) +{ + nsINode *relevantNode = GetRelevantContentNodeFor(aNode); + if (relevantNode != aNode) + return nsnull; + + return GetAccessible(relevantNode); +} PRBool nsAccessibilityService::InitAccessible(nsAccessible *aAccessible, nsRoleMapEntry *aRoleMapEntry) { if (!aAccessible) return PR_FALSE; - nsresult rv = aAccessible->Init(); // Add to cache, etc. - if (NS_FAILED(rv)) { + // Add to cache an accessible, etc. + if (!aAccessible->Init()) { NS_ERROR("Failed to initialize an accessible!"); aAccessible->Shutdown(); return PR_FALSE; } NS_ASSERTION(aAccessible->IsInCache(), "Initialized accessible not in the cache!"); @@ -1336,94 +1177,60 @@ static PRBool HasRelatedContent(nsIConte // ancestor has activedescendant property, this content could be active return PR_TRUE; } } return PR_FALSE; } -// nsAccessibilityService public already_AddRefed<nsAccessible> -nsAccessibilityService::GetAccessible(nsIDOMNode *aNode, +nsAccessibilityService::GetAccessible(nsINode *aNode, nsIPresShell *aPresShell, nsIWeakReference *aWeakShell, PRBool *aIsHidden) { - if (!aPresShell || !aWeakShell || gIsShutdown) + if (!aPresShell || !aWeakShell || !aNode || gIsShutdown) return nsnull; - NS_ASSERTION(aNode, "GetAccessible() called with no node."); - if (aIsHidden) *aIsHidden = PR_FALSE; -#ifdef DEBUG_A11Y - // Please leave this in for now, it's a convenient debugging method - nsAutoString name; - aNode->GetLocalName(name); - if (name.LowerCaseEqualsLiteral("h1")) - printf("## aaronl debugging tag name\n"); - - nsAutoString attrib; - nsCOMPtr<nsIDOMElement> element(do_QueryInterface(aNode)); - if (element) { - element->GetAttribute(NS_LITERAL_STRING("type"), attrib); - if (attrib.EqualsLiteral("statusbarpanel")) - printf("## aaronl debugging attribute\n"); - } -#endif - // Check to see if we already have an accessible for this node in the cache. - nsAccessNode* cachedAccessNode = GetCachedAccessNode(aNode, aWeakShell); - if (cachedAccessNode) { - // XXX: the cache might contain the access node for the DOM node that is not - // accessible because of wrong cache update. In this case try to create new - // accessible. - nsRefPtr<nsAccessible> cachedAccessible = do_QueryObject(cachedAccessNode); - - if (cachedAccessible) - return cachedAccessible.forget(); + nsAccessible *cachedAccessible = GetCachedAccessible(aNode, aWeakShell); + if (cachedAccessible) { + NS_ADDREF(cachedAccessible); + return cachedAccessible; } // No cache entry, so we must create the accessible. - nsRefPtr<nsAccessible> newAcc; - - nsCOMPtr<nsIContent> content(do_QueryInterface(aNode)); - if (!content) { - // This happens when we're on the document node, which will not QI to an - // nsIContent. - nsCOMPtr<nsIDocument> nodeIsDoc = do_QueryInterface(aNode); - if (!nodeIsDoc) // No content, and not doc node. - return nsnull; -#ifdef DEBUG - // XXX: remove me if you don't see an assertion. - nsCOMPtr<nsIAccessibleDocument> accessibleDoc = - nsAccessNode::GetDocAccessibleFor(nodeIsDoc); - NS_ASSERTION(!accessibleDoc, - "Trying to create already cached accessible document!"); -#endif + if (aNode->IsNodeOfType(nsINode::eDOCUMENT)) { + // If it's document node then ask accessible document loader for + // document accessible, otherwise return null. + nsCOMPtr<nsIDocument> document(do_QueryInterface(aNode)); + nsAccessible *accessible = GetDocAccessible(document); + NS_IF_ADDREF(accessible); + return accessible; + } - newAcc = CreateDocOrRootAccessible(aPresShell, nodeIsDoc); - if (InitAccessible(newAcc, nsAccUtils::GetRoleMapEntry(aNode))) - return newAcc.forget(); + // We have a content node. + if (!aNode->IsInDoc()) { + NS_WARNING("Creating accessible for node with no document"); return nsnull; } - // We have a content node. - if (!content->IsInDoc()) { - NS_ERROR("Creating accessible for node with no document"); + if (aNode->GetOwnerDoc() != aPresShell->GetDocument()) { + NS_ERROR("Creating accessible for wrong pres shell"); return nsnull; } - if (content->GetOwnerDoc() != aPresShell->GetDocument()) { - NS_ERROR("Creating accessible for wrong pres shell"); + nsCOMPtr<nsIContent> content(do_QueryInterface(aNode)); + if (!content) return nsnull; - } // Frames can be deallocated when we flush layout, or when we call into code // that can flush layout, either directly, or via DOM manipulation, or some // CSS styles like :hover. We use the weak frame checks to avoid calling // methods on a dead frame pointer. nsWeakFrame weakFrame = content->GetPrimaryFrame(); // Check frame to see if it is hidden. @@ -1435,20 +1242,22 @@ nsAccessibilityService::GetAccessible(ns return nsnull; } if (weakFrame.GetFrame()->GetContent() != content) { // Not the main content for this frame. This happens because <area> // elements return the image frame as their primary frame. The main content // for the image frame is the image content. If the frame is not an image // frame or the node is not an area element then null is returned. + // This setup will change when bug 135040 is fixed. return GetAreaAccessible(weakFrame.GetFrame(), aNode, aWeakShell); } // Attempt to create an accessible based on what we know. + nsRefPtr<nsAccessible> newAcc; if (content->IsNodeOfType(nsINode::eTEXT)) { // --- Create HTML for visible text frames --- nsIFrame* f = weakFrame.GetFrame(); if (f && f->IsEmpty()) { nsAutoString renderedWhitespace; f->GetRenderedText(&renderedWhitespace, nsnull, nsnull, 0, 1); if (renderedWhitespace.IsEmpty()) { // Really empty -- nothing is rendered @@ -1486,17 +1295,17 @@ nsAccessibilityService::GetAccessible(ns content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::name, name); if (!name.IsEmpty()) { if (aIsHidden) *aIsHidden = PR_TRUE; return nsnull; } - newAcc = new nsHyperTextAccessibleWrap(aNode, aWeakShell); + newAcc = new nsHyperTextAccessibleWrap(content, aWeakShell); if (InitAccessible(newAcc, nsAccUtils::GetRoleMapEntry(aNode))) return newAcc.forget(); return nsnull; } nsRoleMapEntry *roleMapEntry = nsAccUtils::GetRoleMapEntry(aNode); if (roleMapEntry && !nsCRT::strcmp(roleMapEntry->roleString, "presentation") && !content->IsFocusable()) { // For presentation only @@ -1523,19 +1332,18 @@ nsAccessibilityService::GetAccessible(ns // accessibles nsIContent *tableContent = content; while ((tableContent = tableContent->GetParent()) != nsnull) { nsIFrame *tableFrame = tableContent->GetPrimaryFrame(); if (!tableFrame) continue; if (tableFrame->GetType() == nsAccessibilityAtoms::tableOuterFrame) { - nsCOMPtr<nsIDOMNode> tableNode(do_QueryInterface(tableContent)); nsAccessible *tableAccessible = - GetAccessibleInWeakShell(tableNode, aWeakShell); + GetAccessibleInWeakShell(tableContent, aWeakShell); if (tableAccessible) { if (!roleMapEntry) { PRUint32 role = nsAccUtils::Role(tableAccessible); if (role != nsIAccessibleRole::ROLE_TABLE && role != nsIAccessibleRole::ROLE_TREE_TABLE) { // No ARIA role and not in table: override role. For example, // <table role="label"><td>content</td></table> @@ -1543,17 +1351,17 @@ nsAccessibilityService::GetAccessible(ns } } break; } #ifdef DEBUG nsRoleMapEntry *tableRoleMapEntry = - nsAccUtils::GetRoleMapEntry(tableNode); + nsAccUtils::GetRoleMapEntry(tableContent); NS_ASSERTION(tableRoleMapEntry && !nsCRT::strcmp(tableRoleMapEntry->roleString, "presentation"), "No accessible for parent table and it didn't have role of presentation"); #endif if (!roleMapEntry && !content->IsFocusable()) { // Table-related descendants of presentation table are also // presentation if they aren't focusable and have not explicit ARIA @@ -1582,22 +1390,22 @@ nsAccessibilityService::GetAccessible(ns if (roleMapEntry) { // Create ARIA grid/treegrid accessibles if node is not of a child or // valid child of HTML table and is not a HTML table. if ((!partOfHTMLTable || !tryTagNameOrFrame) && frameType != nsAccessibilityAtoms::tableOuterFrame) { if (roleMapEntry->role == nsIAccessibleRole::ROLE_TABLE || roleMapEntry->role == nsIAccessibleRole::ROLE_TREE_TABLE) { - newAcc = new nsARIAGridAccessibleWrap(aNode, aWeakShell); + newAcc = new nsARIAGridAccessibleWrap(content, aWeakShell); } else if (roleMapEntry->role == nsIAccessibleRole::ROLE_GRID_CELL || roleMapEntry->role == nsIAccessibleRole::ROLE_ROWHEADER || roleMapEntry->role == nsIAccessibleRole::ROLE_COLUMNHEADER) { - newAcc = new nsARIAGridCellAccessibleWrap(aNode, aWeakShell); + newAcc = new nsARIAGridCellAccessibleWrap(content, aWeakShell); } } } if (!newAcc && tryTagNameOrFrame) { // Prefer to use markup (mostly tag name, perhaps attributes) to // decide if and what kind of accessible to create. // The method creates accessibles for table related content too therefore @@ -1633,35 +1441,35 @@ nsAccessibilityService::GetAccessible(ns newAcc = do_QueryObject(newAccessible); } } } if (!newAcc) { // Elements may implement nsIAccessibleProvider via XBL. This allows them to // say what kind of accessible to create. - newAcc = CreateAccessibleByType(aNode, aWeakShell); + newAcc = CreateAccessibleByType(content, aWeakShell); } if (!newAcc) { // Create generic accessibles for SVG and MathML nodes. if (content->GetNameSpaceID() == kNameSpaceID_SVG && content->Tag() == nsAccessibilityAtoms::svg) { - newAcc = new nsEnumRoleAccessible(aNode, aWeakShell, + newAcc = new nsEnumRoleAccessible(content, aWeakShell, nsIAccessibleRole::ROLE_DIAGRAM); } else if (content->GetNameSpaceID() == kNameSpaceID_MathML && content->Tag() == nsAccessibilityAtoms::math) { - newAcc = new nsEnumRoleAccessible(aNode, aWeakShell, + newAcc = new nsEnumRoleAccessible(content, aWeakShell, nsIAccessibleRole::ROLE_EQUATION); } } if (!newAcc) { - newAcc = CreateAccessibleForDeckChild(weakFrame.GetFrame(), aNode, + newAcc = CreateAccessibleForDeckChild(weakFrame.GetFrame(), content, aWeakShell); } // If no accessible, see if we need to create a generic accessible because // of some property that makes this object interesting // We don't do this for <body>, <html>, <window>, <dialog> etc. which // correspond to the doc accessible and will be created in any case if (!newAcc && content->Tag() != nsAccessibilityAtoms::body && content->GetParent() && @@ -1669,29 +1477,78 @@ nsAccessibilityService::GetAccessible(ns (isHTML && nsCoreUtils::HasClickListener(content)) || HasUniversalAriaProperty(content) || roleMapEntry || HasRelatedContent(content) || nsCoreUtils::IsXLink(content))) { // This content is focusable or has an interesting dynamic content accessibility property. // If it's interesting we need it in the accessibility hierarchy so that events or // other accessibles can point to it, or so that it can hold a state, etc. if (isHTML) { // Interesting HTML container which may have selectable text and/or embedded objects - newAcc = new nsHyperTextAccessibleWrap(aNode, aWeakShell); + newAcc = new nsHyperTextAccessibleWrap(content, aWeakShell); } else { // XUL, SVG, MathML etc. // Interesting generic non-HTML container - newAcc = new nsAccessibleWrap(aNode, aWeakShell); + newAcc = new nsAccessibleWrap(content, aWeakShell); } } if (InitAccessible(newAcc, roleMapEntry)) return newAcc.forget(); return nsnull; } +//////////////////////////////////////////////////////////////////////////////// +// nsAccessibilityService private + +PRBool +nsAccessibilityService::Init() +{ + // Initialize accessible document manager. + if (!nsAccDocManager::Init()) + return PR_FALSE; + + // Add observers. + nsCOMPtr<nsIObserverService> observerService = + mozilla::services::GetObserverService(); + if (!observerService) + return PR_FALSE; + + observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE); + + // Initialize accessibility. + nsAccessNodeWrap::InitAccessibility(); + + gIsShutdown = PR_FALSE; + return PR_TRUE; +} + +void +nsAccessibilityService::Shutdown() +{ + // Remove observers. + nsCOMPtr<nsIObserverService> observerService = + mozilla::services::GetObserverService(); + if (observerService) + observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID); + + // Stop accessible document loader. + nsAccDocManager::Shutdown(); + + // Application is going to be closed, shutdown accessibility and mark + // accessibility service as shutdown to prevent calls of its methods. + // Don't null accessibility service static member at this point to be safe + // if someone will try to operate with it. + + NS_ASSERTION(!gIsShutdown, "Accessibility was shutdown already"); + + gIsShutdown = PR_TRUE; + + nsAccessNodeWrap::ShutdownAccessibility(); +} + PRBool nsAccessibilityService::HasUniversalAriaProperty(nsIContent *aContent) { // ARIA attributes that take token values (NMTOKEN, bool) are special cased // because of special value "undefined" (see HasDefinedARIAToken). return nsAccUtils::HasDefinedARIAToken(aContent, nsAccessibilityAtoms::aria_atomic) || nsAccUtils::HasDefinedARIAToken(aContent, nsAccessibilityAtoms::aria_busy) || aContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_controls) || @@ -1705,20 +1562,18 @@ nsAccessibilityService::HasUniversalAria nsAccUtils::HasDefinedARIAToken(aContent, nsAccessibilityAtoms::aria_invalid) || aContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_label) || aContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_labelledby) || nsAccUtils::HasDefinedARIAToken(aContent, nsAccessibilityAtoms::aria_live) || nsAccUtils::HasDefinedARIAToken(aContent, nsAccessibilityAtoms::aria_owns) || nsAccUtils::HasDefinedARIAToken(aContent, nsAccessibilityAtoms::aria_relevant); } -// nsIAccessibleRetrieval -NS_IMETHODIMP -nsAccessibilityService::GetRelevantContentNodeFor(nsIDOMNode *aNode, - nsIDOMNode **aRelevantNode) +nsINode * +nsAccessibilityService::GetRelevantContentNodeFor(nsINode *aNode) { // The method returns node that is relevant for attached accessible check. // Sometimes element that is XBL widget hasn't accessible children in // anonymous content. This method check whether given node can be accessible // by looking through all nested bindings that given node is anonymous for. If // there is XBL widget that deniedes to be accessible for given node then the // method returns that XBL widget otherwise it returns given node. @@ -1729,337 +1584,315 @@ nsAccessibilityService::GetRelevantConte // 2. xul:texbox has html:input in anonymous content. When given node is // html:input elmement then we return xul:textbox since xul:textbox doesn't // allow accessible nodes in anonymous content. // 3. xforms:input that is hosted in xul document contains xul:textbox // element. When given node is html:input or xul:textbox then we return // xforms:input element since xforms:input hasn't accessible anonymous // children. - NS_ENSURE_ARG(aNode); - NS_ENSURE_ARG_POINTER(aRelevantNode); + if (!aNode) + return nsnull; nsCOMPtr<nsIContent> content(do_QueryInterface(aNode)); if (content) { // Build stack of binding parents so we can walk it in reverse. nsIContent *bindingParent; nsCOMArray<nsIContent> bindingsStack; for (bindingParent = content->GetBindingParent(); bindingParent != nsnull && bindingParent != bindingParent->GetBindingParent(); bindingParent = bindingParent->GetBindingParent()) { bindingsStack.AppendObject(bindingParent); } PRInt32 bindingsCount = bindingsStack.Count(); for (PRInt32 index = bindingsCount - 1; index >= 0 ; index--) { bindingParent = bindingsStack[index]; - nsCOMPtr<nsIDOMNode> bindingNode(do_QueryInterface(bindingParent)); - if (bindingNode) { - // Try to get an accessible by type since XBL widget can be accessible - // only if it implements nsIAccessibleProvider interface. - nsCOMPtr<nsIWeakReference> weakShell; - GetShellFromNode(bindingNode, getter_AddRefs(weakShell)); + + // Try to get an accessible by type since XBL widget can be accessible + // only if it implements nsIAccessibleProvider interface. + nsCOMPtr<nsIWeakReference> weakShell = + nsCoreUtils::GetWeakShellFor(bindingParent); - // XXX: it's a hack we should try the cache before, otherwise to cache - // the accessible. - nsRefPtr<nsAccessible> accessible = - CreateAccessibleByType(bindingNode, weakShell); + // XXX: it's a hack we should try the cache before, otherwise to cache + // the accessible. + nsRefPtr<nsAccessible> accessible = + CreateAccessibleByType(bindingParent, weakShell); - if (accessible) { - if (!accessible->GetAllowsAnonChildAccessibles()) { - NS_ADDREF(*aRelevantNode = bindingNode); - return NS_OK; - } - } + if (accessible) { + if (!accessible->GetAllowsAnonChildAccessibles()) + return bindingParent; } } } - NS_ADDREF(*aRelevantNode = aNode); - return NS_OK; + return aNode; } already_AddRefed<nsAccessible> nsAccessibilityService::GetAreaAccessible(nsIFrame *aImageFrame, - nsIDOMNode *aAreaNode, + nsINode *aAreaNode, nsIWeakReference *aWeakShell) { // Check if frame is an image frame, and content is <area>. nsIImageFrame *imageFrame = do_QueryFrame(aImageFrame); if (!imageFrame) return nsnull; nsCOMPtr<nsIDOMHTMLAreaElement> areaElmt = do_QueryInterface(aAreaNode); if (!areaElmt) return nsnull; // Try to get image map accessible from the global cache or create it // if failed. - nsRefPtr<nsAccessible> imageAcc; - - nsCOMPtr<nsIDOMNode> imageNode(do_QueryInterface(aImageFrame->GetContent())); - nsAccessNode *cachedImgAcc = GetCachedAccessNode(imageNode, aWeakShell); - if (cachedImgAcc) - imageAcc = do_QueryObject(cachedImgAcc); - + nsRefPtr<nsAccessible> imageAcc = + GetCachedAccessible(aImageFrame->GetContent(), aWeakShell); if (!imageAcc) { nsCOMPtr<nsIAccessible> imageAccessible; CreateHTMLImageAccessible(aImageFrame, getter_AddRefs(imageAccessible)); imageAcc = do_QueryObject(imageAccessible); if (!InitAccessible(imageAcc, nsnull)) return nsnull; } // Make sure <area> accessible children of the image map are cached so // that they should be available in global cache. imageAcc->EnsureChildren(); - nsAccessNode *cachedAreaAcc = GetCachedAccessNode(aAreaNode, aWeakShell); - if (!cachedAreaAcc) - return nsnull; - - nsRefPtr<nsAccessible> areaAcc = do_QueryObject(cachedAreaAcc); - return areaAcc.forget(); + nsAccessible *cachedAreaAcc = GetCachedAccessible(aAreaNode, aWeakShell); + NS_IF_ADDREF(cachedAreaAcc); + return cachedAreaAcc; } already_AddRefed<nsAccessible> -nsAccessibilityService::CreateAccessibleByType(nsIDOMNode *aNode, +nsAccessibilityService::CreateAccessibleByType(nsIContent *aContent, nsIWeakReference *aWeakShell) { - nsCOMPtr<nsIAccessibleProvider> accessibleProvider(do_QueryInterface(aNode)); + nsCOMPtr<nsIAccessibleProvider> accessibleProvider(do_QueryInterface(aContent)); if (!accessibleProvider) return nsnull; PRInt32 type; nsresult rv = accessibleProvider->GetAccessibleType(&type); if (NS_FAILED(rv)) return nsnull; nsRefPtr<nsAccessible> accessible; if (type == nsIAccessibleProvider::OuterDoc) { - accessible = new nsOuterDocAccessible(aNode, aWeakShell); + accessible = new nsOuterDocAccessible(aContent, aWeakShell); return accessible.forget(); } switch (type) { #ifdef MOZ_XUL case nsIAccessibleProvider::NoAccessible: return nsnull; // XUL controls case nsIAccessibleProvider::XULAlert: - accessible = new nsXULAlertAccessible(aNode, aWeakShell); + accessible = new nsXULAlertAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULButton: - accessible = new nsXULButtonAccessible(aNode, aWeakShell); + accessible = new nsXULButtonAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULCheckbox: - accessible = new nsXULCheckboxAccessible(aNode, aWeakShell); + accessible = new nsXULCheckboxAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULColorPicker: - accessible = new nsXULColorPickerAccessible(aNode, aWeakShell); + accessible = new nsXULColorPickerAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULColorPickerTile: - accessible = new nsXULColorPickerTileAccessible(aNode, aWeakShell); + accessible = new nsXULColorPickerTileAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULCombobox: - accessible = new nsXULComboboxAccessible(aNode, aWeakShell); + accessible = new nsXULComboboxAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULDropmarker: - accessible = new nsXULDropmarkerAccessible(aNode, aWeakShell); + accessible = new nsXULDropmarkerAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULGroupbox: - accessible = new nsXULGroupboxAccessible(aNode, aWeakShell); + accessible = new nsXULGroupboxAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULImage: { - // Don't include nameless images in accessible tree - nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(aNode)); - if (!elt) + // Don't include nameless images in accessible tree. + if (!aContent->HasAttr(kNameSpaceID_None, + nsAccessibilityAtoms::tooltiptext)) return nsnull; - PRBool hasTextEquivalent; - // Prefer value over tooltiptext - elt->HasAttribute(NS_LITERAL_STRING("tooltiptext"), &hasTextEquivalent); - if (!hasTextEquivalent) - return nsnull; - - accessible = new nsHTMLImageAccessibleWrap(aNode, aWeakShell); + accessible = new nsHTMLImageAccessibleWrap(aContent, aWeakShell); break; } case nsIAccessibleProvider::XULLink: - accessible = new nsXULLinkAccessible(aNode, aWeakShell); + accessible = new nsXULLinkAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULListbox: - accessible = new nsXULListboxAccessibleWrap(aNode, aWeakShell); + accessible = new nsXULListboxAccessibleWrap(aContent, aWeakShell); break; case nsIAccessibleProvider::XULListCell: - accessible = new nsXULListCellAccessibleWrap(aNode, aWeakShell); + accessible = new nsXULListCellAccessibleWrap(aContent, aWeakShell); break; case nsIAccessibleProvider::XULListHead: - accessible = new nsXULColumnsAccessible(aNode, aWeakShell); + accessible = new nsXULColumnsAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULListHeader: - accessible = new nsXULColumnItemAccessible(aNode, aWeakShell); + accessible = new nsXULColumnItemAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULListitem: - accessible = new nsXULListitemAccessible(aNode, aWeakShell); + accessible = new nsXULListitemAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULMenubar: - accessible = new nsXULMenubarAccessible(aNode, aWeakShell); + accessible = new nsXULMenubarAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULMenuitem: - accessible = new nsXULMenuitemAccessibleWrap(aNode, aWeakShell); + accessible = new nsXULMenuitemAccessibleWrap(aContent, aWeakShell); break; case nsIAccessibleProvider::XULMenupopup: { #ifdef MOZ_ACCESSIBILITY_ATK // ATK considers this node to be redundant when within menubars, and it makes menu // navigation with assistive technologies more difficult // XXX In the future we will should this for consistency across the nsIAccessible // implementations on each platform for a consistent scripting environment, but // then strip out redundant accessibles in the nsAccessibleWrap class for each platform. - nsCOMPtr<nsIContent> content = do_QueryInterface(aNode); - if (content) { - nsIContent *parent = content->GetParent(); - if (parent && parent->NodeInfo()->Equals(nsAccessibilityAtoms::menu, kNameSpaceID_XUL)) { - return nsnull; - } - } + nsIContent *parent = aContent->GetParent(); + if (parent && parent->NodeInfo()->Equals(nsAccessibilityAtoms::menu, + kNameSpaceID_XUL)) + return nsnull; #endif - accessible = new nsXULMenupopupAccessible(aNode, aWeakShell); + accessible = new nsXULMenupopupAccessible(aContent, aWeakShell); break; } case nsIAccessibleProvider::XULMenuSeparator: - accessible = new nsXULMenuSeparatorAccessible(aNode, aWeakShell); + accessible = new nsXULMenuSeparatorAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULPane: - accessible = new nsEnumRoleAccessible(aNode, aWeakShell, + accessible = new nsEnumRoleAccessible(aContent, aWeakShell, nsIAccessibleRole::ROLE_PANE); break; case nsIAccessibleProvider::XULProgressMeter: - accessible = new nsXULProgressMeterAccessible(aNode, aWeakShell); + accessible = new nsXULProgressMeterAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULStatusBar: - accessible = new nsXULStatusBarAccessible(aNode, aWeakShell); + accessible = new nsXULStatusBarAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULScale: - accessible = new nsXULSliderAccessible(aNode, aWeakShell); + accessible = new nsXULSliderAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULRadioButton: - accessible = new nsXULRadioButtonAccessible(aNode, aWeakShell); + accessible = new nsXULRadioButtonAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULRadioGroup: - accessible = new nsXULRadioGroupAccessible(aNode, aWeakShell); + accessible = new nsXULRadioGroupAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULTab: - accessible = new nsXULTabAccessible(aNode, aWeakShell); + accessible = new nsXULTabAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULTabs: - accessible = new nsXULTabsAccessible(aNode, aWeakShell); + accessible = new nsXULTabsAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULTabpanels: - accessible = new nsXULTabpanelsAccessible(aNode, aWeakShell); + accessible = new nsXULTabpanelsAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULText: - accessible = new nsXULTextAccessible(aNode, aWeakShell); + accessible = new nsXULTextAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULTextBox: - accessible = new nsXULTextFieldAccessible(aNode, aWeakShell); + accessible = new nsXULTextFieldAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULThumb: - accessible = new nsXULThumbAccessible(aNode, aWeakShell); + accessible = new nsXULThumbAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULTree: - return CreateAccessibleForXULTree(aNode, aWeakShell); + return CreateAccessibleForXULTree(aContent, aWeakShell); case nsIAccessibleProvider::XULTreeColumns: - accessible = new nsXULTreeColumnsAccessible(aNode, aWeakShell); + accessible = new nsXULTreeColumnsAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULTreeColumnItem: - accessible = new nsXULColumnItemAccessible(aNode, aWeakShell); + accessible = new nsXULColumnItemAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULToolbar: - accessible = new nsXULToolbarAccessible(aNode, aWeakShell); + accessible = new nsXULToolbarAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULToolbarSeparator: - accessible = new nsXULToolbarSeparatorAccessible(aNode, aWeakShell); + accessible = new nsXULToolbarSeparatorAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULTooltip: - accessible = new nsXULTooltipAccessible(aNode, aWeakShell); + accessible = new nsXULTooltipAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XULToolbarButton: - accessible = new nsXULToolbarButtonAccessible(aNode, aWeakShell); + accessible = new nsXULToolbarButtonAccessible(aContent, aWeakShell); break; #endif // MOZ_XUL #ifndef DISABLE_XFORMS_HOOKS // XForms elements case nsIAccessibleProvider::XFormsContainer: - accessible = new nsXFormsContainerAccessible(aNode, aWeakShell); + accessible = new nsXFormsContainerAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XFormsLabel: - accessible = new nsXFormsLabelAccessible(aNode, aWeakShell); + accessible = new nsXFormsLabelAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XFormsOutput: - accessible = new nsXFormsOutputAccessible(aNode, aWeakShell); + accessible = new nsXFormsOutputAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XFormsTrigger: - accessible = new nsXFormsTriggerAccessible(aNode, aWeakShell); + accessible = new nsXFormsTriggerAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XFormsInput: - accessible = new nsXFormsInputAccessible(aNode, aWeakShell); + accessible = new nsXFormsInputAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XFormsInputBoolean: - accessible = new nsXFormsInputBooleanAccessible(aNode, aWeakShell); + accessible = new nsXFormsInputBooleanAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XFormsInputDate: - accessible = new nsXFormsInputDateAccessible(aNode, aWeakShell); + accessible = new nsXFormsInputDateAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XFormsSecret: - accessible = new nsXFormsSecretAccessible(aNode, aWeakShell); + accessible = new nsXFormsSecretAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XFormsSliderRange: - accessible = new nsXFormsRangeAccessible(aNode, aWeakShell); + accessible = new nsXFormsRangeAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XFormsSelect: - accessible = new nsXFormsSelectAccessible(aNode, aWeakShell); + accessible = new nsXFormsSelectAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XFormsChoices: - accessible = new nsXFormsChoicesAccessible(aNode, aWeakShell); + accessible = new nsXFormsChoicesAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XFormsSelectFull: - accessible = new nsXFormsSelectFullAccessible(aNode, aWeakShell); + accessible = new nsXFormsSelectFullAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XFormsItemCheckgroup: - accessible = new nsXFormsItemCheckgroupAccessible(aNode, aWeakShell); + accessible = new nsXFormsItemCheckgroupAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XFormsItemRadiogroup: - accessible = new nsXFormsItemRadiogroupAccessible(aNode, aWeakShell); + accessible = new nsXFormsItemRadiogroupAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XFormsSelectCombobox: - accessible = new nsXFormsSelectComboboxAccessible(aNode, aWeakShell); + accessible = new nsXFormsSelectComboboxAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XFormsItemCombobox: - accessible = new nsXFormsItemComboboxAccessible(aNode, aWeakShell); + accessible = new nsXFormsItemComboboxAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XFormsDropmarkerWidget: - accessible = new nsXFormsDropmarkerWidgetAccessible(aNode, aWeakShell); + accessible = new nsXFormsDropmarkerWidgetAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XFormsCalendarWidget: - accessible = new nsXFormsCalendarWidgetAccessible(aNode, aWeakShell); + accessible = new nsXFormsCalendarWidgetAccessible(aContent, aWeakShell); break; case nsIAccessibleProvider::XFormsComboboxPopupWidget: - accessible = new nsXFormsComboboxPopupWidgetAccessible(aNode, aWeakShell); + accessible = new nsXFormsComboboxPopupWidgetAccessible(aContent, aWeakShell); break; #endif default: return nsnull; } return accessible.forget(); @@ -2121,101 +1954,106 @@ nsAccessibilityService::InvalidateSubtre aChangeType == nsIAccessibilityService::FRAME_HIDE || aChangeType == nsIAccessibilityService::NODE_SIGNIFICANT_CHANGE || aChangeType == nsIAccessibilityService::NODE_APPEND || aChangeType == nsIAccessibilityService::NODE_REMOVE, "Incorrect aEvent passed in"); NS_ENSURE_ARG_POINTER(aShell); - nsCOMPtr<nsIAccessibleDocument> accessibleDoc = - nsAccessNode::GetDocAccessibleFor(aShell->GetDocument()); - nsRefPtr<nsDocAccessible> docAcc = do_QueryObject(accessibleDoc); - if (docAcc) - docAcc->InvalidateCacheSubtree(aChangeContent, aChangeType); + nsDocAccessible *docAccessible = GetDocAccessible(aShell->GetDocument()); + if (docAccessible) + docAccessible->InvalidateCacheSubtree(aChangeContent, aChangeType); return NS_OK; } //////////////////////////////////////////////////////////////////////////////// // NS_GetAccessibilityService //////////////////////////////////////////////////////////////////////////////// /** * Return accessibility service; creating one if necessary. */ nsresult NS_GetAccessibilityService(nsIAccessibilityService** aResult) { - NS_ENSURE_TRUE(aResult, NS_ERROR_NULL_POINTER); - *aResult = nsnull; + NS_ENSURE_TRUE(aResult, NS_ERROR_NULL_POINTER); + *aResult = nsnull; - if (!nsAccessibilityService::gAccessibilityService) { - nsAccessibilityService::gAccessibilityService = new nsAccessibilityService(); - NS_ENSURE_TRUE(nsAccessibilityService::gAccessibilityService, NS_ERROR_OUT_OF_MEMORY); - - nsAccessibilityService::gIsShutdown = PR_FALSE; - } - - NS_ADDREF(*aResult = nsAccessibilityService::gAccessibilityService); + if (nsAccessibilityService::gAccessibilityService) { + NS_ADDREF(*aResult = nsAccessibilityService::gAccessibilityService); + return NS_OK; + } + + nsRefPtr<nsAccessibilityService> service = new nsAccessibilityService(); + NS_ENSURE_TRUE(service, NS_ERROR_OUT_OF_MEMORY); + + if (!service->Init()) { + service->Shutdown(); + return NS_ERROR_FAILURE; + } + + nsAccessibilityService::gAccessibilityService = service; + NS_ADDREF(*aResult = service); + return NS_OK; } //////////////////////////////////////////////////////////////////////////////// // nsAccessibilityService private (DON'T put methods here) already_AddRefed<nsAccessible> nsAccessibilityService::CreateAccessibleForDeckChild(nsIFrame* aFrame, - nsIDOMNode *aNode, + nsIContent *aContent, nsIWeakReference *aWeakShell) { nsRefPtr<nsAccessible> accessible; if (aFrame->GetType() == nsAccessibilityAtoms::boxFrame || aFrame->GetType() == nsAccessibilityAtoms::scrollFrame) { nsIFrame* parentFrame = aFrame->GetParent(); if (parentFrame && parentFrame->GetType() == nsAccessibilityAtoms::deckFrame) { // If deck frame is for xul:tabpanels element then the given node has // tabpanel accessible. nsCOMPtr<nsIContent> parentContent = parentFrame->GetContent(); #ifdef MOZ_XUL if (parentContent->NodeInfo()->Equals(nsAccessibilityAtoms::tabpanels, kNameSpaceID_XUL)) { - accessible = new nsXULTabpanelAccessible(aNode, aWeakShell); + accessible = new nsXULTabpanelAccessible(aContent, aWeakShell); } else #endif accessible = - new nsEnumRoleAccessible(aNode, aWeakShell, + new nsEnumRoleAccessible(aContent, aWeakShell, nsIAccessibleRole::ROLE_PROPERTYPAGE); } } return accessible.forget(); } #ifdef MOZ_XUL already_AddRefed<nsAccessible> -nsAccessibilityService::CreateAccessibleForXULTree(nsIDOMNode *aNode, +nsAccessibilityService::CreateAccessibleForXULTree(nsIContent *aContent, nsIWeakReference *aWeakShell) { - nsCOMPtr<nsITreeBoxObject> treeBoxObj; - nsCoreUtils::GetTreeBoxObject(aNode, getter_AddRefs(treeBoxObj)); + nsCOMPtr<nsITreeBoxObject> treeBoxObj = nsCoreUtils::GetTreeBoxObject(aContent); if (!treeBoxObj) return nsnull; nsCOMPtr<nsITreeColumns> treeColumns; treeBoxObj->GetColumns(getter_AddRefs(treeColumns)); if (!treeColumns) return nsnull; nsRefPtr<nsAccessible> accessible; PRInt32 count = 0; treeColumns->GetCount(&count); if (count == 1) // outline of list accessible - accessible = new nsXULTreeAccessible(aNode, aWeakShell); + accessible = new nsXULTreeAccessible(aContent, aWeakShell); else // table or tree table accessible - accessible = new nsXULTreeGridAccessibleWrap(aNode, aWeakShell); + accessible = new nsXULTreeGridAccessibleWrap(aContent, aWeakShell); return accessible.forget(); } #endif
--- a/accessible/src/base/nsAccessibilityService.h +++ b/accessible/src/base/nsAccessibilityService.h @@ -37,48 +37,30 @@ * ***** END LICENSE BLOCK ***** */ #ifndef __nsAccessibilityService_h__ #define __nsAccessibilityService_h__ #include "nsIAccessibilityService.h" #include "a11yGeneric.h" -#include "nsCoreUtils.h" +#include "nsAccDocManager.h" -#include "nsCOMArray.h" #include "nsIObserver.h" -#include "nsIWebProgress.h" -#include "nsIWebProgressListener.h" -#include "nsWeakReference.h" -class nsAccessNode; -class nsAccessible; -class nsIFrame; -class nsIWeakReference; -class nsIDOMNode; -class nsObjectFrame; -class nsIDocShell; -class nsIPresShell; -class nsIContent; -struct nsRoleMapEntry; - -class nsAccessibilityService : public nsIAccessibilityService, - public nsIObserver, - public nsIWebProgressListener, - public nsSupportsWeakReference +class nsAccessibilityService : public nsAccDocManager, + public nsIAccessibilityService, + public nsIObserver { public: - nsAccessibilityService(); virtual ~nsAccessibilityService(); - NS_DECL_ISUPPORTS + NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIACCESSIBLERETRIEVAL NS_DECL_NSIOBSERVER - NS_DECL_NSIWEBPROGRESSLISTENER // nsIAccessibilityService virtual nsAccessible* GetAccessibleInShell(nsIDOMNode *aNode, nsIPresShell *aPresShell); virtual nsresult CreateOuterDocAccessible(nsIDOMNode *aNode, nsIAccessible **aAccessible); virtual nsresult CreateHTML4ButtonAccessible(nsIFrame *aFrame, @@ -137,177 +119,202 @@ public: virtual nsresult RemoveNativeRootAccessible(nsIAccessible *aRootAccessible); virtual nsresult InvalidateSubtreeFor(nsIPresShell *aPresShell, nsIContent *aContent, PRUint32 aChangeType); virtual void NotifyOfAnchorJumpTo(nsIContent *aTarget); + virtual void PresShellDestroyed(nsIPresShell* aPresShell); + virtual nsresult FireAccessibleEvent(PRUint32 aEvent, nsIAccessible *aTarget); // nsAccessibiltiyService /** - * Return presentation shell for the given node. - * - * @param aNode - the given DOM node. + * Return true if accessibility service has been shutdown. */ - static nsresult GetShellFromNode(nsIDOMNode *aNode, - nsIWeakReference **weakShell); - - /** - * Indicates whether accessibility service was shutdown. - */ - static PRBool gIsShutdown; + static PRBool IsShutdown() { return gIsShutdown; } /** * Return an accessible for the given DOM node. * * @param aNode [in] the given node * @param aPresShell [in] the pres shell of the node * @param aWeakShell [in] the weak shell for the pres shell * @param aIsHidden [out, optional] indicates whether the node's frame is * hidden */ already_AddRefed<nsAccessible> - GetAccessible(nsIDOMNode *aNode, nsIPresShell *aPresShell, + GetAccessible(nsINode *aNode, nsIPresShell *aPresShell, nsIWeakReference *aWeakShell, PRBool *aIsHidden = nsnull); /** * Return an accessible for the given DOM node. */ - nsAccessible *GetAccessible(nsIDOMNode *aNode); + nsAccessible *GetAccessible(nsINode *aNode); /** * Return an accessible for a DOM node in the given pres shell. * * @param aNode [in] the given node. * @param aPresShell [in] the presentation shell of the given node. */ - nsAccessible *GetAccessibleInWeakShell(nsIDOMNode *aNode, + nsAccessible *GetAccessibleInWeakShell(nsINode *aNode, nsIWeakReference *aPresShell); /** * Return the first accessible parent of a DOM node. * * @param aDOMNode [in] the DOM node to get an accessible for * @param aCanCreate [in] specifies if accessible can be created if it didn't * exist */ - nsAccessible *GetContainerAccessible(nsIDOMNode *aNode, PRBool aCanCreate); + nsAccessible *GetContainerAccessible(nsINode *aNode, PRBool aCanCreate); /** - * Return an access node for the DOM node in the given presentation shell if - * the access node already exists, otherwise null. + * The same as getAccessibleFor method except it returns accessible only if + * it is attached, i.e. accessible is certified to be a descendant of the root + * accessible. * - * @param aNode [in] the DOM node to get an access node for - * @param aPresShell [in] the presentation shell which contains layout info - * for the DOM node + * XXX: this method must go away once we'll implement correct accessible tree. + * + * @param aNode [in] the DOM node to get an accessible for + * @return the accessible for the given DOM node */ - nsAccessNode* GetCachedAccessNode(nsIDOMNode *aNode, - nsIWeakReference *aShell); + nsAccessible *GetAttachedAccessibleFor(nsINode *aNode); -private: /** - * Return presentation shell, DOM node for the given frame. + * Return an DOM node that is relevant to attached accessible check. This + * node is either from bindings chain if given node is anonymous and owner + * binding denies accessible in anonymous content or given node (it's not + * important whether it is accessible or not). This method doesn't create + * accessible object for returned node. * - * @param aFrame - the given frame - * @param aShell [out] - presentation shell for DOM node associated with the - * given frame - * @param aContent [out] - DOM node associated with the given frame + * XXX: this method must go away once we'll implement correct accessible tree. + * + * @param aNode [in] the DOM node to get relevant content node + * @return the DOM node for parent attached accessible */ - nsresult GetInfo(nsIFrame *aFrame, - nsIWeakReference **aShell, - nsIDOMNode **aContent); + nsINode *GetRelevantContentNodeFor(nsINode *aNode); /** * Initialize an accessible and cache it. The method should be called for * every created accessible. * * @param aAccessible [in] accessible to initialize. * @param aRoleMapEntry [in] the role map entry role the ARIA role or nsnull * if none * * @return true if the accessible was initialized, otherwise false */ PRBool InitAccessible(nsAccessible *aAccessible, nsRoleMapEntry *aRoleMapEntry); +protected: + /** + * Return an accessible for the DOM node in the given presentation shell if + * the accessible already exists, otherwise null. + * + * @param aNode [in] the DOM node to get an access node for + * @param aPresShell [in] the presentation shell which contains layout info + * for the DOM node + */ + nsAccessible *GetCachedAccessible(nsINode *aNode, + nsIWeakReference *aShell); + +private: + // nsAccessibilityService creation is controlled by friend + // NS_GetAccessibilityService, keep constructors private. + nsAccessibilityService(); + nsAccessibilityService(const nsAccessibilityService&); + nsAccessibilityService& operator =(const nsAccessibilityService&); + +private: + /** + * Initialize accessibility service. + */ + PRBool Init(); + + /** + * Shutdowns accessibility service. + */ + void Shutdown(); + + /** + * Return presentation shell, DOM node for the given frame. + * + * @param aFrame [in] the given frame + * @param aShell [out] presentation shell for DOM node associated with the + * given frame + * @param aContent [out] DOM node associated with the given frame + */ + nsresult GetInfo(nsIFrame *aFrame, nsIWeakReference **aShell, + nsIContent **aContent); + /** * Return accessible for HTML area element associated with an image map. */ already_AddRefed<nsAccessible> - GetAreaAccessible(nsIFrame *aImageFrame, nsIDOMNode *aAreaNode, + GetAreaAccessible(nsIFrame *aImageFrame, nsINode *aAreaNode, nsIWeakReference *aWeakShell); /** * Create accessible for the element implementing nsIAccessibleProvider * interface. */ already_AddRefed<nsAccessible> - CreateAccessibleByType(nsIDOMNode *aNode, nsIWeakReference *aWeakShell); - - /** - * Create document or root accessible. - */ - already_AddRefed<nsAccessible> - CreateDocOrRootAccessible(nsIPresShell *aShell, nsIDocument *aDocument); + CreateAccessibleByType(nsIContent *aContent, nsIWeakReference *aWeakShell); /** * Create accessible for HTML node by tag name. */ already_AddRefed<nsAccessible> CreateHTMLAccessibleByMarkup(nsIFrame *aFrame, nsIWeakReference *aWeakShell, - nsIDOMNode *aNode); + nsINode *aNode); /** * Create accessible if parent is a deck frame. */ already_AddRefed<nsAccessible> - CreateAccessibleForDeckChild(nsIFrame *aFrame, nsIDOMNode *aNode, + CreateAccessibleForDeckChild(nsIFrame *aFrame, nsIContent *aContent, nsIWeakReference *aWeakShell); #ifdef MOZ_XUL /** * Create accessible for XUL tree element. */ already_AddRefed<nsAccessible> - CreateAccessibleForXULTree(nsIDOMNode *aNode, nsIWeakReference *aWeakShell); + CreateAccessibleForXULTree(nsIContent *aContent, + nsIWeakReference *aWeakShell); #endif - + + /** + * Reference for accessibility service. + */ static nsAccessibilityService *gAccessibilityService; /** + * Indicates whether accessibility service was shutdown. + */ + static PRBool gIsShutdown; + + /** * Does this content node have a universal ARIA property set on it? * A universal ARIA property is one that can be defined on any element even if there is no role. * * @param aContent The content node to test * @return PR_TRUE if there is a universal ARIA property set on the node */ PRBool HasUniversalAriaProperty(nsIContent *aContent); - /** - * Process the internal doc load event. - * - * @param aWebProgress [in] the nsIWebProgress object for the load event - * @param aEventType [in] the type of load event, one of: - * nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_START, - * nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE, - * nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED - */ - void ProcessDocLoadEvent(nsIWebProgress *aWebProgress, PRUint32 aEventType); - friend nsAccessibilityService* GetAccService(); - friend nsresult NS_GetAccessibilityService(nsIAccessibilityService** aResult); - - - NS_DECL_RUNNABLEMETHOD_ARG2(nsAccessibilityService, ProcessDocLoadEvent, - nsCOMPtr<nsIWebProgress>, PRUint32) + friend nsresult NS_GetAccessibilityService(nsIAccessibilityService** aResult); }; /** * Return the accessibility service instance. (Handy global function) */ inline nsAccessibilityService* GetAccService() { @@ -483,17 +490,16 @@ static const char kEventTypeNames[][40] "dragdrop start", // EVENT_DRAGDROP_START "dragdrop end", // EVENT_DRAGDROP_END "dialog start", // EVENT_DIALOG_START "dialog end", // EVENT_DIALOG_END "scrolling start", // EVENT_SCROLLING_START "scrolling end", // EVENT_SCROLLING_END "minimize start", // EVENT_MINIMIZE_START "minimize end", // EVENT_MINIMIZE_END - "document load start", // EVENT_DOCUMENT_LOAD_START "document load complete", // EVENT_DOCUMENT_LOAD_COMPLETE "document reload", // EVENT_DOCUMENT_RELOAD "document load stopped", // EVENT_DOCUMENT_LOAD_STOPPED "document attributes changed", // EVENT_DOCUMENT_ATTRIBUTES_CHANGED "document content changed", // EVENT_DOCUMENT_CONTENT_CHANGED "property changed", // EVENT_PROPERTY_CHANGED "selection changed", // EVENT_SELECTION_CHANGED "text attribute changed", // EVENT_TEXT_ATTRIBUTE_CHANGED @@ -531,18 +537,17 @@ static const char kEventTypeNames[][40] "hyperlink number of anchors changed", // EVENT_HYPERLINK_NUMBER_OF_ANCHORS_CHANGED "hyperlink selected link changed", // EVENT_HYPERLINK_SELECTED_LINK_CHANGED "hypertext link activated", // EVENT_HYPERTEXT_LINK_ACTIVATED "hypertext link selected", // EVENT_HYPERTEXT_LINK_SELECTED "hyperlink start index changed", // EVENT_HYPERLINK_START_INDEX_CHANGED "hypertext changed", // EVENT_HYPERTEXT_CHANGED "hypertext links count changed", // EVENT_HYPERTEXT_NLINKS_CHANGED "object attribute changed", // EVENT_OBJECT_ATTRIBUTE_CHANGED - "page changed", // EVENT_PAGE_CHANGED - "internal load" // EVENT_INTERNAL_LOAD + "page changed" // EVENT_PAGE_CHANGED }; /** * Map nsIAccessibleRelation constants to strings. Used by * nsIAccessibleRetrieval::getStringRelationType() method. */ static const char kRelationTypeNames[][20] = { "unknown", // RELATION_NUL
--- a/accessible/src/base/nsAccessible.cpp +++ b/accessible/src/base/nsAccessible.cpp @@ -36,17 +36,17 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsAccessible.h" #include "nsIXBLAccessible.h" -#include "nsAccIterator.h" +#include "AccIterator.h" #include "nsAccUtils.h" #include "nsARIAMap.h" #include "nsDocAccessible.h" #include "nsEventShell.h" #include "nsAccessibilityService.h" #include "nsAccTreeWalker.h" #include "nsRelUtils.h" @@ -185,19 +185,19 @@ nsresult nsAccessible::QueryInterface(RE return NS_OK; } return NS_ERROR_NO_INTERFACE; } return nsAccessNodeWrap::QueryInterface(aIID, aInstancePtr); } -nsAccessible::nsAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell): nsAccessNodeWrap(aNode, aShell), - mParent(nsnull), mRoleMapEntry(nsnull), - mAreChildrenInitialized(PR_FALSE) +nsAccessible::nsAccessible(nsIContent *aContent, nsIWeakReference *aShell) : + nsAccessNodeWrap(aContent, aShell), + mParent(nsnull), mAreChildrenInitialized(PR_FALSE), mRoleMapEntry(nsnull) { #ifdef NS_DEBUG_X { nsCOMPtr<nsIPresShell> shell(do_QueryReferent(aShell)); printf(">>> %p Created Acc - DOM: %p PS: %p", (void*)static_cast<nsIAccessible*>(this), (void*)aNode, (void*)shell.get()); nsCOMPtr<nsIContent> content = do_QueryInterface(aNode); @@ -235,46 +235,42 @@ nsAccessible::GetName(nsAString& aName) if (IsDefunct()) return NS_ERROR_FAILURE; GetARIAName(aName); if (!aName.IsEmpty()) return NS_OK; - nsCOMPtr<nsIXBLAccessible> xblAccessible(do_QueryInterface(mDOMNode)); + nsCOMPtr<nsIXBLAccessible> xblAccessible(do_QueryInterface(mContent)); if (xblAccessible) { xblAccessible->GetAccessibleName(aName); if (!aName.IsEmpty()) return NS_OK; } nsresult rv = GetNameInternal(aName); NS_ENSURE_SUCCESS(rv, rv); if (!aName.IsEmpty()) return NS_OK; // In the end get the name from tooltip. - nsCOMPtr<nsIContent> content = nsCoreUtils::GetRoleContent(mDOMNode); - if (!content) - return NS_OK; - nsIAtom *tooltipAttr = nsnull; - if (content->IsHTML()) + if (mContent->IsHTML()) tooltipAttr = nsAccessibilityAtoms::title; - else if (content->IsXUL()) + else if (mContent->IsXUL()) tooltipAttr = nsAccessibilityAtoms::tooltiptext; else return NS_OK; // XXX: if CompressWhiteSpace worked on nsAString we could avoid a copy. nsAutoString name; - if (content->GetAttr(kNameSpaceID_None, tooltipAttr, name)) { + if (mContent->GetAttr(kNameSpaceID_None, tooltipAttr, name)) { name.CompressWhitespace(); aName = name; return NS_OK_NAME_FROM_TOOLTIP; } if (rv != NS_OK_EMPTY_NAME) aName.SetIsVoid(PR_TRUE); @@ -286,47 +282,43 @@ NS_IMETHODIMP nsAccessible::GetDescripti if (IsDefunct()) return NS_ERROR_FAILURE; // There are 4 conditions that make an accessible have no accDescription: // 1. it's a text node; or // 2. It has no DHTML describedby property // 3. it doesn't have an accName; or // 4. its title attribute already equals to its accName nsAutoString name; - nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode)); - NS_ASSERTION(content, "No content of valid accessible!"); - if (!content) - return NS_ERROR_FAILURE; - - if (!content->IsNodeOfType(nsINode::eTEXT)) { + + if (!mContent->IsNodeOfType(nsINode::eTEXT)) { nsAutoString description; nsresult rv = nsTextEquivUtils:: GetTextEquivFromIDRefs(this, nsAccessibilityAtoms::aria_describedby, description); NS_ENSURE_SUCCESS(rv, rv); if (description.IsEmpty()) { - PRBool isXUL = content->IsXUL(); + PRBool isXUL = mContent->IsXUL(); if (isXUL) { // Try XUL <description control="[id]">description text</description> nsIContent *descriptionContent = - nsCoreUtils::FindNeighbourPointingToNode(content, + nsCoreUtils::FindNeighbourPointingToNode(mContent, nsAccessibilityAtoms::control, nsAccessibilityAtoms::description); if (descriptionContent) { // We have a description content node nsTextEquivUtils:: AppendTextEquivFromContent(this, descriptionContent, &description); } } if (description.IsEmpty()) { nsIAtom *descAtom = isXUL ? nsAccessibilityAtoms::tooltiptext : nsAccessibilityAtoms::title; - if (content->GetAttr(kNameSpaceID_None, descAtom, description)) { + if (mContent->GetAttr(kNameSpaceID_None, descAtom, description)) { nsAutoString name; GetName(name); if (name.IsEmpty() || description == name) { // Don't use tooltip for a description if this object // has no name or the tooltip is the same as the name description.Truncate(); } } @@ -396,38 +388,36 @@ GetAccessModifierMask(nsIContent* aConte return NS_SUCCEEDED(rv) ? accessModifierMask : 0; } NS_IMETHODIMP nsAccessible::GetKeyboardShortcut(nsAString& aAccessKey) { aAccessKey.Truncate(); - nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode)); - if (!content) + if (IsDefunct()) return NS_ERROR_FAILURE; - PRUint32 key = nsCoreUtils::GetAccessKeyFor(content); - if (!key && content->IsElement()) { + PRUint32 key = nsCoreUtils::GetAccessKeyFor(mContent); + if (!key && mContent->IsElement()) { // Copy access key from label node unless it is labeled // via an ancestor <label>, in which case that would be redundant - nsCOMPtr<nsIContent> labelContent(nsCoreUtils::GetLabelContent(content)); - nsCOMPtr<nsINode> thisNode = do_QueryInterface(mDOMNode); - if (labelContent && !nsCoreUtils::IsAncestorOf(labelContent, thisNode)) + nsCOMPtr<nsIContent> labelContent(nsCoreUtils::GetLabelContent(mContent)); + if (labelContent && !nsCoreUtils::IsAncestorOf(labelContent, mContent)) key = nsCoreUtils::GetAccessKeyFor(labelContent); } if (!key) return NS_OK; nsAutoString accesskey(key); // Append the modifiers in reverse order, result: Control+Alt+Shift+Meta+<key> nsAutoString propertyKey; - PRInt32 modifierMask = GetAccessModifierMask(content); + PRInt32 modifierMask = GetAccessModifierMask(mContent); if (modifierMask & NS_MODIFIER_META) { propertyKey.AssignLiteral("VK_META"); nsAccessible::GetFullKeyName(propertyKey, accesskey, accesskey); } if (modifierMask & NS_MODIFIER_SHIFT) { propertyKey.AssignLiteral("VK_SHIFT"); nsAccessible::GetFullKeyName(propertyKey, accesskey, accesskey); } @@ -439,30 +429,16 @@ nsAccessible::GetKeyboardShortcut(nsAStr propertyKey.AssignLiteral("VK_CONTROL"); nsAccessible::GetFullKeyName(propertyKey, accesskey, accesskey); } aAccessKey = accesskey; return NS_OK; } -nsresult -nsAccessible::Shutdown() -{ - // Invalidate the child count and pointers to other accessibles, also make - // sure none of its children point to this parent - InvalidateChildren(); - if (mParent) { - mParent->InvalidateChildren(); - mParent = nsnull; - } - - return nsAccessNodeWrap::Shutdown(); -} - NS_IMETHODIMP nsAccessible::GetParent(nsIAccessible **aParent) { NS_ENSURE_ARG_POINTER(aParent); NS_IF_ADDREF(*aParent = GetParent()); return *aParent ? NS_OK : NS_ERROR_FAILURE; } @@ -624,19 +600,18 @@ nsresult nsAccessible::GetFullKeyName(co PRBool nsAccessible::IsVisible(PRBool *aIsOffscreen) { // We need to know if at least a kMinPixels around the object is visible // Otherwise it will be marked nsIAccessibleStates::STATE_OFFSCREEN // The STATE_INVISIBLE flag is for elements which are programmatically hidden *aIsOffscreen = PR_TRUE; - if (!mDOMNode) { - return PR_FALSE; // Defunct object - } + if (IsDefunct()) + return PR_FALSE; const PRUint16 kMinPixels = 12; // Set up the variables we need, return false if we can't get at them all nsCOMPtr<nsIPresShell> shell(GetPresShell()); if (!shell) return PR_FALSE; nsIFrame *frame = GetFrame(); @@ -681,19 +656,17 @@ PRBool nsAccessible::IsVisible(PRBool *a if (isEmpty && !(frame->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) { // Consider zero area objects hidden unless they are absolutely positioned // or floating and may have descendants that have a non-zero size return PR_FALSE; } } // The frame intersects the viewport, but we need to check the parent view chain :( - nsCOMPtr<nsIDOMDocument> domDoc; - mDOMNode->GetOwnerDocument(getter_AddRefs(domDoc)); - nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDoc)); + nsIDocument* doc = mContent->GetOwnerDoc(); if (!doc) { return PR_FALSE; } nsIFrame* frameWithView = frame->HasView() ? frame : frame->GetAncestorWithViewExternal(); nsIView* view = frameWithView->GetViewExternal(); PRBool isVisible = CheckVisibilityInParentChain(doc, view); @@ -713,47 +686,43 @@ nsAccessible::GetStateInternal(PRUint32 *aExtraState = nsIAccessibleStates::EXT_STATE_DEFUNCT; return NS_OK_DEFUNCT_OBJECT; } if (aExtraState) *aExtraState = 0; - nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode)); - if (!content) { - return NS_OK; // On document, this is not an error - } - // Set STATE_UNAVAILABLE state based on disabled attribute // The disabled attribute is mostly used in XUL elements and HTML forms, but // if someone sets it on another attribute, // it seems reasonable to consider it unavailable PRBool isDisabled; - if (content->IsHTML()) { + if (mContent->IsHTML()) { // In HTML, just the presence of the disabled attribute means it is disabled, // therefore disabled="false" indicates disabled! - isDisabled = content->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::disabled); + isDisabled = mContent->HasAttr(kNameSpaceID_None, + nsAccessibilityAtoms::disabled); } else { - isDisabled = content->AttrValueIs(kNameSpaceID_None, - nsAccessibilityAtoms::disabled, - nsAccessibilityAtoms::_true, - eCaseMatters); + isDisabled = mContent->AttrValueIs(kNameSpaceID_None, + nsAccessibilityAtoms::disabled, + nsAccessibilityAtoms::_true, + eCaseMatters); } if (isDisabled) { *aState |= nsIAccessibleStates::STATE_UNAVAILABLE; } - else if (content->IsElement()) { + else if (mContent->IsElement()) { nsIFrame *frame = GetFrame(); if (frame && frame->IsFocusable()) { *aState |= nsIAccessibleStates::STATE_FOCUSABLE; } - if (gLastFocusedNode == mDOMNode) { + if (gLastFocusedNode == mContent) { *aState |= nsIAccessibleStates::STATE_FOCUSED; } } // Check if nsIAccessibleStates::STATE_INVISIBLE and // STATE_OFFSCREEN flags should be turned on for this object. PRBool isOffscreen; if (!IsVisible(&isOffscreen)) { @@ -763,44 +732,39 @@ nsAccessible::GetStateInternal(PRUint32 *aState |= nsIAccessibleStates::STATE_OFFSCREEN; } nsIFrame *frame = GetFrame(); if (frame && (frame->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) *aState |= nsIAccessibleStates::STATE_FLOATING; // Check if a XUL element has the popup attribute (an attached popup menu). - if (content->IsXUL()) - if (content->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::popup)) + if (mContent->IsXUL()) + if (mContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::popup)) *aState |= nsIAccessibleStates::STATE_HASPOPUP; // Add 'linked' state for simple xlink. - if (nsCoreUtils::IsXLink(content)) + if (nsCoreUtils::IsXLink(mContent)) *aState |= nsIAccessibleStates::STATE_LINKED; return NS_OK; } /* readonly attribute boolean focusedChild; */ -NS_IMETHODIMP nsAccessible::GetFocusedChild(nsIAccessible **aFocusedChild) +NS_IMETHODIMP +nsAccessible::GetFocusedChild(nsIAccessible **aFocusedChild) { - nsCOMPtr<nsIAccessible> focusedChild; - if (gLastFocusedNode == mDOMNode) { + nsAccessible *focusedChild = nsnull; + if (gLastFocusedNode == mContent) { focusedChild = this; } else if (gLastFocusedNode) { - GetAccService()->GetAccessibleFor(gLastFocusedNode, - getter_AddRefs(focusedChild)); - if (focusedChild) { - nsCOMPtr<nsIAccessible> focusedParentAccessible; - focusedChild->GetParent(getter_AddRefs(focusedParentAccessible)); - if (focusedParentAccessible != this) { - focusedChild = nsnull; - } - } + focusedChild = GetAccService()->GetAccessible(gLastFocusedNode); + if (focusedChild && focusedChild->GetParent() != this) + focusedChild = nsnull; } NS_IF_ADDREF(*aFocusedChild = focusedChild); return NS_OK; } // nsAccessible::GetChildAtPoint() nsresult @@ -844,26 +808,17 @@ nsAccessible::GetChildAtPoint(PRInt32 aX nsIFrame *foundFrame = presShell->GetFrameForPoint(frame, offset); nsIContent* content = nsnull; if (!foundFrame || !(content = foundFrame->GetContent())) { NS_IF_ADDREF(*aChild = fallbackAnswer); return NS_OK; } - nsCOMPtr<nsIDOMNode> node(do_QueryInterface(content)); - - nsCOMPtr<nsIDOMNode> relevantNode; - GetAccService()->GetRelevantContentNodeFor(node, - getter_AddRefs(relevantNode)); - if (!relevantNode) { - NS_IF_ADDREF(*aChild = fallbackAnswer); - return NS_OK; - } - + nsINode *relevantNode = GetAccService()->GetRelevant