1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "xpcAccessibleHyperText.h"
9 #include "LocalAccessible-inl.h"
10 #include "HyperTextAccessible-inl.h"
11 #include "mozilla/a11y/PDocAccessible.h"
12 #include "mozilla/StaticPrefs_accessibility.h"
13 #include "TextRange.h"
14 #include "AccAttributes.h"
15 #include "nsComponentManagerUtils.h"
16 #include "nsPersistentProperties.h"
17 #include "xpcAccessibleDocument.h"
18 #include "xpcAccessibleTextRange.h"
20 #include "nsIMutableArray.h"
22 using namespace mozilla::a11y
;
24 ////////////////////////////////////////////////////////////////////////////////
27 NS_INTERFACE_MAP_BEGIN(xpcAccessibleHyperText
)
28 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAccessibleText
,
29 mSupportedIfaces
& eText
)
30 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAccessibleEditableText
,
31 mSupportedIfaces
& eText
)
32 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAccessibleHyperText
,
33 mSupportedIfaces
& eText
)
34 NS_INTERFACE_MAP_END_INHERITING(xpcAccessibleGeneric
)
36 NS_IMPL_ADDREF_INHERITED(xpcAccessibleHyperText
, xpcAccessibleGeneric
)
37 NS_IMPL_RELEASE_INHERITED(xpcAccessibleHyperText
, xpcAccessibleGeneric
)
39 ////////////////////////////////////////////////////////////////////////////////
43 xpcAccessibleHyperText::GetCharacterCount(int32_t* aCharacterCount
) {
44 NS_ENSURE_ARG_POINTER(aCharacterCount
);
47 if (!mIntl
) return NS_ERROR_FAILURE
;
50 if (mIntl
->IsRemote() &&
51 !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
52 return NS_ERROR_NOT_IMPLEMENTED
;
56 *aCharacterCount
= static_cast<int32_t>(Intl()->CharacterCount());
61 xpcAccessibleHyperText::GetText(int32_t aStartOffset
, int32_t aEndOffset
,
65 if (!mIntl
) return NS_ERROR_FAILURE
;
67 Intl()->TextSubstring(aStartOffset
, aEndOffset
, aText
);
72 xpcAccessibleHyperText::GetTextBeforeOffset(
73 int32_t aOffset
, AccessibleTextBoundary aBoundaryType
,
74 int32_t* aStartOffset
, int32_t* aEndOffset
, nsAString
& aText
) {
75 NS_ENSURE_ARG_POINTER(aStartOffset
);
76 NS_ENSURE_ARG_POINTER(aEndOffset
);
77 *aStartOffset
= *aEndOffset
= 0;
80 if (!mIntl
) return NS_ERROR_FAILURE
;
82 Intl()->TextBeforeOffset(aOffset
, aBoundaryType
, aStartOffset
, aEndOffset
,
88 xpcAccessibleHyperText::GetTextAtOffset(int32_t aOffset
,
89 AccessibleTextBoundary aBoundaryType
,
90 int32_t* aStartOffset
,
91 int32_t* aEndOffset
, nsAString
& aText
) {
92 NS_ENSURE_ARG_POINTER(aStartOffset
);
93 NS_ENSURE_ARG_POINTER(aEndOffset
);
94 *aStartOffset
= *aEndOffset
= 0;
97 if (!mIntl
) return NS_ERROR_FAILURE
;
99 Intl()->TextAtOffset(aOffset
, aBoundaryType
, aStartOffset
, aEndOffset
, aText
);
104 xpcAccessibleHyperText::GetTextAfterOffset(int32_t aOffset
,
105 AccessibleTextBoundary aBoundaryType
,
106 int32_t* aStartOffset
,
109 NS_ENSURE_ARG_POINTER(aStartOffset
);
110 NS_ENSURE_ARG_POINTER(aEndOffset
);
111 *aStartOffset
= *aEndOffset
= 0;
114 Intl()->TextAfterOffset(aOffset
, aBoundaryType
, aStartOffset
, aEndOffset
,
120 xpcAccessibleHyperText::GetCharacterAtOffset(int32_t aOffset
,
121 char16_t
* aCharacter
) {
122 NS_ENSURE_ARG_POINTER(aCharacter
);
125 if (!mIntl
) return NS_ERROR_FAILURE
;
127 if (mIntl
->IsLocal()) {
128 *aCharacter
= IntlLocal()->CharAt(aOffset
);
131 return NS_ERROR_NOT_IMPLEMENTED
;
133 *aCharacter
= mIntl
->AsRemote()->CharAt(aOffset
);
140 xpcAccessibleHyperText::GetTextAttributes(
141 bool aIncludeDefAttrs
, int32_t aOffset
, int32_t* aStartOffset
,
142 int32_t* aEndOffset
, nsIPersistentProperties
** aAttributes
) {
143 NS_ENSURE_ARG_POINTER(aStartOffset
);
144 NS_ENSURE_ARG_POINTER(aEndOffset
);
145 NS_ENSURE_ARG_POINTER(aAttributes
);
146 *aStartOffset
= *aEndOffset
= 0;
147 *aAttributes
= nullptr;
149 if (!mIntl
) return NS_ERROR_FAILURE
;
151 if (mIntl
->IsRemote() &&
152 !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
153 return NS_ERROR_NOT_IMPLEMENTED
;
156 RefPtr
<AccAttributes
> attributes
= Intl()->TextAttributes(
157 aIncludeDefAttrs
, aOffset
, aStartOffset
, aEndOffset
);
158 RefPtr
<nsPersistentProperties
> props
= new nsPersistentProperties();
160 for (auto iter
: *attributes
) {
162 iter
.NameAsString(name
);
165 iter
.ValueAsString(value
);
167 props
->SetStringProperty(NS_ConvertUTF16toUTF8(name
), value
, unused
);
170 props
.forget(aAttributes
);
175 xpcAccessibleHyperText::GetDefaultTextAttributes(
176 nsIPersistentProperties
** aAttributes
) {
177 NS_ENSURE_ARG_POINTER(aAttributes
);
178 *aAttributes
= nullptr;
180 if (!mIntl
) return NS_ERROR_FAILURE
;
182 if (mIntl
->IsRemote() &&
183 !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
184 return NS_ERROR_NOT_IMPLEMENTED
;
187 RefPtr
<AccAttributes
> attributes
= Intl()->DefaultTextAttributes();
188 RefPtr
<nsPersistentProperties
> props
= new nsPersistentProperties();
190 for (auto iter
: *attributes
) {
192 iter
.NameAsString(name
);
195 iter
.ValueAsString(value
);
197 props
->SetStringProperty(NS_ConvertUTF16toUTF8(name
), value
, unused
);
200 props
.forget(aAttributes
);
206 xpcAccessibleHyperText::GetCharacterExtents(int32_t aOffset
, int32_t* aX
,
207 int32_t* aY
, int32_t* aWidth
,
209 uint32_t aCoordType
) {
210 NS_ENSURE_ARG_POINTER(aX
);
211 NS_ENSURE_ARG_POINTER(aY
);
212 NS_ENSURE_ARG_POINTER(aWidth
);
213 NS_ENSURE_ARG_POINTER(aHeight
);
214 *aX
= *aY
= *aWidth
= *aHeight
;
216 if (!mIntl
) return NS_ERROR_FAILURE
;
219 if (mIntl
->IsRemote() &&
220 !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
221 return NS_ERROR_NOT_IMPLEMENTED
;
225 LayoutDeviceIntRect rect
= Intl()->CharBounds(aOffset
, aCoordType
);
226 rect
.GetRect(aX
, aY
, aWidth
, aHeight
);
231 xpcAccessibleHyperText::GetRangeExtents(int32_t aStartOffset
,
232 int32_t aEndOffset
, int32_t* aX
,
233 int32_t* aY
, int32_t* aWidth
,
234 int32_t* aHeight
, uint32_t aCoordType
) {
235 NS_ENSURE_ARG_POINTER(aX
);
236 NS_ENSURE_ARG_POINTER(aY
);
237 NS_ENSURE_ARG_POINTER(aWidth
);
238 NS_ENSURE_ARG_POINTER(aHeight
);
239 *aX
= *aY
= *aWidth
= *aHeight
= 0;
241 if (!mIntl
) return NS_ERROR_FAILURE
;
244 if (mIntl
->IsRemote() &&
245 !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
246 return NS_ERROR_NOT_IMPLEMENTED
;
250 LayoutDeviceIntRect rect
=
251 Intl()->TextBounds(aStartOffset
, aEndOffset
, aCoordType
);
252 rect
.GetRect(aX
, aY
, aWidth
, aHeight
);
257 xpcAccessibleHyperText::GetOffsetAtPoint(int32_t aX
, int32_t aY
,
260 NS_ENSURE_ARG_POINTER(aOffset
);
263 if (!mIntl
) return NS_ERROR_FAILURE
;
265 *aOffset
= Intl()->OffsetAtPoint(aX
, aY
, aCoordType
);
270 xpcAccessibleHyperText::GetCaretOffset(int32_t* aCaretOffset
) {
271 NS_ENSURE_ARG_POINTER(aCaretOffset
);
274 if (!mIntl
) return NS_ERROR_FAILURE
;
276 *aCaretOffset
= Intl()->CaretOffset();
281 xpcAccessibleHyperText::SetCaretOffset(int32_t aCaretOffset
) {
282 if (!mIntl
) return NS_ERROR_FAILURE
;
284 Intl()->SetCaretOffset(aCaretOffset
);
289 xpcAccessibleHyperText::GetSelectionCount(int32_t* aSelectionCount
) {
290 NS_ENSURE_ARG_POINTER(aSelectionCount
);
291 *aSelectionCount
= 0;
293 if (!mIntl
) return NS_ERROR_FAILURE
;
296 if (mIntl
->IsRemote() &&
297 !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
298 return NS_ERROR_NOT_IMPLEMENTED
;
302 *aSelectionCount
= Intl()->SelectionCount();
307 xpcAccessibleHyperText::GetSelectionBounds(int32_t aSelectionNum
,
308 int32_t* aStartOffset
,
309 int32_t* aEndOffset
) {
310 NS_ENSURE_ARG_POINTER(aStartOffset
);
311 NS_ENSURE_ARG_POINTER(aEndOffset
);
312 *aStartOffset
= *aEndOffset
= 0;
314 if (!mIntl
) return NS_ERROR_FAILURE
;
316 if (aSelectionNum
< 0) return NS_ERROR_INVALID_ARG
;
318 if (mIntl
->IsLocal() ||
319 StaticPrefs::accessibility_cache_enabled_AtStartup()) {
320 if (aSelectionNum
>= Intl()->SelectionCount()) {
321 return NS_ERROR_INVALID_ARG
;
324 Intl()->SelectionBoundsAt(aSelectionNum
, aStartOffset
, aEndOffset
);
327 return NS_ERROR_NOT_IMPLEMENTED
;
330 mIntl
->AsRemote()->SelectionBoundsAt(aSelectionNum
, unused
, aStartOffset
,
338 xpcAccessibleHyperText::SetSelectionBounds(int32_t aSelectionNum
,
339 int32_t aStartOffset
,
340 int32_t aEndOffset
) {
341 if (!mIntl
) return NS_ERROR_FAILURE
;
343 if (aSelectionNum
< 0) return NS_ERROR_INVALID_ARG
;
345 if (mIntl
->IsLocal()) {
346 if (!IntlLocal()->SetSelectionBoundsAt(aSelectionNum
, aStartOffset
,
348 return NS_ERROR_INVALID_ARG
;
352 return NS_ERROR_NOT_IMPLEMENTED
;
354 if (!mIntl
->AsRemote()->SetSelectionBoundsAt(aSelectionNum
, aStartOffset
,
356 return NS_ERROR_INVALID_ARG
;
364 xpcAccessibleHyperText::AddSelection(int32_t aStartOffset
, int32_t aEndOffset
) {
365 if (!mIntl
) return NS_ERROR_FAILURE
;
367 if (mIntl
->IsLocal()) {
368 IntlLocal()->AddToSelection(aStartOffset
, aEndOffset
);
370 mIntl
->AsRemote()->AddToSelection(aStartOffset
, aEndOffset
);
376 xpcAccessibleHyperText::RemoveSelection(int32_t aSelectionNum
) {
377 if (!mIntl
) return NS_ERROR_FAILURE
;
379 if (mIntl
->IsLocal()) {
380 IntlLocal()->RemoveFromSelection(aSelectionNum
);
382 mIntl
->AsRemote()->RemoveFromSelection(aSelectionNum
);
388 xpcAccessibleHyperText::ScrollSubstringTo(int32_t aStartOffset
,
390 uint32_t aScrollType
) {
391 if (!mIntl
) return NS_ERROR_FAILURE
;
393 if (mIntl
->IsLocal()) {
394 IntlLocal()->ScrollSubstringTo(aStartOffset
, aEndOffset
, aScrollType
);
396 mIntl
->AsRemote()->ScrollSubstringTo(aStartOffset
, aEndOffset
, aScrollType
);
402 xpcAccessibleHyperText::ScrollSubstringToPoint(int32_t aStartOffset
,
404 uint32_t aCoordinateType
,
405 int32_t aX
, int32_t aY
) {
406 if (!mIntl
) return NS_ERROR_FAILURE
;
408 if (mIntl
->IsLocal()) {
409 IntlLocal()->ScrollSubstringToPoint(aStartOffset
, aEndOffset
,
410 aCoordinateType
, aX
, aY
);
412 mIntl
->AsRemote()->ScrollSubstringToPoint(aStartOffset
, aEndOffset
,
413 aCoordinateType
, aX
, aY
);
419 xpcAccessibleHyperText::GetEnclosingRange(nsIAccessibleTextRange
** aRange
) {
420 NS_ENSURE_ARG_POINTER(aRange
);
423 if (!IntlLocal()) return NS_ERROR_FAILURE
;
426 IntlLocal()->EnclosingRange(range
);
427 NS_ASSERTION(range
.IsValid(), "Should always have an enclosing range!");
428 RefPtr
<xpcAccessibleTextRange
> xpcRange
= new xpcAccessibleTextRange(range
);
430 xpcRange
.forget(aRange
);
436 xpcAccessibleHyperText::GetSelectionRanges(nsIArray
** aRanges
) {
437 NS_ENSURE_ARG_POINTER(aRanges
);
440 if (!IntlLocal() && !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
441 return NS_ERROR_FAILURE
;
445 nsCOMPtr
<nsIMutableArray
> xpcRanges
=
446 do_CreateInstance(NS_ARRAY_CONTRACTID
, &rv
);
447 NS_ENSURE_SUCCESS(rv
, rv
);
449 AutoTArray
<TextRange
, 1> ranges
;
450 Intl()->SelectionRanges(&ranges
);
451 uint32_t len
= ranges
.Length();
452 for (uint32_t idx
= 0; idx
< len
; idx
++) {
453 xpcRanges
->AppendElement(new xpcAccessibleTextRange(ranges
[idx
]));
456 xpcRanges
.forget(aRanges
);
461 xpcAccessibleHyperText::GetVisibleRanges(nsIArray
** aRanges
) {
462 NS_ENSURE_ARG_POINTER(aRanges
);
465 if (!IntlLocal()) return NS_ERROR_FAILURE
;
468 nsCOMPtr
<nsIMutableArray
> xpcRanges
=
469 do_CreateInstance(NS_ARRAY_CONTRACTID
, &rv
);
470 NS_ENSURE_SUCCESS(rv
, rv
);
472 nsTArray
<TextRange
> ranges
;
473 IntlLocal()->VisibleRanges(&ranges
);
474 uint32_t len
= ranges
.Length();
475 for (uint32_t idx
= 0; idx
< len
; idx
++) {
476 xpcRanges
->AppendElement(new xpcAccessibleTextRange(ranges
[idx
]));
479 xpcRanges
.forget(aRanges
);
484 xpcAccessibleHyperText::GetRangeByChild(nsIAccessible
* aChild
,
485 nsIAccessibleTextRange
** aRange
) {
486 NS_ENSURE_ARG_POINTER(aRange
);
489 if (!IntlLocal()) return NS_ERROR_FAILURE
;
491 LocalAccessible
* child
= aChild
->ToInternalAccessible();
494 IntlLocal()->RangeByChild(child
, range
);
495 if (range
.IsValid()) {
496 RefPtr
<xpcAccessibleTextRange
> xpcRange
=
497 new xpcAccessibleTextRange(range
);
498 xpcRange
.forget(aRange
);
506 xpcAccessibleHyperText::GetRangeAtPoint(int32_t aX
, int32_t aY
,
507 nsIAccessibleTextRange
** aRange
) {
508 NS_ENSURE_ARG_POINTER(aRange
);
511 if (!IntlLocal()) return NS_ERROR_FAILURE
;
514 IntlLocal()->RangeAtPoint(aX
, aY
, range
);
515 if (range
.IsValid()) {
516 RefPtr
<xpcAccessibleTextRange
> xpcRange
= new xpcAccessibleTextRange(range
);
517 xpcRange
.forget(aRange
);
523 ////////////////////////////////////////////////////////////////////////////////
524 // nsIAccessibleEditableText
527 xpcAccessibleHyperText::SetTextContents(const nsAString
& aText
) {
528 if (!mIntl
) return NS_ERROR_FAILURE
;
530 if (mIntl
->IsLocal()) {
531 IntlLocal()->ReplaceText(aText
);
534 return NS_ERROR_NOT_IMPLEMENTED
;
536 nsString
text(aText
);
537 mIntl
->AsRemote()->ReplaceText(text
);
544 xpcAccessibleHyperText::InsertText(const nsAString
& aText
, int32_t aOffset
) {
545 if (!mIntl
) return NS_ERROR_FAILURE
;
547 if (mIntl
->IsLocal()) {
548 IntlLocal()->InsertText(aText
, aOffset
);
551 return NS_ERROR_NOT_IMPLEMENTED
;
553 nsString
text(aText
);
554 mIntl
->AsRemote()->InsertText(text
, aOffset
);
561 xpcAccessibleHyperText::CopyText(int32_t aStartOffset
, int32_t aEndOffset
) {
562 if (!mIntl
) return NS_ERROR_FAILURE
;
564 if (mIntl
->IsLocal()) {
565 IntlLocal()->CopyText(aStartOffset
, aEndOffset
);
568 return NS_ERROR_NOT_IMPLEMENTED
;
570 mIntl
->AsRemote()->CopyText(aStartOffset
, aEndOffset
);
577 xpcAccessibleHyperText::CutText(int32_t aStartOffset
, int32_t aEndOffset
) {
578 if (!mIntl
) return NS_ERROR_FAILURE
;
580 if (mIntl
->IsLocal()) {
581 IntlLocal()->CutText(aStartOffset
, aEndOffset
);
584 return NS_ERROR_NOT_IMPLEMENTED
;
586 mIntl
->AsRemote()->CutText(aStartOffset
, aEndOffset
);
593 xpcAccessibleHyperText::DeleteText(int32_t aStartOffset
, int32_t aEndOffset
) {
594 if (!mIntl
) return NS_ERROR_FAILURE
;
596 if (mIntl
->IsLocal()) {
597 IntlLocal()->DeleteText(aStartOffset
, aEndOffset
);
600 return NS_ERROR_NOT_IMPLEMENTED
;
602 mIntl
->AsRemote()->DeleteText(aStartOffset
, aEndOffset
);
609 xpcAccessibleHyperText::PasteText(int32_t aOffset
) {
610 if (!mIntl
) return NS_ERROR_FAILURE
;
612 if (mIntl
->IsLocal()) {
613 RefPtr
<HyperTextAccessible
> acc
= IntlLocal();
614 acc
->PasteText(aOffset
);
617 return NS_ERROR_NOT_IMPLEMENTED
;
619 mIntl
->AsRemote()->PasteText(aOffset
);
625 ////////////////////////////////////////////////////////////////////////////////
626 // nsIAccessibleHyperText
629 xpcAccessibleHyperText::GetLinkCount(int32_t* aLinkCount
) {
630 NS_ENSURE_ARG_POINTER(aLinkCount
);
633 if (!mIntl
) return NS_ERROR_FAILURE
;
636 if (mIntl
->IsRemote() &&
637 !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
638 return NS_ERROR_NOT_IMPLEMENTED
;
642 *aLinkCount
= static_cast<int32_t>(Intl()->LinkCount());
647 xpcAccessibleHyperText::GetLinkAt(int32_t aIndex
,
648 nsIAccessibleHyperLink
** aLink
) {
649 NS_ENSURE_ARG_POINTER(aLink
);
652 if (!mIntl
) return NS_ERROR_FAILURE
;
655 if (mIntl
->IsRemote() &&
656 !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
657 return NS_ERROR_NOT_IMPLEMENTED
;
661 NS_IF_ADDREF(*aLink
= ToXPC(Intl()->LinkAt(aIndex
)));
666 xpcAccessibleHyperText::GetLinkIndex(nsIAccessibleHyperLink
* aLink
,
668 NS_ENSURE_ARG_POINTER(aLink
);
669 NS_ENSURE_ARG_POINTER(aIndex
);
672 if (!mIntl
) return NS_ERROR_FAILURE
;
674 nsCOMPtr
<nsIAccessible
> xpcLink(do_QueryInterface(aLink
));
675 Accessible
* accLink
= xpcLink
->ToInternalGeneric();
677 if (accLink
->IsRemote() &&
678 !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
679 return NS_ERROR_NOT_IMPLEMENTED
;
682 *aIndex
= Intl()->LinkIndexOf(accLink
);
687 xpcAccessibleHyperText::GetLinkIndexAtOffset(int32_t aOffset
,
688 int32_t* aLinkIndex
) {
689 NS_ENSURE_ARG_POINTER(aLinkIndex
);
690 *aLinkIndex
= -1; // API says this magic value means 'not found'
692 if (!mIntl
) return NS_ERROR_FAILURE
;
695 if (mIntl
->IsRemote() &&
696 !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
697 return NS_ERROR_NOT_IMPLEMENTED
;
701 *aLinkIndex
= Intl()->LinkIndexAtOffset(aOffset
);