Bug 1869092 - Fix timeouts in browser_PanelMultiView.js. r=twisniewski,test-only
[gecko.git] / accessible / ipc / RemoteAccessible.h
blob9215fd7bc56b19d324251b036e1d2b85ba7c29a4
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
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_a11y_RemoteAccessible_h
8 #define mozilla_a11y_RemoteAccessible_h
10 #include "mozilla/a11y/Accessible.h"
11 #include "mozilla/a11y/CacheConstants.h"
12 #include "mozilla/a11y/HyperTextAccessibleBase.h"
13 #include "mozilla/a11y/Role.h"
14 #include "AccAttributes.h"
15 #include "nsIAccessibleText.h"
16 #include "nsIAccessibleTypes.h"
17 #include "nsTArray.h"
18 #include "nsRect.h"
19 #include "LocalAccessible.h"
21 namespace mozilla {
22 namespace a11y {
24 class Attribute;
25 class DocAccessibleParent;
26 class RemoteAccessible;
27 enum class RelationType;
29 /**
30 * The class for an accessibility tree node that originated in the parent
31 * process.
33 class RemoteAccessible : public Accessible, public HyperTextAccessibleBase {
34 public:
35 virtual ~RemoteAccessible() {
36 MOZ_ASSERT(!mWrapper);
37 MOZ_COUNT_DTOR(RemoteAccessible);
40 virtual bool IsRemote() const override { return true; }
42 void AddChildAt(uint32_t aIdx, RemoteAccessible* aChild) {
43 mChildren.InsertElementAt(aIdx, aChild);
44 if (IsHyperText()) {
45 InvalidateCachedHyperTextOffsets();
49 virtual uint32_t ChildCount() const override { return mChildren.Length(); }
50 RemoteAccessible* RemoteChildAt(uint32_t aIdx) const {
51 return mChildren.SafeElementAt(aIdx);
53 RemoteAccessible* RemoteFirstChild() const {
54 return mChildren.Length() ? mChildren[0] : nullptr;
56 RemoteAccessible* RemoteLastChild() const {
57 return mChildren.Length() ? mChildren[mChildren.Length() - 1] : nullptr;
59 RemoteAccessible* RemotePrevSibling() const {
60 if (IsDoc()) {
61 // The normal code path doesn't work for documents because the parent
62 // might be a local OuterDoc, but IndexInParent() will return 1.
63 // A document is always a single child of an OuterDoc anyway.
64 return nullptr;
66 int32_t idx = IndexInParent();
67 if (idx == -1) {
68 return nullptr; // No parent.
70 return idx > 0 ? RemoteParent()->mChildren[idx - 1] : nullptr;
72 RemoteAccessible* RemoteNextSibling() const {
73 if (IsDoc()) {
74 // The normal code path doesn't work for documents because the parent
75 // might be a local OuterDoc, but IndexInParent() will return 1.
76 // A document is always a single child of an OuterDoc anyway.
77 return nullptr;
79 int32_t idx = IndexInParent();
80 if (idx == -1) {
81 return nullptr; // No parent.
83 MOZ_ASSERT(idx >= 0);
84 size_t newIdx = idx + 1;
85 return newIdx < RemoteParent()->mChildren.Length()
86 ? RemoteParent()->mChildren[newIdx]
87 : nullptr;
90 // Accessible hierarchy method overrides
92 virtual Accessible* Parent() const override { return RemoteParent(); }
94 virtual Accessible* ChildAt(uint32_t aIndex) const override {
95 return RemoteChildAt(aIndex);
98 virtual Accessible* NextSibling() const override {
99 return RemoteNextSibling();
102 virtual Accessible* PrevSibling() const override {
103 return RemotePrevSibling();
106 // XXX evaluate if this is fast enough.
107 virtual int32_t IndexInParent() const override {
108 RemoteAccessible* parent = RemoteParent();
109 if (!parent) {
110 return -1;
112 return parent->mChildren.IndexOf(
113 static_cast<const RemoteAccessible*>(this));
115 virtual uint32_t EmbeddedChildCount() override;
116 virtual int32_t IndexOfEmbeddedChild(Accessible* aChild) override;
117 virtual Accessible* EmbeddedChildAt(uint32_t aChildIdx) override;
119 void Shutdown();
121 void SetChildDoc(DocAccessibleParent* aChildDoc);
122 void ClearChildDoc(DocAccessibleParent* aChildDoc);
125 * Remove The given child.
127 void RemoveChild(RemoteAccessible* aChild) {
128 mChildren.RemoveElement(aChild);
129 if (IsHyperText()) {
130 InvalidateCachedHyperTextOffsets();
135 * Return the proxy for the parent of the wrapped accessible.
137 RemoteAccessible* RemoteParent() const;
139 LocalAccessible* OuterDocOfRemoteBrowser() const;
142 * Get the role of the accessible we're proxying.
144 virtual role Role() const override { return mRole; }
147 * Return true if this is an embedded object.
149 bool IsEmbeddedObject() const { return !IsText(); }
151 virtual bool IsLink() const override {
152 if (IsHTMLLink()) {
153 // XXX: HTML links always return true for IsLink.
154 return true;
157 if (IsText()) {
158 return false;
161 if (Accessible* parent = Parent()) {
162 return parent->IsHyperText();
165 return false;
168 virtual bool HasNumericValue() const override {
169 // XXX: We combine the aria and native "has numeric value" field
170 // when we serialize the local accessible into eNumericValue.
171 return HasGenericType(eNumericValue);
174 // Methods that potentially access a cache.
176 virtual ENameValueFlag Name(nsString& aName) const override;
177 virtual void Description(nsString& aDescription) const override;
178 virtual void Value(nsString& aValue) const override;
180 virtual double CurValue() const override;
181 virtual double MinValue() const override;
182 virtual double MaxValue() const override;
183 virtual double Step() const override;
184 virtual bool SetCurValue(double aValue) override;
186 virtual Accessible* ChildAtPoint(
187 int32_t aX, int32_t aY,
188 LocalAccessible::EWhichChildAtPoint aWhichChild) override;
190 virtual LayoutDeviceIntRect Bounds() const override;
192 virtual nsRect BoundsInAppUnits() const override;
194 virtual Relation RelationByType(RelationType aType) const override;
196 virtual uint64_t State() override;
198 virtual already_AddRefed<AccAttributes> Attributes() override;
200 virtual nsAtom* TagName() const override;
202 virtual already_AddRefed<nsAtom> InputType() const override;
204 virtual already_AddRefed<nsAtom> DisplayStyle() const override;
206 virtual float Opacity() const override;
208 virtual void LiveRegionAttributes(nsAString* aLive, nsAString* aRelevant,
209 Maybe<bool>* aAtomic,
210 nsAString* aBusy) const override;
212 virtual Maybe<bool> ARIASelected() const override;
214 virtual uint8_t ActionCount() const override;
216 virtual void ActionNameAt(uint8_t aIndex, nsAString& aName) override;
218 virtual bool DoAction(uint8_t aIndex) const override;
220 virtual KeyBinding AccessKey() const override;
222 virtual void SelectionRanges(nsTArray<TextRange>* aRanges) const override;
224 MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual bool RemoveFromSelection(
225 int32_t aSelectionNum) override;
227 virtual Maybe<int32_t> GetIntARIAAttr(nsAtom* aAttrName) const override;
229 virtual void Language(nsAString& aLocale) override;
231 //////////////////////////////////////////////////////////////////////////////
232 // EditableTextAccessible
234 MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual void ReplaceText(
235 const nsAString& aText) override;
236 MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual void InsertText(
237 const nsAString& aText, int32_t aPosition) override;
238 MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual void CopyText(int32_t aStartPos,
239 int32_t aEndPos) override;
240 MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual void CutText(int32_t aStartPos,
241 int32_t aEndPos) override;
242 MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual void DeleteText(int32_t aStartPos,
243 int32_t aEndPos) override;
244 MOZ_CAN_RUN_SCRIPT virtual void PasteText(int32_t aPosition) override;
246 //////////////////////////////////////////////////////////////////////////////
247 // SelectAccessible
249 virtual void SelectedItems(nsTArray<Accessible*>* aItems) override;
251 virtual uint32_t SelectedItemCount() override;
253 virtual Accessible* GetSelectedItem(uint32_t aIndex) override;
255 virtual bool IsItemSelected(uint32_t aIndex) override;
257 virtual bool AddItemToSelection(uint32_t aIndex) override;
259 virtual bool RemoveItemFromSelection(uint32_t aIndex) override;
261 virtual bool SelectAll() override;
263 virtual bool UnselectAll() override;
265 virtual void TakeSelection() override;
267 virtual void SetSelected(bool aSelect) override;
269 // Methods that interact with content.
271 virtual void TakeFocus() const override;
272 virtual void ScrollTo(uint32_t aHow) const override;
273 virtual void SetCaretOffset(int32_t aOffset) override;
276 * Allow the platform to store a pointers worth of data on us.
278 uintptr_t GetWrapper() const { return mWrapper; }
279 void SetWrapper(uintptr_t aWrapper) { mWrapper = aWrapper; }
281 virtual uint64_t ID() const override { return mID; }
284 * Return the document containing this proxy, or the proxy itself if it is a
285 * document.
287 DocAccessibleParent* Document() const { return mDoc; }
289 DocAccessibleParent* AsDoc() const { return IsDoc() ? mDoc : nullptr; }
291 void ApplyCache(CacheUpdateType aUpdateType, AccAttributes* aFields);
293 void UpdateStateCache(uint64_t aState, bool aEnabled) {
294 if (aState & kRemoteCalculatedStates) {
295 return;
297 uint64_t state = 0;
298 if (mCachedFields) {
299 if (auto oldState =
300 mCachedFields->GetAttribute<uint64_t>(CacheKey::State)) {
301 state = *oldState;
303 } else {
304 mCachedFields = new AccAttributes();
306 if (aEnabled) {
307 state |= aState;
308 } else {
309 state &= ~aState;
311 mCachedFields->SetAttribute(CacheKey::State, state);
314 void InvalidateGroupInfo();
316 virtual void AppendTextTo(nsAString& aText, uint32_t aStartOffset = 0,
317 uint32_t aLength = UINT32_MAX) override;
319 virtual bool TableIsProbablyForLayout();
322 * Iterates through each atom in kRelationTypeAtoms, checking to see
323 * if it is present in aFields. If it is present (or if aFields contains
324 * a DeleteEntry() for this atom) and mCachedFields is initialized,
325 * fetches the old rel targets and removes their existing reverse relations
326 * stored in mReverseRelations.
327 * Returns an array of bools where the ith array entry corresponds
328 * to whether or not the rel at the ith entry of kRelationTypeAtoms
329 * requires a post-processing update.
331 nsTArray<bool> PreProcessRelations(AccAttributes* aFields);
334 * Takes in the array returned from PreProcessRelations.
335 * For each entry requiring an update, fetches the new relation
336 * targets stored in mCachedFields and appropriately
337 * updates their reverse relations in mReverseRelations.
339 void PostProcessRelations(const nsTArray<bool>& aToUpdate);
342 * This method is called during shutdown, before we clear our
343 * reverse rel map from the document's mReverseRelations cache.
344 * Here, we traverse our reverse relations, removing our ID from
345 * the corresponding forward relation's target list. This ensures
346 * the stored forward relations do not reference defunct accessibles.
348 void PruneRelationsOnShutdown();
350 uint32_t GetCachedTextLength();
351 Maybe<const nsTArray<int32_t>&> GetCachedTextLines();
352 nsRect GetCachedCharRect(int32_t aOffset);
353 RefPtr<const AccAttributes> GetCachedTextAttributes();
354 RefPtr<const AccAttributes> GetCachedARIAAttributes() const;
356 nsString GetCachedHTMLNameAttribute() const;
358 virtual HyperTextAccessibleBase* AsHyperTextBase() override {
359 return IsHyperText() ? static_cast<HyperTextAccessibleBase*>(this)
360 : nullptr;
363 virtual TableAccessible* AsTable() override;
364 virtual TableCellAccessible* AsTableCell() override;
366 virtual void DOMNodeID(nsString& aID) const override;
368 virtual void ScrollToPoint(uint32_t aScrollType, int32_t aX,
369 int32_t aY) override;
371 #if !defined(XP_WIN)
372 void Announce(const nsString& aAnnouncement, uint16_t aPriority);
373 #endif // !defined(XP_WIN)
375 // HyperTextAccessibleBase
376 virtual already_AddRefed<AccAttributes> DefaultTextAttributes() override;
378 virtual void ScrollSubstringToPoint(int32_t aStartOffset, int32_t aEndOffset,
379 uint32_t aCoordinateType, int32_t aX,
380 int32_t aY) override;
383 * Invalidate cached HyperText offsets. This should be called whenever a
384 * child is added or removed or the text of a text leaf child is changed.
385 * Although GetChildOffset can either fully or partially invalidate the
386 * offsets cache, calculating which offset to invalidate is not worthwhile
387 * because a client might not even query offsets. This is in contrast to
388 * LocalAccessible, where the offsets are always needed to fire text change
389 * events. For RemoteAccessible, it's cheaper overall to just rebuild the
390 * offsets cache when a client next needs it.
392 void InvalidateCachedHyperTextOffsets() {
393 if (mCachedFields) {
394 mCachedFields->Remove(CacheKey::HyperTextOffsets);
398 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf);
399 virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf);
401 protected:
402 RemoteAccessible(uint64_t aID, DocAccessibleParent* aDoc, role aRole,
403 AccType aType, AccGenericType aGenericTypes,
404 uint8_t aRoleMapEntryIndex)
405 : Accessible(aType, aGenericTypes, aRoleMapEntryIndex),
406 mParent(kNoParent),
407 mDoc(aDoc),
408 mWrapper(0),
409 mID(aID),
410 mCachedFields(nullptr),
411 mRole(aRole) {
412 MOZ_COUNT_CTOR(RemoteAccessible);
415 explicit RemoteAccessible(DocAccessibleParent* aThisAsDoc)
416 : mParent(kNoParent),
417 mDoc(aThisAsDoc),
418 mWrapper(0),
419 mID(0),
420 mCachedFields(nullptr),
421 mRole(roles::DOCUMENT) {
422 mGenericTypes = eDocument | eHyperText;
423 MOZ_COUNT_CTOR(RemoteAccessible);
426 protected:
427 void SetParent(RemoteAccessible* aParent);
428 Maybe<nsRect> RetrieveCachedBounds() const;
429 bool ApplyTransform(nsRect& aCumulativeBounds) const;
430 bool ApplyScrollOffset(nsRect& aBounds) const;
431 void ApplyCrossDocOffset(nsRect& aBounds) const;
432 LayoutDeviceIntRect BoundsWithOffset(
433 Maybe<nsRect> aOffset, bool aBoundsAreForHittesting = false) const;
434 bool IsFixedPos() const;
435 bool IsOverflowHidden() const;
438 * Returns true if an accessible's frame has no scrollable overflow, and
439 * false otherwise.
440 * Does not return true for partially clipped accessibles.
442 bool IsClipped() const;
445 * Checks if our hittesting match has any clipped children and, if so
446 * descends it and subsequent TEXT_CONTAINERs in search of a text leaf.
447 * We do this because some sites use clipping to hide text that is only
448 * visible to a11y, while displaying a visual version of the same text on
449 * the web page. We want a hittest of the visible text to resolve to the
450 * hidden, a11y-only text node.
452 RemoteAccessible* DoFuzzyHittesting();
454 // This function is used exclusively for hit testing.
455 bool ContainsPoint(int32_t aX, int32_t aY);
457 virtual void ARIAGroupPosition(int32_t* aLevel, int32_t* aSetSize,
458 int32_t* aPosInSet) const override;
460 virtual AccGroupInfo* GetGroupInfo() const override;
462 virtual AccGroupInfo* GetOrCreateGroupInfo() override;
464 virtual void GetPositionAndSetSize(int32_t* aPosInSet,
465 int32_t* aSetSize) override;
467 virtual bool HasPrimaryAction() const override;
469 nsAtom* GetPrimaryAction() const;
471 virtual nsTArray<int32_t>& GetCachedHyperTextOffsets() override;
473 private:
474 uintptr_t mParent;
475 static const uintptr_t kNoParent = UINTPTR_MAX;
477 friend DocAccessibleParent;
478 friend TextLeafPoint;
479 friend HyperTextAccessibleBase;
480 friend class xpcAccessible;
481 friend class CachedTableCellAccessible;
482 #ifdef XP_WIN
483 friend class sdnAccessible;
484 #endif
486 nsTArray<RemoteAccessible*> mChildren;
487 DocAccessibleParent* mDoc;
488 uintptr_t mWrapper;
489 uint64_t mID;
491 protected:
492 virtual const Accessible* Acc() const override { return this; }
494 RefPtr<AccAttributes> mCachedFields;
496 // XXX DocAccessibleParent gets to change this to change the role of
497 // documents.
498 role mRole : 27;
501 ////////////////////////////////////////////////////////////////////////////////
502 // RemoteAccessible downcasting method
504 inline RemoteAccessible* Accessible::AsRemote() {
505 return IsRemote() ? static_cast<RemoteAccessible*>(this) : nullptr;
508 } // namespace a11y
509 } // namespace mozilla
511 #endif