OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/accessibility/accessibility_tree_formatter.h" | 5 #include "content/browser/accessibility/accessibility_tree_formatter.h" |
6 | 6 |
7 #import <Cocoa/Cocoa.h> | 7 #import <Cocoa/Cocoa.h> |
8 | 8 |
| 9 #include "base/basictypes.h" |
9 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
| 11 #include "base/stringprintf.h" |
| 12 #include "base/strings/sys_string_conversions.h" |
10 #include "base/utf_string_conversions.h" | 13 #include "base/utf_string_conversions.h" |
11 #include "content/browser/accessibility/browser_accessibility_cocoa.h" | 14 #include "content/browser/accessibility/browser_accessibility_cocoa.h" |
12 #include "content/browser/accessibility/browser_accessibility_mac.h" | 15 #include "content/browser/accessibility/browser_accessibility_mac.h" |
13 #include "content/browser/accessibility/browser_accessibility_manager.h" | 16 #include "content/browser/accessibility/browser_accessibility_manager.h" |
14 | 17 |
| 18 using base::StringPrintf; |
| 19 using base::SysNSStringToUTF8; |
| 20 using base::SysNSStringToUTF16; |
| 21 using std::string; |
| 22 |
15 namespace content { | 23 namespace content { |
16 | 24 |
17 namespace { | 25 namespace { |
18 | 26 |
19 string16 Format(const char *prefix, | 27 const char* kPositionDictAttr = "position"; |
20 id value, | 28 const char* kXCoordDictAttr = "x"; |
21 const char *suffix) { | 29 const char* kYCoordDictAttr = "y"; |
22 if (value == nil) | 30 const char* kSizeDictAttr = "size"; |
23 return UTF8ToUTF16(""); | 31 const char* kWidthDictAttr = "width"; |
24 NSString* format_str = | 32 const char* kHeightDictAttr = "height"; |
25 [NSString stringWithFormat:@"%s%%@%s", prefix, suffix]; | |
26 NSString* tmp = [NSString stringWithFormat:format_str, value]; | |
27 return UTF8ToUTF16([tmp cStringUsingEncoding:NSUTF8StringEncoding]); | |
28 } | |
29 | 33 |
30 string16 FormatPosition(BrowserAccessibility* node) { | 34 scoped_ptr<DictionaryValue> PopulatePosition(const BrowserAccessibility& node) { |
| 35 scoped_ptr<DictionaryValue> position(new DictionaryValue); |
31 // The NSAccessibility position of an object is in global coordinates and | 36 // The NSAccessibility position of an object is in global coordinates and |
32 // based on the lower-left corner of the object. To make this easier and less | 37 // based on the lower-left corner of the object. To make this easier and less |
33 // confusing, convert it to local window coordinates using the top-left | 38 // confusing, convert it to local window coordinates using the top-left |
34 // corner when dumping the position. | 39 // corner when dumping the position. |
35 BrowserAccessibility* root = node->manager()->GetRoot(); | 40 BrowserAccessibility* root = node.manager()->GetRoot(); |
36 BrowserAccessibilityCocoa* cocoa_root = root->ToBrowserAccessibilityCocoa(); | 41 BrowserAccessibilityCocoa* cocoa_root = root->ToBrowserAccessibilityCocoa(); |
37 NSPoint root_position = [[cocoa_root position] pointValue]; | 42 NSPoint root_position = [[cocoa_root position] pointValue]; |
38 NSSize root_size = [[cocoa_root size] sizeValue]; | 43 NSSize root_size = [[cocoa_root size] sizeValue]; |
39 int root_top = -static_cast<int>(root_position.y + root_size.height); | 44 int root_top = -static_cast<int>(root_position.y + root_size.height); |
40 int root_left = static_cast<int>(root_position.x); | 45 int root_left = static_cast<int>(root_position.x); |
41 | 46 |
42 BrowserAccessibilityCocoa* cocoa_node = node->ToBrowserAccessibilityCocoa(); | 47 BrowserAccessibilityCocoa* cocoa_node = |
| 48 const_cast<BrowserAccessibility*>(&node)->ToBrowserAccessibilityCocoa(); |
43 NSPoint node_position = [[cocoa_node position] pointValue]; | 49 NSPoint node_position = [[cocoa_node position] pointValue]; |
44 NSSize node_size = [[cocoa_node size] sizeValue]; | 50 NSSize node_size = [[cocoa_node size] sizeValue]; |
45 | 51 |
46 NSString* position_str = | 52 position->SetInteger(kXCoordDictAttr, |
47 [NSString stringWithFormat:@"position=(%d, %d)", | 53 static_cast<int>(node_position.x - root_left)); |
48 static_cast<int>(node_position.x - root_left), | 54 position->SetInteger(kYCoordDictAttr, |
49 static_cast<int>( | 55 static_cast<int>(-node_position.y - node_size.height - root_top)); |
50 -node_position.y - node_size.height - root_top)]; | 56 return position.Pass(); |
51 return UTF8ToUTF16([position_str cStringUsingEncoding:NSUTF8StringEncoding]); | |
52 } | 57 } |
53 | 58 |
54 string16 FormatSize(BrowserAccessibility* node) { | 59 scoped_ptr<DictionaryValue> |
55 BrowserAccessibilityCocoa* cocoa_node = node->ToBrowserAccessibilityCocoa(); | 60 PopulateSize(const BrowserAccessibilityCocoa* cocoa_node) { |
| 61 scoped_ptr<DictionaryValue> size(new DictionaryValue); |
56 NSSize node_size = [[cocoa_node size] sizeValue]; | 62 NSSize node_size = [[cocoa_node size] sizeValue]; |
57 NSString* size_str = | 63 size->SetInteger(kHeightDictAttr, static_cast<int>(node_size.height)); |
58 [NSString stringWithFormat:@"size=(%d, %d)", | 64 size->SetInteger(kWidthDictAttr, static_cast<int>(node_size.width)); |
59 static_cast<int>(node_size.width), | 65 return size.Pass(); |
60 static_cast<int>(node_size.height)]; | |
61 return UTF8ToUTF16([size_str cStringUsingEncoding:NSUTF8StringEncoding]); | |
62 } | 66 } |
63 | 67 |
64 } // namespace | 68 NSArray* BuildAllAttributesArray() { |
65 | 69 return [NSArray arrayWithObjects: |
66 void AccessibilityTreeFormatter::Initialize() {} | |
67 | |
68 string16 AccessibilityTreeFormatter::ToString(BrowserAccessibility* node, | |
69 char* prefix) { | |
70 StartLine(); | |
71 NSArray* requestedAttributes = [NSArray arrayWithObjects: | |
72 NSAccessibilityRoleDescriptionAttribute, | 70 NSAccessibilityRoleDescriptionAttribute, |
73 NSAccessibilityTitleAttribute, | 71 NSAccessibilityTitleAttribute, |
74 NSAccessibilityValueAttribute, | 72 NSAccessibilityValueAttribute, |
75 NSAccessibilityMinValueAttribute, | 73 NSAccessibilityMinValueAttribute, |
76 NSAccessibilityMaxValueAttribute, | 74 NSAccessibilityMaxValueAttribute, |
77 NSAccessibilityValueDescriptionAttribute, | 75 NSAccessibilityValueDescriptionAttribute, |
78 NSAccessibilityDescriptionAttribute, | 76 NSAccessibilityDescriptionAttribute, |
79 NSAccessibilityHelpAttribute, | 77 NSAccessibilityHelpAttribute, |
80 @"AXInvalid", | 78 @"AXInvalid", |
81 NSAccessibilityDisclosingAttribute, | 79 NSAccessibilityDisclosingAttribute, |
82 NSAccessibilityDisclosureLevelAttribute, | 80 NSAccessibilityDisclosureLevelAttribute, |
83 @"AXAccessKey", | 81 @"AXAccessKey", |
84 @"AXARIAAtomic", | 82 @"AXARIAAtomic", |
85 @"AXARIABusy", | 83 @"AXARIABusy", |
86 @"AXARIALive", | 84 @"AXARIALive", |
87 @"AXARIARelevant", | 85 @"AXARIARelevant", |
88 NSAccessibilityEnabledAttribute, | 86 NSAccessibilityEnabledAttribute, |
89 NSAccessibilityFocusedAttribute, | 87 NSAccessibilityFocusedAttribute, |
90 @"AXLoaded", | 88 @"AXLoaded", |
91 @"AXLoadingProcess", | 89 @"AXLoadingProcess", |
92 NSAccessibilityNumberOfCharactersAttribute, | 90 NSAccessibilityNumberOfCharactersAttribute, |
93 NSAccessibilityOrientationAttribute, | 91 NSAccessibilityOrientationAttribute, |
94 @"AXRequired", | 92 @"AXRequired", |
95 NSAccessibilityURLAttribute, | 93 NSAccessibilityURLAttribute, |
96 NSAccessibilityVisibleCharacterRangeAttribute, | 94 NSAccessibilityVisibleCharacterRangeAttribute, |
97 @"AXVisited", | 95 @"AXVisited", |
98 nil]; | 96 nil]; |
| 97 } |
99 | 98 |
100 NSArray* defaultAttributes = [NSArray arrayWithObjects: | 99 } // namespace |
101 NSAccessibilityTitleAttribute, | |
102 NSAccessibilityValueAttribute, | |
103 nil]; | |
104 | 100 |
105 BrowserAccessibilityCocoa* cocoa_node = node->ToBrowserAccessibilityCocoa(); | 101 void AccessibilityTreeFormatter::Initialize() { |
| 102 } |
| 103 |
| 104 |
| 105 void AccessibilityTreeFormatter::AddProperties(const BrowserAccessibility& node, |
| 106 DictionaryValue* dict) { |
| 107 BrowserAccessibilityCocoa* cocoa_node = |
| 108 const_cast<BrowserAccessibility*>(&node)->ToBrowserAccessibilityCocoa(); |
106 NSArray* supportedAttributes = [cocoa_node accessibilityAttributeNames]; | 109 NSArray* supportedAttributes = [cocoa_node accessibilityAttributeNames]; |
107 | 110 |
108 Add(true, | 111 string role = SysNSStringToUTF8( |
109 Format("", [cocoa_node accessibilityAttributeValue: | 112 [cocoa_node accessibilityAttributeValue:NSAccessibilityRoleAttribute]); |
110 NSAccessibilityRoleAttribute], | 113 dict->SetString(SysNSStringToUTF8(NSAccessibilityRoleAttribute), role); |
111 "")); | 114 |
112 Add(false, | 115 NSString* subrole = |
113 Format("subrole=", [cocoa_node accessibilityAttributeValue: | 116 [cocoa_node accessibilityAttributeValue:NSAccessibilitySubroleAttribute]; |
114 NSAccessibilitySubroleAttribute], | 117 if (subrole != nil) { |
115 "")); | 118 dict->SetString(SysNSStringToUTF8(NSAccessibilitySubroleAttribute), |
116 for (NSString* requestedAttribute in requestedAttributes) { | 119 SysNSStringToUTF8(subrole)); |
| 120 } |
| 121 |
| 122 CR_DEFINE_STATIC_LOCAL(NSArray*, all_attributes, (BuildAllAttributesArray())); |
| 123 for (NSString* requestedAttribute in all_attributes) { |
117 if (![supportedAttributes containsObject:requestedAttribute]) { | 124 if (![supportedAttributes containsObject:requestedAttribute]) { |
118 continue; | 125 continue; |
119 } | 126 } |
120 NSString* methodName = | 127 id value = [cocoa_node accessibilityAttributeValue:requestedAttribute]; |
121 [cocoa_node methodNameForAttribute:requestedAttribute]; | 128 if (value != nil) { |
122 Add([defaultAttributes containsObject:requestedAttribute], | 129 dict->SetString( |
123 Format([[NSString stringWithFormat:@"%@='", methodName] | 130 SysNSStringToUTF8(requestedAttribute), |
124 cStringUsingEncoding:NSUTF8StringEncoding], | 131 SysNSStringToUTF16([NSString stringWithFormat:@"%@", value])); |
125 [cocoa_node accessibilityAttributeValue: | 132 } |
126 requestedAttribute], | |
127 "'")); | |
128 } | 133 } |
129 Add(false, FormatPosition(node)); | 134 dict->Set(kPositionDictAttr, PopulatePosition(node).release()); |
130 Add(false, FormatSize(node)); | 135 dict->Set(kSizeDictAttr, PopulateSize(cocoa_node).release()); |
| 136 } |
131 | 137 |
132 return ASCIIToUTF16(prefix) + FinishLine() + ASCIIToUTF16("\n"); | 138 string16 AccessibilityTreeFormatter::ToString(const DictionaryValue& dict, |
| 139 const string16& indent) { |
| 140 string16 line; |
| 141 NSArray* defaultAttributes = |
| 142 [NSArray arrayWithObjects:NSAccessibilityTitleAttribute, |
| 143 NSAccessibilityValueAttribute, |
| 144 nil]; |
| 145 string s_value; |
| 146 dict.GetString(SysNSStringToUTF8(NSAccessibilityRoleAttribute), &s_value); |
| 147 WriteAttribute(true, UTF8ToUTF16(s_value), &line); |
| 148 |
| 149 string subroleAttribute = SysNSStringToUTF8(NSAccessibilitySubroleAttribute); |
| 150 if (dict.GetString(subroleAttribute, &s_value)) { |
| 151 WriteAttribute(false, |
| 152 StringPrintf("%s=%s", |
| 153 subroleAttribute.c_str(), s_value.c_str()), |
| 154 &line); |
| 155 } |
| 156 |
| 157 CR_DEFINE_STATIC_LOCAL(NSArray*, all_attributes, (BuildAllAttributesArray())); |
| 158 for (NSString* requestedAttribute in all_attributes) { |
| 159 string requestedAttributeUTF8 = SysNSStringToUTF8(requestedAttribute); |
| 160 if (!dict.GetString(requestedAttributeUTF8, &s_value)) |
| 161 continue; |
| 162 WriteAttribute([defaultAttributes containsObject:requestedAttribute], |
| 163 StringPrintf("%s='%s'", |
| 164 requestedAttributeUTF8.c_str(), |
| 165 s_value.c_str()), |
| 166 &line); |
| 167 } |
| 168 const DictionaryValue* d_value = NULL; |
| 169 if (dict.GetDictionary(kPositionDictAttr, &d_value)) { |
| 170 WriteAttribute(false, |
| 171 FormatCoordinates(kPositionDictAttr, |
| 172 kXCoordDictAttr, kYCoordDictAttr, |
| 173 *d_value), |
| 174 &line); |
| 175 } |
| 176 if (dict.GetDictionary(kSizeDictAttr, &d_value)) { |
| 177 WriteAttribute(false, |
| 178 FormatCoordinates(kSizeDictAttr, |
| 179 kWidthDictAttr, kHeightDictAttr, *d_value), |
| 180 &line); |
| 181 } |
| 182 |
| 183 return indent + line + ASCIIToUTF16("\n"); |
133 } | 184 } |
134 | 185 |
135 // static | 186 // static |
136 const base::FilePath::StringType | 187 const base::FilePath::StringType |
137 AccessibilityTreeFormatter::GetActualFileSuffix() { | 188 AccessibilityTreeFormatter::GetActualFileSuffix() { |
138 return FILE_PATH_LITERAL("-actual-mac.txt"); | 189 return FILE_PATH_LITERAL("-actual-mac.txt"); |
139 } | 190 } |
140 | 191 |
141 // static | 192 // static |
142 const base::FilePath::StringType | 193 const base::FilePath::StringType |
143 AccessibilityTreeFormatter::GetExpectedFileSuffix() { | 194 AccessibilityTreeFormatter::GetExpectedFileSuffix() { |
144 return FILE_PATH_LITERAL("-expected-mac.txt"); | 195 return FILE_PATH_LITERAL("-expected-mac.txt"); |
145 } | 196 } |
146 | 197 |
147 // static | 198 // static |
148 const std::string AccessibilityTreeFormatter::GetAllowEmptyString() { | 199 const string AccessibilityTreeFormatter::GetAllowEmptyString() { |
149 return "@MAC-ALLOW-EMPTY:"; | 200 return "@MAC-ALLOW-EMPTY:"; |
150 } | 201 } |
151 | 202 |
152 // static | 203 // static |
153 const std::string AccessibilityTreeFormatter::GetAllowString() { | 204 const string AccessibilityTreeFormatter::GetAllowString() { |
154 return "@MAC-ALLOW:"; | 205 return "@MAC-ALLOW:"; |
155 } | 206 } |
156 | 207 |
157 // static | 208 // static |
158 const std::string AccessibilityTreeFormatter::GetDenyString() { | 209 const string AccessibilityTreeFormatter::GetDenyString() { |
159 return "@MAC-DENY:"; | 210 return "@MAC-DENY:"; |
160 } | 211 } |
161 | 212 |
162 } // namespace content | 213 } // namespace content |
OLD | NEW |