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/. */ 6 7 #ifndef mozilla_a11y_RemoteAccessibleBase_h 8 #define mozilla_a11y_RemoteAccessibleBase_h 9 10 #include "mozilla/a11y/Accessible.h" 11 #include "mozilla/a11y/Role.h" 12 #include "nsIAccessibleText.h" 13 #include "nsIAccessibleTypes.h" 14 #include "LocalAccessible.h" 15 #include "nsString.h" 16 #include "nsTArray.h" 17 #include "nsRect.h" 18 #include "LocalAccessible.h" 19 20 namespace mozilla { 21 namespace a11y { 22 23 class LocalAccessible; 24 class Attribute; 25 class DocAccessibleParent; 26 class RemoteAccessible; 27 enum class RelationType; 28 29 template <class Derived> 30 class RemoteAccessibleBase : public Accessible { 31 public: ~RemoteAccessibleBase()32 virtual ~RemoteAccessibleBase() { MOZ_ASSERT(!mWrapper); } 33 IsRemote()34 virtual bool IsRemote() const override { return true; } 35 AddChildAt(uint32_t aIdx,Derived * aChild)36 void AddChildAt(uint32_t aIdx, Derived* aChild) { 37 mChildren.InsertElementAt(aIdx, aChild); 38 } 39 ChildCount()40 virtual uint32_t ChildCount() const override { return mChildren.Length(); } RemoteChildAt(uint32_t aIdx)41 Derived* RemoteChildAt(uint32_t aIdx) const { return mChildren[aIdx]; } RemoteFirstChild()42 Derived* RemoteFirstChild() const { 43 return mChildren.Length() ? mChildren[0] : nullptr; 44 } RemoteLastChild()45 Derived* RemoteLastChild() const { 46 return mChildren.Length() ? mChildren[mChildren.Length() - 1] : nullptr; 47 } RemotePrevSibling()48 Derived* RemotePrevSibling() const { 49 if (IsDoc()) { 50 // The normal code path doesn't work for documents because the parent 51 // might be a local OuterDoc, but IndexInParent() will return 1. 52 // A document is always a single child of an OuterDoc anyway. 53 return nullptr; 54 } 55 int32_t idx = IndexInParent(); 56 if (idx == -1) { 57 return nullptr; // No parent. 58 } 59 return idx > 0 ? RemoteParent()->mChildren[idx - 1] : nullptr; 60 } RemoteNextSibling()61 Derived* RemoteNextSibling() const { 62 if (IsDoc()) { 63 // The normal code path doesn't work for documents because the parent 64 // might be a local OuterDoc, but IndexInParent() will return 1. 65 // A document is always a single child of an OuterDoc anyway. 66 return nullptr; 67 } 68 int32_t idx = IndexInParent(); 69 if (idx == -1) { 70 return nullptr; // No parent. 71 } 72 MOZ_ASSERT(idx >= 0); 73 size_t newIdx = idx + 1; 74 return newIdx < RemoteParent()->mChildren.Length() 75 ? RemoteParent()->mChildren[newIdx] 76 : nullptr; 77 } 78 79 // Accessible hierarchy method overrides 80 Parent()81 virtual Accessible* Parent() const override { 82 if (Derived* parent = RemoteParent()) { 83 return parent; 84 } 85 86 return OuterDocOfRemoteBrowser(); 87 } 88 ChildAt(uint32_t aIndex)89 virtual Accessible* ChildAt(uint32_t aIndex) const override { 90 return RemoteChildAt(aIndex); 91 } 92 NextSibling()93 virtual Accessible* NextSibling() const override { 94 return RemoteNextSibling(); 95 } 96 PrevSibling()97 virtual Accessible* PrevSibling() const override { 98 return RemotePrevSibling(); 99 } 100 101 // XXX evaluate if this is fast enough. IndexInParent()102 virtual int32_t IndexInParent() const override { 103 Derived* parent = RemoteParent(); 104 if (!parent) { 105 return -1; 106 } 107 return parent->mChildren.IndexOf(static_cast<const Derived*>(this)); 108 } 109 uint32_t EmbeddedChildCount() const; 110 int32_t IndexOfEmbeddedChild(const Derived* aChild); 111 Derived* EmbeddedChildAt(size_t aChildIdx); 112 113 void Shutdown(); 114 115 void SetChildDoc(DocAccessibleParent* aChildDoc); 116 void ClearChildDoc(DocAccessibleParent* aChildDoc); 117 118 /** 119 * Remove The given child. 120 */ RemoveChild(Derived * aChild)121 void RemoveChild(Derived* aChild) { mChildren.RemoveElement(aChild); } 122 123 /** 124 * Return the proxy for the parent of the wrapped accessible. 125 */ 126 Derived* RemoteParent() const; 127 128 LocalAccessible* OuterDocOfRemoteBrowser() const; 129 130 /** 131 * Get the role of the accessible we're proxying. 132 */ Role()133 virtual role Role() const override { return mRole; } 134 135 /** 136 * Return true if this is an embedded object. 137 */ IsEmbeddedObject()138 bool IsEmbeddedObject() const { 139 role role = Role(); 140 return role != roles::TEXT_LEAF && role != roles::WHITESPACE && 141 role != roles::STATICTEXT; 142 } 143 IsLink()144 virtual bool IsLink() const override { 145 if (IsHTMLLink()) { 146 // XXX: HTML links always return true for IsLink. 147 return true; 148 } 149 150 if (IsText()) { 151 return false; 152 } 153 154 if (Accessible* parent = Parent()) { 155 return parent->IsHyperText(); 156 } 157 158 return false; 159 } 160 HasNumericValue()161 virtual bool HasNumericValue() const override { 162 // XXX: We combine the aria and native "has numeric value" field 163 // when we serialize the local accessible into eNumericValue. 164 return HasGenericType(eNumericValue); 165 } 166 167 /** 168 * Allow the platform to store a pointers worth of data on us. 169 */ GetWrapper()170 uintptr_t GetWrapper() const { return mWrapper; } SetWrapper(uintptr_t aWrapper)171 void SetWrapper(uintptr_t aWrapper) { mWrapper = aWrapper; } 172 173 /* 174 * Return the ID of the accessible being proxied. 175 */ ID()176 uint64_t ID() const { return mID; } 177 178 /** 179 * Return the document containing this proxy, or the proxy itself if it is a 180 * document. 181 */ Document()182 DocAccessibleParent* Document() const { return mDoc; } 183 AsDoc()184 DocAccessibleParent* AsDoc() const { return IsDoc() ? mDoc : nullptr; } 185 186 protected: RemoteAccessibleBase(uint64_t aID,Derived * aParent,DocAccessibleParent * aDoc,role aRole,AccType aType,AccGenericType aGenericTypes,uint8_t aRoleMapEntryIndex)187 RemoteAccessibleBase(uint64_t aID, Derived* aParent, 188 DocAccessibleParent* aDoc, role aRole, AccType aType, 189 AccGenericType aGenericTypes, uint8_t aRoleMapEntryIndex) 190 : Accessible(aType, aGenericTypes, aRoleMapEntryIndex), 191 mParent(aParent->ID()), 192 mDoc(aDoc), 193 mWrapper(0), 194 mID(aID), 195 mRole(aRole) {} 196 RemoteAccessibleBase(DocAccessibleParent * aThisAsDoc)197 explicit RemoteAccessibleBase(DocAccessibleParent* aThisAsDoc) 198 : Accessible(), 199 mParent(kNoParent), 200 mDoc(aThisAsDoc), 201 mWrapper(0), 202 mID(0), 203 mRole(roles::DOCUMENT) { 204 mGenericTypes = eDocument | eHyperText; 205 } 206 207 protected: 208 void SetParent(Derived* aParent); 209 210 private: 211 uintptr_t mParent; 212 static const uintptr_t kNoParent = UINTPTR_MAX; 213 214 friend Derived; 215 216 nsTArray<Derived*> mChildren; 217 DocAccessibleParent* mDoc; 218 uintptr_t mWrapper; 219 uint64_t mID; 220 221 protected: 222 // XXX DocAccessibleParent gets to change this to change the role of 223 // documents. 224 role mRole : 27; 225 }; 226 227 extern template class RemoteAccessibleBase<RemoteAccessible>; 228 229 } // namespace a11y 230 } // namespace mozilla 231 232 #endif 233