OLD | NEW |
| (Empty) |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "content/shell/renderer/test_runner/web_ax_object_proxy.h" | |
6 | |
7 #include "base/strings/stringprintf.h" | |
8 #include "gin/handle.h" | |
9 #include "third_party/WebKit/public/platform/WebPoint.h" | |
10 #include "third_party/WebKit/public/platform/WebRect.h" | |
11 #include "third_party/WebKit/public/platform/WebString.h" | |
12 #include "third_party/WebKit/public/web/WebFrame.h" | |
13 #include "third_party/WebKit/public/web/WebKit.h" | |
14 | |
15 namespace content { | |
16 | |
17 namespace { | |
18 | |
19 // Map role value to string, matching Safari/Mac platform implementation to | |
20 // avoid rebaselining layout tests. | |
21 std::string RoleToString(blink::WebAXRole role) | |
22 { | |
23 std::string result = "AXRole: AX"; | |
24 switch (role) { | |
25 case blink::WebAXRoleAlertDialog: | |
26 return result.append("AlertDialog"); | |
27 case blink::WebAXRoleAlert: | |
28 return result.append("Alert"); | |
29 case blink::WebAXRoleAnnotation: | |
30 return result.append("Annotation"); | |
31 case blink::WebAXRoleApplication: | |
32 return result.append("Application"); | |
33 case blink::WebAXRoleArticle: | |
34 return result.append("Article"); | |
35 case blink::WebAXRoleBanner: | |
36 return result.append("Banner"); | |
37 case blink::WebAXRoleBlockquote: | |
38 return result.append("Blockquote"); | |
39 case blink::WebAXRoleBusyIndicator: | |
40 return result.append("BusyIndicator"); | |
41 case blink::WebAXRoleButton: | |
42 return result.append("Button"); | |
43 case blink::WebAXRoleCanvas: | |
44 return result.append("Canvas"); | |
45 case blink::WebAXRoleCaption: | |
46 return result.append("Caption"); | |
47 case blink::WebAXRoleCell: | |
48 return result.append("Cell"); | |
49 case blink::WebAXRoleCheckBox: | |
50 return result.append("CheckBox"); | |
51 case blink::WebAXRoleColorWell: | |
52 return result.append("ColorWell"); | |
53 case blink::WebAXRoleColumnHeader: | |
54 return result.append("ColumnHeader"); | |
55 case blink::WebAXRoleColumn: | |
56 return result.append("Column"); | |
57 case blink::WebAXRoleComboBox: | |
58 return result.append("ComboBox"); | |
59 case blink::WebAXRoleComplementary: | |
60 return result.append("Complementary"); | |
61 case blink::WebAXRoleContentInfo: | |
62 return result.append("ContentInfo"); | |
63 case blink::WebAXRoleDate: | |
64 return result.append("DateField"); | |
65 case blink::WebAXRoleDateTime: | |
66 return result.append("DateTimeField"); | |
67 case blink::WebAXRoleDefinition: | |
68 return result.append("Definition"); | |
69 case blink::WebAXRoleDescriptionListDetail: | |
70 return result.append("DescriptionListDetail"); | |
71 case blink::WebAXRoleDescriptionList: | |
72 return result.append("DescriptionList"); | |
73 case blink::WebAXRoleDescriptionListTerm: | |
74 return result.append("DescriptionListTerm"); | |
75 case blink::WebAXRoleDetails: | |
76 return result.append("Details"); | |
77 case blink::WebAXRoleDialog: | |
78 return result.append("Dialog"); | |
79 case blink::WebAXRoleDirectory: | |
80 return result.append("Directory"); | |
81 case blink::WebAXRoleDisclosureTriangle: | |
82 return result.append("DisclosureTriangle"); | |
83 case blink::WebAXRoleDiv: | |
84 return result.append("Div"); | |
85 case blink::WebAXRoleDocument: | |
86 return result.append("Document"); | |
87 case blink::WebAXRoleEmbeddedObject: | |
88 return result.append("EmbeddedObject"); | |
89 case blink::WebAXRoleFigcaption: | |
90 return result.append("Figcaption"); | |
91 case blink::WebAXRoleFigure: | |
92 return result.append("Figure"); | |
93 case blink::WebAXRoleFooter: | |
94 return result.append("Footer"); | |
95 case blink::WebAXRoleForm: | |
96 return result.append("Form"); | |
97 case blink::WebAXRoleGrid: | |
98 return result.append("Grid"); | |
99 case blink::WebAXRoleGroup: | |
100 return result.append("Group"); | |
101 case blink::WebAXRoleHeading: | |
102 return result.append("Heading"); | |
103 case blink::WebAXRoleIgnored: | |
104 return result.append("Ignored"); | |
105 case blink::WebAXRoleImageMapLink: | |
106 return result.append("ImageMapLink"); | |
107 case blink::WebAXRoleImageMap: | |
108 return result.append("ImageMap"); | |
109 case blink::WebAXRoleImage: | |
110 return result.append("Image"); | |
111 case blink::WebAXRoleInlineTextBox: | |
112 return result.append("InlineTextBox"); | |
113 case blink::WebAXRoleInputTime: | |
114 return result.append("InputTime"); | |
115 case blink::WebAXRoleLabel: | |
116 return result.append("Label"); | |
117 case blink::WebAXRoleLegend: | |
118 return result.append("Legend"); | |
119 case blink::WebAXRoleLink: | |
120 return result.append("Link"); | |
121 case blink::WebAXRoleListBoxOption: | |
122 return result.append("ListBoxOption"); | |
123 case blink::WebAXRoleListBox: | |
124 return result.append("ListBox"); | |
125 case blink::WebAXRoleListItem: | |
126 return result.append("ListItem"); | |
127 case blink::WebAXRoleListMarker: | |
128 return result.append("ListMarker"); | |
129 case blink::WebAXRoleList: | |
130 return result.append("List"); | |
131 case blink::WebAXRoleLog: | |
132 return result.append("Log"); | |
133 case blink::WebAXRoleMain: | |
134 return result.append("Main"); | |
135 case blink::WebAXRoleMarquee: | |
136 return result.append("Marquee"); | |
137 case blink::WebAXRoleMath: | |
138 return result.append("Math"); | |
139 case blink::WebAXRoleMenuBar: | |
140 return result.append("MenuBar"); | |
141 case blink::WebAXRoleMenuButton: | |
142 return result.append("MenuButton"); | |
143 case blink::WebAXRoleMenuItem: | |
144 return result.append("MenuItem"); | |
145 case blink::WebAXRoleMenuItemCheckBox: | |
146 return result.append("MenuItemCheckBox"); | |
147 case blink::WebAXRoleMenuItemRadio: | |
148 return result.append("MenuItemRadio"); | |
149 case blink::WebAXRoleMenuListOption: | |
150 return result.append("MenuListOption"); | |
151 case blink::WebAXRoleMenuListPopup: | |
152 return result.append("MenuListPopup"); | |
153 case blink::WebAXRoleMenu: | |
154 return result.append("Menu"); | |
155 case blink::WebAXRoleMeter: | |
156 return result.append("Meter"); | |
157 case blink::WebAXRoleNavigation: | |
158 return result.append("Navigation"); | |
159 case blink::WebAXRoleNone: | |
160 return result.append("None"); | |
161 case blink::WebAXRoleNote: | |
162 return result.append("Note"); | |
163 case blink::WebAXRoleOutline: | |
164 return result.append("Outline"); | |
165 case blink::WebAXRoleParagraph: | |
166 return result.append("Paragraph"); | |
167 case blink::WebAXRolePopUpButton: | |
168 return result.append("PopUpButton"); | |
169 case blink::WebAXRolePre: | |
170 return result.append("Pre"); | |
171 case blink::WebAXRolePresentational: | |
172 return result.append("Presentational"); | |
173 case blink::WebAXRoleProgressIndicator: | |
174 return result.append("ProgressIndicator"); | |
175 case blink::WebAXRoleRadioButton: | |
176 return result.append("RadioButton"); | |
177 case blink::WebAXRoleRadioGroup: | |
178 return result.append("RadioGroup"); | |
179 case blink::WebAXRoleRegion: | |
180 return result.append("Region"); | |
181 case blink::WebAXRoleRootWebArea: | |
182 return result.append("RootWebArea"); | |
183 case blink::WebAXRoleRowHeader: | |
184 return result.append("RowHeader"); | |
185 case blink::WebAXRoleRow: | |
186 return result.append("Row"); | |
187 case blink::WebAXRoleRuby: | |
188 return result.append("Ruby"); | |
189 case blink::WebAXRoleRuler: | |
190 return result.append("Ruler"); | |
191 case blink::WebAXRoleSVGRoot: | |
192 return result.append("SVGRoot"); | |
193 case blink::WebAXRoleScrollArea: | |
194 return result.append("ScrollArea"); | |
195 case blink::WebAXRoleScrollBar: | |
196 return result.append("ScrollBar"); | |
197 case blink::WebAXRoleSeamlessWebArea: | |
198 return result.append("SeamlessWebArea"); | |
199 case blink::WebAXRoleSearch: | |
200 return result.append("Search"); | |
201 case blink::WebAXRoleSearchBox: | |
202 return result.append("SearchBox"); | |
203 case blink::WebAXRoleSlider: | |
204 return result.append("Slider"); | |
205 case blink::WebAXRoleSliderThumb: | |
206 return result.append("SliderThumb"); | |
207 case blink::WebAXRoleSpinButtonPart: | |
208 return result.append("SpinButtonPart"); | |
209 case blink::WebAXRoleSpinButton: | |
210 return result.append("SpinButton"); | |
211 case blink::WebAXRoleSplitter: | |
212 return result.append("Splitter"); | |
213 case blink::WebAXRoleStaticText: | |
214 return result.append("StaticText"); | |
215 case blink::WebAXRoleStatus: | |
216 return result.append("Status"); | |
217 case blink::WebAXRoleSwitch: | |
218 return result.append("Switch"); | |
219 case blink::WebAXRoleTabGroup: | |
220 return result.append("TabGroup"); | |
221 case blink::WebAXRoleTabList: | |
222 return result.append("TabList"); | |
223 case blink::WebAXRoleTabPanel: | |
224 return result.append("TabPanel"); | |
225 case blink::WebAXRoleTab: | |
226 return result.append("Tab"); | |
227 case blink::WebAXRoleTableHeaderContainer: | |
228 return result.append("TableHeaderContainer"); | |
229 case blink::WebAXRoleTable: | |
230 return result.append("Table"); | |
231 case blink::WebAXRoleTextField: | |
232 return result.append("TextField"); | |
233 case blink::WebAXRoleTime: | |
234 return result.append("Time"); | |
235 case blink::WebAXRoleTimer: | |
236 return result.append("Timer"); | |
237 case blink::WebAXRoleToggleButton: | |
238 return result.append("ToggleButton"); | |
239 case blink::WebAXRoleToolbar: | |
240 return result.append("Toolbar"); | |
241 case blink::WebAXRoleTreeGrid: | |
242 return result.append("TreeGrid"); | |
243 case blink::WebAXRoleTreeItem: | |
244 return result.append("TreeItem"); | |
245 case blink::WebAXRoleTree: | |
246 return result.append("Tree"); | |
247 case blink::WebAXRoleUnknown: | |
248 return result.append("Unknown"); | |
249 case blink::WebAXRoleUserInterfaceTooltip: | |
250 return result.append("UserInterfaceTooltip"); | |
251 case blink::WebAXRoleWebArea: | |
252 return result.append("WebArea"); | |
253 case blink::WebAXRoleWindow: | |
254 return result.append("Window"); | |
255 default: | |
256 return result.append("Unknown"); | |
257 } | |
258 } | |
259 | |
260 std::string DeprecatedGetDescription(const blink::WebAXObject& object) { | |
261 std::string description = object.deprecatedAccessibilityDescription().utf8(); | |
262 return description.insert(0, "AXDescription: "); | |
263 } | |
264 | |
265 std::string DeprecatedGetHelpText(const blink::WebAXObject& object) { | |
266 std::string help_text = object.deprecatedHelpText().utf8(); | |
267 return help_text.insert(0, "AXHelp: "); | |
268 } | |
269 | |
270 std::string GetStringValue(const blink::WebAXObject& object) { | |
271 std::string value; | |
272 if (object.role() == blink::WebAXRoleColorWell) { | |
273 unsigned int color = object.colorValue(); | |
274 unsigned int red = (color >> 16) & 0xFF; | |
275 unsigned int green = (color >> 8) & 0xFF; | |
276 unsigned int blue = color & 0xFF; | |
277 value = base::StringPrintf("rgba(%d, %d, %d, 1)", | |
278 red, green, blue); | |
279 } else { | |
280 value = object.stringValue().utf8(); | |
281 } | |
282 return value.insert(0, "AXValue: "); | |
283 } | |
284 | |
285 std::string GetRole(const blink::WebAXObject& object) { | |
286 std::string role_string = RoleToString(object.role()); | |
287 | |
288 // Special-case canvas with fallback content because Chromium wants to treat | |
289 // this as essentially a separate role that it can map differently depending | |
290 // on the platform. | |
291 if (object.role() == blink::WebAXRoleCanvas && | |
292 object.canvasHasFallbackContent()) { | |
293 role_string += "WithFallbackContent"; | |
294 } | |
295 | |
296 return role_string; | |
297 } | |
298 | |
299 std::string DeprecatedGetTitle(const blink::WebAXObject& object) { | |
300 std::string title = object.deprecatedTitle().utf8(); | |
301 return title.insert(0, "AXTitle: "); | |
302 } | |
303 | |
304 std::string GetValueDescription(const blink::WebAXObject& object) { | |
305 std::string value_description = object.valueDescription().utf8(); | |
306 return value_description.insert(0, "AXValueDescription: "); | |
307 } | |
308 | |
309 std::string GetLanguage(const blink::WebAXObject& object) { | |
310 std::string language = object.language().utf8(); | |
311 return language.insert(0, "AXLanguage: "); | |
312 } | |
313 | |
314 std::string GetAttributes(const blink::WebAXObject& object) { | |
315 // FIXME: Concatenate all attributes of the AXObject. | |
316 std::string attributes(DeprecatedGetTitle(object)); | |
317 attributes.append("\n"); | |
318 attributes.append(GetRole(object)); | |
319 attributes.append("\n"); | |
320 attributes.append(DeprecatedGetDescription(object)); | |
321 return attributes; | |
322 } | |
323 | |
324 blink::WebRect BoundsForCharacter(const blink::WebAXObject& object, | |
325 int characterIndex) { | |
326 DCHECK_EQ(object.role(), blink::WebAXRoleStaticText); | |
327 int end = 0; | |
328 for (unsigned i = 0; i < object.childCount(); i++) { | |
329 blink::WebAXObject inline_text_box = object.childAt(i); | |
330 DCHECK_EQ(inline_text_box.role(), blink::WebAXRoleInlineTextBox); | |
331 int start = end; | |
332 end += inline_text_box.stringValue().length(); | |
333 if (characterIndex < start || characterIndex >= end) | |
334 continue; | |
335 blink::WebRect inline_text_box_rect = inline_text_box.boundingBoxRect(); | |
336 int localIndex = characterIndex - start; | |
337 blink::WebVector<int> character_offsets; | |
338 inline_text_box.characterOffsets(character_offsets); | |
339 DCHECK(character_offsets.size() > 0 && | |
340 character_offsets.size() == inline_text_box.stringValue().length()); | |
341 switch (inline_text_box.textDirection()) { | |
342 case blink::WebAXTextDirectionLR: { | |
343 if (localIndex) { | |
344 int left = inline_text_box_rect.x + character_offsets[localIndex - 1]; | |
345 int width = character_offsets[localIndex] - | |
346 character_offsets[localIndex - 1]; | |
347 return blink::WebRect(left, inline_text_box_rect.y, | |
348 width, inline_text_box_rect.height); | |
349 } | |
350 return blink::WebRect( | |
351 inline_text_box_rect.x, inline_text_box_rect.y, | |
352 character_offsets[0], inline_text_box_rect.height); | |
353 } | |
354 case blink::WebAXTextDirectionRL: { | |
355 int right = inline_text_box_rect.x + inline_text_box_rect.width; | |
356 | |
357 if (localIndex) { | |
358 int left = right - character_offsets[localIndex]; | |
359 int width = character_offsets[localIndex] - | |
360 character_offsets[localIndex - 1]; | |
361 return blink::WebRect(left, inline_text_box_rect.y, | |
362 width, inline_text_box_rect.height); | |
363 } | |
364 int left = right - character_offsets[0]; | |
365 return blink::WebRect( | |
366 left, inline_text_box_rect.y, | |
367 character_offsets[0], inline_text_box_rect.height); | |
368 } | |
369 case blink::WebAXTextDirectionTB: { | |
370 if (localIndex) { | |
371 int top = inline_text_box_rect.y + character_offsets[localIndex - 1]; | |
372 int height = character_offsets[localIndex] - | |
373 character_offsets[localIndex - 1]; | |
374 return blink::WebRect(inline_text_box_rect.x, top, | |
375 inline_text_box_rect.width, height); | |
376 } | |
377 return blink::WebRect(inline_text_box_rect.x, inline_text_box_rect.y, | |
378 inline_text_box_rect.width, character_offsets[0]); | |
379 } | |
380 case blink::WebAXTextDirectionBT: { | |
381 int bottom = inline_text_box_rect.y + inline_text_box_rect.height; | |
382 | |
383 if (localIndex) { | |
384 int top = bottom - character_offsets[localIndex]; | |
385 int height = character_offsets[localIndex] - | |
386 character_offsets[localIndex - 1]; | |
387 return blink::WebRect(inline_text_box_rect.x, top, | |
388 inline_text_box_rect.width, height); | |
389 } | |
390 int top = bottom - character_offsets[0]; | |
391 return blink::WebRect(inline_text_box_rect.x, top, | |
392 inline_text_box_rect.width, character_offsets[0]); | |
393 } | |
394 } | |
395 } | |
396 | |
397 DCHECK(false); | |
398 return blink::WebRect(); | |
399 } | |
400 | |
401 void GetBoundariesForOneWord(const blink::WebAXObject& object, | |
402 int character_index, | |
403 int& word_start, | |
404 int& word_end) { | |
405 int end = 0; | |
406 for (unsigned i = 0; i < object.childCount(); i++) { | |
407 blink::WebAXObject inline_text_box = object.childAt(i); | |
408 DCHECK_EQ(inline_text_box.role(), blink::WebAXRoleInlineTextBox); | |
409 int start = end; | |
410 end += inline_text_box.stringValue().length(); | |
411 if (end <= character_index) | |
412 continue; | |
413 int localIndex = character_index - start; | |
414 | |
415 blink::WebVector<int> starts; | |
416 blink::WebVector<int> ends; | |
417 inline_text_box.wordBoundaries(starts, ends); | |
418 size_t word_count = starts.size(); | |
419 DCHECK_EQ(ends.size(), word_count); | |
420 | |
421 // If there are no words, use the InlineTextBox boundaries. | |
422 if (!word_count) { | |
423 word_start = start; | |
424 word_end = end; | |
425 return; | |
426 } | |
427 | |
428 // Look for a character within any word other than the last. | |
429 for (size_t j = 0; j < word_count - 1; j++) { | |
430 if (localIndex <= ends[j]) { | |
431 word_start = start + starts[j]; | |
432 word_end = start + ends[j]; | |
433 return; | |
434 } | |
435 } | |
436 | |
437 // Return the last word by default. | |
438 word_start = start + starts[word_count - 1]; | |
439 word_end = start + ends[word_count - 1]; | |
440 return; | |
441 } | |
442 } | |
443 | |
444 // Collects attributes into a string, delimited by dashes. Used by all methods | |
445 // that output lists of attributes: attributesOfLinkedUIElementsCallback, | |
446 // AttributesOfChildrenCallback, etc. | |
447 class AttributesCollector { | |
448 public: | |
449 AttributesCollector() {} | |
450 ~AttributesCollector() {} | |
451 | |
452 void CollectAttributes(const blink::WebAXObject& object) { | |
453 attributes_.append("\n------------\n"); | |
454 attributes_.append(GetAttributes(object)); | |
455 } | |
456 | |
457 std::string attributes() const { return attributes_; } | |
458 | |
459 private: | |
460 std::string attributes_; | |
461 | |
462 DISALLOW_COPY_AND_ASSIGN(AttributesCollector); | |
463 }; | |
464 | |
465 } // namespace | |
466 | |
467 gin::WrapperInfo WebAXObjectProxy::kWrapperInfo = { | |
468 gin::kEmbedderNativeGin}; | |
469 | |
470 WebAXObjectProxy::WebAXObjectProxy(const blink::WebAXObject& object, | |
471 WebAXObjectProxy::Factory* factory) | |
472 : accessibility_object_(object), | |
473 factory_(factory) { | |
474 } | |
475 | |
476 WebAXObjectProxy::~WebAXObjectProxy() {} | |
477 | |
478 gin::ObjectTemplateBuilder | |
479 WebAXObjectProxy::GetObjectTemplateBuilder(v8::Isolate* isolate) { | |
480 return gin::Wrappable<WebAXObjectProxy>::GetObjectTemplateBuilder(isolate) | |
481 .SetProperty("role", &WebAXObjectProxy::Role) | |
482 .SetProperty("stringValue", &WebAXObjectProxy::StringValue) | |
483 .SetProperty("language", &WebAXObjectProxy::Language) | |
484 .SetProperty("x", &WebAXObjectProxy::X) | |
485 .SetProperty("y", &WebAXObjectProxy::Y) | |
486 .SetProperty("width", &WebAXObjectProxy::Width) | |
487 .SetProperty("height", &WebAXObjectProxy::Height) | |
488 .SetProperty("intValue", &WebAXObjectProxy::IntValue) | |
489 .SetProperty("minValue", &WebAXObjectProxy::MinValue) | |
490 .SetProperty("maxValue", &WebAXObjectProxy::MaxValue) | |
491 .SetProperty("valueDescription", &WebAXObjectProxy::ValueDescription) | |
492 .SetProperty("childrenCount", &WebAXObjectProxy::ChildrenCount) | |
493 .SetProperty("selectionStart", &WebAXObjectProxy::SelectionStart) | |
494 .SetProperty("selectionEnd", &WebAXObjectProxy::SelectionEnd) | |
495 .SetProperty("selectionStartLineNumber", | |
496 &WebAXObjectProxy::SelectionStartLineNumber) | |
497 .SetProperty("selectionEndLineNumber", | |
498 &WebAXObjectProxy::SelectionEndLineNumber) | |
499 .SetProperty("isEnabled", &WebAXObjectProxy::IsEnabled) | |
500 .SetProperty("isRequired", &WebAXObjectProxy::IsRequired) | |
501 .SetProperty("isFocused", &WebAXObjectProxy::IsFocused) | |
502 .SetProperty("isFocusable", &WebAXObjectProxy::IsFocusable) | |
503 .SetProperty("isSelected", &WebAXObjectProxy::IsSelected) | |
504 .SetProperty("isSelectable", &WebAXObjectProxy::IsSelectable) | |
505 .SetProperty("isMultiSelectable", &WebAXObjectProxy::IsMultiSelectable) | |
506 .SetProperty("isSelectedOptionActive", | |
507 &WebAXObjectProxy::IsSelectedOptionActive) | |
508 .SetProperty("isExpanded", &WebAXObjectProxy::IsExpanded) | |
509 .SetProperty("isChecked", &WebAXObjectProxy::IsChecked) | |
510 .SetProperty("isVisible", &WebAXObjectProxy::IsVisible) | |
511 .SetProperty("isOffScreen", &WebAXObjectProxy::IsOffScreen) | |
512 .SetProperty("isCollapsed", &WebAXObjectProxy::IsCollapsed) | |
513 .SetProperty("hasPopup", &WebAXObjectProxy::HasPopup) | |
514 .SetProperty("isValid", &WebAXObjectProxy::IsValid) | |
515 .SetProperty("isReadOnly", &WebAXObjectProxy::IsReadOnly) | |
516 .SetProperty("backgroundColor", &WebAXObjectProxy::BackgroundColor) | |
517 .SetProperty("color", &WebAXObjectProxy::Color) | |
518 .SetProperty("colorValue", &WebAXObjectProxy::ColorValue) | |
519 .SetProperty("fontSize", &WebAXObjectProxy::FontSize) | |
520 .SetProperty("orientation", &WebAXObjectProxy::Orientation) | |
521 .SetProperty("posInSet", &WebAXObjectProxy::PosInSet) | |
522 .SetProperty("setSize", &WebAXObjectProxy::SetSize) | |
523 .SetProperty("clickPointX", &WebAXObjectProxy::ClickPointX) | |
524 .SetProperty("clickPointY", &WebAXObjectProxy::ClickPointY) | |
525 .SetProperty("rowCount", &WebAXObjectProxy::RowCount) | |
526 .SetProperty("rowHeadersCount", &WebAXObjectProxy::RowHeadersCount) | |
527 .SetProperty("columnCount", &WebAXObjectProxy::ColumnCount) | |
528 .SetProperty("columnHeadersCount", &WebAXObjectProxy::ColumnHeadersCount) | |
529 .SetProperty("isClickable", &WebAXObjectProxy::IsClickable) | |
530 .SetProperty("isButtonStateMixed", &WebAXObjectProxy::IsButtonStateMixed) | |
531 .SetMethod("allAttributes", &WebAXObjectProxy::AllAttributes) | |
532 .SetMethod("attributesOfChildren", | |
533 &WebAXObjectProxy::AttributesOfChildren) | |
534 .SetMethod("ariaControlsElementAtIndex", | |
535 &WebAXObjectProxy::AriaControlsElementAtIndex) | |
536 .SetMethod("ariaFlowToElementAtIndex", | |
537 &WebAXObjectProxy::AriaFlowToElementAtIndex) | |
538 .SetMethod("ariaOwnsElementAtIndex", | |
539 &WebAXObjectProxy::AriaOwnsElementAtIndex) | |
540 .SetMethod("lineForIndex", &WebAXObjectProxy::LineForIndex) | |
541 .SetMethod("boundsForRange", &WebAXObjectProxy::BoundsForRange) | |
542 .SetMethod("childAtIndex", &WebAXObjectProxy::ChildAtIndex) | |
543 .SetMethod("elementAtPoint", &WebAXObjectProxy::ElementAtPoint) | |
544 .SetMethod("tableHeader", &WebAXObjectProxy::TableHeader) | |
545 .SetMethod("rowHeaderAtIndex", &WebAXObjectProxy::RowHeaderAtIndex) | |
546 .SetMethod("columnHeaderAtIndex", &WebAXObjectProxy::ColumnHeaderAtIndex) | |
547 .SetMethod("rowIndexRange", &WebAXObjectProxy::RowIndexRange) | |
548 .SetMethod("columnIndexRange", &WebAXObjectProxy::ColumnIndexRange) | |
549 .SetMethod("cellForColumnAndRow", &WebAXObjectProxy::CellForColumnAndRow) | |
550 .SetMethod("setSelectedTextRange", | |
551 &WebAXObjectProxy::SetSelectedTextRange) | |
552 .SetMethod("isAttributeSettable", &WebAXObjectProxy::IsAttributeSettable) | |
553 .SetMethod("isPressActionSupported", | |
554 &WebAXObjectProxy::IsPressActionSupported) | |
555 .SetMethod("isIncrementActionSupported", | |
556 &WebAXObjectProxy::IsIncrementActionSupported) | |
557 .SetMethod("isDecrementActionSupported", | |
558 &WebAXObjectProxy::IsDecrementActionSupported) | |
559 .SetMethod("parentElement", &WebAXObjectProxy::ParentElement) | |
560 .SetMethod("increment", &WebAXObjectProxy::Increment) | |
561 .SetMethod("decrement", &WebAXObjectProxy::Decrement) | |
562 .SetMethod("showMenu", &WebAXObjectProxy::ShowMenu) | |
563 .SetMethod("press", &WebAXObjectProxy::Press) | |
564 .SetMethod("isEqual", &WebAXObjectProxy::IsEqual) | |
565 .SetMethod("setNotificationListener", | |
566 &WebAXObjectProxy::SetNotificationListener) | |
567 .SetMethod("unsetNotificationListener", | |
568 &WebAXObjectProxy::UnsetNotificationListener) | |
569 .SetMethod("takeFocus", &WebAXObjectProxy::TakeFocus) | |
570 .SetMethod("scrollToMakeVisible", &WebAXObjectProxy::ScrollToMakeVisible) | |
571 .SetMethod("scrollToMakeVisibleWithSubFocus", | |
572 &WebAXObjectProxy::ScrollToMakeVisibleWithSubFocus) | |
573 .SetMethod("scrollToGlobalPoint", &WebAXObjectProxy::ScrollToGlobalPoint) | |
574 .SetMethod("wordStart", &WebAXObjectProxy::WordStart) | |
575 .SetMethod("wordEnd", &WebAXObjectProxy::WordEnd) | |
576 .SetMethod("nextOnLine", &WebAXObjectProxy::NextOnLine) | |
577 .SetMethod("previousOnLine", &WebAXObjectProxy::PreviousOnLine) | |
578 // TODO(hajimehoshi): This is for backward compatibility. Remove them. | |
579 .SetMethod("addNotificationListener", | |
580 &WebAXObjectProxy::SetNotificationListener) | |
581 .SetMethod("removeNotificationListener", | |
582 &WebAXObjectProxy::UnsetNotificationListener) | |
583 // | |
584 // DEPRECATED accessible name and description accessors | |
585 // | |
586 .SetProperty("title", &WebAXObjectProxy::DeprecatedTitle) | |
587 .SetProperty("description", &WebAXObjectProxy::DeprecatedDescription) | |
588 .SetProperty("helpText", &WebAXObjectProxy::DeprecatedHelpText) | |
589 .SetMethod("titleUIElement", &WebAXObjectProxy::DeprecatedTitleUIElement) | |
590 .SetProperty("deprecatedTitle", | |
591 &WebAXObjectProxy::DeprecatedTitle) | |
592 .SetProperty("deprecatedDescription", | |
593 &WebAXObjectProxy::DeprecatedDescription) | |
594 .SetProperty("deprecatedHelpText", | |
595 &WebAXObjectProxy::DeprecatedHelpText) | |
596 .SetMethod("deprecatedTitleUIElement", | |
597 &WebAXObjectProxy::DeprecatedTitleUIElement) | |
598 // | |
599 // NEW accessible name and description accessors | |
600 // | |
601 .SetProperty("name", &WebAXObjectProxy::Name) | |
602 .SetProperty("nameFrom", &WebAXObjectProxy::NameFrom) | |
603 .SetMethod("nameElementCount", &WebAXObjectProxy::NameElementCount) | |
604 .SetMethod("nameElementAtIndex", &WebAXObjectProxy::NameElementAtIndex); | |
605 // TODO(dmazzoni): add "description", etc. once LayoutTests have | |
606 // been updated to call deprecatedDescription instead. | |
607 | |
608 } | |
609 | |
610 v8::Local<v8::Object> WebAXObjectProxy::GetChildAtIndex(unsigned index) { | |
611 return factory_->GetOrCreate(accessibility_object_.childAt(index)); | |
612 } | |
613 | |
614 bool WebAXObjectProxy::IsRoot() const { | |
615 return false; | |
616 } | |
617 | |
618 bool WebAXObjectProxy::IsEqualToObject(const blink::WebAXObject& other) { | |
619 return accessibility_object_.equals(other); | |
620 } | |
621 | |
622 void WebAXObjectProxy::NotificationReceived( | |
623 blink::WebFrame* frame, | |
624 const std::string& notification_name) { | |
625 if (notification_callback_.IsEmpty()) | |
626 return; | |
627 | |
628 v8::Local<v8::Context> context = frame->mainWorldScriptContext(); | |
629 if (context.IsEmpty()) | |
630 return; | |
631 | |
632 v8::Isolate* isolate = blink::mainThreadIsolate(); | |
633 | |
634 v8::Local<v8::Value> argv[] = { | |
635 v8::String::NewFromUtf8(isolate, notification_name.data(), | |
636 v8::String::kNormalString, | |
637 notification_name.size()), | |
638 }; | |
639 frame->callFunctionEvenIfScriptDisabled( | |
640 v8::Local<v8::Function>::New(isolate, notification_callback_), | |
641 context->Global(), | |
642 arraysize(argv), | |
643 argv); | |
644 } | |
645 | |
646 void WebAXObjectProxy::Reset() { | |
647 notification_callback_.Reset(); | |
648 } | |
649 | |
650 std::string WebAXObjectProxy::Role() { | |
651 accessibility_object_.updateLayoutAndCheckValidity(); | |
652 return GetRole(accessibility_object_); | |
653 } | |
654 | |
655 std::string WebAXObjectProxy::DeprecatedTitle() { | |
656 accessibility_object_.updateLayoutAndCheckValidity(); | |
657 return DeprecatedGetTitle(accessibility_object_); | |
658 } | |
659 | |
660 std::string WebAXObjectProxy::DeprecatedDescription() { | |
661 accessibility_object_.updateLayoutAndCheckValidity(); | |
662 return DeprecatedGetDescription(accessibility_object_); | |
663 } | |
664 | |
665 std::string WebAXObjectProxy::DeprecatedHelpText() { | |
666 accessibility_object_.updateLayoutAndCheckValidity(); | |
667 return DeprecatedGetHelpText(accessibility_object_); | |
668 } | |
669 | |
670 std::string WebAXObjectProxy::StringValue() { | |
671 accessibility_object_.updateLayoutAndCheckValidity(); | |
672 return GetStringValue(accessibility_object_); | |
673 } | |
674 | |
675 std::string WebAXObjectProxy::Language() { | |
676 accessibility_object_.updateLayoutAndCheckValidity(); | |
677 return GetLanguage(accessibility_object_); | |
678 } | |
679 | |
680 int WebAXObjectProxy::X() { | |
681 accessibility_object_.updateLayoutAndCheckValidity(); | |
682 return accessibility_object_.boundingBoxRect().x; | |
683 } | |
684 | |
685 int WebAXObjectProxy::Y() { | |
686 accessibility_object_.updateLayoutAndCheckValidity(); | |
687 return accessibility_object_.boundingBoxRect().y; | |
688 } | |
689 | |
690 int WebAXObjectProxy::Width() { | |
691 accessibility_object_.updateLayoutAndCheckValidity(); | |
692 return accessibility_object_.boundingBoxRect().width; | |
693 } | |
694 | |
695 int WebAXObjectProxy::Height() { | |
696 accessibility_object_.updateLayoutAndCheckValidity(); | |
697 return accessibility_object_.boundingBoxRect().height; | |
698 } | |
699 | |
700 int WebAXObjectProxy::IntValue() { | |
701 accessibility_object_.updateLayoutAndCheckValidity(); | |
702 if (accessibility_object_.supportsRangeValue()) | |
703 return accessibility_object_.valueForRange(); | |
704 else if (accessibility_object_.role() == blink::WebAXRoleHeading) | |
705 return accessibility_object_.headingLevel(); | |
706 else | |
707 return atoi(accessibility_object_.stringValue().utf8().data()); | |
708 } | |
709 | |
710 int WebAXObjectProxy::MinValue() { | |
711 accessibility_object_.updateLayoutAndCheckValidity(); | |
712 return accessibility_object_.minValueForRange(); | |
713 } | |
714 | |
715 int WebAXObjectProxy::MaxValue() { | |
716 accessibility_object_.updateLayoutAndCheckValidity(); | |
717 return accessibility_object_.maxValueForRange(); | |
718 } | |
719 | |
720 std::string WebAXObjectProxy::ValueDescription() { | |
721 accessibility_object_.updateLayoutAndCheckValidity(); | |
722 return GetValueDescription(accessibility_object_); | |
723 } | |
724 | |
725 int WebAXObjectProxy::ChildrenCount() { | |
726 accessibility_object_.updateLayoutAndCheckValidity(); | |
727 int count = 1; // Root object always has only one child, the WebView. | |
728 if (!IsRoot()) | |
729 count = accessibility_object_.childCount(); | |
730 return count; | |
731 } | |
732 | |
733 int WebAXObjectProxy::SelectionStart() { | |
734 accessibility_object_.updateLayoutAndCheckValidity(); | |
735 return accessibility_object_.selectionStart(); | |
736 } | |
737 | |
738 int WebAXObjectProxy::SelectionEnd() { | |
739 accessibility_object_.updateLayoutAndCheckValidity(); | |
740 return accessibility_object_.selectionEnd(); | |
741 } | |
742 | |
743 int WebAXObjectProxy::SelectionStartLineNumber() { | |
744 accessibility_object_.updateLayoutAndCheckValidity(); | |
745 return accessibility_object_.selectionStartLineNumber(); | |
746 } | |
747 | |
748 int WebAXObjectProxy::SelectionEndLineNumber() { | |
749 accessibility_object_.updateLayoutAndCheckValidity(); | |
750 return accessibility_object_.selectionEndLineNumber(); | |
751 } | |
752 | |
753 bool WebAXObjectProxy::IsEnabled() { | |
754 accessibility_object_.updateLayoutAndCheckValidity(); | |
755 return accessibility_object_.isEnabled(); | |
756 } | |
757 | |
758 bool WebAXObjectProxy::IsRequired() { | |
759 accessibility_object_.updateLayoutAndCheckValidity(); | |
760 return accessibility_object_.isRequired(); | |
761 } | |
762 | |
763 bool WebAXObjectProxy::IsFocused() { | |
764 accessibility_object_.updateLayoutAndCheckValidity(); | |
765 return accessibility_object_.isFocused(); | |
766 } | |
767 | |
768 bool WebAXObjectProxy::IsFocusable() { | |
769 accessibility_object_.updateLayoutAndCheckValidity(); | |
770 return accessibility_object_.canSetFocusAttribute(); | |
771 } | |
772 | |
773 bool WebAXObjectProxy::IsSelected() { | |
774 accessibility_object_.updateLayoutAndCheckValidity(); | |
775 return accessibility_object_.isSelected(); | |
776 } | |
777 | |
778 bool WebAXObjectProxy::IsSelectable() { | |
779 accessibility_object_.updateLayoutAndCheckValidity(); | |
780 return accessibility_object_.canSetSelectedAttribute(); | |
781 } | |
782 | |
783 bool WebAXObjectProxy::IsMultiSelectable() { | |
784 accessibility_object_.updateLayoutAndCheckValidity(); | |
785 return accessibility_object_.isMultiSelectable(); | |
786 } | |
787 | |
788 bool WebAXObjectProxy::IsSelectedOptionActive() { | |
789 accessibility_object_.updateLayoutAndCheckValidity(); | |
790 return accessibility_object_.isSelectedOptionActive(); | |
791 } | |
792 | |
793 bool WebAXObjectProxy::IsExpanded() { | |
794 accessibility_object_.updateLayoutAndCheckValidity(); | |
795 return accessibility_object_.isExpanded() == blink::WebAXExpandedExpanded; | |
796 } | |
797 | |
798 bool WebAXObjectProxy::IsChecked() { | |
799 accessibility_object_.updateLayoutAndCheckValidity(); | |
800 return accessibility_object_.isChecked(); | |
801 } | |
802 | |
803 bool WebAXObjectProxy::IsCollapsed() { | |
804 accessibility_object_.updateLayoutAndCheckValidity(); | |
805 return accessibility_object_.isExpanded() == blink::WebAXExpandedCollapsed; | |
806 } | |
807 | |
808 bool WebAXObjectProxy::IsVisible() { | |
809 accessibility_object_.updateLayoutAndCheckValidity(); | |
810 return accessibility_object_.isVisible(); | |
811 } | |
812 | |
813 bool WebAXObjectProxy::IsOffScreen() { | |
814 accessibility_object_.updateLayoutAndCheckValidity(); | |
815 return accessibility_object_.isOffScreen(); | |
816 } | |
817 | |
818 bool WebAXObjectProxy::HasPopup() { | |
819 accessibility_object_.updateLayoutAndCheckValidity(); | |
820 return accessibility_object_.ariaHasPopup(); | |
821 } | |
822 | |
823 bool WebAXObjectProxy::IsValid() { | |
824 accessibility_object_.updateLayoutAndCheckValidity(); | |
825 return !accessibility_object_.isDetached(); | |
826 } | |
827 | |
828 bool WebAXObjectProxy::IsReadOnly() { | |
829 accessibility_object_.updateLayoutAndCheckValidity(); | |
830 return accessibility_object_.isReadOnly(); | |
831 } | |
832 | |
833 unsigned int WebAXObjectProxy::BackgroundColor() { | |
834 accessibility_object_.updateLayoutAndCheckValidity(); | |
835 return accessibility_object_.backgroundColor(); | |
836 } | |
837 | |
838 unsigned int WebAXObjectProxy::Color() { | |
839 accessibility_object_.updateLayoutAndCheckValidity(); | |
840 unsigned int color = accessibility_object_.color(); | |
841 // Remove the alpha because it's always 1 and thus not informative. | |
842 return color & 0xFFFFFF; | |
843 } | |
844 | |
845 // For input elements of type color. | |
846 unsigned int WebAXObjectProxy::ColorValue() { | |
847 accessibility_object_.updateLayoutAndCheckValidity(); | |
848 return accessibility_object_.colorValue(); | |
849 } | |
850 | |
851 float WebAXObjectProxy::FontSize() { | |
852 accessibility_object_.updateLayoutAndCheckValidity(); | |
853 return accessibility_object_.fontSize(); | |
854 } | |
855 | |
856 std::string WebAXObjectProxy::Orientation() { | |
857 accessibility_object_.updateLayoutAndCheckValidity(); | |
858 if (accessibility_object_.orientation() == blink::WebAXOrientationVertical) | |
859 return "AXOrientation: AXVerticalOrientation"; | |
860 else if (accessibility_object_.orientation() | |
861 == blink::WebAXOrientationHorizontal) | |
862 return "AXOrientation: AXHorizontalOrientation"; | |
863 | |
864 return std::string(); | |
865 } | |
866 | |
867 int WebAXObjectProxy::PosInSet() { | |
868 accessibility_object_.updateLayoutAndCheckValidity(); | |
869 return accessibility_object_.posInSet(); | |
870 } | |
871 | |
872 int WebAXObjectProxy::SetSize() { | |
873 accessibility_object_.updateLayoutAndCheckValidity(); | |
874 return accessibility_object_.setSize(); | |
875 } | |
876 | |
877 int WebAXObjectProxy::ClickPointX() { | |
878 accessibility_object_.updateLayoutAndCheckValidity(); | |
879 return accessibility_object_.clickPoint().x; | |
880 } | |
881 | |
882 int WebAXObjectProxy::ClickPointY() { | |
883 accessibility_object_.updateLayoutAndCheckValidity(); | |
884 return accessibility_object_.clickPoint().y; | |
885 } | |
886 | |
887 int32_t WebAXObjectProxy::RowCount() { | |
888 accessibility_object_.updateLayoutAndCheckValidity(); | |
889 return static_cast<int32_t>(accessibility_object_.rowCount()); | |
890 } | |
891 | |
892 int32_t WebAXObjectProxy::RowHeadersCount() { | |
893 accessibility_object_.updateLayoutAndCheckValidity(); | |
894 blink::WebVector<blink::WebAXObject> headers; | |
895 accessibility_object_.rowHeaders(headers); | |
896 return static_cast<int32_t>(headers.size()); | |
897 } | |
898 | |
899 int32_t WebAXObjectProxy::ColumnCount() { | |
900 accessibility_object_.updateLayoutAndCheckValidity(); | |
901 return static_cast<int32_t>(accessibility_object_.columnCount()); | |
902 } | |
903 | |
904 int32_t WebAXObjectProxy::ColumnHeadersCount() | |
905 { | |
906 accessibility_object_.updateLayoutAndCheckValidity(); | |
907 blink::WebVector<blink::WebAXObject> headers; | |
908 accessibility_object_.columnHeaders(headers); | |
909 return static_cast<int32_t>(headers.size()); | |
910 } | |
911 | |
912 bool WebAXObjectProxy::IsClickable() { | |
913 accessibility_object_.updateLayoutAndCheckValidity(); | |
914 return accessibility_object_.isClickable(); | |
915 } | |
916 | |
917 bool WebAXObjectProxy::IsButtonStateMixed() { | |
918 accessibility_object_.updateLayoutAndCheckValidity(); | |
919 return accessibility_object_.isButtonStateMixed(); | |
920 } | |
921 | |
922 v8::Local<v8::Object> WebAXObjectProxy::AriaControlsElementAtIndex( | |
923 unsigned index) | |
924 { | |
925 accessibility_object_.updateLayoutAndCheckValidity(); | |
926 blink::WebVector<blink::WebAXObject> elements; | |
927 accessibility_object_.ariaControls(elements); | |
928 size_t elementCount = elements.size(); | |
929 if (index >= elementCount) | |
930 return v8::Local<v8::Object>(); | |
931 | |
932 return factory_->GetOrCreate(elements[index]); | |
933 } | |
934 | |
935 v8::Local<v8::Object> WebAXObjectProxy::AriaFlowToElementAtIndex( | |
936 unsigned index) | |
937 { | |
938 accessibility_object_.updateLayoutAndCheckValidity(); | |
939 blink::WebVector<blink::WebAXObject> elements; | |
940 accessibility_object_.ariaFlowTo(elements); | |
941 size_t elementCount = elements.size(); | |
942 if (index >= elementCount) | |
943 return v8::Local<v8::Object>(); | |
944 | |
945 return factory_->GetOrCreate(elements[index]); | |
946 } | |
947 | |
948 v8::Local<v8::Object> WebAXObjectProxy::AriaOwnsElementAtIndex(unsigned index) | |
949 { | |
950 accessibility_object_.updateLayoutAndCheckValidity(); | |
951 blink::WebVector<blink::WebAXObject> elements; | |
952 accessibility_object_.ariaOwns(elements); | |
953 size_t elementCount = elements.size(); | |
954 if (index >= elementCount) | |
955 return v8::Local<v8::Object>(); | |
956 | |
957 return factory_->GetOrCreate(elements[index]); | |
958 } | |
959 | |
960 std::string WebAXObjectProxy::AllAttributes() { | |
961 accessibility_object_.updateLayoutAndCheckValidity(); | |
962 return GetAttributes(accessibility_object_); | |
963 } | |
964 | |
965 std::string WebAXObjectProxy::AttributesOfChildren() { | |
966 accessibility_object_.updateLayoutAndCheckValidity(); | |
967 AttributesCollector collector; | |
968 unsigned size = accessibility_object_.childCount(); | |
969 for (unsigned i = 0; i < size; ++i) | |
970 collector.CollectAttributes(accessibility_object_.childAt(i)); | |
971 return collector.attributes(); | |
972 } | |
973 | |
974 int WebAXObjectProxy::LineForIndex(int index) { | |
975 accessibility_object_.updateLayoutAndCheckValidity(); | |
976 blink::WebVector<int> line_breaks; | |
977 accessibility_object_.lineBreaks(line_breaks); | |
978 int line = 0; | |
979 int vector_size = static_cast<int>(line_breaks.size()); | |
980 while (line < vector_size && line_breaks[line] <= index) | |
981 line++; | |
982 return line; | |
983 } | |
984 | |
985 std::string WebAXObjectProxy::BoundsForRange(int start, int end) { | |
986 accessibility_object_.updateLayoutAndCheckValidity(); | |
987 if (accessibility_object_.role() != blink::WebAXRoleStaticText) | |
988 return std::string(); | |
989 | |
990 if (!accessibility_object_.updateLayoutAndCheckValidity()) | |
991 return std::string(); | |
992 | |
993 int len = end - start; | |
994 | |
995 // Get the bounds for each character and union them into one large rectangle. | |
996 // This is just for testing so it doesn't need to be efficient. | |
997 blink::WebRect bounds = BoundsForCharacter(accessibility_object_, start); | |
998 for (int i = 1; i < len; i++) { | |
999 blink::WebRect next = BoundsForCharacter(accessibility_object_, start + i); | |
1000 int right = std::max(bounds.x + bounds.width, next.x + next.width); | |
1001 int bottom = std::max(bounds.y + bounds.height, next.y + next.height); | |
1002 bounds.x = std::min(bounds.x, next.x); | |
1003 bounds.y = std::min(bounds.y, next.y); | |
1004 bounds.width = right - bounds.x; | |
1005 bounds.height = bottom - bounds.y; | |
1006 } | |
1007 | |
1008 return base::StringPrintf("{x: %d, y: %d, width: %d, height: %d}", | |
1009 bounds.x, bounds.y, bounds.width, bounds.height); | |
1010 } | |
1011 | |
1012 v8::Local<v8::Object> WebAXObjectProxy::ChildAtIndex(int index) { | |
1013 accessibility_object_.updateLayoutAndCheckValidity(); | |
1014 return GetChildAtIndex(index); | |
1015 } | |
1016 | |
1017 v8::Local<v8::Object> WebAXObjectProxy::ElementAtPoint(int x, int y) { | |
1018 accessibility_object_.updateLayoutAndCheckValidity(); | |
1019 blink::WebPoint point(x, y); | |
1020 blink::WebAXObject obj = accessibility_object_.hitTest(point); | |
1021 if (obj.isNull()) | |
1022 return v8::Local<v8::Object>(); | |
1023 | |
1024 return factory_->GetOrCreate(obj); | |
1025 } | |
1026 | |
1027 v8::Local<v8::Object> WebAXObjectProxy::TableHeader() { | |
1028 accessibility_object_.updateLayoutAndCheckValidity(); | |
1029 blink::WebAXObject obj = accessibility_object_.headerContainerObject(); | |
1030 if (obj.isNull()) | |
1031 return v8::Local<v8::Object>(); | |
1032 | |
1033 return factory_->GetOrCreate(obj); | |
1034 } | |
1035 | |
1036 v8::Local<v8::Object> WebAXObjectProxy::RowHeaderAtIndex(unsigned index) { | |
1037 accessibility_object_.updateLayoutAndCheckValidity(); | |
1038 blink::WebVector<blink::WebAXObject> headers; | |
1039 accessibility_object_.rowHeaders(headers); | |
1040 size_t headerCount = headers.size(); | |
1041 if (index >= headerCount) | |
1042 return v8::Local<v8::Object>(); | |
1043 | |
1044 return factory_->GetOrCreate(headers[index]); | |
1045 } | |
1046 | |
1047 v8::Local<v8::Object> WebAXObjectProxy::ColumnHeaderAtIndex(unsigned index) { | |
1048 accessibility_object_.updateLayoutAndCheckValidity(); | |
1049 blink::WebVector<blink::WebAXObject> headers; | |
1050 accessibility_object_.columnHeaders(headers); | |
1051 size_t headerCount = headers.size(); | |
1052 if (index >= headerCount) | |
1053 return v8::Local<v8::Object>(); | |
1054 | |
1055 return factory_->GetOrCreate(headers[index]); | |
1056 } | |
1057 | |
1058 std::string WebAXObjectProxy::RowIndexRange() { | |
1059 accessibility_object_.updateLayoutAndCheckValidity(); | |
1060 unsigned row_index = accessibility_object_.cellRowIndex(); | |
1061 unsigned row_span = accessibility_object_.cellRowSpan(); | |
1062 return base::StringPrintf("{%d, %d}", row_index, row_span); | |
1063 } | |
1064 | |
1065 std::string WebAXObjectProxy::ColumnIndexRange() { | |
1066 accessibility_object_.updateLayoutAndCheckValidity(); | |
1067 unsigned column_index = accessibility_object_.cellColumnIndex(); | |
1068 unsigned column_span = accessibility_object_.cellColumnSpan(); | |
1069 return base::StringPrintf("{%d, %d}", column_index, column_span); | |
1070 } | |
1071 | |
1072 v8::Local<v8::Object> WebAXObjectProxy::CellForColumnAndRow( | |
1073 int column, int row) { | |
1074 accessibility_object_.updateLayoutAndCheckValidity(); | |
1075 blink::WebAXObject obj = | |
1076 accessibility_object_.cellForColumnAndRow(column, row); | |
1077 if (obj.isNull()) | |
1078 return v8::Local<v8::Object>(); | |
1079 | |
1080 return factory_->GetOrCreate(obj); | |
1081 } | |
1082 | |
1083 v8::Local<v8::Object> WebAXObjectProxy::DeprecatedTitleUIElement() { | |
1084 accessibility_object_.updateLayoutAndCheckValidity(); | |
1085 blink::WebAXObject obj = accessibility_object_.deprecatedTitleUIElement(); | |
1086 if (obj.isNull()) | |
1087 return v8::Local<v8::Object>(); | |
1088 | |
1089 return factory_->GetOrCreate(obj); | |
1090 } | |
1091 | |
1092 void WebAXObjectProxy::SetSelectedTextRange(int selection_start, | |
1093 int length) { | |
1094 accessibility_object_.updateLayoutAndCheckValidity(); | |
1095 accessibility_object_.setSelectedTextRange(selection_start, | |
1096 selection_start + length); | |
1097 } | |
1098 | |
1099 bool WebAXObjectProxy::IsAttributeSettable(const std::string& attribute) { | |
1100 accessibility_object_.updateLayoutAndCheckValidity(); | |
1101 bool settable = false; | |
1102 if (attribute == "AXValue") | |
1103 settable = accessibility_object_.canSetValueAttribute(); | |
1104 return settable; | |
1105 } | |
1106 | |
1107 bool WebAXObjectProxy::IsPressActionSupported() { | |
1108 accessibility_object_.updateLayoutAndCheckValidity(); | |
1109 return accessibility_object_.canPress(); | |
1110 } | |
1111 | |
1112 bool WebAXObjectProxy::IsIncrementActionSupported() { | |
1113 accessibility_object_.updateLayoutAndCheckValidity(); | |
1114 return accessibility_object_.canIncrement(); | |
1115 } | |
1116 | |
1117 bool WebAXObjectProxy::IsDecrementActionSupported() { | |
1118 accessibility_object_.updateLayoutAndCheckValidity(); | |
1119 return accessibility_object_.canDecrement(); | |
1120 } | |
1121 | |
1122 v8::Local<v8::Object> WebAXObjectProxy::ParentElement() { | |
1123 accessibility_object_.updateLayoutAndCheckValidity(); | |
1124 blink::WebAXObject parent_object = accessibility_object_.parentObject(); | |
1125 while (parent_object.accessibilityIsIgnored()) | |
1126 parent_object = parent_object.parentObject(); | |
1127 return factory_->GetOrCreate(parent_object); | |
1128 } | |
1129 | |
1130 void WebAXObjectProxy::Increment() { | |
1131 accessibility_object_.updateLayoutAndCheckValidity(); | |
1132 accessibility_object_.increment(); | |
1133 } | |
1134 | |
1135 void WebAXObjectProxy::Decrement() { | |
1136 accessibility_object_.updateLayoutAndCheckValidity(); | |
1137 accessibility_object_.decrement(); | |
1138 } | |
1139 | |
1140 void WebAXObjectProxy::ShowMenu() { | |
1141 accessibility_object_.showContextMenu(); | |
1142 } | |
1143 | |
1144 void WebAXObjectProxy::Press() { | |
1145 accessibility_object_.updateLayoutAndCheckValidity(); | |
1146 accessibility_object_.press(); | |
1147 } | |
1148 | |
1149 bool WebAXObjectProxy::IsEqual(v8::Local<v8::Object> proxy) { | |
1150 WebAXObjectProxy* unwrapped_proxy = NULL; | |
1151 if (!gin::ConvertFromV8(blink::mainThreadIsolate(), proxy, &unwrapped_proxy)) | |
1152 return false; | |
1153 return unwrapped_proxy->IsEqualToObject(accessibility_object_); | |
1154 } | |
1155 | |
1156 void WebAXObjectProxy::SetNotificationListener( | |
1157 v8::Local<v8::Function> callback) { | |
1158 v8::Isolate* isolate = blink::mainThreadIsolate(); | |
1159 notification_callback_.Reset(isolate, callback); | |
1160 } | |
1161 | |
1162 void WebAXObjectProxy::UnsetNotificationListener() { | |
1163 notification_callback_.Reset(); | |
1164 } | |
1165 | |
1166 void WebAXObjectProxy::TakeFocus() { | |
1167 accessibility_object_.updateLayoutAndCheckValidity(); | |
1168 accessibility_object_.setFocused(true); | |
1169 } | |
1170 | |
1171 void WebAXObjectProxy::ScrollToMakeVisible() { | |
1172 accessibility_object_.updateLayoutAndCheckValidity(); | |
1173 accessibility_object_.scrollToMakeVisible(); | |
1174 } | |
1175 | |
1176 void WebAXObjectProxy::ScrollToMakeVisibleWithSubFocus(int x, int y, | |
1177 int width, int height) { | |
1178 accessibility_object_.updateLayoutAndCheckValidity(); | |
1179 accessibility_object_.scrollToMakeVisibleWithSubFocus( | |
1180 blink::WebRect(x, y, width, height)); | |
1181 } | |
1182 | |
1183 void WebAXObjectProxy::ScrollToGlobalPoint(int x, int y) { | |
1184 accessibility_object_.updateLayoutAndCheckValidity(); | |
1185 accessibility_object_.scrollToGlobalPoint(blink::WebPoint(x, y)); | |
1186 } | |
1187 | |
1188 int WebAXObjectProxy::WordStart(int character_index) { | |
1189 accessibility_object_.updateLayoutAndCheckValidity(); | |
1190 if (accessibility_object_.role() != blink::WebAXRoleStaticText) | |
1191 return -1; | |
1192 | |
1193 int word_start = 0, word_end = 0; | |
1194 GetBoundariesForOneWord(accessibility_object_, character_index, | |
1195 word_start, word_end); | |
1196 return word_start; | |
1197 } | |
1198 | |
1199 int WebAXObjectProxy::WordEnd(int character_index) { | |
1200 accessibility_object_.updateLayoutAndCheckValidity(); | |
1201 if (accessibility_object_.role() != blink::WebAXRoleStaticText) | |
1202 return -1; | |
1203 | |
1204 int word_start = 0, word_end = 0; | |
1205 GetBoundariesForOneWord(accessibility_object_, character_index, | |
1206 word_start, word_end); | |
1207 return word_end; | |
1208 } | |
1209 | |
1210 v8::Local<v8::Object> WebAXObjectProxy::NextOnLine() { | |
1211 accessibility_object_.updateLayoutAndCheckValidity(); | |
1212 blink::WebAXObject obj = accessibility_object_.nextOnLine(); | |
1213 if (obj.isNull()) | |
1214 return v8::Local<v8::Object>(); | |
1215 | |
1216 return factory_->GetOrCreate(obj); | |
1217 } | |
1218 | |
1219 v8::Local<v8::Object> WebAXObjectProxy::PreviousOnLine() { | |
1220 accessibility_object_.updateLayoutAndCheckValidity(); | |
1221 blink::WebAXObject obj = accessibility_object_.previousOnLine(); | |
1222 if (obj.isNull()) | |
1223 return v8::Local<v8::Object>(); | |
1224 | |
1225 return factory_->GetOrCreate(obj); | |
1226 } | |
1227 | |
1228 std::string WebAXObjectProxy::Name() { | |
1229 accessibility_object_.updateLayoutAndCheckValidity(); | |
1230 blink::WebAXNameFrom nameFrom; | |
1231 blink::WebVector<blink::WebAXObject> nameObjects; | |
1232 return accessibility_object_.name(nameFrom, nameObjects).utf8(); | |
1233 } | |
1234 | |
1235 std::string WebAXObjectProxy::NameFrom() { | |
1236 accessibility_object_.updateLayoutAndCheckValidity(); | |
1237 blink::WebAXNameFrom nameFrom = blink::WebAXNameFromContents; | |
1238 blink::WebVector<blink::WebAXObject> nameObjects; | |
1239 accessibility_object_.name(nameFrom, nameObjects); | |
1240 switch(nameFrom) { | |
1241 case blink::WebAXNameFromAttribute: | |
1242 return "attribute"; | |
1243 case blink::WebAXNameFromContents: | |
1244 return "contents"; | |
1245 case blink::WebAXNameFromPlaceholder: | |
1246 return "placeholder"; | |
1247 case blink::WebAXNameFromRelatedElement: | |
1248 return "relatedElement"; | |
1249 default: | |
1250 return "unknown"; | |
1251 } | |
1252 } | |
1253 | |
1254 int WebAXObjectProxy::NameElementCount() { | |
1255 accessibility_object_.updateLayoutAndCheckValidity(); | |
1256 blink::WebAXNameFrom nameFrom; | |
1257 blink::WebVector<blink::WebAXObject> nameObjects; | |
1258 accessibility_object_.name(nameFrom, nameObjects); | |
1259 return static_cast<int>(nameObjects.size()); | |
1260 } | |
1261 | |
1262 v8::Local<v8::Object> WebAXObjectProxy::NameElementAtIndex(unsigned index) { | |
1263 accessibility_object_.updateLayoutAndCheckValidity(); | |
1264 blink::WebAXNameFrom nameFrom; | |
1265 blink::WebVector<blink::WebAXObject> nameObjects; | |
1266 accessibility_object_.name(nameFrom, nameObjects); | |
1267 if (index >= nameObjects.size()) | |
1268 return v8::Local<v8::Object>(); | |
1269 return factory_->GetOrCreate(nameObjects[index]); | |
1270 } | |
1271 | |
1272 RootWebAXObjectProxy::RootWebAXObjectProxy( | |
1273 const blink::WebAXObject &object, Factory *factory) | |
1274 : WebAXObjectProxy(object, factory) { | |
1275 } | |
1276 | |
1277 v8::Local<v8::Object> RootWebAXObjectProxy::GetChildAtIndex(unsigned index) { | |
1278 if (index) | |
1279 return v8::Local<v8::Object>(); | |
1280 | |
1281 return factory()->GetOrCreate(accessibility_object()); | |
1282 } | |
1283 | |
1284 bool RootWebAXObjectProxy::IsRoot() const { | |
1285 return true; | |
1286 } | |
1287 | |
1288 WebAXObjectProxyList::WebAXObjectProxyList() | |
1289 : elements_(blink::mainThreadIsolate()) { | |
1290 } | |
1291 | |
1292 WebAXObjectProxyList::~WebAXObjectProxyList() { | |
1293 Clear(); | |
1294 } | |
1295 | |
1296 void WebAXObjectProxyList::Clear() { | |
1297 v8::Isolate* isolate = blink::mainThreadIsolate(); | |
1298 v8::HandleScope handle_scope(isolate); | |
1299 size_t elementCount = elements_.Size(); | |
1300 for (size_t i = 0; i < elementCount; i++) { | |
1301 WebAXObjectProxy* unwrapped_object = NULL; | |
1302 bool result = gin::ConvertFromV8(isolate, elements_.Get(i), | |
1303 &unwrapped_object); | |
1304 DCHECK(result); | |
1305 DCHECK(unwrapped_object); | |
1306 unwrapped_object->Reset(); | |
1307 } | |
1308 elements_.Clear(); | |
1309 } | |
1310 | |
1311 v8::Local<v8::Object> WebAXObjectProxyList::GetOrCreate( | |
1312 const blink::WebAXObject& object) { | |
1313 if (object.isNull()) | |
1314 return v8::Local<v8::Object>(); | |
1315 | |
1316 v8::Isolate* isolate = blink::mainThreadIsolate(); | |
1317 | |
1318 size_t elementCount = elements_.Size(); | |
1319 for (size_t i = 0; i < elementCount; i++) { | |
1320 WebAXObjectProxy* unwrapped_object = NULL; | |
1321 bool result = gin::ConvertFromV8(isolate, elements_.Get(i), | |
1322 &unwrapped_object); | |
1323 DCHECK(result); | |
1324 DCHECK(unwrapped_object); | |
1325 if (unwrapped_object->IsEqualToObject(object)) | |
1326 return elements_.Get(i); | |
1327 } | |
1328 | |
1329 v8::Local<v8::Value> value_handle = gin::CreateHandle( | |
1330 isolate, new WebAXObjectProxy(object, this)).ToV8(); | |
1331 if (value_handle.IsEmpty()) | |
1332 return v8::Local<v8::Object>(); | |
1333 v8::Local<v8::Object> handle = value_handle->ToObject(isolate); | |
1334 elements_.Append(handle); | |
1335 return handle; | |
1336 } | |
1337 | |
1338 } // namespace content | |
OLD | NEW |