1 // Copyright 2017 The Chromium Embedded Framework Authors. Portions copyright
2 // 2013 The Chromium Authors. All rights reserved. Use of this source code is
3 // governed by a BSD-style license that can be found in the LICENSE file.
4
5 // Base class implementation for CEF Acccessibility node. This is subclassed and
6 // used by both IAccessible/NSAccessibility protocol implementation.
7
8 #include "tests/cefclient/browser/osr_accessibility_node.h"
9
10 #include "tests/cefclient/browser/osr_accessibility_helper.h"
11
12 namespace client {
13
OsrAXNode(const CefString & treeId,int nodeId,CefRefPtr<CefDictionaryValue> value,OsrAccessibilityHelper * helper)14 OsrAXNode::OsrAXNode(const CefString& treeId,
15 int nodeId,
16 CefRefPtr<CefDictionaryValue> value,
17 OsrAccessibilityHelper* helper)
18 : tree_id_(treeId),
19 node_id_(nodeId),
20 platform_accessibility_(nullptr),
21 parent_(nullptr),
22 offset_container_id_(-1),
23 accessibility_helper_(helper) {
24 UpdateValue(value);
25 }
26
UpdateLocation(CefRefPtr<CefDictionaryValue> value)27 void OsrAXNode::UpdateLocation(CefRefPtr<CefDictionaryValue> value) {
28 // Update Bounds
29 if (value->HasKey("bounds")) {
30 CefRefPtr<CefDictionaryValue> loc = value->GetDictionary("bounds");
31 if (loc) {
32 location_ = CefRect(loc->GetDouble("x"), loc->GetDouble("y"),
33 loc->GetDouble("width"), loc->GetDouble("height"));
34 }
35 }
36 // Update offsets
37 if (value->HasKey("offset_container_id")) {
38 offset_container_id_ = OsrAccessibilityHelper::CastToInt(
39 value->GetValue("offset_container_id"));
40 }
41 }
42
UpdateValue(CefRefPtr<CefDictionaryValue> value)43 void OsrAXNode::UpdateValue(CefRefPtr<CefDictionaryValue> value) {
44 if (value->HasKey("role"))
45 role_ = value->GetString("role");
46
47 if (value->HasKey("child_ids")) {
48 CefRefPtr<CefListValue> childs = value->GetList("child_ids");
49 // Reset child Ids
50 child_ids_.clear();
51 for (size_t idx = 0; idx < childs->GetSize(); idx++)
52 child_ids_.push_back(
53 OsrAccessibilityHelper::CastToInt(childs->GetValue(idx)));
54 }
55 // Update Location
56 if (value->HasKey("location")) {
57 CefRefPtr<CefDictionaryValue> loc = value->GetDictionary("location");
58 if (loc) {
59 location_ = CefRect(loc->GetDouble("x"), loc->GetDouble("y"),
60 loc->GetDouble("width"), loc->GetDouble("height"));
61 }
62 }
63 // Update offsets
64 if (value->HasKey("offset_container_id")) {
65 offset_container_id_ = OsrAccessibilityHelper::CastToInt(
66 value->GetValue("offset_container_id"));
67 }
68 // Update attributes
69 if (value->HasKey("attributes")) {
70 child_tree_id_ = "";
71
72 attributes_ = value->GetDictionary("attributes");
73
74 if (attributes_) {
75 scroll_.x = attributes_->HasKey("scrollX")
76 ? OsrAccessibilityHelper::CastToInt(
77 attributes_->GetValue("scrollX"))
78 : 0;
79 scroll_.y = attributes_->HasKey("scrollY")
80 ? OsrAccessibilityHelper::CastToInt(
81 attributes_->GetValue("scrollY"))
82 : 0;
83 }
84
85 if (attributes_ && attributes_->HasKey("childTreeId")) {
86 child_tree_id_ = attributes_->GetString("childTreeId");
87 }
88 if (attributes_ && attributes_->HasKey("name"))
89 name_ = attributes_->GetString("name");
90 if (attributes_ && attributes_->HasKey("value"))
91 value_ = attributes_->GetString("value");
92 if (attributes_ && attributes_->HasKey("description"))
93 description_ = attributes_->GetString("description");
94 }
95 }
96
GetWindowHandle() const97 CefWindowHandle OsrAXNode::GetWindowHandle() const {
98 if (accessibility_helper_)
99 return accessibility_helper_->GetWindowHandle();
100 return nullptr;
101 }
102
GetBrowser() const103 CefRefPtr<CefBrowser> OsrAXNode::GetBrowser() const {
104 if (accessibility_helper_)
105 return accessibility_helper_->GetBrowser();
106 return nullptr;
107 }
108
SetParent(OsrAXNode * parent)109 void OsrAXNode::SetParent(OsrAXNode* parent) {
110 parent_ = parent;
111 }
112
AxLocation() const113 CefRect OsrAXNode::AxLocation() const {
114 CefRect loc = location_;
115 loc.x -= scroll_.x;
116 loc.y -= scroll_.y;
117 OsrAXNode* offsetNode =
118 accessibility_helper_->GetNode(OsrAXTreeId(), offset_container_id_);
119 if (!offsetNode) {
120 OsrAXNode* p = parent_;
121 while (p) {
122 if (p->OsrAXTreeId() != OsrAXTreeId()) {
123 offsetNode = p;
124 break;
125 }
126 p = p->parent_;
127 }
128 }
129 // Add offset from parent Location
130 if (offsetNode) {
131 CefRect offset = offsetNode->AxLocation();
132 loc.x += offset.x;
133 loc.y += offset.y;
134 }
135 return loc;
136 }
137
GetChildCount() const138 int OsrAXNode::GetChildCount() const {
139 int count = static_cast<int>(child_ids_.size());
140 if (!child_tree_id_.empty()) {
141 OsrAXNode* childTreeRootNode =
142 accessibility_helper_->GetTreeRootNode(child_tree_id_);
143 if (childTreeRootNode) {
144 count++;
145 }
146 }
147 return count;
148 }
149
ChildAtIndex(int index) const150 OsrAXNode* OsrAXNode::ChildAtIndex(int index) const {
151 int count = static_cast<int>(child_ids_.size());
152 if (index < count)
153 return accessibility_helper_->GetNode(OsrAXTreeId(), child_ids_[index]);
154 if ((index == count) && (!child_tree_id_.empty())) {
155 OsrAXNode* childTreeRootNode =
156 accessibility_helper_->GetTreeRootNode(child_tree_id_);
157 if (childTreeRootNode) {
158 return childTreeRootNode;
159 }
160 }
161
162 return nullptr;
163 }
164
165 // Create and return the platform specific OsrAXNode Object
CreateNode(const CefString & treeId,int nodeId,CefRefPtr<CefDictionaryValue> value,OsrAccessibilityHelper * helper)166 OsrAXNode* OsrAXNode::CreateNode(const CefString& treeId,
167 int nodeId,
168 CefRefPtr<CefDictionaryValue> value,
169 OsrAccessibilityHelper* helper) {
170 return new OsrAXNode(treeId, nodeId, value, helper);
171 }
172
173 } // namespace client
174