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 // TODO(hajimehoshi): Remove this when UnsafePersistent is removed.
6 #define V8_ALLOW_ACCESS_TO_RAW_HANDLE_CONSTRUCTOR
8 #include "content/shell/renderer/test_runner/web_ax_object_proxy.h"
10 #include "base/strings/stringprintf.h"
11 #include "gin/handle.h"
12 #include "third_party/WebKit/public/platform/WebPoint.h"
13 #include "third_party/WebKit/public/platform/WebRect.h"
14 #include "third_party/WebKit/public/platform/WebString.h"
15 #include "third_party/WebKit/public/web/WebFrame.h"
16 #include "third_party/WebKit/public/web/WebKit.h"
22 // Map role value to string, matching Safari/Mac platform implementation to
23 // avoid rebaselining layout tests.
24 std::string RoleToString(blink::WebAXRole role)
26 std::string result = "AXRole: AX";
28 case blink::WebAXRoleAlertDialog:
29 return result.append("AlertDialog");
30 case blink::WebAXRoleAlert:
31 return result.append("Alert");
32 case blink::WebAXRoleAnnotation:
33 return result.append("Annotation");
34 case blink::WebAXRoleApplication:
35 return result.append("Application");
36 case blink::WebAXRoleArticle:
37 return result.append("Article");
38 case blink::WebAXRoleBanner:
39 return result.append("Banner");
40 case blink::WebAXRoleBrowser:
41 return result.append("Browser");
42 case blink::WebAXRoleBusyIndicator:
43 return result.append("BusyIndicator");
44 case blink::WebAXRoleButton:
45 return result.append("Button");
46 case blink::WebAXRoleCanvas:
47 return result.append("Canvas");
48 case blink::WebAXRoleCell:
49 return result.append("Cell");
50 case blink::WebAXRoleCheckBox:
51 return result.append("CheckBox");
52 case blink::WebAXRoleColorWell:
53 return result.append("ColorWell");
54 case blink::WebAXRoleColumnHeader:
55 return result.append("ColumnHeader");
56 case blink::WebAXRoleColumn:
57 return result.append("Column");
58 case blink::WebAXRoleComboBox:
59 return result.append("ComboBox");
60 case blink::WebAXRoleComplementary:
61 return result.append("Complementary");
62 case blink::WebAXRoleContentInfo:
63 return result.append("ContentInfo");
64 case blink::WebAXRoleDefinition:
65 return result.append("Definition");
66 case blink::WebAXRoleDescriptionListDetail:
67 return result.append("DescriptionListDetail");
68 case blink::WebAXRoleDescriptionListTerm:
69 return result.append("DescriptionListTerm");
70 case blink::WebAXRoleDialog:
71 return result.append("Dialog");
72 case blink::WebAXRoleDirectory:
73 return result.append("Directory");
74 case blink::WebAXRoleDisclosureTriangle:
75 return result.append("DisclosureTriangle");
76 case blink::WebAXRoleDiv:
77 return result.append("Div");
78 case blink::WebAXRoleDocument:
79 return result.append("Document");
80 case blink::WebAXRoleDrawer:
81 return result.append("Drawer");
82 case blink::WebAXRoleEditableText:
83 return result.append("EditableText");
84 case blink::WebAXRoleFooter:
85 return result.append("Footer");
86 case blink::WebAXRoleForm:
87 return result.append("Form");
88 case blink::WebAXRoleGrid:
89 return result.append("Grid");
90 case blink::WebAXRoleGroup:
91 return result.append("Group");
92 case blink::WebAXRoleGrowArea:
93 return result.append("GrowArea");
94 case blink::WebAXRoleHeading:
95 return result.append("Heading");
96 case blink::WebAXRoleHelpTag:
97 return result.append("HelpTag");
98 case blink::WebAXRoleHorizontalRule:
99 return result.append("HorizontalRule");
100 case blink::WebAXRoleIgnored:
101 return result.append("Ignored");
102 case blink::WebAXRoleImageMapLink:
103 return result.append("ImageMapLink");
104 case blink::WebAXRoleImageMap:
105 return result.append("ImageMap");
106 case blink::WebAXRoleImage:
107 return result.append("Image");
108 case blink::WebAXRoleIncrementor:
109 return result.append("Incrementor");
110 case blink::WebAXRoleInlineTextBox:
111 return result.append("InlineTextBox");
112 case blink::WebAXRoleLabel:
113 return result.append("Label");
114 case blink::WebAXRoleLegend:
115 return result.append("Legend");
116 case blink::WebAXRoleLink:
117 return result.append("Link");
118 case blink::WebAXRoleListBoxOption:
119 return result.append("ListBoxOption");
120 case blink::WebAXRoleListBox:
121 return result.append("ListBox");
122 case blink::WebAXRoleListItem:
123 return result.append("ListItem");
124 case blink::WebAXRoleListMarker:
125 return result.append("ListMarker");
126 case blink::WebAXRoleList:
127 return result.append("List");
128 case blink::WebAXRoleLog:
129 return result.append("Log");
130 case blink::WebAXRoleMain:
131 return result.append("Main");
132 case blink::WebAXRoleMarquee:
133 return result.append("Marquee");
134 case blink::WebAXRoleMathElement:
135 return result.append("MathElement");
136 case blink::WebAXRoleMath:
137 return result.append("Math");
138 case blink::WebAXRoleMatte:
139 return result.append("Matte");
140 case blink::WebAXRoleMenuBar:
141 return result.append("MenuBar");
142 case blink::WebAXRoleMenuButton:
143 return result.append("MenuButton");
144 case blink::WebAXRoleMenuItem:
145 return result.append("MenuItem");
146 case blink::WebAXRoleMenuListOption:
147 return result.append("MenuListOption");
148 case blink::WebAXRoleMenuListPopup:
149 return result.append("MenuListPopup");
150 case blink::WebAXRoleMenu:
151 return result.append("Menu");
152 case blink::WebAXRoleNavigation:
153 return result.append("Navigation");
154 case blink::WebAXRoleNote:
155 return result.append("Note");
156 case blink::WebAXRoleOutline:
157 return result.append("Outline");
158 case blink::WebAXRoleParagraph:
159 return result.append("Paragraph");
160 case blink::WebAXRolePopUpButton:
161 return result.append("PopUpButton");
162 case blink::WebAXRolePresentational:
163 return result.append("Presentational");
164 case blink::WebAXRoleProgressIndicator:
165 return result.append("ProgressIndicator");
166 case blink::WebAXRoleRadioButton:
167 return result.append("RadioButton");
168 case blink::WebAXRoleRadioGroup:
169 return result.append("RadioGroup");
170 case blink::WebAXRoleRegion:
171 return result.append("Region");
172 case blink::WebAXRoleRootWebArea:
173 return result.append("RootWebArea");
174 case blink::WebAXRoleRowHeader:
175 return result.append("RowHeader");
176 case blink::WebAXRoleRow:
177 return result.append("Row");
178 case blink::WebAXRoleRulerMarker:
179 return result.append("RulerMarker");
180 case blink::WebAXRoleRuler:
181 return result.append("Ruler");
182 case blink::WebAXRoleSVGRoot:
183 return result.append("SVGRoot");
184 case blink::WebAXRoleScrollArea:
185 return result.append("ScrollArea");
186 case blink::WebAXRoleScrollBar:
187 return result.append("ScrollBar");
188 case blink::WebAXRoleSeamlessWebArea:
189 return result.append("SeamlessWebArea");
190 case blink::WebAXRoleSearch:
191 return result.append("Search");
192 case blink::WebAXRoleSheet:
193 return result.append("Sheet");
194 case blink::WebAXRoleSlider:
195 return result.append("Slider");
196 case blink::WebAXRoleSliderThumb:
197 return result.append("SliderThumb");
198 case blink::WebAXRoleSpinButtonPart:
199 return result.append("SpinButtonPart");
200 case blink::WebAXRoleSpinButton:
201 return result.append("SpinButton");
202 case blink::WebAXRoleSplitGroup:
203 return result.append("SplitGroup");
204 case blink::WebAXRoleSplitter:
205 return result.append("Splitter");
206 case blink::WebAXRoleStaticText:
207 return result.append("StaticText");
208 case blink::WebAXRoleStatus:
209 return result.append("Status");
210 case blink::WebAXRoleSystemWide:
211 return result.append("SystemWide");
212 case blink::WebAXRoleTabGroup:
213 return result.append("TabGroup");
214 case blink::WebAXRoleTabList:
215 return result.append("TabList");
216 case blink::WebAXRoleTabPanel:
217 return result.append("TabPanel");
218 case blink::WebAXRoleTab:
219 return result.append("Tab");
220 case blink::WebAXRoleTableHeaderContainer:
221 return result.append("TableHeaderContainer");
222 case blink::WebAXRoleTable:
223 return result.append("Table");
224 case blink::WebAXRoleTextArea:
225 return result.append("TextArea");
226 case blink::WebAXRoleTextField:
227 return result.append("TextField");
228 case blink::WebAXRoleTimer:
229 return result.append("Timer");
230 case blink::WebAXRoleToggleButton:
231 return result.append("ToggleButton");
232 case blink::WebAXRoleToolbar:
233 return result.append("Toolbar");
234 case blink::WebAXRoleTreeGrid:
235 return result.append("TreeGrid");
236 case blink::WebAXRoleTreeItem:
237 return result.append("TreeItem");
238 case blink::WebAXRoleTree:
239 return result.append("Tree");
240 case blink::WebAXRoleUnknown:
241 return result.append("Unknown");
242 case blink::WebAXRoleUserInterfaceTooltip:
243 return result.append("UserInterfaceTooltip");
244 case blink::WebAXRoleValueIndicator:
245 return result.append("ValueIndicator");
246 case blink::WebAXRoleWebArea:
247 return result.append("WebArea");
248 case blink::WebAXRoleWindow:
249 return result.append("Window");
251 return result.append("Unknown");
255 std::string GetDescription(const blink::WebAXObject& object) {
256 std::string description = object.accessibilityDescription().utf8();
257 return description.insert(0, "AXDescription: ");
260 std::string GetHelpText(const blink::WebAXObject& object) {
261 std::string help_text = object.helpText().utf8();
262 return help_text.insert(0, "AXHelp: ");
265 std::string GetStringValue(const blink::WebAXObject& object) {
267 if (object.role() == blink::WebAXRoleColorWell) {
269 object.colorValue(r, g, b);
270 value = base::StringPrintf("rgb %7.5f %7.5f %7.5f 1",
271 r / 255., g / 255., b / 255.);
273 value = object.stringValue().utf8();
275 return value.insert(0, "AXValue: ");
278 std::string GetRole(const blink::WebAXObject& object) {
279 std::string role_string = RoleToString(object.role());
281 // Special-case canvas with fallback content because Chromium wants to treat
282 // this as essentially a separate role that it can map differently depending
284 if (object.role() == blink::WebAXRoleCanvas &&
285 object.canvasHasFallbackContent()) {
286 role_string += "WithFallbackContent";
292 std::string GetTitle(const blink::WebAXObject& object) {
293 std::string title = object.title().utf8();
294 return title.insert(0, "AXTitle: ");
297 std::string GetOrientation(const blink::WebAXObject& object) {
298 if (object.isVertical())
299 return "AXOrientation: AXVerticalOrientation";
301 return "AXOrientation: AXHorizontalOrientation";
304 std::string GetValueDescription(const blink::WebAXObject& object) {
305 std::string value_description = object.valueDescription().utf8();
306 return value_description.insert(0, "AXValueDescription: ");
309 std::string GetAttributes(const blink::WebAXObject& object) {
310 // FIXME: Concatenate all attributes of the AXObject.
311 std::string attributes(GetTitle(object));
312 attributes.append("\n");
313 attributes.append(GetRole(object));
314 attributes.append("\n");
315 attributes.append(GetDescription(object));
319 blink::WebRect BoundsForCharacter(const blink::WebAXObject& object,
320 int characterIndex) {
321 DCHECK_EQ(object.role(), blink::WebAXRoleStaticText);
323 for (unsigned i = 0; i < object.childCount(); i++) {
324 blink::WebAXObject inline_text_box = object.childAt(i);
325 DCHECK_EQ(inline_text_box.role(), blink::WebAXRoleInlineTextBox);
327 end += inline_text_box.stringValue().length();
328 if (characterIndex < start || characterIndex >= end)
330 blink::WebRect inline_text_box_rect = inline_text_box.boundingBoxRect();
331 int localIndex = characterIndex - start;
332 blink::WebVector<int> character_offsets;
333 inline_text_box.characterOffsets(character_offsets);
334 DCHECK(character_offsets.size() > 0 &&
335 character_offsets.size() == inline_text_box.stringValue().length());
336 switch (inline_text_box.textDirection()) {
337 case blink::WebAXTextDirectionLR: {
339 int left = inline_text_box_rect.x + character_offsets[localIndex - 1];
340 int width = character_offsets[localIndex] -
341 character_offsets[localIndex - 1];
342 return blink::WebRect(left, inline_text_box_rect.y,
343 width, inline_text_box_rect.height);
345 return blink::WebRect(
346 inline_text_box_rect.x, inline_text_box_rect.y,
347 character_offsets[0], inline_text_box_rect.height);
349 case blink::WebAXTextDirectionRL: {
350 int right = inline_text_box_rect.x + inline_text_box_rect.width;
353 int left = right - character_offsets[localIndex];
354 int width = character_offsets[localIndex] -
355 character_offsets[localIndex - 1];
356 return blink::WebRect(left, inline_text_box_rect.y,
357 width, inline_text_box_rect.height);
359 int left = right - character_offsets[0];
360 return blink::WebRect(
361 left, inline_text_box_rect.y,
362 character_offsets[0], inline_text_box_rect.height);
364 case blink::WebAXTextDirectionTB: {
366 int top = inline_text_box_rect.y + character_offsets[localIndex - 1];
367 int height = character_offsets[localIndex] -
368 character_offsets[localIndex - 1];
369 return blink::WebRect(inline_text_box_rect.x, top,
370 inline_text_box_rect.width, height);
372 return blink::WebRect(inline_text_box_rect.x, inline_text_box_rect.y,
373 inline_text_box_rect.width, character_offsets[0]);
375 case blink::WebAXTextDirectionBT: {
376 int bottom = inline_text_box_rect.y + inline_text_box_rect.height;
379 int top = bottom - character_offsets[localIndex];
380 int height = character_offsets[localIndex] -
381 character_offsets[localIndex - 1];
382 return blink::WebRect(inline_text_box_rect.x, top,
383 inline_text_box_rect.width, height);
385 int top = bottom - character_offsets[0];
386 return blink::WebRect(inline_text_box_rect.x, top,
387 inline_text_box_rect.width, character_offsets[0]);
393 return blink::WebRect();
396 void GetBoundariesForOneWord(const blink::WebAXObject& object,
401 for (unsigned i = 0; i < object.childCount(); i++) {
402 blink::WebAXObject inline_text_box = object.childAt(i);
403 DCHECK_EQ(inline_text_box.role(), blink::WebAXRoleInlineTextBox);
405 end += inline_text_box.stringValue().length();
406 if (end <= character_index)
408 int localIndex = character_index - start;
410 blink::WebVector<int> starts;
411 blink::WebVector<int> ends;
412 inline_text_box.wordBoundaries(starts, ends);
413 size_t word_count = starts.size();
414 DCHECK_EQ(ends.size(), word_count);
416 // If there are no words, use the InlineTextBox boundaries.
423 // Look for a character within any word other than the last.
424 for (size_t j = 0; j < word_count - 1; j++) {
425 if (localIndex <= ends[j]) {
426 word_start = start + starts[j];
427 word_end = start + ends[j];
432 // Return the last word by default.
433 word_start = start + starts[word_count - 1];
434 word_end = start + ends[word_count - 1];
439 // Collects attributes into a string, delimited by dashes. Used by all methods
440 // that output lists of attributes: attributesOfLinkedUIElementsCallback,
441 // AttributesOfChildrenCallback, etc.
442 class AttributesCollector {
444 AttributesCollector() {}
445 ~AttributesCollector() {}
447 void CollectAttributes(const blink::WebAXObject& object) {
448 attributes_.append("\n------------\n");
449 attributes_.append(GetAttributes(object));
452 std::string attributes() const { return attributes_; }
455 std::string attributes_;
457 DISALLOW_COPY_AND_ASSIGN(AttributesCollector);
462 gin::WrapperInfo WebAXObjectProxy::kWrapperInfo = {
463 gin::kEmbedderNativeGin};
465 WebAXObjectProxy::WebAXObjectProxy(const blink::WebAXObject& object,
466 WebAXObjectProxy::Factory* factory)
467 : accessibility_object_(object),
471 WebAXObjectProxy::~WebAXObjectProxy() {}
473 gin::ObjectTemplateBuilder
474 WebAXObjectProxy::GetObjectTemplateBuilder(v8::Isolate* isolate) {
475 return gin::Wrappable<WebAXObjectProxy>::GetObjectTemplateBuilder(isolate)
476 .SetProperty("role", &WebAXObjectProxy::Role)
477 .SetProperty("title", &WebAXObjectProxy::Title)
478 .SetProperty("description", &WebAXObjectProxy::Description)
479 .SetProperty("helpText", &WebAXObjectProxy::HelpText)
480 .SetProperty("stringValue", &WebAXObjectProxy::StringValue)
481 .SetProperty("x", &WebAXObjectProxy::X)
482 .SetProperty("y", &WebAXObjectProxy::Y)
483 .SetProperty("width", &WebAXObjectProxy::Width)
484 .SetProperty("height", &WebAXObjectProxy::Height)
485 .SetProperty("intValue", &WebAXObjectProxy::IntValue)
486 .SetProperty("minValue", &WebAXObjectProxy::MinValue)
487 .SetProperty("maxValue", &WebAXObjectProxy::MaxValue)
488 .SetProperty("valueDescription", &WebAXObjectProxy::ValueDescription)
489 .SetProperty("childrenCount", &WebAXObjectProxy::ChildrenCount)
490 .SetProperty("insertionPointLineNumber",
491 &WebAXObjectProxy::InsertionPointLineNumber)
492 .SetProperty("selectedTextRange", &WebAXObjectProxy::SelectedTextRange)
493 .SetProperty("isEnabled", &WebAXObjectProxy::IsEnabled)
494 .SetProperty("isRequired", &WebAXObjectProxy::IsRequired)
495 .SetProperty("isFocused", &WebAXObjectProxy::IsFocused)
496 .SetProperty("isFocusable", &WebAXObjectProxy::IsFocusable)
497 .SetProperty("isSelected", &WebAXObjectProxy::IsSelected)
498 .SetProperty("isSelectable", &WebAXObjectProxy::IsSelectable)
499 .SetProperty("isMultiSelectable", &WebAXObjectProxy::IsMultiSelectable)
500 .SetProperty("isSelectedOptionActive",
501 &WebAXObjectProxy::IsSelectedOptionActive)
502 .SetProperty("isExpanded", &WebAXObjectProxy::IsExpanded)
503 .SetProperty("isChecked", &WebAXObjectProxy::IsChecked)
504 .SetProperty("isVisible", &WebAXObjectProxy::IsVisible)
505 .SetProperty("isOffScreen", &WebAXObjectProxy::IsOffScreen)
506 .SetProperty("isCollapsed", &WebAXObjectProxy::IsCollapsed)
507 .SetProperty("hasPopup", &WebAXObjectProxy::HasPopup)
508 .SetProperty("isValid", &WebAXObjectProxy::IsValid)
509 .SetProperty("isReadOnly", &WebAXObjectProxy::IsReadOnly)
510 .SetProperty("orientation", &WebAXObjectProxy::Orientation)
511 .SetProperty("clickPointX", &WebAXObjectProxy::ClickPointX)
512 .SetProperty("clickPointY", &WebAXObjectProxy::ClickPointY)
513 .SetProperty("rowCount", &WebAXObjectProxy::RowCount)
514 .SetProperty("columnCount", &WebAXObjectProxy::ColumnCount)
515 .SetProperty("isClickable", &WebAXObjectProxy::IsClickable)
516 .SetMethod("allAttributes", &WebAXObjectProxy::AllAttributes)
517 .SetMethod("attributesOfChildren",
518 &WebAXObjectProxy::AttributesOfChildren)
519 .SetMethod("lineForIndex", &WebAXObjectProxy::LineForIndex)
520 .SetMethod("boundsForRange", &WebAXObjectProxy::BoundsForRange)
521 .SetMethod("childAtIndex", &WebAXObjectProxy::ChildAtIndex)
522 .SetMethod("elementAtPoint", &WebAXObjectProxy::ElementAtPoint)
523 .SetMethod("tableHeader", &WebAXObjectProxy::TableHeader)
524 .SetMethod("rowIndexRange", &WebAXObjectProxy::RowIndexRange)
525 .SetMethod("columnIndexRange", &WebAXObjectProxy::ColumnIndexRange)
526 .SetMethod("cellForColumnAndRow", &WebAXObjectProxy::CellForColumnAndRow)
527 .SetMethod("titleUIElement", &WebAXObjectProxy::TitleUIElement)
528 .SetMethod("setSelectedTextRange",
529 &WebAXObjectProxy::SetSelectedTextRange)
530 .SetMethod("isAttributeSettable", &WebAXObjectProxy::IsAttributeSettable)
531 .SetMethod("isPressActionSupported",
532 &WebAXObjectProxy::IsPressActionSupported)
533 .SetMethod("isIncrementActionSupported",
534 &WebAXObjectProxy::IsIncrementActionSupported)
535 .SetMethod("isDecrementActionSupported",
536 &WebAXObjectProxy::IsDecrementActionSupported)
537 .SetMethod("parentElement", &WebAXObjectProxy::ParentElement)
538 .SetMethod("increment", &WebAXObjectProxy::Increment)
539 .SetMethod("decrement", &WebAXObjectProxy::Decrement)
540 .SetMethod("showMenu", &WebAXObjectProxy::ShowMenu)
541 .SetMethod("press", &WebAXObjectProxy::Press)
542 .SetMethod("isEqual", &WebAXObjectProxy::IsEqual)
543 .SetMethod("setNotificationListener",
544 &WebAXObjectProxy::SetNotificationListener)
545 .SetMethod("unsetNotificationListener",
546 &WebAXObjectProxy::UnsetNotificationListener)
547 .SetMethod("takeFocus", &WebAXObjectProxy::TakeFocus)
548 .SetMethod("scrollToMakeVisible", &WebAXObjectProxy::ScrollToMakeVisible)
549 .SetMethod("scrollToMakeVisibleWithSubFocus",
550 &WebAXObjectProxy::ScrollToMakeVisibleWithSubFocus)
551 .SetMethod("scrollToGlobalPoint", &WebAXObjectProxy::ScrollToGlobalPoint)
552 .SetMethod("wordStart", &WebAXObjectProxy::WordStart)
553 .SetMethod("wordEnd", &WebAXObjectProxy::WordEnd)
554 // TODO(hajimehoshi): This is for backward compatibility. Remove them.
555 .SetMethod("addNotificationListener",
556 &WebAXObjectProxy::SetNotificationListener)
557 .SetMethod("removeNotificationListener",
558 &WebAXObjectProxy::UnsetNotificationListener);
561 v8::Handle<v8::Object> WebAXObjectProxy::GetChildAtIndex(unsigned index) {
562 return factory_->GetOrCreate(accessibility_object().childAt(index));
565 bool WebAXObjectProxy::IsRoot() const {
569 bool WebAXObjectProxy::IsEqualToObject(const blink::WebAXObject& other) {
570 return accessibility_object().equals(other);
573 void WebAXObjectProxy::NotificationReceived(
574 blink::WebFrame* frame,
575 const std::string& notification_name) {
576 if (notification_callback_.IsEmpty())
579 v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
580 if (context.IsEmpty())
583 v8::Isolate* isolate = blink::mainThreadIsolate();
585 v8::Handle<v8::Value> argv[] = {
586 v8::String::NewFromUtf8(isolate, notification_name.data(),
587 v8::String::kNormalString,
588 notification_name.size()),
590 frame->callFunctionEvenIfScriptDisabled(
591 v8::Local<v8::Function>::New(isolate, notification_callback_),
597 std::string WebAXObjectProxy::Role() {
598 return GetRole(accessibility_object());
601 std::string WebAXObjectProxy::Title() {
602 return GetTitle(accessibility_object());
605 std::string WebAXObjectProxy::Description() {
606 return GetDescription(accessibility_object());
609 std::string WebAXObjectProxy::HelpText() {
610 return GetHelpText(accessibility_object());
613 std::string WebAXObjectProxy::StringValue() {
614 return GetStringValue(accessibility_object());
617 int WebAXObjectProxy::X() {
618 return accessibility_object().boundingBoxRect().x;
621 int WebAXObjectProxy::Y() {
622 return accessibility_object().boundingBoxRect().y;
625 int WebAXObjectProxy::Width() {
626 return accessibility_object().boundingBoxRect().width;
629 int WebAXObjectProxy::Height() {
630 return accessibility_object().boundingBoxRect().height;
633 int WebAXObjectProxy::IntValue() {
634 if (accessibility_object().supportsRangeValue())
635 return accessibility_object().valueForRange();
636 else if (accessibility_object().role() == blink::WebAXRoleHeading)
637 return accessibility_object().headingLevel();
639 return atoi(accessibility_object().stringValue().utf8().data());
642 int WebAXObjectProxy::MinValue() {
643 return accessibility_object().minValueForRange();
646 int WebAXObjectProxy::MaxValue() {
647 return accessibility_object().maxValueForRange();
650 std::string WebAXObjectProxy::ValueDescription() {
651 return GetValueDescription(accessibility_object());
654 int WebAXObjectProxy::ChildrenCount() {
655 int count = 1; // Root object always has only one child, the WebView.
657 count = accessibility_object().childCount();
661 int WebAXObjectProxy::InsertionPointLineNumber() {
662 if (!accessibility_object().isFocused())
664 return accessibility_object().selectionEndLineNumber();
667 std::string WebAXObjectProxy::SelectedTextRange() {
668 unsigned selection_start = accessibility_object().selectionStart();
669 unsigned selection_end = accessibility_object().selectionEnd();
670 return base::StringPrintf("{%d, %d}",
671 selection_start, selection_end - selection_start);
674 bool WebAXObjectProxy::IsEnabled() {
675 return accessibility_object().isEnabled();
678 bool WebAXObjectProxy::IsRequired() {
679 return accessibility_object().isRequired();
682 bool WebAXObjectProxy::IsFocused() {
683 return accessibility_object().isFocused();
686 bool WebAXObjectProxy::IsFocusable() {
687 return accessibility_object().canSetFocusAttribute();
690 bool WebAXObjectProxy::IsSelected() {
691 return accessibility_object().isSelected();
694 bool WebAXObjectProxy::IsSelectable() {
695 return accessibility_object().canSetSelectedAttribute();
698 bool WebAXObjectProxy::IsMultiSelectable() {
699 return accessibility_object().isMultiSelectable();
702 bool WebAXObjectProxy::IsSelectedOptionActive() {
703 return accessibility_object().isSelectedOptionActive();
706 bool WebAXObjectProxy::IsExpanded() {
707 return !accessibility_object().isCollapsed();
710 bool WebAXObjectProxy::IsChecked() {
711 return accessibility_object().isChecked();
714 bool WebAXObjectProxy::IsVisible() {
715 return accessibility_object().isVisible();
718 bool WebAXObjectProxy::IsOffScreen() {
719 return accessibility_object().isOffScreen();
722 bool WebAXObjectProxy::IsCollapsed() {
723 return accessibility_object().isCollapsed();
726 bool WebAXObjectProxy::HasPopup() {
727 return accessibility_object().ariaHasPopup();
730 bool WebAXObjectProxy::IsValid() {
731 return !accessibility_object().isDetached();
734 bool WebAXObjectProxy::IsReadOnly() {
735 return accessibility_object().isReadOnly();
738 std::string WebAXObjectProxy::Orientation() {
739 return GetOrientation(accessibility_object());
742 int WebAXObjectProxy::ClickPointX() {
743 return accessibility_object().clickPoint().x;
746 int WebAXObjectProxy::ClickPointY() {
747 return accessibility_object().clickPoint().y;
750 int32_t WebAXObjectProxy::RowCount() {
751 return static_cast<int32_t>(accessibility_object().rowCount());
754 int32_t WebAXObjectProxy::ColumnCount() {
755 return static_cast<int32_t>(accessibility_object().columnCount());
758 bool WebAXObjectProxy::IsClickable() {
759 return accessibility_object().isClickable();
762 std::string WebAXObjectProxy::AllAttributes() {
763 return GetAttributes(accessibility_object());
766 std::string WebAXObjectProxy::AttributesOfChildren() {
767 AttributesCollector collector;
768 unsigned size = accessibility_object().childCount();
769 for (unsigned i = 0; i < size; ++i)
770 collector.CollectAttributes(accessibility_object().childAt(i));
771 return collector.attributes();
774 int WebAXObjectProxy::LineForIndex(int index) {
775 blink::WebVector<int> line_breaks;
776 accessibility_object().lineBreaks(line_breaks);
778 int vector_size = static_cast<int>(line_breaks.size());
779 while (line < vector_size && line_breaks[line] <= index)
784 std::string WebAXObjectProxy::BoundsForRange(int start, int end) {
785 if (accessibility_object().role() != blink::WebAXRoleStaticText)
786 return std::string();
788 int len = end - start;
790 // Get the bounds for each character and union them into one large rectangle.
791 // This is just for testing so it doesn't need to be efficient.
792 blink::WebRect bounds = BoundsForCharacter(accessibility_object(), start);
793 for (int i = 1; i < len; i++) {
794 blink::WebRect next = BoundsForCharacter(accessibility_object(), start + i);
795 int right = std::max(bounds.x + bounds.width, next.x + next.width);
796 int bottom = std::max(bounds.y + bounds.height, next.y + next.height);
797 bounds.x = std::min(bounds.x, next.x);
798 bounds.y = std::min(bounds.y, next.y);
799 bounds.width = right - bounds.x;
800 bounds.height = bottom - bounds.y;
803 return base::StringPrintf("{x: %d, y: %d, width: %d, height: %d}",
804 bounds.x, bounds.y, bounds.width, bounds.height);
807 v8::Handle<v8::Object> WebAXObjectProxy::ChildAtIndex(int index) {
808 return GetChildAtIndex(index);
811 v8::Handle<v8::Object> WebAXObjectProxy::ElementAtPoint(int x, int y) {
812 blink::WebPoint point(x, y);
813 blink::WebAXObject obj = accessibility_object().hitTest(point);
815 return v8::Handle<v8::Object>();
817 return factory_->GetOrCreate(obj);
820 v8::Handle<v8::Object> WebAXObjectProxy::TableHeader() {
821 blink::WebAXObject obj = accessibility_object().headerContainerObject();
823 return v8::Handle<v8::Object>();
825 return factory_->GetOrCreate(obj);
828 std::string WebAXObjectProxy::RowIndexRange() {
829 unsigned row_index = accessibility_object().cellRowIndex();
830 unsigned row_span = accessibility_object().cellRowSpan();
831 return base::StringPrintf("{%d, %d}", row_index, row_span);
834 std::string WebAXObjectProxy::ColumnIndexRange() {
835 unsigned column_index = accessibility_object().cellColumnIndex();
836 unsigned column_span = accessibility_object().cellColumnSpan();
837 return base::StringPrintf("{%d, %d}", column_index, column_span);
840 v8::Handle<v8::Object> WebAXObjectProxy::CellForColumnAndRow(
841 int column, int row) {
842 blink::WebAXObject obj =
843 accessibility_object().cellForColumnAndRow(column, row);
845 return v8::Handle<v8::Object>();
847 return factory_->GetOrCreate(obj);
850 v8::Handle<v8::Object> WebAXObjectProxy::TitleUIElement() {
851 blink::WebAXObject obj = accessibility_object().titleUIElement();
853 return v8::Handle<v8::Object>();
855 return factory_->GetOrCreate(obj);
858 void WebAXObjectProxy::SetSelectedTextRange(int selection_start,
860 accessibility_object().setSelectedTextRange(selection_start,
861 selection_start + length);
864 bool WebAXObjectProxy::IsAttributeSettable(const std::string& attribute) {
865 bool settable = false;
866 if (attribute == "AXValue")
867 settable = accessibility_object().canSetValueAttribute();
871 bool WebAXObjectProxy::IsPressActionSupported() {
872 return accessibility_object().canPress();
875 bool WebAXObjectProxy::IsIncrementActionSupported() {
876 return accessibility_object().canIncrement();
879 bool WebAXObjectProxy::IsDecrementActionSupported() {
880 return accessibility_object().canDecrement();
883 v8::Handle<v8::Object> WebAXObjectProxy::ParentElement() {
884 blink::WebAXObject parent_object = accessibility_object().parentObject();
885 while (parent_object.accessibilityIsIgnored())
886 parent_object = parent_object.parentObject();
887 return factory_->GetOrCreate(parent_object);
890 void WebAXObjectProxy::Increment() {
891 accessibility_object().increment();
894 void WebAXObjectProxy::Decrement() {
895 accessibility_object().decrement();
898 void WebAXObjectProxy::ShowMenu() {
901 void WebAXObjectProxy::Press() {
902 accessibility_object().press();
905 bool WebAXObjectProxy::IsEqual(v8::Handle<v8::Object> proxy) {
906 WebAXObjectProxy* unwrapped_proxy = NULL;
907 if (!gin::ConvertFromV8(blink::mainThreadIsolate(), proxy, &unwrapped_proxy))
909 return unwrapped_proxy->IsEqualToObject(accessibility_object_);
912 void WebAXObjectProxy::SetNotificationListener(
913 v8::Handle<v8::Function> callback) {
914 v8::Isolate* isolate = blink::mainThreadIsolate();
915 notification_callback_.Reset(isolate, callback);
918 void WebAXObjectProxy::UnsetNotificationListener() {
919 notification_callback_.Reset();
922 void WebAXObjectProxy::TakeFocus() {
923 accessibility_object().setFocused(true);
926 void WebAXObjectProxy::ScrollToMakeVisible() {
927 accessibility_object().scrollToMakeVisible();
930 void WebAXObjectProxy::ScrollToMakeVisibleWithSubFocus(int x, int y,
931 int width, int height) {
932 accessibility_object().scrollToMakeVisibleWithSubFocus(
933 blink::WebRect(x, y, width, height));
936 void WebAXObjectProxy::ScrollToGlobalPoint(int x, int y) {
937 accessibility_object().scrollToGlobalPoint(blink::WebPoint(x, y));
940 int WebAXObjectProxy::WordStart(int character_index) {
941 if (accessibility_object().role() != blink::WebAXRoleStaticText)
944 int word_start, word_end;
945 GetBoundariesForOneWord(accessibility_object(), character_index,
946 word_start, word_end);
950 int WebAXObjectProxy::WordEnd(int character_index) {
951 if (accessibility_object().role() != blink::WebAXRoleStaticText)
954 int word_start, word_end;
955 GetBoundariesForOneWord(accessibility_object(), character_index,
956 word_start, word_end);
960 RootWebAXObjectProxy::RootWebAXObjectProxy(
961 const blink::WebAXObject &object, Factory *factory)
962 : WebAXObjectProxy(object, factory) {
965 v8::Handle<v8::Object> RootWebAXObjectProxy::GetChildAtIndex(unsigned index) {
967 return v8::Handle<v8::Object>();
969 return factory()->GetOrCreate(accessibility_object());
972 bool RootWebAXObjectProxy::IsRoot() const {
976 WebAXObjectProxyList::WebAXObjectProxyList() {
979 WebAXObjectProxyList::~WebAXObjectProxyList() {
983 void WebAXObjectProxyList::Clear() {
984 for (ElementList::iterator i = elements_.begin(); i != elements_.end(); ++i)
989 v8::Handle<v8::Object> WebAXObjectProxyList::GetOrCreate(
990 const blink::WebAXObject& object) {
992 return v8::Handle<v8::Object>();
994 v8::Isolate* isolate = blink::mainThreadIsolate();
996 size_t elementCount = elements_.size();
997 for (size_t i = 0; i < elementCount; i++) {
998 WebAXObjectProxy* unwrapped_object = NULL;
999 bool result = gin::ConvertFromV8(isolate, elements_[i].NewLocal(isolate),
1002 DCHECK(unwrapped_object);
1003 if (unwrapped_object->IsEqualToObject(object))
1004 return elements_[i].NewLocal(isolate);
1007 v8::Handle<v8::Value> value_handle = gin::CreateHandle(
1008 isolate, new WebAXObjectProxy(object, this)).ToV8();
1009 if (value_handle.IsEmpty())
1010 return v8::Handle<v8::Object>();
1011 v8::Handle<v8::Object> handle = value_handle->ToObject();
1012 UnsafePersistent<v8::Object> unsafe_handle(isolate, handle);
1013 elements_.push_back(unsafe_handle);
1014 return unsafe_handle.NewLocal(isolate);
1017 v8::Handle<v8::Object> WebAXObjectProxyList::CreateRoot(
1018 const blink::WebAXObject& object) {
1019 v8::Isolate* isolate = blink::mainThreadIsolate();
1020 v8::Handle<v8::Value> value_handle = gin::CreateHandle(
1021 isolate, new RootWebAXObjectProxy(object, this)).ToV8();
1022 if (value_handle.IsEmpty())
1023 return v8::Handle<v8::Object>();
1024 v8::Handle<v8::Object> handle = value_handle->ToObject();
1025 UnsafePersistent<v8::Object> unsafe_handle(isolate, handle);
1026 elements_.push_back(unsafe_handle);
1027 return unsafe_handle.NewLocal(isolate);
1030 } // namespace content