AccessibleNode.cpp (4665B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "AccessibleNode.h" 7 #include "mozilla/dom/AccessibleNodeBinding.h" 8 #include "mozilla/dom/BindingDeclarations.h" 9 #include "mozilla/dom/DOMStringList.h" 10 #include "mozilla/StaticPrefs_accessibility.h" 11 #include "nsContentUtils.h" 12 13 #include "LocalAccessible-inl.h" 14 #include "nsAccessibilityService.h" 15 #include "DocAccessible.h" 16 17 #include "mozilla/dom/ToJSValue.h" 18 19 using namespace mozilla; 20 using namespace mozilla::a11y; 21 using namespace mozilla::dom; 22 23 bool AccessibleNode::IsAOMEnabled(JSContext* aCx, JSObject* /*unused*/) { 24 return nsContentUtils::IsSystemCaller(aCx) || 25 StaticPrefs::accessibility_AOM_enabled(); 26 } 27 28 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(AccessibleNode, mRelationProperties, 29 mIntl, mDOMNode, mStates) 30 31 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AccessibleNode) 32 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY 33 NS_INTERFACE_MAP_ENTRY(nsISupports) 34 NS_INTERFACE_MAP_END 35 36 NS_IMPL_CYCLE_COLLECTING_ADDREF(AccessibleNode) 37 NS_IMPL_CYCLE_COLLECTING_RELEASE(AccessibleNode) 38 39 AccessibleNode::AccessibleNode(nsINode* aNode) 40 : mDoubleProperties(3), 41 mIntProperties(3), 42 mUIntProperties(6), 43 mBooleanProperties(0), 44 mRelationProperties(3), 45 mStringProperties(16), 46 mDOMNode(aNode) { 47 nsAccessibilityService* accService = GetOrCreateAccService(); 48 if (!accService) { 49 return; 50 } 51 52 DocAccessible* doc = accService->GetDocAccessible(mDOMNode->OwnerDoc()); 53 if (doc) { 54 mIntl = doc->GetAccessible(mDOMNode); 55 } 56 } 57 58 AccessibleNode::~AccessibleNode() {} 59 60 /* virtual */ 61 JSObject* AccessibleNode::WrapObject(JSContext* aCx, 62 JS::Handle<JSObject*> aGivenProto) { 63 return AccessibleNode_Binding::Wrap(aCx, this, aGivenProto); 64 } 65 66 /* virtual */ 67 ParentObject AccessibleNode::GetParentObject() const { 68 return mDOMNode->GetParentObject(); 69 } 70 71 void AccessibleNode::GetComputedRole(nsAString& aRole) { 72 if (mIntl) { 73 nsAccessibilityService* accService = GetOrCreateAccService(); 74 if (accService) { 75 accService->GetStringRole(mIntl->Role(), aRole); 76 return; 77 } 78 } 79 80 aRole.AssignLiteral("unknown"); 81 } 82 83 void AccessibleNode::GetStates(nsTArray<nsString>& aStates) { 84 nsAccessibilityService* accService = GetOrCreateAccService(); 85 if (!mIntl || !accService) { 86 aStates.AppendElement(u"defunct"_ns); 87 return; 88 } 89 90 if (mStates) { 91 aStates = mStates->StringArray().Clone(); 92 return; 93 } 94 95 mStates = accService->GetStringStates(mIntl->State()); 96 aStates = mStates->StringArray().Clone(); 97 } 98 99 void AccessibleNode::GetAttributes(nsTArray<nsString>& aAttributes) { 100 if (!mIntl) { 101 return; 102 } 103 104 RefPtr<AccAttributes> attrs = mIntl->Attributes(); 105 106 for (const auto& iter : *attrs) { 107 aAttributes.AppendElement(nsAtomString(iter.Name())); 108 } 109 } 110 111 bool AccessibleNode::Is(const Sequence<nsString>& aFlavors) { 112 nsAccessibilityService* accService = GetOrCreateAccService(); 113 if (!mIntl || !accService) { 114 for (const auto& flavor : aFlavors) { 115 if (!flavor.EqualsLiteral("unknown") && 116 !flavor.EqualsLiteral("defunct")) { 117 return false; 118 } 119 } 120 return true; 121 } 122 123 nsAutoString role; 124 accService->GetStringRole(mIntl->Role(), role); 125 126 if (!mStates) { 127 mStates = accService->GetStringStates(mIntl->State()); 128 } 129 130 for (const auto& flavor : aFlavors) { 131 if (!flavor.Equals(role) && !mStates->Contains(flavor)) { 132 return false; 133 } 134 } 135 return true; 136 } 137 138 bool AccessibleNode::Has(const Sequence<nsString>& aAttributes) { 139 if (!mIntl) { 140 return false; 141 } 142 RefPtr<AccAttributes> attrs = mIntl->Attributes(); 143 for (const auto& attr : aAttributes) { 144 RefPtr<nsAtom> attrAtom = NS_Atomize(attr); 145 if (!attrs->HasAttribute(attrAtom)) { 146 return false; 147 } 148 } 149 return true; 150 } 151 152 void AccessibleNode::Get(JSContext* aCX, const nsAString& aAttribute, 153 JS::MutableHandle<JS::Value> aValue, 154 ErrorResult& aRv) { 155 if (!mIntl) { 156 aRv.ThrowInvalidStateError("No attributes available"); 157 return; 158 } 159 160 RefPtr<nsAtom> attrAtom = NS_Atomize(aAttribute); 161 RefPtr<AccAttributes> attrs = mIntl->Attributes(); 162 nsAutoString valueStr; 163 attrs->GetAttribute(attrAtom, valueStr); 164 if (!ToJSValue(aCX, valueStr, aValue)) { 165 aRv.NoteJSContextException(aCX); 166 return; 167 } 168 } 169 170 nsINode* AccessibleNode::GetDOMNode() { return mDOMNode; }