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.
5 #include "content/shell/renderer/test_runner/web_ax_object_proxy.h"
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"
19 // Map role value to string, matching Safari/Mac platform implementation to
20 // avoid rebaselining layout tests.
21 std::string
RoleToString(blink::WebAXRole role
)
23 std::string result
= "AXRole: AX";
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::WebAXRoleBrowser
:
38 return result
.append("Browser");
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::WebAXRoleCell
:
46 return result
.append("Cell");
47 case blink::WebAXRoleCheckBox
:
48 return result
.append("CheckBox");
49 case blink::WebAXRoleColorWell
:
50 return result
.append("ColorWell");
51 case blink::WebAXRoleColumnHeader
:
52 return result
.append("ColumnHeader");
53 case blink::WebAXRoleColumn
:
54 return result
.append("Column");
55 case blink::WebAXRoleComboBox
:
56 return result
.append("ComboBox");
57 case blink::WebAXRoleComplementary
:
58 return result
.append("Complementary");
59 case blink::WebAXRoleContentInfo
:
60 return result
.append("ContentInfo");
61 case blink::WebAXRoleDefinition
:
62 return result
.append("Definition");
63 case blink::WebAXRoleDescriptionListDetail
:
64 return result
.append("DescriptionListDetail");
65 case blink::WebAXRoleDescriptionListTerm
:
66 return result
.append("DescriptionListTerm");
67 case blink::WebAXRoleDialog
:
68 return result
.append("Dialog");
69 case blink::WebAXRoleDirectory
:
70 return result
.append("Directory");
71 case blink::WebAXRoleDisclosureTriangle
:
72 return result
.append("DisclosureTriangle");
73 case blink::WebAXRoleDiv
:
74 return result
.append("Div");
75 case blink::WebAXRoleDocument
:
76 return result
.append("Document");
77 case blink::WebAXRoleDrawer
:
78 return result
.append("Drawer");
79 case blink::WebAXRoleEditableText
:
80 return result
.append("EditableText");
81 case blink::WebAXRoleFooter
:
82 return result
.append("Footer");
83 case blink::WebAXRoleForm
:
84 return result
.append("Form");
85 case blink::WebAXRoleGrid
:
86 return result
.append("Grid");
87 case blink::WebAXRoleGroup
:
88 return result
.append("Group");
89 case blink::WebAXRoleGrowArea
:
90 return result
.append("GrowArea");
91 case blink::WebAXRoleHeading
:
92 return result
.append("Heading");
93 case blink::WebAXRoleHelpTag
:
94 return result
.append("HelpTag");
95 case blink::WebAXRoleHorizontalRule
:
96 return result
.append("HorizontalRule");
97 case blink::WebAXRoleIgnored
:
98 return result
.append("Ignored");
99 case blink::WebAXRoleImageMapLink
:
100 return result
.append("ImageMapLink");
101 case blink::WebAXRoleImageMap
:
102 return result
.append("ImageMap");
103 case blink::WebAXRoleImage
:
104 return result
.append("Image");
105 case blink::WebAXRoleIncrementor
:
106 return result
.append("Incrementor");
107 case blink::WebAXRoleInlineTextBox
:
108 return result
.append("InlineTextBox");
109 case blink::WebAXRoleLabel
:
110 return result
.append("Label");
111 case blink::WebAXRoleLegend
:
112 return result
.append("Legend");
113 case blink::WebAXRoleLink
:
114 return result
.append("Link");
115 case blink::WebAXRoleListBoxOption
:
116 return result
.append("ListBoxOption");
117 case blink::WebAXRoleListBox
:
118 return result
.append("ListBox");
119 case blink::WebAXRoleListItem
:
120 return result
.append("ListItem");
121 case blink::WebAXRoleListMarker
:
122 return result
.append("ListMarker");
123 case blink::WebAXRoleList
:
124 return result
.append("List");
125 case blink::WebAXRoleLog
:
126 return result
.append("Log");
127 case blink::WebAXRoleMain
:
128 return result
.append("Main");
129 case blink::WebAXRoleMarquee
:
130 return result
.append("Marquee");
131 case blink::WebAXRoleMathElement
:
132 return result
.append("MathElement");
133 case blink::WebAXRoleMath
:
134 return result
.append("Math");
135 case blink::WebAXRoleMatte
:
136 return result
.append("Matte");
137 case blink::WebAXRoleMenuBar
:
138 return result
.append("MenuBar");
139 case blink::WebAXRoleMenuButton
:
140 return result
.append("MenuButton");
141 case blink::WebAXRoleMenuItem
:
142 return result
.append("MenuItem");
143 case blink::WebAXRoleMenuListOption
:
144 return result
.append("MenuListOption");
145 case blink::WebAXRoleMenuListPopup
:
146 return result
.append("MenuListPopup");
147 case blink::WebAXRoleMenu
:
148 return result
.append("Menu");
149 case blink::WebAXRoleNavigation
:
150 return result
.append("Navigation");
151 case blink::WebAXRoleNote
:
152 return result
.append("Note");
153 case blink::WebAXRoleOutline
:
154 return result
.append("Outline");
155 case blink::WebAXRoleParagraph
:
156 return result
.append("Paragraph");
157 case blink::WebAXRolePopUpButton
:
158 return result
.append("PopUpButton");
159 case blink::WebAXRolePresentational
:
160 return result
.append("Presentational");
161 case blink::WebAXRoleProgressIndicator
:
162 return result
.append("ProgressIndicator");
163 case blink::WebAXRoleRadioButton
:
164 return result
.append("RadioButton");
165 case blink::WebAXRoleRadioGroup
:
166 return result
.append("RadioGroup");
167 case blink::WebAXRoleRegion
:
168 return result
.append("Region");
169 case blink::WebAXRoleRootWebArea
:
170 return result
.append("RootWebArea");
171 case blink::WebAXRoleRowHeader
:
172 return result
.append("RowHeader");
173 case blink::WebAXRoleRow
:
174 return result
.append("Row");
175 case blink::WebAXRoleRulerMarker
:
176 return result
.append("RulerMarker");
177 case blink::WebAXRoleRuler
:
178 return result
.append("Ruler");
179 case blink::WebAXRoleSVGRoot
:
180 return result
.append("SVGRoot");
181 case blink::WebAXRoleScrollArea
:
182 return result
.append("ScrollArea");
183 case blink::WebAXRoleScrollBar
:
184 return result
.append("ScrollBar");
185 case blink::WebAXRoleSeamlessWebArea
:
186 return result
.append("SeamlessWebArea");
187 case blink::WebAXRoleSearch
:
188 return result
.append("Search");
189 case blink::WebAXRoleSheet
:
190 return result
.append("Sheet");
191 case blink::WebAXRoleSlider
:
192 return result
.append("Slider");
193 case blink::WebAXRoleSliderThumb
:
194 return result
.append("SliderThumb");
195 case blink::WebAXRoleSpinButtonPart
:
196 return result
.append("SpinButtonPart");
197 case blink::WebAXRoleSpinButton
:
198 return result
.append("SpinButton");
199 case blink::WebAXRoleSplitGroup
:
200 return result
.append("SplitGroup");
201 case blink::WebAXRoleSplitter
:
202 return result
.append("Splitter");
203 case blink::WebAXRoleStaticText
:
204 return result
.append("StaticText");
205 case blink::WebAXRoleStatus
:
206 return result
.append("Status");
207 case blink::WebAXRoleSystemWide
:
208 return result
.append("SystemWide");
209 case blink::WebAXRoleTabGroup
:
210 return result
.append("TabGroup");
211 case blink::WebAXRoleTabList
:
212 return result
.append("TabList");
213 case blink::WebAXRoleTabPanel
:
214 return result
.append("TabPanel");
215 case blink::WebAXRoleTab
:
216 return result
.append("Tab");
217 case blink::WebAXRoleTableHeaderContainer
:
218 return result
.append("TableHeaderContainer");
219 case blink::WebAXRoleTable
:
220 return result
.append("Table");
221 case blink::WebAXRoleTextArea
:
222 return result
.append("TextArea");
223 case blink::WebAXRoleTextField
:
224 return result
.append("TextField");
225 case blink::WebAXRoleTimer
:
226 return result
.append("Timer");
227 case blink::WebAXRoleToggleButton
:
228 return result
.append("ToggleButton");
229 case blink::WebAXRoleToolbar
:
230 return result
.append("Toolbar");
231 case blink::WebAXRoleTreeGrid
:
232 return result
.append("TreeGrid");
233 case blink::WebAXRoleTreeItem
:
234 return result
.append("TreeItem");
235 case blink::WebAXRoleTree
:
236 return result
.append("Tree");
237 case blink::WebAXRoleUnknown
:
238 return result
.append("Unknown");
239 case blink::WebAXRoleUserInterfaceTooltip
:
240 return result
.append("UserInterfaceTooltip");
241 case blink::WebAXRoleValueIndicator
:
242 return result
.append("ValueIndicator");
243 case blink::WebAXRoleWebArea
:
244 return result
.append("WebArea");
245 case blink::WebAXRoleWindow
:
246 return result
.append("Window");
248 return result
.append("Unknown");
252 std::string
GetDescription(const blink::WebAXObject
& object
) {
253 std::string description
= object
.accessibilityDescription().utf8();
254 return description
.insert(0, "AXDescription: ");
257 std::string
GetHelpText(const blink::WebAXObject
& object
) {
258 std::string help_text
= object
.helpText().utf8();
259 return help_text
.insert(0, "AXHelp: ");
262 std::string
GetStringValue(const blink::WebAXObject
& object
) {
264 if (object
.role() == blink::WebAXRoleColorWell
) {
266 object
.colorValue(r
, g
, b
);
267 value
= base::StringPrintf("rgb %7.5f %7.5f %7.5f 1",
268 r
/ 255., g
/ 255., b
/ 255.);
270 value
= object
.stringValue().utf8();
272 return value
.insert(0, "AXValue: ");
275 std::string
GetRole(const blink::WebAXObject
& object
) {
276 std::string role_string
= RoleToString(object
.role());
278 // Special-case canvas with fallback content because Chromium wants to treat
279 // this as essentially a separate role that it can map differently depending
281 if (object
.role() == blink::WebAXRoleCanvas
&&
282 object
.canvasHasFallbackContent()) {
283 role_string
+= "WithFallbackContent";
289 std::string
GetTitle(const blink::WebAXObject
& object
) {
290 std::string title
= object
.title().utf8();
291 return title
.insert(0, "AXTitle: ");
294 std::string
GetOrientation(const blink::WebAXObject
& object
) {
295 if (object
.isVertical())
296 return "AXOrientation: AXVerticalOrientation";
298 return "AXOrientation: AXHorizontalOrientation";
301 std::string
GetValueDescription(const blink::WebAXObject
& object
) {
302 std::string value_description
= object
.valueDescription().utf8();
303 return value_description
.insert(0, "AXValueDescription: ");
306 std::string
GetAttributes(const blink::WebAXObject
& object
) {
307 // FIXME: Concatenate all attributes of the AXObject.
308 std::string
attributes(GetTitle(object
));
309 attributes
.append("\n");
310 attributes
.append(GetRole(object
));
311 attributes
.append("\n");
312 attributes
.append(GetDescription(object
));
316 blink::WebRect
BoundsForCharacter(const blink::WebAXObject
& object
,
317 int characterIndex
) {
318 DCHECK_EQ(object
.role(), blink::WebAXRoleStaticText
);
320 for (unsigned i
= 0; i
< object
.childCount(); i
++) {
321 blink::WebAXObject inline_text_box
= object
.childAt(i
);
322 DCHECK_EQ(inline_text_box
.role(), blink::WebAXRoleInlineTextBox
);
324 end
+= inline_text_box
.stringValue().length();
325 if (characterIndex
< start
|| characterIndex
>= end
)
327 blink::WebRect inline_text_box_rect
= inline_text_box
.boundingBoxRect();
328 int localIndex
= characterIndex
- start
;
329 blink::WebVector
<int> character_offsets
;
330 inline_text_box
.characterOffsets(character_offsets
);
331 DCHECK(character_offsets
.size() > 0 &&
332 character_offsets
.size() == inline_text_box
.stringValue().length());
333 switch (inline_text_box
.textDirection()) {
334 case blink::WebAXTextDirectionLR
: {
336 int left
= inline_text_box_rect
.x
+ character_offsets
[localIndex
- 1];
337 int width
= character_offsets
[localIndex
] -
338 character_offsets
[localIndex
- 1];
339 return blink::WebRect(left
, inline_text_box_rect
.y
,
340 width
, inline_text_box_rect
.height
);
342 return blink::WebRect(
343 inline_text_box_rect
.x
, inline_text_box_rect
.y
,
344 character_offsets
[0], inline_text_box_rect
.height
);
346 case blink::WebAXTextDirectionRL
: {
347 int right
= inline_text_box_rect
.x
+ inline_text_box_rect
.width
;
350 int left
= right
- character_offsets
[localIndex
];
351 int width
= character_offsets
[localIndex
] -
352 character_offsets
[localIndex
- 1];
353 return blink::WebRect(left
, inline_text_box_rect
.y
,
354 width
, inline_text_box_rect
.height
);
356 int left
= right
- character_offsets
[0];
357 return blink::WebRect(
358 left
, inline_text_box_rect
.y
,
359 character_offsets
[0], inline_text_box_rect
.height
);
361 case blink::WebAXTextDirectionTB
: {
363 int top
= inline_text_box_rect
.y
+ character_offsets
[localIndex
- 1];
364 int height
= character_offsets
[localIndex
] -
365 character_offsets
[localIndex
- 1];
366 return blink::WebRect(inline_text_box_rect
.x
, top
,
367 inline_text_box_rect
.width
, height
);
369 return blink::WebRect(inline_text_box_rect
.x
, inline_text_box_rect
.y
,
370 inline_text_box_rect
.width
, character_offsets
[0]);
372 case blink::WebAXTextDirectionBT
: {
373 int bottom
= inline_text_box_rect
.y
+ inline_text_box_rect
.height
;
376 int top
= bottom
- character_offsets
[localIndex
];
377 int height
= character_offsets
[localIndex
] -
378 character_offsets
[localIndex
- 1];
379 return blink::WebRect(inline_text_box_rect
.x
, top
,
380 inline_text_box_rect
.width
, height
);
382 int top
= bottom
- character_offsets
[0];
383 return blink::WebRect(inline_text_box_rect
.x
, top
,
384 inline_text_box_rect
.width
, character_offsets
[0]);
390 return blink::WebRect();
393 void GetBoundariesForOneWord(const blink::WebAXObject
& object
,
398 for (unsigned i
= 0; i
< object
.childCount(); i
++) {
399 blink::WebAXObject inline_text_box
= object
.childAt(i
);
400 DCHECK_EQ(inline_text_box
.role(), blink::WebAXRoleInlineTextBox
);
402 end
+= inline_text_box
.stringValue().length();
403 if (end
<= character_index
)
405 int localIndex
= character_index
- start
;
407 blink::WebVector
<int> starts
;
408 blink::WebVector
<int> ends
;
409 inline_text_box
.wordBoundaries(starts
, ends
);
410 size_t word_count
= starts
.size();
411 DCHECK_EQ(ends
.size(), word_count
);
413 // If there are no words, use the InlineTextBox boundaries.
420 // Look for a character within any word other than the last.
421 for (size_t j
= 0; j
< word_count
- 1; j
++) {
422 if (localIndex
<= ends
[j
]) {
423 word_start
= start
+ starts
[j
];
424 word_end
= start
+ ends
[j
];
429 // Return the last word by default.
430 word_start
= start
+ starts
[word_count
- 1];
431 word_end
= start
+ ends
[word_count
- 1];
436 // Collects attributes into a string, delimited by dashes. Used by all methods
437 // that output lists of attributes: attributesOfLinkedUIElementsCallback,
438 // AttributesOfChildrenCallback, etc.
439 class AttributesCollector
{
441 AttributesCollector() {}
442 ~AttributesCollector() {}
444 void CollectAttributes(const blink::WebAXObject
& object
) {
445 attributes_
.append("\n------------\n");
446 attributes_
.append(GetAttributes(object
));
449 std::string
attributes() const { return attributes_
; }
452 std::string attributes_
;
454 DISALLOW_COPY_AND_ASSIGN(AttributesCollector
);
459 gin::WrapperInfo
WebAXObjectProxy::kWrapperInfo
= {
460 gin::kEmbedderNativeGin
};
462 WebAXObjectProxy::WebAXObjectProxy(const blink::WebAXObject
& object
,
463 WebAXObjectProxy::Factory
* factory
)
464 : accessibility_object_(object
),
468 WebAXObjectProxy::~WebAXObjectProxy() {}
470 gin::ObjectTemplateBuilder
471 WebAXObjectProxy::GetObjectTemplateBuilder(v8::Isolate
* isolate
) {
472 return gin::Wrappable
<WebAXObjectProxy
>::GetObjectTemplateBuilder(isolate
)
473 .SetProperty("role", &WebAXObjectProxy::Role
)
474 .SetProperty("title", &WebAXObjectProxy::Title
)
475 .SetProperty("description", &WebAXObjectProxy::Description
)
476 .SetProperty("helpText", &WebAXObjectProxy::HelpText
)
477 .SetProperty("stringValue", &WebAXObjectProxy::StringValue
)
478 .SetProperty("x", &WebAXObjectProxy::X
)
479 .SetProperty("y", &WebAXObjectProxy::Y
)
480 .SetProperty("width", &WebAXObjectProxy::Width
)
481 .SetProperty("height", &WebAXObjectProxy::Height
)
482 .SetProperty("intValue", &WebAXObjectProxy::IntValue
)
483 .SetProperty("minValue", &WebAXObjectProxy::MinValue
)
484 .SetProperty("maxValue", &WebAXObjectProxy::MaxValue
)
485 .SetProperty("valueDescription", &WebAXObjectProxy::ValueDescription
)
486 .SetProperty("childrenCount", &WebAXObjectProxy::ChildrenCount
)
487 .SetProperty("insertionPointLineNumber",
488 &WebAXObjectProxy::InsertionPointLineNumber
)
489 .SetProperty("selectedTextRange", &WebAXObjectProxy::SelectedTextRange
)
490 .SetProperty("isEnabled", &WebAXObjectProxy::IsEnabled
)
491 .SetProperty("isRequired", &WebAXObjectProxy::IsRequired
)
492 .SetProperty("isFocused", &WebAXObjectProxy::IsFocused
)
493 .SetProperty("isFocusable", &WebAXObjectProxy::IsFocusable
)
494 .SetProperty("isSelected", &WebAXObjectProxy::IsSelected
)
495 .SetProperty("isSelectable", &WebAXObjectProxy::IsSelectable
)
496 .SetProperty("isMultiSelectable", &WebAXObjectProxy::IsMultiSelectable
)
497 .SetProperty("isSelectedOptionActive",
498 &WebAXObjectProxy::IsSelectedOptionActive
)
499 .SetProperty("isExpanded", &WebAXObjectProxy::IsExpanded
)
500 .SetProperty("isChecked", &WebAXObjectProxy::IsChecked
)
501 .SetProperty("isVisible", &WebAXObjectProxy::IsVisible
)
502 .SetProperty("isOffScreen", &WebAXObjectProxy::IsOffScreen
)
503 .SetProperty("isCollapsed", &WebAXObjectProxy::IsCollapsed
)
504 .SetProperty("hasPopup", &WebAXObjectProxy::HasPopup
)
505 .SetProperty("isValid", &WebAXObjectProxy::IsValid
)
506 .SetProperty("isReadOnly", &WebAXObjectProxy::IsReadOnly
)
507 .SetProperty("orientation", &WebAXObjectProxy::Orientation
)
508 .SetProperty("clickPointX", &WebAXObjectProxy::ClickPointX
)
509 .SetProperty("clickPointY", &WebAXObjectProxy::ClickPointY
)
510 .SetProperty("rowCount", &WebAXObjectProxy::RowCount
)
511 .SetProperty("columnCount", &WebAXObjectProxy::ColumnCount
)
512 .SetProperty("isClickable", &WebAXObjectProxy::IsClickable
)
513 .SetMethod("allAttributes", &WebAXObjectProxy::AllAttributes
)
514 .SetMethod("attributesOfChildren",
515 &WebAXObjectProxy::AttributesOfChildren
)
516 .SetMethod("lineForIndex", &WebAXObjectProxy::LineForIndex
)
517 .SetMethod("boundsForRange", &WebAXObjectProxy::BoundsForRange
)
518 .SetMethod("childAtIndex", &WebAXObjectProxy::ChildAtIndex
)
519 .SetMethod("elementAtPoint", &WebAXObjectProxy::ElementAtPoint
)
520 .SetMethod("tableHeader", &WebAXObjectProxy::TableHeader
)
521 .SetMethod("rowIndexRange", &WebAXObjectProxy::RowIndexRange
)
522 .SetMethod("columnIndexRange", &WebAXObjectProxy::ColumnIndexRange
)
523 .SetMethod("cellForColumnAndRow", &WebAXObjectProxy::CellForColumnAndRow
)
524 .SetMethod("titleUIElement", &WebAXObjectProxy::TitleUIElement
)
525 .SetMethod("setSelectedTextRange",
526 &WebAXObjectProxy::SetSelectedTextRange
)
527 .SetMethod("isAttributeSettable", &WebAXObjectProxy::IsAttributeSettable
)
528 .SetMethod("isPressActionSupported",
529 &WebAXObjectProxy::IsPressActionSupported
)
530 .SetMethod("isIncrementActionSupported",
531 &WebAXObjectProxy::IsIncrementActionSupported
)
532 .SetMethod("isDecrementActionSupported",
533 &WebAXObjectProxy::IsDecrementActionSupported
)
534 .SetMethod("parentElement", &WebAXObjectProxy::ParentElement
)
535 .SetMethod("increment", &WebAXObjectProxy::Increment
)
536 .SetMethod("decrement", &WebAXObjectProxy::Decrement
)
537 .SetMethod("showMenu", &WebAXObjectProxy::ShowMenu
)
538 .SetMethod("press", &WebAXObjectProxy::Press
)
539 .SetMethod("isEqual", &WebAXObjectProxy::IsEqual
)
540 .SetMethod("setNotificationListener",
541 &WebAXObjectProxy::SetNotificationListener
)
542 .SetMethod("unsetNotificationListener",
543 &WebAXObjectProxy::UnsetNotificationListener
)
544 .SetMethod("takeFocus", &WebAXObjectProxy::TakeFocus
)
545 .SetMethod("scrollToMakeVisible", &WebAXObjectProxy::ScrollToMakeVisible
)
546 .SetMethod("scrollToMakeVisibleWithSubFocus",
547 &WebAXObjectProxy::ScrollToMakeVisibleWithSubFocus
)
548 .SetMethod("scrollToGlobalPoint", &WebAXObjectProxy::ScrollToGlobalPoint
)
549 .SetMethod("wordStart", &WebAXObjectProxy::WordStart
)
550 .SetMethod("wordEnd", &WebAXObjectProxy::WordEnd
)
551 // TODO(hajimehoshi): This is for backward compatibility. Remove them.
552 .SetMethod("addNotificationListener",
553 &WebAXObjectProxy::SetNotificationListener
)
554 .SetMethod("removeNotificationListener",
555 &WebAXObjectProxy::UnsetNotificationListener
);
558 v8::Handle
<v8::Object
> WebAXObjectProxy::GetChildAtIndex(unsigned index
) {
559 return factory_
->GetOrCreate(accessibility_object().childAt(index
));
562 bool WebAXObjectProxy::IsRoot() const {
566 bool WebAXObjectProxy::IsEqualToObject(const blink::WebAXObject
& other
) {
567 return accessibility_object().equals(other
);
570 void WebAXObjectProxy::NotificationReceived(
571 blink::WebFrame
* frame
,
572 const std::string
& notification_name
) {
573 if (notification_callback_
.IsEmpty())
576 v8::Handle
<v8::Context
> context
= frame
->mainWorldScriptContext();
577 if (context
.IsEmpty())
580 v8::Isolate
* isolate
= blink::mainThreadIsolate();
582 v8::Handle
<v8::Value
> argv
[] = {
583 v8::String::NewFromUtf8(isolate
, notification_name
.data(),
584 v8::String::kNormalString
,
585 notification_name
.size()),
587 frame
->callFunctionEvenIfScriptDisabled(
588 v8::Local
<v8::Function
>::New(isolate
, notification_callback_
),
594 std::string
WebAXObjectProxy::Role() {
595 return GetRole(accessibility_object());
598 std::string
WebAXObjectProxy::Title() {
599 return GetTitle(accessibility_object());
602 std::string
WebAXObjectProxy::Description() {
603 return GetDescription(accessibility_object());
606 std::string
WebAXObjectProxy::HelpText() {
607 return GetHelpText(accessibility_object());
610 std::string
WebAXObjectProxy::StringValue() {
611 return GetStringValue(accessibility_object());
614 int WebAXObjectProxy::X() {
615 accessibility_object_
.updateBackingStoreAndCheckValidity();
616 return accessibility_object().boundingBoxRect().x
;
619 int WebAXObjectProxy::Y() {
620 accessibility_object_
.updateBackingStoreAndCheckValidity();
621 return accessibility_object().boundingBoxRect().y
;
624 int WebAXObjectProxy::Width() {
625 accessibility_object_
.updateBackingStoreAndCheckValidity();
626 return accessibility_object().boundingBoxRect().width
;
629 int WebAXObjectProxy::Height() {
630 accessibility_object_
.updateBackingStoreAndCheckValidity();
631 return accessibility_object().boundingBoxRect().height
;
634 int WebAXObjectProxy::IntValue() {
635 if (accessibility_object().supportsRangeValue())
636 return accessibility_object().valueForRange();
637 else if (accessibility_object().role() == blink::WebAXRoleHeading
)
638 return accessibility_object().headingLevel();
640 return atoi(accessibility_object().stringValue().utf8().data());
643 int WebAXObjectProxy::MinValue() {
644 return accessibility_object().minValueForRange();
647 int WebAXObjectProxy::MaxValue() {
648 return accessibility_object().maxValueForRange();
651 std::string
WebAXObjectProxy::ValueDescription() {
652 return GetValueDescription(accessibility_object());
655 int WebAXObjectProxy::ChildrenCount() {
656 int count
= 1; // Root object always has only one child, the WebView.
658 count
= accessibility_object().childCount();
662 int WebAXObjectProxy::InsertionPointLineNumber() {
663 if (!accessibility_object().isFocused())
665 return accessibility_object().selectionEndLineNumber();
668 std::string
WebAXObjectProxy::SelectedTextRange() {
669 unsigned selection_start
= accessibility_object().selectionStart();
670 unsigned selection_end
= accessibility_object().selectionEnd();
671 return base::StringPrintf("{%d, %d}",
672 selection_start
, selection_end
- selection_start
);
675 bool WebAXObjectProxy::IsEnabled() {
676 return accessibility_object().isEnabled();
679 bool WebAXObjectProxy::IsRequired() {
680 return accessibility_object().isRequired();
683 bool WebAXObjectProxy::IsFocused() {
684 return accessibility_object().isFocused();
687 bool WebAXObjectProxy::IsFocusable() {
688 return accessibility_object().canSetFocusAttribute();
691 bool WebAXObjectProxy::IsSelected() {
692 return accessibility_object().isSelected();
695 bool WebAXObjectProxy::IsSelectable() {
696 return accessibility_object().canSetSelectedAttribute();
699 bool WebAXObjectProxy::IsMultiSelectable() {
700 return accessibility_object().isMultiSelectable();
703 bool WebAXObjectProxy::IsSelectedOptionActive() {
704 return accessibility_object().isSelectedOptionActive();
707 bool WebAXObjectProxy::IsExpanded() {
708 return !accessibility_object().isCollapsed();
711 bool WebAXObjectProxy::IsChecked() {
712 return accessibility_object().isChecked();
715 bool WebAXObjectProxy::IsVisible() {
716 return accessibility_object().isVisible();
719 bool WebAXObjectProxy::IsOffScreen() {
720 return accessibility_object().isOffScreen();
723 bool WebAXObjectProxy::IsCollapsed() {
724 return accessibility_object().isCollapsed();
727 bool WebAXObjectProxy::HasPopup() {
728 return accessibility_object().ariaHasPopup();
731 bool WebAXObjectProxy::IsValid() {
732 return !accessibility_object().isDetached();
735 bool WebAXObjectProxy::IsReadOnly() {
736 return accessibility_object().isReadOnly();
739 std::string
WebAXObjectProxy::Orientation() {
740 return GetOrientation(accessibility_object());
743 int WebAXObjectProxy::ClickPointX() {
744 return accessibility_object().clickPoint().x
;
747 int WebAXObjectProxy::ClickPointY() {
748 return accessibility_object().clickPoint().y
;
751 int32_t WebAXObjectProxy::RowCount() {
752 return static_cast<int32_t>(accessibility_object().rowCount());
755 int32_t WebAXObjectProxy::ColumnCount() {
756 return static_cast<int32_t>(accessibility_object().columnCount());
759 bool WebAXObjectProxy::IsClickable() {
760 return accessibility_object().isClickable();
763 std::string
WebAXObjectProxy::AllAttributes() {
764 return GetAttributes(accessibility_object());
767 std::string
WebAXObjectProxy::AttributesOfChildren() {
768 AttributesCollector collector
;
769 unsigned size
= accessibility_object().childCount();
770 for (unsigned i
= 0; i
< size
; ++i
)
771 collector
.CollectAttributes(accessibility_object().childAt(i
));
772 return collector
.attributes();
775 int WebAXObjectProxy::LineForIndex(int index
) {
776 blink::WebVector
<int> line_breaks
;
777 accessibility_object().lineBreaks(line_breaks
);
779 int vector_size
= static_cast<int>(line_breaks
.size());
780 while (line
< vector_size
&& line_breaks
[line
] <= index
)
785 std::string
WebAXObjectProxy::BoundsForRange(int start
, int end
) {
786 if (accessibility_object().role() != blink::WebAXRoleStaticText
)
787 return std::string();
789 if (!accessibility_object_
.updateBackingStoreAndCheckValidity())
790 return std::string();
792 int len
= end
- start
;
794 // Get the bounds for each character and union them into one large rectangle.
795 // This is just for testing so it doesn't need to be efficient.
796 blink::WebRect bounds
= BoundsForCharacter(accessibility_object(), start
);
797 for (int i
= 1; i
< len
; i
++) {
798 blink::WebRect next
= BoundsForCharacter(accessibility_object(), start
+ i
);
799 int right
= std::max(bounds
.x
+ bounds
.width
, next
.x
+ next
.width
);
800 int bottom
= std::max(bounds
.y
+ bounds
.height
, next
.y
+ next
.height
);
801 bounds
.x
= std::min(bounds
.x
, next
.x
);
802 bounds
.y
= std::min(bounds
.y
, next
.y
);
803 bounds
.width
= right
- bounds
.x
;
804 bounds
.height
= bottom
- bounds
.y
;
807 return base::StringPrintf("{x: %d, y: %d, width: %d, height: %d}",
808 bounds
.x
, bounds
.y
, bounds
.width
, bounds
.height
);
811 v8::Handle
<v8::Object
> WebAXObjectProxy::ChildAtIndex(int index
) {
812 return GetChildAtIndex(index
);
815 v8::Handle
<v8::Object
> WebAXObjectProxy::ElementAtPoint(int x
, int y
) {
816 blink::WebPoint
point(x
, y
);
817 blink::WebAXObject obj
= accessibility_object().hitTest(point
);
819 return v8::Handle
<v8::Object
>();
821 return factory_
->GetOrCreate(obj
);
824 v8::Handle
<v8::Object
> WebAXObjectProxy::TableHeader() {
825 blink::WebAXObject obj
= accessibility_object().headerContainerObject();
827 return v8::Handle
<v8::Object
>();
829 return factory_
->GetOrCreate(obj
);
832 std::string
WebAXObjectProxy::RowIndexRange() {
833 unsigned row_index
= accessibility_object().cellRowIndex();
834 unsigned row_span
= accessibility_object().cellRowSpan();
835 return base::StringPrintf("{%d, %d}", row_index
, row_span
);
838 std::string
WebAXObjectProxy::ColumnIndexRange() {
839 unsigned column_index
= accessibility_object().cellColumnIndex();
840 unsigned column_span
= accessibility_object().cellColumnSpan();
841 return base::StringPrintf("{%d, %d}", column_index
, column_span
);
844 v8::Handle
<v8::Object
> WebAXObjectProxy::CellForColumnAndRow(
845 int column
, int row
) {
846 blink::WebAXObject obj
=
847 accessibility_object().cellForColumnAndRow(column
, row
);
849 return v8::Handle
<v8::Object
>();
851 return factory_
->GetOrCreate(obj
);
854 v8::Handle
<v8::Object
> WebAXObjectProxy::TitleUIElement() {
855 blink::WebAXObject obj
= accessibility_object().titleUIElement();
857 return v8::Handle
<v8::Object
>();
859 return factory_
->GetOrCreate(obj
);
862 void WebAXObjectProxy::SetSelectedTextRange(int selection_start
,
864 accessibility_object().setSelectedTextRange(selection_start
,
865 selection_start
+ length
);
868 bool WebAXObjectProxy::IsAttributeSettable(const std::string
& attribute
) {
869 bool settable
= false;
870 if (attribute
== "AXValue")
871 settable
= accessibility_object().canSetValueAttribute();
875 bool WebAXObjectProxy::IsPressActionSupported() {
876 return accessibility_object().canPress();
879 bool WebAXObjectProxy::IsIncrementActionSupported() {
880 return accessibility_object().canIncrement();
883 bool WebAXObjectProxy::IsDecrementActionSupported() {
884 return accessibility_object().canDecrement();
887 v8::Handle
<v8::Object
> WebAXObjectProxy::ParentElement() {
888 blink::WebAXObject parent_object
= accessibility_object().parentObject();
889 while (parent_object
.accessibilityIsIgnored())
890 parent_object
= parent_object
.parentObject();
891 return factory_
->GetOrCreate(parent_object
);
894 void WebAXObjectProxy::Increment() {
895 accessibility_object().increment();
898 void WebAXObjectProxy::Decrement() {
899 accessibility_object().decrement();
902 void WebAXObjectProxy::ShowMenu() {
905 void WebAXObjectProxy::Press() {
906 accessibility_object().press();
909 bool WebAXObjectProxy::IsEqual(v8::Handle
<v8::Object
> proxy
) {
910 WebAXObjectProxy
* unwrapped_proxy
= NULL
;
911 if (!gin::ConvertFromV8(blink::mainThreadIsolate(), proxy
, &unwrapped_proxy
))
913 return unwrapped_proxy
->IsEqualToObject(accessibility_object_
);
916 void WebAXObjectProxy::SetNotificationListener(
917 v8::Handle
<v8::Function
> callback
) {
918 v8::Isolate
* isolate
= blink::mainThreadIsolate();
919 notification_callback_
.Reset(isolate
, callback
);
922 void WebAXObjectProxy::UnsetNotificationListener() {
923 notification_callback_
.Reset();
926 void WebAXObjectProxy::TakeFocus() {
927 accessibility_object().setFocused(true);
930 void WebAXObjectProxy::ScrollToMakeVisible() {
931 accessibility_object().scrollToMakeVisible();
934 void WebAXObjectProxy::ScrollToMakeVisibleWithSubFocus(int x
, int y
,
935 int width
, int height
) {
936 accessibility_object().scrollToMakeVisibleWithSubFocus(
937 blink::WebRect(x
, y
, width
, height
));
940 void WebAXObjectProxy::ScrollToGlobalPoint(int x
, int y
) {
941 accessibility_object().scrollToGlobalPoint(blink::WebPoint(x
, y
));
944 int WebAXObjectProxy::WordStart(int character_index
) {
945 if (accessibility_object().role() != blink::WebAXRoleStaticText
)
948 int word_start
, word_end
;
949 GetBoundariesForOneWord(accessibility_object(), character_index
,
950 word_start
, word_end
);
954 int WebAXObjectProxy::WordEnd(int character_index
) {
955 if (accessibility_object().role() != blink::WebAXRoleStaticText
)
958 int word_start
, word_end
;
959 GetBoundariesForOneWord(accessibility_object(), character_index
,
960 word_start
, word_end
);
964 RootWebAXObjectProxy::RootWebAXObjectProxy(
965 const blink::WebAXObject
&object
, Factory
*factory
)
966 : WebAXObjectProxy(object
, factory
) {
969 v8::Handle
<v8::Object
> RootWebAXObjectProxy::GetChildAtIndex(unsigned index
) {
971 return v8::Handle
<v8::Object
>();
973 return factory()->GetOrCreate(accessibility_object());
976 bool RootWebAXObjectProxy::IsRoot() const {
980 WebAXObjectProxyList::WebAXObjectProxyList()
981 : elements_(blink::mainThreadIsolate()) {
984 WebAXObjectProxyList::~WebAXObjectProxyList() {
988 void WebAXObjectProxyList::Clear() {
992 v8::Handle
<v8::Object
> WebAXObjectProxyList::GetOrCreate(
993 const blink::WebAXObject
& object
) {
995 return v8::Handle
<v8::Object
>();
997 v8::Isolate
* isolate
= blink::mainThreadIsolate();
999 size_t elementCount
= elements_
.Size();
1000 for (size_t i
= 0; i
< elementCount
; i
++) {
1001 WebAXObjectProxy
* unwrapped_object
= NULL
;
1002 bool result
= gin::ConvertFromV8(isolate
, elements_
.Get(i
),
1005 DCHECK(unwrapped_object
);
1006 if (unwrapped_object
->IsEqualToObject(object
))
1007 return elements_
.Get(i
);
1010 v8::Handle
<v8::Value
> value_handle
= gin::CreateHandle(
1011 isolate
, new WebAXObjectProxy(object
, this)).ToV8();
1012 if (value_handle
.IsEmpty())
1013 return v8::Handle
<v8::Object
>();
1014 v8::Handle
<v8::Object
> handle
= value_handle
->ToObject();
1015 elements_
.Append(handle
);
1019 v8::Handle
<v8::Object
> WebAXObjectProxyList::CreateRoot(
1020 const blink::WebAXObject
& object
) {
1021 v8::Isolate
* isolate
= blink::mainThreadIsolate();
1022 v8::Handle
<v8::Value
> value_handle
= gin::CreateHandle(
1023 isolate
, new RootWebAXObjectProxy(object
, this)).ToV8();
1024 if (value_handle
.IsEmpty())
1025 return v8::Handle
<v8::Object
>();
1026 v8::Handle
<v8::Object
> handle
= value_handle
->ToObject();
1027 elements_
.Append(handle
);
1031 } // namespace content