Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / accessible / src / html / nsHTMLTextAccessible.cpp
blob69b815e373de7e91d18ae73dacbc66815f60c494
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Aaron Leventhal (aaronl@netscape.com)
24 * Kyle Yuan (kyle.yuan@sun.com)
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #include "nsHTMLTextAccessible.h"
41 #include "nsAccessibleTreeWalker.h"
42 #include "nsIAccessibleDocument.h"
43 #include "nsIAccessibleEvent.h"
44 #include "nsIFrame.h"
45 #include "nsPresContext.h"
46 #include "nsIPresShell.h"
47 #include "nsISelection.h"
48 #include "nsISelectionController.h"
49 #include "nsComponentManagerUtils.h"
51 nsHTMLTextAccessible::nsHTMLTextAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell):
52 nsTextAccessibleWrap(aDomNode, aShell)
56 NS_IMETHODIMP
57 nsHTMLTextAccessible::GetName(nsAString& aName)
59 // Text node, ARIA can't be used.
60 aName.Truncate();
61 return AppendTextTo(aName, 0, PR_UINT32_MAX);
64 NS_IMETHODIMP nsHTMLTextAccessible::GetRole(PRUint32 *aRole)
66 nsIFrame *frame = GetFrame();
67 // Don't return on null frame -- we still return a role
68 // after accessible is shutdown/DEFUNCT
69 if (frame && frame->IsGeneratedContentFrame()) {
70 *aRole = nsIAccessibleRole::ROLE_STATICTEXT;
71 return NS_OK;
74 return nsTextAccessible::GetRole(aRole);
77 nsresult
78 nsHTMLTextAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState)
80 nsresult rv = nsTextAccessible::GetStateInternal(aState, aExtraState);
81 NS_ENSURE_A11Y_SUCCESS(rv, rv);
83 nsCOMPtr<nsIAccessible> docAccessible =
84 do_QueryInterface(nsCOMPtr<nsIAccessibleDocument>(GetDocAccessible()));
85 if (docAccessible) {
86 PRUint32 state, extState;
87 docAccessible->GetState(&state, &extState);
88 if (0 == (extState & nsIAccessibleStates::EXT_STATE_EDITABLE)) {
89 *aState |= nsIAccessibleStates::STATE_READONLY; // Links not focusable in editor
93 return NS_OK;
96 nsresult
97 nsHTMLTextAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
99 if (!mDOMNode) {
100 return NS_ERROR_FAILURE; // Node already shut down
103 PRUint32 role;
104 GetRole(&role);
105 if (role == nsIAccessibleRole::ROLE_STATICTEXT) {
106 nsAutoString oldValueUnused;
107 aAttributes->SetStringProperty(NS_LITERAL_CSTRING("auto-generated"),
108 NS_LITERAL_STRING("true"), oldValueUnused);
111 return NS_OK;
114 nsHTMLHRAccessible::nsHTMLHRAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell):
115 nsLeafAccessible(aDomNode, aShell)
119 NS_IMETHODIMP nsHTMLHRAccessible::GetRole(PRUint32 *aRole)
121 *aRole = nsIAccessibleRole::ROLE_SEPARATOR;
122 return NS_OK;
125 nsHTMLBRAccessible::nsHTMLBRAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell):
126 nsLeafAccessible(aDomNode, aShell)
130 NS_IMETHODIMP nsHTMLBRAccessible::GetRole(PRUint32 *aRole)
132 *aRole = nsIAccessibleRole::ROLE_WHITESPACE;
133 return NS_OK;
136 nsresult
137 nsHTMLBRAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState)
139 *aState = 0;
141 if (IsDefunct()) {
142 if (aExtraState)
143 *aExtraState = nsIAccessibleStates::EXT_STATE_DEFUNCT;
145 return NS_OK_DEFUNCT_OBJECT;
148 *aState = nsIAccessibleStates::STATE_READONLY;
149 if (aExtraState)
150 *aExtraState = 0;
152 return NS_OK;
155 nsresult
156 nsHTMLBRAccessible::GetNameInternal(nsAString& aName)
158 aName = static_cast<PRUnichar>('\n'); // Newline char
159 return NS_OK;
162 // A label is an element (not a leaf) and thus can support advanced interfaces.
163 // We need to skip over nsTextAccessible QI which prevents that
164 NS_IMPL_ISUPPORTS_INHERITED0(nsHTMLLabelAccessible, nsLinkableAccessible)
166 nsHTMLLabelAccessible::nsHTMLLabelAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell):
167 nsTextAccessible(aDomNode, aShell)
171 nsresult
172 nsHTMLLabelAccessible::GetNameInternal(nsAString& aReturn)
174 nsresult rv = NS_ERROR_FAILURE;
175 nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
177 nsAutoString name;
178 if (content)
179 rv = AppendFlatStringFromSubtree(content, &name);
181 if (NS_SUCCEEDED(rv)) {
182 // Temp var needed until CompressWhitespace built for nsAString
183 name.CompressWhitespace();
184 aReturn = name;
187 return rv;
190 NS_IMETHODIMP nsHTMLLabelAccessible::GetRole(PRUint32 *aRole)
192 *aRole = nsIAccessibleRole::ROLE_LABEL;
193 return NS_OK;
196 nsresult
197 nsHTMLLabelAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState)
199 nsresult rv = nsTextAccessible::GetStateInternal(aState, aExtraState);
200 NS_ENSURE_A11Y_SUCCESS(rv, rv);
202 *aState &= (nsIAccessibleStates::STATE_LINKED |
203 nsIAccessibleStates::STATE_TRAVERSED); // Only use link states
205 return NS_OK;
208 NS_IMETHODIMP nsHTMLLabelAccessible::GetFirstChild(nsIAccessible **aFirstChild)
210 // A <label> is not necessarily a leaf!
211 return nsAccessible::GetFirstChild(aFirstChild);
214 /* readonly attribute nsIAccessible accFirstChild; */
215 NS_IMETHODIMP nsHTMLLabelAccessible::GetLastChild(nsIAccessible **aLastChild)
217 // A <label> is not necessarily a leaf!
218 return nsAccessible::GetLastChild(aLastChild);
221 /* readonly attribute long accChildCount; */
222 NS_IMETHODIMP nsHTMLLabelAccessible::GetChildCount(PRInt32 *aAccChildCount)
224 // A <label> is not necessarily a leaf!
225 return nsAccessible::GetChildCount(aAccChildCount);
228 nsHTMLLIAccessible::nsHTMLLIAccessible(nsIDOMNode *aDOMNode, nsIWeakReference* aShell,
229 const nsAString& aBulletText):
230 nsLinkableAccessible(aDOMNode, aShell)
232 if (!aBulletText.IsEmpty()) {
233 mBulletAccessible = new nsHTMLListBulletAccessible(mDOMNode, mWeakShell,
234 aBulletText);
235 if (mBulletAccessible)
236 mBulletAccessible->Init();
240 nsresult
241 nsHTMLLIAccessible::Shutdown()
243 if (mBulletAccessible) {
244 // Ensure that weak pointer to this is nulled out
245 mBulletAccessible->Shutdown();
247 nsresult rv = nsLinkableAccessible::Shutdown();
248 mBulletAccessible = nsnull;
249 return rv;
252 nsresult
253 nsHTMLLIAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState)
255 nsresult rv = nsAccessibleWrap::GetStateInternal(aState, aExtraState);
256 NS_ENSURE_A11Y_SUCCESS(rv, rv);
258 *aState |= nsIAccessibleStates::STATE_READONLY;
259 return NS_OK;
262 NS_IMETHODIMP nsHTMLLIAccessible::GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height)
264 nsresult rv = nsAccessibleWrap::GetBounds(x, y, width, height);
265 if (NS_FAILED(rv) || !mBulletAccessible) {
266 return rv;
269 PRInt32 bulletX, bulletY, bulletWidth, bulletHeight;
270 rv = mBulletAccessible->GetBounds(&bulletX, &bulletY, &bulletWidth, &bulletHeight);
271 NS_ENSURE_SUCCESS(rv, rv);
273 *x = bulletX; // Move x coordinate of list item over to cover bullet as well
274 *width += bulletWidth;
275 return NS_OK;
278 void nsHTMLLIAccessible::CacheChildren()
280 if (!mWeakShell || mAccChildCount != eChildCountUninitialized) {
281 return;
284 nsAccessibleWrap::CacheChildren();
286 if (mBulletAccessible) {
287 mBulletAccessible->SetNextSibling(mFirstChild);
288 mBulletAccessible->SetParent(this); // Set weak parent;
289 SetFirstChild(mBulletAccessible);
290 ++ mAccChildCount;
295 // nsHTMLListBulletAccessible
296 nsHTMLListBulletAccessible::
297 nsHTMLListBulletAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell,
298 const nsAString& aBulletText) :
299 nsLeafAccessible(aDomNode, aShell), mWeakParent(nsnull),
300 mBulletText(aBulletText)
302 mBulletText += ' '; // Otherwise bullets are jammed up against list text
305 NS_IMETHODIMP
306 nsHTMLListBulletAccessible::GetUniqueID(void **aUniqueID)
308 // Since mDOMNode is same as for list item, use |this| pointer as the unique Id
309 *aUniqueID = static_cast<void*>(this);
310 return NS_OK;
313 nsresult
314 nsHTMLListBulletAccessible::Shutdown()
316 mBulletText.Truncate();
317 mWeakParent = nsnull;
319 return nsLeafAccessible::Shutdown();
322 NS_IMETHODIMP
323 nsHTMLListBulletAccessible::GetName(nsAString &aName)
325 // Native anonymous content, ARIA can't be used.
326 aName = mBulletText;
327 return NS_OK;
330 NS_IMETHODIMP
331 nsHTMLListBulletAccessible::GetRole(PRUint32 *aRole)
333 *aRole = nsIAccessibleRole::ROLE_STATICTEXT;
334 return NS_OK;
337 nsresult
338 nsHTMLListBulletAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState)
340 nsresult rv = nsLeafAccessible::GetStateInternal(aState, aExtraState);
341 NS_ENSURE_A11Y_SUCCESS(rv, rv);
343 *aState &= ~nsIAccessibleStates::STATE_FOCUSABLE;
344 *aState |= nsIAccessibleStates::STATE_READONLY;
345 return NS_OK;
348 NS_IMETHODIMP
349 nsHTMLListBulletAccessible::SetParent(nsIAccessible *aParentAccessible)
351 mParent = nsnull;
352 mWeakParent = aParentAccessible;
353 return NS_OK;
356 NS_IMETHODIMP
357 nsHTMLListBulletAccessible::GetParent(nsIAccessible **aParentAccessible)
359 NS_IF_ADDREF(*aParentAccessible = mWeakParent);
360 return NS_OK;
363 NS_IMETHODIMP
364 nsHTMLListBulletAccessible::AppendTextTo(nsAString& aText, PRUint32 aStartOffset,
365 PRUint32 aLength)
367 PRUint32 maxLength = mBulletText.Length() - aStartOffset;
368 if (aLength > maxLength) {
369 aLength = maxLength;
371 aText += nsDependentSubstring(mBulletText, aStartOffset, aLength);
372 return NS_OK;
375 // nsHTMLListAccessible
377 nsresult
378 nsHTMLListAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState)
380 nsresult rv = nsHyperTextAccessibleWrap::GetStateInternal(aState,
381 aExtraState);
382 NS_ENSURE_A11Y_SUCCESS(rv, rv);
384 *aState |= nsIAccessibleStates::STATE_READONLY;
385 return NS_OK;